Skip to content

release: v2.0.0 - HMAC-signed dispatch witness + agent best-practice audit#17

Open
filip-ceos wants to merge 2 commits into
mainfrom
release/v2.0.0
Open

release: v2.0.0 - HMAC-signed dispatch witness + agent best-practice audit#17
filip-ceos wants to merge 2 commits into
mainfrom
release/v2.0.0

Conversation

@filip-ceos

Copy link
Copy Markdown
Collaborator

Summary

Bundled release combining two independent PRs that both required a MAJOR version bump to 2.0.0, integrated via a short-lived release/v2.0.0 branch per CLAUDE.md's "Multiple PRs → one release" process (re-targeted, squash-merged in sequence, conflicts resolved on the integration branch, single reconciled version bump + CHANGELOG entry).

  • PR Bind overlay into dispatch witness and audit #15 — HMAC-signed dispatch witness (witness-toml-overlay, fork PR from jakubsenk/agent-flow): moves the dispatch witness from an orchestrator-written sha256 receipt to a gate-signed HMAC keyed witness (new blocking PreToolUse Task gate hooks/validate-dispatch-pre.sh, schema_version 1.0 → 2.0, ## Step Completion Invariants wording updated in lockstep across all 17 agents).
  • PR fix: remediate 232 findings from deep quality audit (agents, skills, core, docs, tests) #16 — best-practice audit + output-contract fixes (fix/deep-audit-remediation-2026-07): originally 232 findings from a deep quality audit across agents/skills/core/docs/tests, extended in this session with a two-tier subagent review (2 verifiers + a reconciling orchestrator per agent) of all 10 core pipeline agents, closing structural output-contract gaps and reliability bugs — most notably browser-agent's reproduction status silently misclassifying most assertion-only UI bugs as not_reproduced.

Conflict resolution (27 files, both PRs independently touched all 17 agent definitions)

Every conflict was resolved by tracing to ground truth rather than picking a side arbitrarily:

Test plan

  • bash tests/harness/run-tests.sh (HARNESS_JOBS=1, full sequential run) on the final merged release/v2.0.0: 268 scenarios, 267 pass, 0 fail, 1 skip
  • Re-ran the full suite after every conflict-resolution pass (3 full runs total) rather than trusting the merge diff alone
  • Both source PRs were individually green before integration

Version bump

.claude-plugin/plugin.json and .claude-plugin/marketplace.json: 1.2.02.0.0 (MAJOR, both PRs independently qualified). CHANGELOG.md [2.0.0] entry covers both.

Human review

  • A human has reviewed the complete diff before merge — this PR is presented for that review now; not merged by the assistant

jakubsenk and others added 2 commits July 3, 2026 20:07
* Bind overlay into dispatch witness and audit

Fold TOML overlay provenance into the per-stage dispatch receipt: dispatch_witness is now sha256("<subagent_type>|<model>|<prompt_head_128>|<overlay_source>|<overlay_digest>"). Added prompt_head_128 and overlay_digest state fields and compute_overlay_digest/__sha256_hex helpers in core/lib/stage-invariant.sh, and extended compute_dispatch_witness/check_dispatch_witness to perform V1 (recompute-and-compare) and V2 (overlay-presence) verification. Rewrote hooks/validate-dispatch.sh as a single Python process that emits presence and witness audit lines (strict-by-default controlled by AGENT_FLOW_STRICT_DISPATCH), and updated README/docs/guides/docs/reference to document the new witness semantics, audit behavior, and environment variables. Tests and examples updated to match the new 5-tuple witness and audit flow.

* fix "tests"

* feat(witness): L1 keyed-witness core + A1 fix + claim ritual + CEOS rename

Phase 7 Level 1 (forge): task-001 hooks/lib/witness_core.py (HMAC-SHA256
sub-hash canon, head128, alg constant); task-002 A1 __read_stage_field
json.load fix (+A9 comment); task-005 centralized claim-ritual + per-dispatch
marker across all 3 skills; task-006 CEOS_*->AGENT_FLOW_* rename + dead-var.
Harness 232/0/1 (no regression). Not pushed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(witness): L2 per-run key lifecycle + bash verifier demote

