From 3746c452ea0b62460e6579e7ea9cb0d395b0289e Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 17 May 2026 03:56:35 +0100 Subject: [PATCH 1/3] fix(codegen): emit K9! magic line + pedigree block (closes #8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_k9_contract emitted `# Auto-generated…` as the first line and no pedigree, so every generated .k9 failed the canonical hyperpolymath/k9-validate-action: - Missing K9! magic number (first non-empty line must be 'K9!') - Missing pedigree block Now emits `K9!` as the first line, an SPDX header, and a `pedigree` block (schema_version + metadata.name + security.leash + signature_ required) — matching the template-.k9.ncl shape and satisfying the validator's name(error)/version(warn)/leash(warn)/hunt-signature checks. Verified end-to-end against k9-validate-action@2d96f43: 3 files scanned, 0 errors, 0 warnings. Unit test strengthened: asserts K9! first line + pedigree fields. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/codegen/contract.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/codegen/contract.rs b/src/codegen/contract.rs index 741d3cc..2139a9f 100644 --- a/src/codegen/contract.rs +++ b/src/codegen/contract.rs @@ -15,9 +15,17 @@ use crate::codegen::parser::{ParsedEntry, ValueType}; /// /// The output format: /// ```text +/// K9! +/// # SPDX-License-Identifier: PMPL-1.0-or-later /// # Auto-generated K9 contract for /// # Safety tier: /// +/// pedigree = { +/// schema_version = "1.0.0" +/// metadata = { name = "" version = "1.0.0" } +/// security = { leash = "" signature_required = false } +/// } +/// /// [must] /// key : type { constraint, ... } /// @@ -41,11 +49,31 @@ pub fn generate_k9_contract( ) -> String { let mut output = String::new(); - // Header + // Header — `K9!` MUST be the first non-empty line and a `pedigree` + // block is mandatory, per the canonical hyperpolymath/k9-validate-action. + output.push_str("K9!\n"); + output.push_str("# SPDX-License-Identifier: PMPL-1.0-or-later\n"); output.push_str(&format!("# Auto-generated K9 contract for {}\n", name)); output.push_str(&format!("# Safety tier: {}\n", safety_tier)); output.push('\n'); + // [pedigree] — provenance + security leash. Required fields: + // metadata.name (error if absent), version/schema_version (warning), + // security.leash ∈ {kennel,yard,hunt} (warning if absent), and a + // signature field (error at hunt level if absent). + output.push_str("pedigree = {\n"); + output.push_str(" schema_version = \"1.0.0\"\n"); + output.push_str(" metadata = {\n"); + output.push_str(&format!(" name = \"{}\"\n", name)); + output.push_str(" version = \"1.0.0\"\n"); + output.push_str(" }\n"); + output.push_str(" security = {\n"); + output.push_str(&format!(" leash = \"{}\"\n", safety_tier)); + output.push_str(" signature_required = false\n"); + output.push_str(" }\n"); + output.push_str("}\n"); + output.push('\n'); + // [must] section — group rules by key, augment with type info from parsed entries output.push_str("[must]\n"); if must_rules.is_empty() { @@ -231,6 +259,12 @@ mod tests { ], ); + // K9! magic must be the first non-empty line (k9-validate-action). + assert_eq!(content.lines().next(), Some("K9!")); + // Mandatory pedigree block with name + version + leash. + assert!(content.contains("pedigree = {")); + assert!(content.contains("name = \"app-config\"")); + assert!(content.contains("leash = \"kennel\"")); assert!(content.contains("# Auto-generated K9 contract for app-config")); assert!(content.contains("# Safety tier: kennel")); assert!(content.contains("[must]")); From 062fd75e2004f83bfd04287361b0dad4f4505482 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 18 May 2026 04:42:11 +0100 Subject: [PATCH 2/3] chore(examples): remove orphaned ReScript web-example scaffold (Refs #8) examples/SafeDOMExample.res `open`s a SafeDOM module that does not exist anywhere in this repo, depends on the external ReScript repo hyperpolymath/rescript-dom-mounter, is referenced by nothing, and was only ever introduced by a bulk governance-bundle chore. Its partner web-project-deno.json (self-described 'Example deno.json for ReScript web projects', same dead safe-dom dep) is referenced by nothing. This is dead estate ReScript-elimination drift in a Rust codegen repo, not live code: there is nothing to port (no SafeDOM module, no consumer) and the real k9iser example is examples/web-app/k9iser.toml. Removing the orphaned scaffold is the resolve-at-source fix and clears the Governance / language anti-pattern gate. Co-Authored-By: Claude Opus 4.7 (1M context) --- examples/SafeDOMExample.res | 109 --------------------------------- examples/web-project-deno.json | 20 ------ 2 files changed, 129 deletions(-) delete mode 100644 examples/SafeDOMExample.res delete mode 100644 examples/web-project-deno.json diff --git a/examples/SafeDOMExample.res b/examples/SafeDOMExample.res deleted file mode 100644 index 2c1b5b3..0000000 --- a/examples/SafeDOMExample.res +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: PMPL-1.0-or-later -// Example: Using SafeDOM for formally verified DOM mounting - -open SafeDOM - -// Example 1: Basic mounting with error handling -let mountApp = () => { - mountSafe( - "#app", - "

Hello, World!

Mounted safely with proofs.

", - ~onSuccess=el => { - Console.log("✓ App mounted successfully!") - Console.log("Element:", el) - }, - ~onError=err => { - Console.error("✗ Mount failed:", err) - } - ) -} - -// Example 2: Wait for DOM ready before mounting -let mountWhenDOMReady = () => { - mountWhenReady( - "#app", - "

App Title

", - ~onSuccess=_ => Console.log("✓ Mounted after DOM ready"), - ~onError=err => Console.error("✗ Failed:", err) - ) -} - -// Example 3: Batch mounting (atomic - all or nothing) -let mountMultiple = () => { - let specs = [ - {selector: "#header", html: "

Site Title

"}, - {selector: "#nav", html: ""}, - {selector: "#main", html: "

Content here

"}, - {selector: "#footer", html: "
© 2026
"} - ] - - switch mountBatch(specs) { - | Ok(elements) => { - Console.log(`✓ Successfully mounted ${Array.length(elements)} elements`) - elements->Array.forEach(el => Console.log(" -", el)) - } - | Error(err) => { - Console.error("✗ Batch mount failed:", err) - Console.error(" (None were mounted - atomic operation)") - } - } -} - -// Example 4: Explicit validation before mounting -let mountWithValidation = () => { - // Validate selector first - switch ProvenSelector.validate("#my-app") { - | Error(e) => Console.error(`Invalid selector: ${e}`) - | Ok(validSelector) => { - // Validate HTML - switch ProvenHTML.validate("
Content
") { - | Error(e) => Console.error(`Invalid HTML: ${e}`) - | Ok(validHtml) => { - // Now mount with proven safety - switch mount(validSelector, validHtml) { - | Mounted(el) => Console.log("✓ Mounted with validated inputs:", el) - | MountPointNotFound(s) => Console.error(`✗ Element not found: ${s}`) - | InvalidSelector(_) => Console.error("Impossible - already validated") - | InvalidHTML(_) => Console.error("Impossible - already validated") - } - } - } - } -} - -// Example 5: Integration with TEA -module MyApp = { - type model = {message: string} - type msg = NoOp - - let init = () => {message: "Hello from TEA"} - let update = (model, _msg) => model - let view = model => `

${model.message}

` -} - -let mountTEAApp = () => { - let model = MyApp.init() - let html = MyApp.view(model) - - mountWhenReady( - "#tea-app", - html, - ~onSuccess=el => { - Console.log("✓ TEA app mounted") - // Set up event handlers, subscriptions here - }, - ~onError=err => Console.error(`✗ TEA mount failed: ${err}`) - ) -} - -// Entry point -let main = () => { - Console.log("SafeDOM Examples") - Console.log("================\n") - - // Choose which example to run - mountWhenDOMReady() // Run on DOM ready -} - -// Auto-execute when module loads -main() diff --git a/examples/web-project-deno.json b/examples/web-project-deno.json deleted file mode 100644 index 5ddd3bd..0000000 --- a/examples/web-project-deno.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "// NOTE": "Example deno.json for ReScript web projects", - "tasks": { - "build": "deno run -A npm:rescript", - "clean": "deno run -A npm:rescript clean", - "watch": "deno run -A npm:rescript -w", - "serve": "deno run -A jsr:@std/http/file-server .", - "test": "deno test --allow-all" - }, - "imports": { - "rescript": "^12.0.0", - "@rescript/core": "npm:@rescript/core@^1.6.0", - "safe-dom/": "https://raw.githubusercontent.com/hyperpolymath/rescript-dom-mounter/main/src/", - "proven/": "../proven/bindings/rescript/src/" - }, - "compilerOptions": { - "allowJs": true, - "checkJs": false - } -} From 4f489a034ddddf3e148c086d9c712b2cbb5ed111 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 18 May 2026 04:42:33 +0100 Subject: [PATCH 3/3] ci(codeql): converge to canonical language-autodetect workflow (Refs #8) k9iser's codeql.yml was a stale hardcoded `javascript-typescript`-only matrix (left as a local security workflow by the b618a53 bundle migration). On this Rust-only repo CodeQL exits with a permanent false-red 'no source / configuration error' on the analyze job. Replace it verbatim with the canonical estate template shipped by rsr-template-repo / v3-templater / reposystem: a detect job reads the repo's actual language stats and only analyses CodeQL-supported, buildless-safe languages (here: rust), skipping entirely when none apply. Also brings the estate concurrency guardrail (cancel superseded runs). This is resolve-at-source + convergence to the central canonical template rather than a k9iser-local divergence. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/codeql.yml | 43 ++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e152a86..ee15d90 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,12 +8,49 @@ on: branches: [main, master] schedule: - cron: '0 6 * * 1' +# Estate guardrail: cancel superseded runs so re-pushes don't pile up +# queued runs across the estate. Safe here because this workflow only +# performs read-only checks/lint/test/scan with no publish or mutation. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true permissions: contents: read jobs: + # The estate is heterogeneous (Rust, Idris2, Agda, Elixir, ReScript, + # occasional JS/TS/Python). A hard-coded `javascript-typescript` matrix + # made CodeQL exit with a "no source / configuration error" on every + # non-JS/TS repo — a permanent false-red `analyze` on most repos' main. + # Detect the languages the repo ACTUALLY contains and only analyse the + # CodeQL-supported, buildless-safe ones; skip entirely when none apply. + detect: + runs-on: ubuntu-latest + outputs: + langs: ${{ steps.pick.outputs.langs }} + steps: + - name: Pick CodeQL languages from repo language stats + id: pick + env: + GH_TOKEN: ${{ github.token }} + run: | + stats=$(gh api "repos/${{ github.repository }}/languages" --jq 'keys[]' 2>/dev/null || echo "") + out="" + add() { out="$out $1"; } + echo "$stats" | grep -qix 'Rust' && add rust + echo "$stats" | grep -qixE 'JavaScript|TypeScript' && add javascript-typescript + echo "$stats" | grep -qix 'Python' && add python + echo "$stats" | grep -qix 'Ruby' && add ruby + echo "$stats" | grep -qix 'Go' && add go + arr=$(printf '%s\n' $out | grep . | sort -u | jq -R . | jq -s -c .) + [ -z "$arr" ] && arr='[]' + echo "Detected CodeQL languages: $arr" + echo "langs=$arr" >> "$GITHUB_OUTPUT" + analyze: + needs: detect + if: needs.detect.outputs.langs != '[]' runs-on: ubuntu-latest permissions: contents: read @@ -21,9 +58,7 @@ jobs: strategy: fail-fast: false matrix: - include: - - language: javascript-typescript - build-mode: none + language: ${{ fromJSON(needs.detect.outputs.langs) }} steps: - name: Checkout @@ -33,7 +68,7 @@ jobs: uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.28.1 with: languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} + build-mode: none - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.28.1