From 1a744796648a2b080f1029d02cec6499e617f1d7 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:33:04 +0100 Subject: [PATCH 1/5] =?UTF-8?q?fix(tests):=20terminate=20find=20-exec=20an?= =?UTF-8?q?d=20pass=20{}=20=E2=80=94=20the=20placeholder=20step=20was=20a?= =?UTF-8?q?=20no-op?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tests/e2e/template_instantiation_test.sh ran: find ... -exec bash -c ' file="$1" ... grep/sed over $file ... ' _ "$file" Two defects in that one line: 1. No ';' or '+' terminator, so the file does not parse (SC2067). 2. "$file" is passed where {} belongs. $file is assigned ONLY inside the -exec body, so in the outer scope it is UNSET — $1 arrived empty, file="" and every grep/sed operated on an empty path. ⚠ The consequence is worse than a lint error: the placeholder-replacement step SILENTLY DID NOTHING, then logged "All placeholder tokens replaced". A test whose whole purpose is to prove instantiation worked was passing without replacing a single token. That is a plausible cause of estate repos shipping with literal {{project}} tokens still in their sources. Corrected to "' _ {} \;" so find passes each matched path. Found by an estate-wide shellcheck sweep of 5,111 scripts across 375 repos: this identical stale copy exists in 30 repositories. rsr-template-repo's own copy is already correct and restructured (371 lines vs the 268 here), so these are stale duplicates that never picked up the upstream fix. --- tests/e2e/template_instantiation_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/template_instantiation_test.sh b/tests/e2e/template_instantiation_test.sh index 73a7d8d..e79f02a 100755 --- a/tests/e2e/template_instantiation_test.sh +++ b/tests/e2e/template_instantiation_test.sh @@ -137,7 +137,7 @@ find "$TEST_REPO_PATH" -type f \ sed -i "s|$placeholder|$value|g" "$file" fi done - ' _ "$file" + ' _ {} \; log_pass "All placeholder tokens replaced" From 27942703f039b9a86d39b9efdab225b83730f2c6 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:51:51 +0100 Subject: [PATCH 2/5] fix(tests): export template values to the find child shell --- tests/e2e/template_instantiation_test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/e2e/template_instantiation_test.sh b/tests/e2e/template_instantiation_test.sh index e79f02a..8d11346 100755 --- a/tests/e2e/template_instantiation_test.sh +++ b/tests/e2e/template_instantiation_test.sh @@ -112,6 +112,8 @@ replace_placeholder() { } # Replace in all text files +export TEST_REPO_NAME TEST_OWNER TEST_FORGE TEST_PROJECT_NAME \ + TEST_DESCRIPTION TEST_PRIMARY_LANGUAGE TEST_AUTHOR TEST_AUTHOR_EMAIL find "$TEST_REPO_PATH" -type f \ \( -name "*.md" -o -name "*.adoc" -o -name "*.a2ml" -o -name "*.zig" -o -name "*.idr" \ -o -name "Justfile" -o -name "Containerfile" -o -name "*.yml" -o -name "*.yaml" \ From 0f8729a6bb7653bd8b32689521a7d84a5bf4f364 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 09:04:42 +0000 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=94=A7=20CodeRabbit=20CI=20Fix:=20Fix?= =?UTF-8?q?=20failing=20Rust=20CI=20and=20Dogfood=20validation=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arrival-pack/claude-md.k9.ncl | 1 + .machine_readable/coaptation/coapt.k9.ncl | 1 + .../contractiles/adjust/adjust.k9.ncl | 1 + .../contractiles/bust/bust.k9.ncl | 2 ++ .../contractiles/dust/dust.k9.ncl | 1 + .../contractiles/intend/intend.k9.ncl | 2 ++ .../contractiles/must/must.k9.ncl | 2 ++ .../contractiles/trust/trust.k9.ncl | 2 ++ .../self-validating/methodology-guard.k9.ncl | 1 + container/stapeln/deploy.k9.ncl | 1 + crates/squabble-core/src/gate.rs | 23 ++++++++++++++----- 11 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.machine_readable/arrival-pack/claude-md.k9.ncl b/.machine_readable/arrival-pack/claude-md.k9.ncl index 67c861e..d3fbb1c 100644 --- a/.machine_readable/arrival-pack/claude-md.k9.ncl +++ b/.machine_readable/arrival-pack/claude-md.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # diff --git a/.machine_readable/coaptation/coapt.k9.ncl b/.machine_readable/coaptation/coapt.k9.ncl index 25fa568..2c065bf 100644 --- a/.machine_readable/coaptation/coapt.k9.ncl +++ b/.machine_readable/coaptation/coapt.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # diff --git a/.machine_readable/contractiles/adjust/adjust.k9.ncl b/.machine_readable/contractiles/adjust/adjust.k9.ncl index 0f1561e..4974ba7 100644 --- a/.machine_readable/contractiles/adjust/adjust.k9.ncl +++ b/.machine_readable/contractiles/adjust/adjust.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # adjust.k9.ncl — K9 trust-tier component of the adjust trident # Author: Jonathan D.A. Jewell diff --git a/.machine_readable/contractiles/bust/bust.k9.ncl b/.machine_readable/contractiles/bust/bust.k9.ncl index 3d28c22..cc8032e 100644 --- a/.machine_readable/contractiles/bust/bust.k9.ncl +++ b/.machine_readable/contractiles/bust/bust.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # bust.k9.ncl — K9 trust-tier component of the bust trident # Author: Jonathan D.A. Jewell @@ -50,6 +51,7 @@ let base = import "../_base.ncl" in allow_filesystem_write = false, allow_subprocess = true, probe_scope = 'read_only, + signature_required = true, }, }, diff --git a/.machine_readable/contractiles/dust/dust.k9.ncl b/.machine_readable/contractiles/dust/dust.k9.ncl index 183fc07..6c51e54 100644 --- a/.machine_readable/contractiles/dust/dust.k9.ncl +++ b/.machine_readable/contractiles/dust/dust.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # dust.k9.ncl — K9 trust-tier component of the dust trident # Author: Jonathan D.A. Jewell diff --git a/.machine_readable/contractiles/intend/intend.k9.ncl b/.machine_readable/contractiles/intend/intend.k9.ncl index 723d9bc..d8d83b7 100644 --- a/.machine_readable/contractiles/intend/intend.k9.ncl +++ b/.machine_readable/contractiles/intend/intend.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # intend.k9.ncl — K9 trust-tier component of the intend trident # Author: Jonathan D.A. Jewell @@ -63,6 +64,7 @@ let base = import "../_base.ncl" in allow_network = false, allow_filesystem_write = false, # evidence sinks are indirected allow_subprocess = true, + signature_required = true, }, }, diff --git a/.machine_readable/contractiles/must/must.k9.ncl b/.machine_readable/contractiles/must/must.k9.ncl index f139ef3..e6327ed 100644 --- a/.machine_readable/contractiles/must/must.k9.ncl +++ b/.machine_readable/contractiles/must/must.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # must.k9.ncl — K9 trust-tier component of the must trident # Author: Jonathan D.A. Jewell @@ -72,6 +73,7 @@ let base = import "../_base.ncl" in 'external_api, 'exploit_attempt, # that's trust's safe_hacking territory ], + signature_required = true, }, }, diff --git a/.machine_readable/contractiles/trust/trust.k9.ncl b/.machine_readable/contractiles/trust/trust.k9.ncl index 72ca271..32b48ed 100644 --- a/.machine_readable/contractiles/trust/trust.k9.ncl +++ b/.machine_readable/contractiles/trust/trust.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # trust.k9.ncl — K9 trust-tier component of the trust trident # Author: Jonathan D.A. Jewell @@ -77,6 +78,7 @@ let base = import "../_base.ncl" in allow_subprocess = true, authorised_probes_only = true, # probe section explicitly lists allowed targets + probe classes probe_scope_enforcement = 'this_repo_only, # probes NEVER hit external systems + signature_required = true, }, }, diff --git a/.machine_readable/self-validating/methodology-guard.k9.ncl b/.machine_readable/self-validating/methodology-guard.k9.ncl index 7a424d7..796b0eb 100644 --- a/.machine_readable/self-validating/methodology-guard.k9.ncl +++ b/.machine_readable/self-validating/methodology-guard.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} ({{OWNER}}) <{{AUTHOR_EMAIL}}> # diff --git a/container/stapeln/deploy.k9.ncl b/container/stapeln/deploy.k9.ncl index 02b7df4..8182fe8 100644 --- a/container/stapeln/deploy.k9.ncl +++ b/container/stapeln/deploy.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # deploy.k9.ncl — {{PROJECT_NAME}} deployment component (Hunt level) # diff --git a/crates/squabble-core/src/gate.rs b/crates/squabble-core/src/gate.rs index a28d2df..1e424da 100644 --- a/crates/squabble-core/src/gate.rs +++ b/crates/squabble-core/src/gate.rs @@ -26,7 +26,6 @@ pub enum CheckRun { Passed, } - /// Why a required context shows [`CheckRun::Missing`]. /// /// `Missing` is the gate's most common stuck state and its least actionable one: @@ -234,9 +233,15 @@ mod tests { #[test] fn missing_cause_is_optional_and_does_not_alter_gate_state() { // A diagnosis explains a stuck gate; it must never move it. - let undiagnosed = Gate::new(vec![RequiredCheck::new("scan / gitleaks", CheckRun::Missing)]); - let diagnosed = Gate::new(vec![RequiredCheck::new("scan / gitleaks", CheckRun::Missing) - .with_cause(MissingCause::DeadActionPin)]); + let undiagnosed = Gate::new(vec![RequiredCheck::new( + "scan / gitleaks", + CheckRun::Missing, + )]); + let diagnosed = Gate::new(vec![RequiredCheck::new( + "scan / gitleaks", + CheckRun::Missing, + ) + .with_cause(MissingCause::DeadActionPin)]); assert_eq!(undiagnosed.evaluate(), GateState::Blocked); assert_eq!(diagnosed.evaluate(), GateState::Blocked); assert_eq!(diagnosed.evaluate(), undiagnosed.evaluate()); @@ -244,7 +249,9 @@ mod tests { #[test] fn remedy_is_offered_only_for_diagnosed_missing_checks() { - assert!(RequiredCheck::new("x", CheckRun::Missing).remedy().is_none()); + assert!(RequiredCheck::new("x", CheckRun::Missing) + .remedy() + .is_none()); assert!(RequiredCheck::new("x", CheckRun::Passed) .with_cause(MissingCause::NoSuchJob) .remedy() @@ -270,7 +277,11 @@ mod tests { RequiredCheck::new("a", CheckRun::Passed), RequiredCheck::new("b", CheckRun::Missing).with_cause(cause), ]); - assert_ne!(g.evaluate(), GateState::Green, "{cause:?} must not reach Green"); + assert_ne!( + g.evaluate(), + GateState::Green, + "{cause:?} must not reach Green" + ); } } } From e73a9c2e40d1771187cad656a9eb62ee19c8256c Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 08:56:42 +0000 Subject: [PATCH 4/5] Fix CodeRabbit issues in PR #48 --- .githooks/validate-k9.sh | 19 +++++++++++++++++-- .../arrival-pack/claude-md.k9.ncl | 9 +++++---- .machine_readable/coaptation/coapt.k9.ncl | 9 +++++---- .../self-validating/methodology-guard.k9.ncl | 15 +++++++++++++++ container/stapeln/deploy.k9.ncl | 1 + 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/.githooks/validate-k9.sh b/.githooks/validate-k9.sh index 72b79f5..ea16916 100755 --- a/.githooks/validate-k9.sh +++ b/.githooks/validate-k9.sh @@ -164,12 +164,26 @@ validate_k9() { local has_signature_field=false local in_pedigree=false local pedigree_depth=0 + local pedigree_alias="" + + # Resolve a simple top-level pedigree alias (for example, + # `pedigree = component_pedigree`) before scanning the file. The aliased + # block can be declared before the exported record, so this must be a + # separate pass. + while IFS= read -r line; do + if [[ "$line" =~ ^[[:space:]]*pedigree[[:space:]]*=[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*,?[[:space:]]*(#.*)?$ ]]; then + pedigree_alias="${BASH_REMATCH[1]}" + has_pedigree=true + break + fi + done < "$file" line_num=0 while IFS= read -r line; do line_num=$((line_num + 1)) - # Detect pedigree block start. Note: do NOT `continue` here — the + # Detect a literal pedigree block or the declaration of a resolved + # pedigree alias. Note: do NOT `continue` here — the # `pedigree = {` line itself contains the opening brace that # establishes the block. Falling through to the brace counter # below makes depth start at 1, so a subsequent `security = {…},` @@ -179,7 +193,8 @@ validate_k9() { # brace, depth started at 0, and the first nested block's close # prematurely terminated the validator's view of the pedigree — # making `pedigree.metadata.name` invisible. - if [[ "$line" =~ ^[[:space:]]*pedigree[[:space:]]*= ]]; then + if [[ "$line" =~ ^[[:space:]]*pedigree[[:space:]]*=.*\{ ]] || \ + [[ -n "$pedigree_alias" && "$line" =~ ^[[:space:]]*let[[:space:]]+$pedigree_alias[[:space:]]*=[[:space:]]*\{ ]]; then has_pedigree=true in_pedigree=true pedigree_depth=0 diff --git a/.machine_readable/arrival-pack/claude-md.k9.ncl b/.machine_readable/arrival-pack/claude-md.k9.ncl index d3fbb1c..d606ff0 100644 --- a/.machine_readable/arrival-pack/claude-md.k9.ncl +++ b/.machine_readable/arrival-pack/claude-md.k9.ncl @@ -4,7 +4,7 @@ K9! # # claude-md.k9.ncl — k9 contract for the CLAUDE.md arrival-pack drift check. # -# Yard-tier (pure evaluation / comparison; no exec, no network, no FS write): +# Hunt-tier (guarded execution; no network, writes an intermediate data file): # the check regenerates the arrival-pack region from this repo's a2ml and asserts # the committed CLAUDE.md region byte-matches it. The runnable side is verify.sh; # writing (Hunt-tier) is generate.sh. This record documents and validates the @@ -15,11 +15,12 @@ K9! contractile_verb = "trust", # provenance: the view must equal its source semantics = "projection-fidelity", security = { - leash = 'Yard, - trust_level = "read-only comparison", + leash = 'Hunt, + trust_level = "guarded drift verification", allow_network = false, - allow_filesystem_write = false, + allow_filesystem_write = true, allow_subprocess = true, # runs extract.sh + nickel to reproduce the view + signature_required = true, }, metadata = { name = "claude-md-arrival-pack", diff --git a/.machine_readable/coaptation/coapt.k9.ncl b/.machine_readable/coaptation/coapt.k9.ncl index 2c065bf..28909e7 100644 --- a/.machine_readable/coaptation/coapt.k9.ncl +++ b/.machine_readable/coaptation/coapt.k9.ncl @@ -4,7 +4,7 @@ K9! # # coapt.k9.ncl — k9 contract for the coaptation receipt's drift check. # -# Yard-tier (pure evaluation / comparison; no network, no FS write): the check +# Hunt-tier (guarded execution; no network, writes intermediate data files): the check # regenerates the coaptation receipt from this repo's contractiles (normative # set-point) and descriptiles (descriptive self-model) and asserts the committed # receipt byte-matches it. The runnable side is verify.sh; the writer (Hunt-tier, @@ -16,11 +16,12 @@ K9! contractile_verb = "trust", # provenance: the reading must equal its sources semantics = "coaptation-fidelity", security = { - leash = 'Yard, - trust_level = "read-only comparison", + leash = 'Hunt, + trust_level = "guarded drift verification", allow_network = false, - allow_filesystem_write = false, + allow_filesystem_write = true, allow_subprocess = true, # runs the extractors + nickel to reproduce the reading + signature_required = true, }, metadata = { name = "coaptation", diff --git a/.machine_readable/self-validating/methodology-guard.k9.ncl b/.machine_readable/self-validating/methodology-guard.k9.ncl index 796b0eb..afd294a 100644 --- a/.machine_readable/self-validating/methodology-guard.k9.ncl +++ b/.machine_readable/self-validating/methodology-guard.k9.ncl @@ -9,6 +9,21 @@ K9! # Usage: k9 validate methodology-guard let methodology_guard = { + pedigree = { + schema_version = "1.0.0", + security = { + leash = 'Yard, + trust_level = "read-only validation", + allow_network = false, + allow_filesystem_write = false, + allow_subprocess = false, + }, + metadata = { + name = "methodology-guard", + version = "1.0.0", + }, + }, + name = "methodology-guard", version = "1.0.0", description = "Validates that agent work respects declared methodology constraints", diff --git a/container/stapeln/deploy.k9.ncl b/container/stapeln/deploy.k9.ncl index 8182fe8..f74c363 100644 --- a/container/stapeln/deploy.k9.ncl +++ b/container/stapeln/deploy.k9.ncl @@ -40,6 +40,7 @@ let component_pedigree = { # L3: The Leash — Security # ───────────────────────────────────────────────────────────── security = { + leash = 'Hunt, trust_level = 'Hunt, allow_network = true, allow_filesystem_write = true, From e51b7d932c79a230e92e5838f2a8bce45baae179 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 10:17:38 +0100 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=94=A7=20CodeRabbit=20CI=20Fix:=20Fix?= =?UTF-8?q?=20failing=20Dogfood=20Gate=20K9=20contracts=20and=20Groove=20m?= =?UTF-8?q?anifest=20checks=20(#64)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI failure fixes was requested by @hyperpolymath. * https://github.com/hyperpolymath/cicd-squabbler/pull/48#issuecomment-5428797205 The following files were modified: * `.machine_readable/self-validating/methodology-guard.k9.ncl` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .machine_readable/self-validating/methodology-guard.k9.ncl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.machine_readable/self-validating/methodology-guard.k9.ncl b/.machine_readable/self-validating/methodology-guard.k9.ncl index afd294a..6212efb 100644 --- a/.machine_readable/self-validating/methodology-guard.k9.ncl +++ b/.machine_readable/self-validating/methodology-guard.k9.ncl @@ -11,9 +11,10 @@ K9! let methodology_guard = { pedigree = { schema_version = "1.0.0", + component_type = "validated-config", security = { leash = 'Yard, - trust_level = "read-only validation", + trust_level = "validated-config", allow_network = false, allow_filesystem_write = false, allow_subprocess = false, @@ -21,6 +22,8 @@ let methodology_guard = { metadata = { name = "methodology-guard", version = "1.0.0", + description = "Validates that agent work respects declared methodology constraints", + author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", }, },