Phase 7 Level 2 (forge): task-004 hooks/lib/witness_key.py (atomic O_EXCL 0600
key gen, discover/read, forge-resistant bootstrap_decision tree:
KEYED/GENERATE/UNVERIFIABLE/LEGACY; key never in versioned files);
task-003 demote bash verifier to parity-pinned --self-test (no keyed path in
bash; shells to witness_core/witness_key), add __overlay_short_name traversal
guard (reject / \ ..). Harness 232/0/1. Not pushed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(witness): L3 PreToolUse gate-as-signer + dual-mode PostToolUse audit

Phase 7 Level 3 (forge): task-007 hooks/validate-dispatch-pre.sh (+probe-task-shape.sh)
- PreToolUse Task gate: STRICT_OFF flag -> marker match-or-pass-through (never glob[-1])
-> forge-resistant bootstrap -> observe-and-sign head128 -> compare {subagent_type,model}
-> HMAC tag -> gate-owned dispatch-ledger.jsonl -> ALLOW/clear, else deny-JSON + exit 2
(fail-closed). task-008 validate-dispatch.sh dual-mode audit: runnability probe (LOUD),
4th verdict WITNESS_UNVERIFIABLE, key-presence downgrade authority, legacy sha256 dual-mode
preserved. witness-keyed-parity Part B (golden ledger tag) green E2E. Harness 232/0/1.
Known: gate-owned-ledger.sh grep too broad vs claim-ritual prose -> reconcile in task-012.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(witness): L4 overlay ground-truth binding + check-setup + A2 lockstep

Phase 7 Level 4 (forge): task-009 hooks/lib/witness_overlay.py (recompute_overlay_digest
= sha256 of RAW LF-normalized .toml bytes, allowlist + traversal guard; resolve_model
reuses injector tomli/tomllib parser) wired into gate+audit, override_path persisted (A6),
agent-override-injector.md digest redefinition + honest wording; task-010 check-setup
Block 8 (stdlib/TOML/claude>=2.1.90/deny-canary handshake); task-011 A2 lockstep across
21 files (17 agents + 4 examples) to keyed witness wording + acceptance-gate ledger repoint.
Also reworded claim-ritual.md ledger mention (gate-owned-ledger scenario). Harness 232/0/1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(witness): L5 port 30 scenarios into harness + fixtures + count reconcile

Phase 7 Level 5 (forge): task-012 port all 30 staged scenarios into tests/scenarios/
(drop AGENT_FLOW_REPO_ROOT shim -> $(dirname)/../..; assertions intact), materialize 5
keyed/downgrade fixtures (schema 2.0) + freeze state-{a,b,c}.json at 1.0, add .gitattributes
LF pins, reconcile scenario count 233->263 in README, fill PR template. Harness 263:
259 pass / 3 fail / 1 skip. The 3 fails are task-013-driven (release-readiness,
doc-enum-and-wording, rhetoric threat-model) — red-by-design until L6. CRLF audit-log
writer bug (Windows) flagged for L6 newline=LF fix. No impl/regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(witness)!: L6 release v2.0.0 + threat-model rewrite + docs + CRLF fix

Phase 7 Level 6 (forge): task-013 MAJOR release artifacts (plugin.json + both
marketplace.json + dated CHANGELOG [2.0.0]); honest threat-model rewrite in
state/schema.md (detection of out-of-key tampering + real pre-dispatch block;
residuals: same-user forge, not proof-of-run, marker-deletion DoS; best-effort
append-only log; schema_version 2.0; override_path/claim_nonce/dispatch_seq;
overlay_digest=RAW .toml; prompt_head gate-observed); docs lockstep (zero PACKAGE
deps wording, A8/A9 reconcile, rollback runbook; counts 17/17/17 + config 18).
Plus CRLF fix: audit-log + ledger writers open newline=LF (Windows byte-identity);
stage-class [a-z_]->[a-z0-9_] for e2e_test. Harness 263: 262 pass / 0 fail / 1 skip.

BREAKING CHANGE: keyed HMAC witness output contract + schema_version 1.0->2.0 +
blocking PreToolUse gate + CEOS_*->AGENT_FLOW_* env rename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(witness): Phase8 revision c1 — overlay_digest gate-computed-only + key-loss runbook

Phase 8 robustness FAIL (0.60) revision. S2 (Windows-breaking): overlay_digest was a
producer-committed/compared claim while the gate signs its own LF-normalized recompute
-> CRLF divergence DENYed every overlay dispatch on Windows (same class as prompt_head).
Fix: gate-computed-only — claim drops overlay_digest (keeps overlay_source+override_path),
gate drops the compare (structural absent/traversal checks remain), audit re-verifies the
gate-signed ledger digest vs live .toml (A5 ground truth). compute_overlay_digest reframed
LEGACY-only; docs de-over-claimed ("both sides agree" removed). CRLF regression test added.
S1: key-loss recovery is operator-explicit runbook (rebaseline / STRICT_OFF), NOT auto-regen
(auto-regen would reopen f-c570b4); fail-closed UNVERIFIABLE kept; recovery test added.
Harness 264: 263 pass / 0 fail / 1 skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: Phase 9 doc-audit — reconcile zero-dep wording + v2.0.0 banner

Phase 9 completion doc-audit fixes: CLAUDE.md:14 + docs/architecture.md:3 stale
"no/zero runtime dependencies" -> "zero third-party PACKAGE dependencies; requires
bash + Python 3 (stdlib only)"; README.md banner v1.0.0 -> v2.0.0. Harness re-run
264/263/0/1 (0 fail). Completion verdict: COMPLETE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(witness): resolve Phase-8 residuals — override_path allowlist + audit advisory split

In-PR resolution of the two non-blocking Phase-8 cycle-1 residuals (not deferred):
- #3 (REQ-031): witness_overlay.py confines override_path to the configured Agent-Overrides
  allowlist root (default customization/, via optional state.json agent_overrides_path),
  not the whole project root; outside-allowlist -> DENY/MISMATCH. Threaded override_root
  through gate + audit.
- #2 (robustness Scn1 "cry wolf"): audit ledger-tag HMAC stays STRICT (MISMATCH+exit2) and
  the gate-time A5 binding stays STRICT (DENY); only the audit's post-dispatch re-read of a
  completed stage's live .toml is now ADVISORY (OVERLAY_DRIFT_ADVISORY -> WITNESS_OK, never
  exit2 on a benign edit). Documented in state/schema.md. No forge path opened.
Harness 264/263/0/1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(check-setup,fix-bugs): detect dispatch hooks across the full settings tree

check-setup Block 6 read only ~/.claude/settings.json, so the PreToolUse Task
gate / PostToolUse audit wired at project (.claude/settings.json) or
project-local (.claude/settings.local.json) scope was reported "not configured"
— a false negative. Claude Code merges the settings tree and hooks COMBINE
across scopes (none overrides another; only disableAllHooks turns them off).

- New shared helper core/lib/detect-dispatch-hooks.sh scans user+project+local
  for BOTH the gate (validate-dispatch-pre.sh) and the audit
  (validate-dispatch.sh): per-scope wiring, gate matcher==Task, disableAllHooks.
  Cross-platform (cygpath translation for native Windows Python; LF-only
  output). Managed/OS-level settings are an advisory gap, not reported wired.
- check-setup Block 6 rewritten to use the helper and report both hooks; stays
  advisory (never changes the FAIL verdict).
- fix-bugs gains an advisory dispatch-enforcement preflight
  (core/snippets/dispatch-enforcement-preflight.md) so the orchestrator knows
  whether a dispatch mismatch would be BLOCKED or only audited.
- docs: reconcile dispatch-enforcement.md (project/local scopes valid + combine;
  fix the wrong "not a project-level file" troubleshooting line) and hooks.md
  scope note; CHANGELOG bullets under [2.0.0].
- test: tests/scenarios/dispatch-hook-tree-detection.sh (7 cases incl. the
  settings.local.json regression). Full suite green (264 pass / 1 skip).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Filip Šabacký <filip.sabacky@ceosdata.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…core, docs, tests)

* fix(agents): resolve 73 audit findings across 17 agent definitions

Applied all confirmed (critical/high/medium) and unverified (low/nit)
findings from audit-agent-flow-2026-07-02.md against agents/*.md, one
fixer subagent per file. Covers Step Completion Invariant agent_name
namespace mismatches, contradictory verdict/control-flow logic,
duplicate tracker-mutation ownership (rollback-agent), unsatisfiable
invariants (backlog-creator), and numerous cross-file consistency
gaps against skills/*, core/*, and state/schema.md.

Verified: mandatory section order and Constraints NEVER/hard-limit
convention intact across all 17 files; relevant test scenarios
(frontmatter-completeness-roster, section-order-with-output-contract,
agents-enumeration, read-only-agents-roster,
step-completion-invariants-completeness, model-assignment, and
per-agent shape tests) pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(skills): resolve 101 audit findings across 17 skills

Applied all confirmed (critical/high/medium) and unverified (low/nit)
findings from audit-agent-flow-2026-07-02.md against skills/*/SKILL.md,
one fixer subagent per file, run after the agents/*.md fixes so skill
dispatch contexts reference the corrected agent contracts. Also fixed
3 stale step-number cross-references in skills/fix-bugs/steps/ that
the audit attributed to fix-bugs/SKILL.md but whose actual defect
lived in the referenced step files.

Notable root-cause fixes: create-backlog's --decompose ordering and
config-gate wiring, setup-agents' symlink-escape guard fail-closed
behavior, autopilot's ISSUE_ID path-traversal validation and Max
blocked per run enforcement, analyze-bug's dispatch-witness gap.

Verified: frontmatter and code-fence integrity across all 20 touched
files; skills-frontmatter-check, skills-directory-structure,
count-skills(-2), xref-command-count, dispatch-idiom-strict,
pipeline-consistency/feature-agents/step-order/hook-order,
stage-list-consistency, profile-parser-stage-names,
webhook-pipeline-events, block-comment-template, matrix-fixbugs/
implfeat-default all pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(core,docs,tests): resolve 58 audit findings + fix 10 regressions

Applied all confirmed and unverified findings from the deep audit
against core/*.md contracts, docs/, examples/, versioning files
(README, SECURITY.md, CLAUDE.md, PR template), and tests/, regrouped
by their actual primary file rather than the original audit batching.

Notable fixes: relocated 5 scenario scripts out of a stray
tests/scenarios/plugin-version-tracking/ subdirectory the harness
never executed (find -maxdepth 1 silently skipped them), added a
fail-fast harness guard against this recurring; deleted one exact-
duplicate scenario; corrected the three-way-contradictory legacy .md
overlay documentation to match the actually-shipped .toml-only
behavior; fixed the false claim that check_dispatch_witness
cryptographically verifies the witness hash; documented hooks/ in
CLAUDE.md's Repository Structure (confirmed intentional operator
opt-in, not dead code); synced numeric counts (18 config sections,
scenario count) across README/tests/README.md/PR template.

Fixed 10 test regressions surfaced by the above (both from this
phase and residually from Phases 1-2):
- 6 genuine regressions: bare `core/X.md` cross-references introduced
  by prior phases' fixer prose (missing ../ or ../../ depth prefix,
  now fixed repo-wide with the harness's own canonical sed pattern),
  a reworded NEVER-bullet that dropped the literal MUST/NEEDS_DECOMPOSITION
  match, a reworded EXTERNAL INPUT bullet that broke the repo-wide
  verbatim-consistency check, hardcoded GitHub URLs in installation.md
  where the test requires host-agnostic placeholders, and a
  tests/README.md scenario count left at the old value after the
  relocation above changed 233 -> 237.
- 4 tests exposed real, previously-invisible pre-existing gaps once
  the relocation made them executable for the first time: added a
  Config Validity Gate to fix-bugs/SKILL.md (implement-feature/SKILL.md
  already had one), removed a stale/broken "/agent-flow:init" alias
  reference, corrected two tests whose literal string expectations had
  drifted from current (correct) architecture without ever being
  re-validated (test-engineer's Phase->Mode heading rename,
  state-manager.md's more precise "malformed JSON" wording).
- Trimmed skills/fix-bugs/SKILL.md back under its 260-line thin-
  controller ceiling (258L) after the above additions pushed it to
  307L, by reflowing wrapped prose and condensing delegated-detail
  sections without losing content.

Verified: full suite green — 237 scenarios, 236 pass, 1 by-design skip.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(agents): complete two systemic Step Completion Invariant fixes repo-wide

Phase 1/3 fixers correctly identified two bugs but, being scoped to
single files, only applied the fix to the 1-2 files their assigned
findings named — both bugs are verified (via grep) to have been
present identically across all 17 agent files. Completing both here,
now that the pattern is confirmed systemic per the remediation plan's
own recommendation #2 ("treat as systemic until proven otherwise").

1. False cryptographic-verification claim: every agents/*.md said
   check_dispatch_witness "matches the sha256 of ... computed BEFORE
   Tier-1 variable expansion" — but the function only checks presence
   and hex-shape; nothing recomputes or compares against the sha256
   after dispatch. Reworded to state what the function actually does
   (agents/fixer.md already had the correct wording from Phase 1;
   applied the same correction to the other 16).
2. Un-namespaced agent_name in Step Completion Invariant #5: every
   agents/*.md hardcoded the bare agent name (e.g. `publisher`) as
   the expected agent_name / EXPECTED_AGENT_NAME value, contradicting
   state/schema.md and every skills/*/steps/*.md dispatch site, which
   inject the namespaced `agent-flow:{name}` form. Reworded to
   reference the injected value symbolically instead of hardcoding
   the wrong literal (agents/analyst.md and fixer.md already had this
   fix from Phase 1; applied to the other 15).

Verified: full suite green — 237 scenarios, 236 pass, 1 by-design skip.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(docs,tests,core): close 32 gaps found by adversarial re-verification

After the prior three remediation waves, an independent adversarial
re-check of all 175 originally-confirmed audit findings against the
current repo found 141 genuinely resolved, 27 partially resolved, and
7 not resolved -- almost all of the 34 open items were cases where the
primary file was correctly fixed but a companion/reference file (docs,
a sibling skill's dispatch context, an example config) still asserted
the old, now-contradicted behavior. This closes 32 of those 33
addressable items (1 is left as a documented architectural limitation
-- see below) across 40 files.

Highlights: corrected CLAUDE.md's Agent Definition Format callout to
describe the actual 5-field agent-side Step Completion Invariant
contract instead of a never-implemented 4-field orchestrator-side one
(the single largest source of repeat cross-file contradictions in the
earlier re-verify pass); added pipeline-paused/pipeline-resumed to
core/config-reader.md's valid-events list to match CLAUDE.md; fixed
the mcp-detection.md <-> check-setup "single source of truth" circular
citation; propagated the Branch-naming-token fix to the 7 example
config templates onboard's wizard offers; propagated the Output
Contract section to the 3 remaining examples/custom-agents/*.md
templates; deleted 4 more duplicate test-scenario pairs; added new
scenario coverage for previously-untested CLAUDE.md callouts
(reproduction_steps, <=5 affected files, PR-description-language).

Not addressed (documented, not fixed): skills/implement-feature's
architect dispatch still shares the code_analysis resume-tracked
stage key with the preceding analyst step rather than having its own
-- the file already self-labels this a "Known limitation" with a
mitigating cross-check; fully removing it requires a coordinated
stage-key rename across steps/02-architect.md and
core/resume-detection.md's phase-scan regex, which is a structural
change warranting its own review rather than a blind edit here.

Also fixed one regression this wave introduced: the Step 8b pointer-
ification in skills/scaffold/SKILL.md initially reworded several
phrases that tests/scenarios/scaffold-tracker-integration.sh asserts
verbatim (Done-mapping WARN wording, "blocked features list" term,
a phrase that wrapped across a line break) -- restored the exact
required phrasing while keeping the pointer-to-steps/07-spec-verify.md
framing.

Verified: full suite green -- 236 scenarios, 235 pass, 1 by-design skip.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(tests): count-core.sh must invoke its delegate via bash, not exec directly

count-core.sh (deduplicated in the prior commit to delegate to
count-core-contracts.sh instead of re-implementing the same assertion)
used `exec "$path"`, which requires the target file to carry the
executable bit. Neither file has it set in git (100644, same as every
other scenario script in this suite -- they're normally invoked via
`bash "$scenario"` in the harness worker, which doesn't need +x).
Git Bash on Windows tolerated the direct exec; Linux CI correctly
rejected it with "Permission denied", failing the PR's CI run.

Fix: `exec bash "$path"`, matching the equivalent delegation already
used correctly in webhook-no-step-skipped.sh. Verified no other
scenario in the suite has the same bare-exec pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(agents)!: close best-practice gaps across 10 core agent definitions

Two-tier subagent audit (2 independent verifiers + a reconciling
orchestrator per agent) reviewed analyst, architect, browser-agent,
fixer, deployment-verifier, reviewer, spec-analyst, spec-reviewer,
spec-writer, and test-engineer against Claude Code agent-definition
best practices and fixed confirmed defects in each.

Most notable: browser-agent's reproduction status ignored
assertion-only failures, so most everyday UI bugs (wrong label,
disabled-should-be-enabled button, missing element) were
systematically misclassified as not_reproduced and the fixer never
saw evidence for them. Also fixed: fixer's contradictory scope-limit
escape hatch and unbounded correction loops, reviewer's fabrication-
inducing "≥3 findings" floor, analyst's AC-count/NEEDS_CLARIFICATION/
UI-keyword-detection contradictions, spec-writer's mismatched
stage-name literal, and assorted contract-consistency gaps in
deployment-verifier, architect, spec-analyst, and spec-reviewer.

BREAKING CHANGE: Output Contract sections changed for analyst,
architect, browser-agent, deployment-verifier, reviewer,
spec-reviewer, spec-writer, and test-engineer (new/modified
structured output fields — see CHANGELOG.md [2.0.0] for the
full field-by-field list). Bumps plugin.json/marketplace.json
to 2.0.0 per CLAUDE.md's Versioning Policy.

Full local test suite (236 scenarios, HARNESS_JOBS=1): 235 pass,
1 skip, 0 fail.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(changelog): drop internal audit-methodology note from v2.0.0 entry

How the fixes were found (subagent review process) isn't relevant to
someone reading the changelog to see what changed in the plugin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(claude-md): codify that CHANGELOG entries exclude audit/process methodology

Prompted by having to strip a "found via N-agent review" note out of the
v2.0.0 entry — the rule wasn't written down anywhere, so it's now a named
subsection under Versioning Policy: changelog entries describe the
consumer-facing change and its defect rationale, never the internal
process that produced it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(fix-bugs): resolve 2 regressions surfaced by the merged test suite

- skills/fix-bugs/SKILL.md exceeded the thin-controller 260-line ceiling
  (268L) after combining PR #16's Config Validity Gate pointer with PR
  #15's renamed/expanded Preflight checks section -- condensed several
  3-line prose paragraphs to 2 lines each (no content removed) to bring
  it to 259L.
- tests/scenarios/fix-bugs-config-validity-gate.sh still looked for the
  old heading text "## Architecture freshness", which PR #15 correctly
  renamed to "## Preflight checks" (now covers both architecture
  freshness and dispatch-enforcement preflight) -- updated the test to
  match either heading rather than reverting the more accurate rename.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants