@event4u/agent-config 14.8.0 → 14.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +214 -237
- package/README.md +1 -1
- package/agents/templates/.ai-council.yml.example +34 -4
- package/dist/agent-src/commands/pr/merge.md +9 -5
- package/dist/agent-src/commands/review/changes.md +95 -14
- package/dist/agent-src/commands/roadmap/process-full.md +2 -2
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +77 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +36 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +80 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +9 -3
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/code-refactoring/SKILL.md +1 -1
- package/dist/agent-src/skills/code-review/evals/evals.json +87 -46
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/design-review/SKILL.md +1 -1
- package/dist/agent-src/skills/discovery-interview/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +1 -1
- package/dist/agent-src/skills/github-ci/SKILL.md +1 -1
- package/dist/agent-src/skills/humanizer/SKILL.md +39 -0
- package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +57 -0
- package/dist/agent-src/skills/humanizer/references/fixtures.md +54 -0
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-spec-compliance/SKILL.md +154 -0
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +45 -0
- package/dist/agent-src/skills/laravel-validation/SKILL.md +1 -1
- package/dist/agent-src/skills/legal-intake-triage/SKILL.md +1 -1
- package/dist/agent-src/skills/legal-practice-profile/SKILL.md +1 -1
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +1 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +1 -1
- package/dist/agent-src/skills/module-management/SKILL.md +1 -1
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +1 -1
- package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
- package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +18 -18
- package/dist/agent-src/skills/scene-expander/SKILL.md +1 -1
- package/dist/agent-src/skills/secrets-management/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +8 -0
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-MMSGVZKV.js → chunk-77GR3VD4.js} +65 -40
- package/dist/cli-delegate/{chunk-Q26HT4QT.js → chunk-E46KPN6K.js} +251 -150
- package/dist/cli-delegate/{chunk-EEJUMCDZ.js → chunk-PLSG6UL5.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +89 -13
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +2 -2
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +64 -42
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +562 -204
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +808 -331
- package/dist/scripts/_lib/claude_plugin.js +162 -0
- package/dist/scripts/_lib/claude_plugin.js.map +1 -0
- package/dist/scripts/_lib/environment_detector.js +397 -0
- package/dist/scripts/_lib/environment_detector.js.map +1 -0
- package/dist/scripts/_lib/spawn_env.js +129 -0
- package/dist/scripts/_lib/spawn_env.js.map +1 -0
- package/dist/scripts/ai_council/modes.js +199 -0
- package/dist/scripts/ai_council/modes.js.map +1 -0
- package/dist/scripts/ai_council/transport_resolver.js +418 -0
- package/dist/scripts/ai_council/transport_resolver.js.map +1 -0
- package/dist/server/routes/wizard.js +3 -2
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/ui/assets/index-Cxgy63kz.js +26 -0
- package/dist/ui/assets/index-Cxgy63kz.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
- package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +17 -0
- package/package.json +7 -3
- package/src/config/estate-count-budget.json +13 -744
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +267 -9
- package/src/config/gate-violation-baselines.json +72 -72
- package/src/config/preamble-payload-budget.json +71 -67
- package/src/config/publish-surface.json +60 -0
- package/src/config/requirements-trace-budget.json +32 -0
- package/src/config/rule-stub-ceilings.json +8 -1
- package/src/scripts/_dispatch.bash +7 -0
- package/src/scripts/_lib/base_tree.ts +175 -0
- package/src/scripts/_lib/billing_grant.ts +165 -0
- package/src/scripts/_lib/billing_grant_cli.ts +123 -0
- package/src/scripts/_lib/council_fallback_posture.ts +53 -6
- package/src/scripts/_lib/council_fallback_wiring.ts +61 -1
- package/src/scripts/_lib/host_capability.ts +59 -5
- package/src/scripts/_lib/quota_parked.ts +133 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +62 -0
- package/src/scripts/_lib/review_telemetry.ts +196 -0
- package/src/scripts/_lib/subagent_response.ts +92 -0
- package/src/scripts/adr/regenerate_index.ts +14 -7
- package/src/scripts/ai_council/clients.ts +12 -1
- package/src/scripts/ai_council/config.ts +72 -115
- package/src/scripts/ai_council/fallback_config.ts +19 -7
- package/src/scripts/ai_council/mid_flight_fallback.ts +88 -7
- package/src/scripts/ai_council/orchestrator.ts +2 -2
- package/src/scripts/ai_council/py_format.ts +124 -0
- package/src/scripts/ai_council/seating.ts +211 -0
- package/src/scripts/ai_council/transport_resolver.ts +65 -2
- package/src/scripts/audit_adr_coverage.ts +33 -6
- package/src/scripts/check_council_pin_staleness.ts +300 -0
- package/src/scripts/check_estate_count.ts +420 -293
- package/src/scripts/check_gate_coverage.ts +91 -0
- package/src/scripts/check_no_stub_inventory_table.ts +292 -0
- package/src/scripts/check_pack_passport_reconciliation.ts +274 -0
- package/src/scripts/check_pack_size.ts +234 -1
- package/src/scripts/check_publish_surface.ts +297 -0
- package/src/scripts/check_requirements_trace.ts +378 -0
- package/src/scripts/check_secret_leak.ts +166 -12
- package/src/scripts/code_graph/cli.ts +44 -5
- package/src/scripts/code_graph/extract.ts +87 -0
- package/src/scripts/council_cli.ts +12 -16
- package/src/scripts/detect_ai_tells.ts +87 -0
- package/src/scripts/dispatch_r2_reviewer.ts +42 -0
- package/src/scripts/generate_capabilities_index.ts +41 -0
- package/src/scripts/generate_pack_manifests.ts +78 -0
- package/src/scripts/git_authorization_hook.ts +54 -4
- package/src/scripts/hooks/block_unauthorized_git.ts +19 -1
- package/src/scripts/hooks/run_continuation_hook.ts +3 -1
- package/src/scripts/hooks/subagent_ledger_hook.ts +76 -11
- package/src/scripts/injection_scan_hook.ts +120 -10
- package/src/scripts/lint_adr_sweep_routing.ts +365 -0
- package/src/scripts/lint_workflow_security.ts +53 -10
- package/src/scripts/lint_workflow_security_allowlist.json +2 -18
- package/src/scripts/report_envelope_rate.ts +166 -0
- package/src/scripts/review_axis_report.ts +218 -0
- package/src/scripts/run_supervise.ts +46 -1
- package/src/scripts/schemas/evals.schema.json +5 -0
- package/src/scripts/schemas/pack.schema.json +62 -4
- package/src/scripts/schemas/skill.schema.json +2 -2
- package/src/scripts/sync_pr_branch.ts +14 -7
- package/src/scripts/tighten_skill_descriptions.ts +264 -0
- package/dist/cli/commands/commands.candidates.test.js +0 -257
- package/dist/cli/commands/commands.candidates.test.js.map +0 -1
- package/dist/cli/commands/profiles.test.js +0 -88
- package/dist/cli/commands/profiles.test.js.map +0 -1
- package/dist/cli/commands/recordTriggerEval.test.js +0 -113
- package/dist/cli/commands/recordTriggerEval.test.js.map +0 -1
- package/dist/cli/configRoot.test.js +0 -97
- package/dist/cli/configRoot.test.js.map +0 -1
- package/dist/cli/mcp/content.test.js +0 -54
- package/dist/cli/mcp/content.test.js.map +0 -1
- package/dist/cli/mcp/dispatch.test.js +0 -108
- package/dist/cli/mcp/dispatch.test.js.map +0 -1
- package/dist/server/writeRoot.test.js +0 -91
- package/dist/server/writeRoot.test.js.map +0 -1
- package/dist/shared/capabilities.test.js +0 -39
- package/dist/shared/capabilities.test.js.map +0 -1
- package/dist/ui/assets/index-C1pBRm1f.js +0 -26
- package/dist/ui/assets/index-C1pBRm1f.js.map +0 -1
- /package/dist/cli-delegate/{chunk-N7CDDGI3.js → chunk-CYH5SP6M.js} +0 -0
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"deterministic": false
|
|
59
59
|
},
|
|
60
60
|
"cli_help_command_count": {
|
|
61
|
-
"max":
|
|
62
|
-
"last_measured":
|
|
63
|
-
"last_measured_at": "2026-08-
|
|
61
|
+
"max": 104,
|
|
62
|
+
"last_measured": 104,
|
|
63
|
+
"last_measured_at": "2026-08-22",
|
|
64
64
|
"method": "registry enumeration — count of `{ name: '...', disposition` entries in src/cli/registry.ts (NOT --help prose parsing; methods historically disagreed 74 vs 76 vs 79)",
|
|
65
|
-
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 → 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time — there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 → 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop — the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 → 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 — the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 — brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 → 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 — the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when — CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97. 97 -> 98 on 2026-08-15: the `workspace:doctor` verb (road-to-inbox-harvest-2026-08-c-workspace-identity Phase 3 — the read-only report over the new `workspaceIdentity()` resolver) registers in the same PR that adds the surface, per this record's own contract. It exists for the same inference-from-a-filename shape as the council:status and gates entries above, one layer down: the tree answered \"where am I\" in eight ad-hoc places across six files, and the 12.0.0 span shipped the same worktree misclassification twice, so no verb could be asked which checkout is the main one. Read-only by construction — the roadmap's Non-goals put worktree disposal out of scope and its Risk 3 names \"the pressure read becomes a disposal path by accident\" as the failure to design against, so the command carries no --fix and no --prune. Re-measured twice via the pinned method on the unchanged tree: 98/98. 98 -> 99 on 2026-08-17: the `council:quota` verb (road-to-council-quota-accounting-truth Phase 2) registers in the same PR that adds the surface, per this record's own contract. Exactly the inference-from-a-filename shape as the council:status entry above, one layer down: `cmd_quota` had existed in council_cli.ts and been reachable only via `scripts-run`, so the documented recovery path for an exhausted shared counter -- read the usage, reset one provider -- did not resolve through `agent-config`, and an operator debugging a quota failure met `unknown command`. The verb is read-only apart from the pre-existing `--reset <provider>`, which already required `--confirm`. Re-measured twice via the pinned method on the unchanged tree: 99/99. 99 -> 100 on 2026-08-19: the `decision:memo` verb (road-to-long-horizon-execution Phase 2.2, sequencing UOTL Phase 4.3 -- the decision-memo channel) registers in the same PR that adds the surface, per this record's own contract. It exists because the question ladder gained a rung between \"halt and ask\" and \"decide silently\": a resolution the run makes without contacting the operator is only legitimate if it is reviewable afterwards, and there was no surface that wrote such a record with a fixed shape. Write-and-list only, local-only (agents/runtime/ is gitignored), and it gates nothing -- the locked decision classes are refused at the config schema, never in the ledger. 100 -> 101 in the same PR: `run:supervise` (Phase 3.1 -- the out-of-process watcher for runs whose session died with open steps left). It is the operator-facing half of session continuity: nothing anywhere had the job of noticing that a claimed run stopped moving, so a roadmap 40% done and a roadmap finished looked identical from outside the dead session. Report-only by default and it NEVER merges, pushes or closes -- the auto-merge the reference design carries is a named rejection in the roadmap's harvest section, not an unbuilt feature. Re-measured twice via the pinned method on the unchanged tree: 101/101. 101 → 102 on 2026-08-22: the `adr:effective` verb (road-to-evidence-based-adr-governance step 2.2 — the effective-state projection over one decision record) registers in the same PR that adds the surface, per this record's own contract. It exists because current truth about an ADR was only reconstructable from linear prose: an agent had to read the body, then every amendment, and decide for itself which clauses still stand. The verb reports status, the Decision verbatim, clauses the record's own amendments superseded, active amendments, the three descriptive axes and the review-trigger state. It AUTHORIZES NOTHING — Phase 2 of that roadmap is titled \"surfacing only; no authority\" and its AC-7 forbids any authority consequence, so the verb reports an absent axis as absent (`— (no provenance axis)`, `— (ungraded)`, `absent → evidence`) and an unresolvable trigger as `indeterminate` rather than inferring one. Re-measured twice via the pinned method on the unchanged tree: 102/102."
|
|
65
|
+
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 → 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time — there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 → 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop — the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 → 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 — the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 — brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 → 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 — the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when — CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97. 97 -> 98 on 2026-08-15: the `workspace:doctor` verb (road-to-inbox-harvest-2026-08-c-workspace-identity Phase 3 — the read-only report over the new `workspaceIdentity()` resolver) registers in the same PR that adds the surface, per this record's own contract. It exists for the same inference-from-a-filename shape as the council:status and gates entries above, one layer down: the tree answered \"where am I\" in eight ad-hoc places across six files, and the 12.0.0 span shipped the same worktree misclassification twice, so no verb could be asked which checkout is the main one. Read-only by construction — the roadmap's Non-goals put worktree disposal out of scope and its Risk 3 names \"the pressure read becomes a disposal path by accident\" as the failure to design against, so the command carries no --fix and no --prune. Re-measured twice via the pinned method on the unchanged tree: 98/98. 98 -> 99 on 2026-08-17: the `council:quota` verb (road-to-council-quota-accounting-truth Phase 2) registers in the same PR that adds the surface, per this record's own contract. Exactly the inference-from-a-filename shape as the council:status entry above, one layer down: `cmd_quota` had existed in council_cli.ts and been reachable only via `scripts-run`, so the documented recovery path for an exhausted shared counter -- read the usage, reset one provider -- did not resolve through `agent-config`, and an operator debugging a quota failure met `unknown command`. The verb is read-only apart from the pre-existing `--reset <provider>`, which already required `--confirm`. Re-measured twice via the pinned method on the unchanged tree: 99/99. 99 -> 100 on 2026-08-19: the `decision:memo` verb (road-to-long-horizon-execution Phase 2.2, sequencing UOTL Phase 4.3 -- the decision-memo channel) registers in the same PR that adds the surface, per this record's own contract. It exists because the question ladder gained a rung between \"halt and ask\" and \"decide silently\": a resolution the run makes without contacting the operator is only legitimate if it is reviewable afterwards, and there was no surface that wrote such a record with a fixed shape. Write-and-list only, local-only (agents/runtime/ is gitignored), and it gates nothing -- the locked decision classes are refused at the config schema, never in the ledger. 100 -> 101 in the same PR: `run:supervise` (Phase 3.1 -- the out-of-process watcher for runs whose session died with open steps left). It is the operator-facing half of session continuity: nothing anywhere had the job of noticing that a claimed run stopped moving, so a roadmap 40% done and a roadmap finished looked identical from outside the dead session. Report-only by default and it NEVER merges, pushes or closes -- the auto-merge the reference design carries is a named rejection in the roadmap's harvest section, not an unbuilt feature. Re-measured twice via the pinned method on the unchanged tree: 101/101. 101 → 102 on 2026-08-22: the `adr:effective` verb (road-to-evidence-based-adr-governance step 2.2 — the effective-state projection over one decision record) registers in the same PR that adds the surface, per this record's own contract. It exists because current truth about an ADR was only reconstructable from linear prose: an agent had to read the body, then every amendment, and decide for itself which clauses still stand. The verb reports status, the Decision verbatim, clauses the record's own amendments superseded, active amendments, the three descriptive axes and the review-trigger state. It AUTHORIZES NOTHING — Phase 2 of that roadmap is titled \"surfacing only; no authority\" and its AC-7 forbids any authority consequence, so the verb reports an absent axis as absent (`— (no provenance axis)`, `— (ungraded)`, `absent → evidence`) and an unresolvable trigger as `indeterminate` rather than inferring one. Re-measured twice via the pinned method on the unchanged tree: 102/102. 102 → 104 on 2026-08-22: the `council:grant-billing` + `council:revoke-billing` verbs (road-to-billing-cliff-gate Phase 2 — the run-scoped billing grant that lets `ai_council.fallback.api_on_quota: 'ask'` be answered once per run instead of once per seat) register in the same PR that adds the surface, per this record's own contract. The two are a pair by construction rather than by convenience: a grant that can be issued and not revoked would outlive its run, which is the failure the run-scoped TTL exists to prevent. Re-measured via the pinned method: 104."
|
|
66
66
|
},
|
|
67
67
|
"mcp_public_tool_count": {
|
|
68
68
|
"max": 20,
|
|
@@ -42,13 +42,24 @@
|
|
|
42
42
|
#
|
|
43
43
|
# COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-18)
|
|
44
44
|
# ----------------------------------------------------------
|
|
45
|
-
#
|
|
45
|
+
# 272 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
|
|
46
46
|
# (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`,
|
|
47
|
-
# re-run 2026-08-
|
|
48
|
-
# **
|
|
49
|
-
# CI-identical argv, and
|
|
47
|
+
# re-run 2026-08-22 and it returns 272).
|
|
48
|
+
# **47 of them emit the machine-readable `scanned: <N>` line under their
|
|
49
|
+
# CI-identical argv, and 44 of those 47 are listed below.** The manifest is
|
|
50
50
|
# therefore complete with respect to its own contract for every gate that can
|
|
51
|
-
# carry a floor, and covers ~
|
|
51
|
+
# carry a floor, and covers ~17 % of the population.
|
|
52
|
+
#
|
|
53
|
+
# RECOUNTED on 2026-08-22, and it was wrong on every figure before the recount —
|
|
54
|
+
# which is the fourth time, and the reason this paragraph keeps asking to be
|
|
55
|
+
# computed. `check_no_stub_inventory_table` added ONE row and ONE script, but the
|
|
56
|
+
# readings moved by more than one in three of the four places: population
|
|
57
|
+
# 269 -> 272 (two scripts had landed since 2026-08-21 without touching this
|
|
58
|
+
# prose), listed rows 42 -> 44 (the file already held 43 before this change; the
|
|
59
|
+
# prose had again been adjusted instead of recounted, and the paragraph below
|
|
60
|
+
# says so about its own previous revision), emitters 45 -> 47. Every number here
|
|
61
|
+
# is reproducible: `grep -c '^ - id:' src/config/gate-coverage.yml` for the rows
|
|
62
|
+
# and `count_gate_scripts()` for the population.
|
|
52
63
|
#
|
|
53
64
|
# Both halves were RE-DERIVED on 2026-08-21, not incremented, and the previous
|
|
54
65
|
# reading was off by one in a way worth recording: it said "42 … and 41 of those
|
|
@@ -59,14 +70,14 @@
|
|
|
59
70
|
# the prose was adjusted by one instead of recounted.
|
|
60
71
|
#
|
|
61
72
|
# The derivation now, so the next reader can check it rather than trust it:
|
|
62
|
-
# `grep -c '^ - id:'` returns
|
|
73
|
+
# `grep -c '^ - id:'` returns 44 (computable, and computed); every listed row
|
|
63
74
|
# is an emitter, because a row that did not emit could carry no floor and the
|
|
64
75
|
# guard would report it `failing`; THREE emitters are deliberately unlisted —
|
|
65
76
|
# `lint_evidence_artifacts` (below), `adr_cite_check` and
|
|
66
77
|
# `check_new_adr_evidence` (each in the block where its row would have sat);
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
78
|
+
# 44 + 3 = 47. The population figure comes from the function, and
|
|
79
|
+
# `check_new_adr_evidence` matches the population prefix whether or not it
|
|
80
|
+
# carries a row here.
|
|
70
81
|
#
|
|
71
82
|
# `adr/evidence_census` emits a `scanned:` line too and is NOT in either number:
|
|
72
83
|
# it carries no `lint|check|audit` prefix, so `count_gate_scripts()` never sees
|
|
@@ -206,11 +217,113 @@
|
|
|
206
217
|
# contract is `dist == rewrite(src)`; `check_ci_local_parity`, whose corpus is
|
|
207
218
|
# workflow files) carries no recipe and is reported UNPROVEN, never green.
|
|
208
219
|
gates:
|
|
220
|
+
- id: check_pack_size
|
|
221
|
+
argv: []
|
|
222
|
+
min_scanned: 2000
|
|
223
|
+
corpus: "the `npm pack --dry-run --ignore-scripts` payload — every file package.json `files[]` resolves (2,954 in a built worktree and 2,686 in an unbuilt one on 2026-08-22, which is why the floor sits well under both)"
|
|
224
|
+
status: enforced
|
|
225
|
+
canary:
|
|
226
|
+
class: contract-violation
|
|
227
|
+
path: src/scripts/zz-canary-shipped-credential.pem
|
|
228
|
+
content: |
|
|
229
|
+
zz canary probe: not a key, and deliberately not shaped like one.
|
|
230
|
+
The credential-shaped class matches on the PATH (`\.pem$`), never on the
|
|
231
|
+
body, so the plant needs no key-shaped content to red the class - and a
|
|
232
|
+
PEM header here would be a high-confidence check_secret_leak finding in
|
|
233
|
+
this tracked file. Measured, not guessed: the first draft carried a
|
|
234
|
+
BEGIN PRIVATE KEY block and reddened the secret gate at
|
|
235
|
+
gate-coverage.yml:229 in both `diff` and the new `pack` mode. A canary
|
|
236
|
+
that breaks a sibling gate to prove its own is not a canary.
|
|
237
|
+
note: >
|
|
238
|
+
ONE canary, and the entry shape is why. `canary:` is a single recipe per
|
|
239
|
+
gate id, not a list, while this gate carries FOUR content classes — so
|
|
240
|
+
per-class red observation lives in the gate's own `--self-test` (9 cases,
|
|
241
|
+
6 rejecting), which proves every class discriminates over a synthetic
|
|
242
|
+
payload with no pack run. Two of the four cannot be planted through the
|
|
243
|
+
register at all: `compiled-test-artefact` is excluded from the payload by
|
|
244
|
+
the `files[]` negations that fixed it, so a plant never ships and never
|
|
245
|
+
reds, and `source-map` needs 121 files in a BUILT tree.
|
|
246
|
+
|
|
247
|
+
The credential class is the one that gets the recipe. It is empty today,
|
|
248
|
+
and an empty class with no check is indistinguishable from a class nobody
|
|
249
|
+
looked at — so it is the class where "has this ever been red" is a real
|
|
250
|
+
question. The plant sits under `src/scripts/`, which IS a `files[]` root;
|
|
251
|
+
an earlier attempt under `src/skills/` was silently absent from the
|
|
252
|
+
payload because that path is not shipped, and a canary that cannot reach
|
|
253
|
+
the corpus proves nothing.
|
|
254
|
+
|
|
255
|
+
Floor is a count, not a size. The size arm has a budget file; the count
|
|
256
|
+
arm is what stops an empty payload — a botched `files[]`, a pack that
|
|
257
|
+
resolved nothing — from measuring 0 MB and passing every budget. The gate
|
|
258
|
+
already exits 2 rather than 0 on that, via `assertScanned`.
|
|
259
|
+
|
|
260
|
+
- id: check_secret_leak
|
|
261
|
+
argv: ["--pack"]
|
|
262
|
+
min_scanned: 2000
|
|
263
|
+
corpus: "the npm pack payload — every file package.json `files[]` resolves, INCLUDING shipped-but-gitignored paths no git-backed mode can reach (2,684 in an unbuilt worktree on 2026-08-22)"
|
|
264
|
+
status: enforced
|
|
265
|
+
canary:
|
|
266
|
+
class: contract-violation
|
|
267
|
+
path: dist/zz-canary-shipped-and-gitignored.pem
|
|
268
|
+
content: |
|
|
269
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
270
|
+
MIIEowIBAAKCAQEAzz-canary-not-a-real-key-zz
|
|
271
|
+
-----END RSA PRIVATE KEY-----
|
|
272
|
+
note: >
|
|
273
|
+
Registered on the `--pack` argv specifically, and the canary path is the
|
|
274
|
+
whole point: `dist/` is a `files[]` root while `/dist/*` is
|
|
275
|
+
`.gitignore:206`, so this plant is shipped and untracked at the same time.
|
|
276
|
+
`git check-ignore -q` matches it and `npm pack` includes it. A canary in a
|
|
277
|
+
tracked file would pass under the pre-existing `diff` and `all` modes too
|
|
278
|
+
and would prove nothing about the scope this entry exists for.
|
|
279
|
+
|
|
280
|
+
Measured, not assumed: with the plant in place `--pack` exits 1 and names
|
|
281
|
+
the path, while the default `diff` mode exits 0. The plant carries a real
|
|
282
|
+
PEM shape because THIS gate matches on CONTENT — unlike its sibling
|
|
283
|
+
`check_pack_size`, whose credential class matches on the path and whose
|
|
284
|
+
canary therefore deliberately carries no key-shaped body.
|
|
285
|
+
|
|
286
|
+
Two reasons the scope was blind, and adding the mode only fixed the first.
|
|
287
|
+
Mode enumeration walks the git tree; the `DEFAULT_EXCLUDE` list ALSO drops
|
|
288
|
+
all of `dist/`, regardless of mode. Until that exclusion became
|
|
289
|
+
mode-aware, the new scope resolved the payload and then filtered away
|
|
290
|
+
exactly the paths it was built to reach — the mode was measurably inert.
|
|
291
|
+
|
|
292
|
+
- id: check_publish_surface
|
|
293
|
+
argv: []
|
|
294
|
+
min_scanned: 2000
|
|
295
|
+
corpus: "the npm pack payload (2,686 in an unbuilt worktree on 2026-08-22), read to classify each .npmignore pattern against what actually shipped"
|
|
296
|
+
status: enforced
|
|
297
|
+
no_canary_reason: >-
|
|
298
|
+
the violation is a MODIFICATION, not a creation: this gate reds when package.json `files[]` or `.npmignore` changes and the committed artefact does not, and the canary contract is create-only. A planted FILE cannot move either surface — the closest it gets is changing the payload-derived shadowed set, which is informational and deliberately excluded from the drift verdict, so a plant would leave the gate green and be reported as dead. Discrimination is proven by the gate's own `--self-test` (8 cases, 5 rejecting) over the pattern matcher, and end to end by hand: editing `files[]` alone exits 1, regenerating exits 0, editing `.npmignore` alone exits 1, restoring exits 0.
|
|
299
|
+
|
|
300
|
+
- id: check_pack_passport_reconciliation
|
|
301
|
+
argv: []
|
|
302
|
+
min_scanned: 15
|
|
303
|
+
corpus: "the generated token_passport block in every src/packs/*/pack.yaml (17 at registration)"
|
|
304
|
+
status: enforced
|
|
305
|
+
no_canary_reason: >-
|
|
306
|
+
this is a LISTING, not an enforcement: `main()` returns 0 on every path by design, so no planted file can make it red and the harness's "caught the planted defect" observation is unreachable by construction. It is registered for its `scanned:` floor, which is the one thing about it that CAN break — a passport block that stops being generated, or a packs root that moves. Discrimination is proven by the gate's own `--self-test` (6 cases, 3 rejecting) over the two pure units behind the number: the passport parser and the reconciliation ratio.
|
|
307
|
+
note: >
|
|
308
|
+
Registered because it emits the `scanned:` contract line, and a test in
|
|
309
|
+
this tree requires every emitter to be registered — it caught this entry
|
|
310
|
+
being absent, which is the coverage register working as intended.
|
|
311
|
+
|
|
312
|
+
It exits 0 on a large gap ON PURPOSE. The ±10 % band it was specified with
|
|
313
|
+
assumed packs roughly PARTITION the tree; measured, `dependencies` claims
|
|
314
|
+
4 skills and 0 rules against 291 and 118, so gaps of 84 % and above are a
|
|
315
|
+
property of the tree rather than a defect. A gate red by construction gets
|
|
316
|
+
disabled rather than fixed, so this reports coverage instead. The condition
|
|
317
|
+
that would make the exit code follow the band — pack coverage approaching
|
|
318
|
+
the tree — is recorded in docs/contracts/pack-token-passport.md.
|
|
319
|
+
|
|
209
320
|
- id: check_gate_completeness
|
|
210
321
|
argv: []
|
|
211
322
|
min_scanned: 180
|
|
212
323
|
corpus: "gates reachable from the `ci` / `consistency` task roots (220 at baseline)"
|
|
213
324
|
status: enforced
|
|
325
|
+
no_canary_reason: >-
|
|
326
|
+
whole-graph: it parses every gate invocation in the task roots at once, so a planted file has no property to violate — the defect it detects is a MISSING edge, which cannot be planted.
|
|
214
327
|
note: >
|
|
215
328
|
Floor set below the live count on purpose: the registered set legitimately
|
|
216
329
|
shrinks when a gate is retired, and a floor pinned at today's exact number
|
|
@@ -224,6 +337,8 @@ gates:
|
|
|
224
337
|
min_scanned: 0
|
|
225
338
|
corpus: "the five project rule directories that receive a projected tree (.claude/rules, .cursor/rules, .clinerules, .windsurf/rules, .augment/rules)"
|
|
226
339
|
status: enforced
|
|
340
|
+
no_canary_reason: >-
|
|
341
|
+
cross-tree: the violation is one rule appearing in two projected trees, so it needs both trees, not a file.
|
|
227
342
|
note: >
|
|
228
343
|
`min_scanned: 0` is the honest floor and not the false-count shape this file
|
|
229
344
|
rejects elsewhere. This gate compares a project rule directory against its
|
|
@@ -246,6 +361,8 @@ gates:
|
|
|
246
361
|
min_scanned: 100
|
|
247
362
|
corpus: "rule files under src/rules/ (117 at baseline)"
|
|
248
363
|
status: enforced
|
|
364
|
+
no_canary_reason: >-
|
|
365
|
+
whole-corpus census: it reports an aggregate over every rule; a single planted rule moves a number rather than producing a red.
|
|
249
366
|
note: >
|
|
250
367
|
Floor set below the live count so a legitimate rule retirement does not red
|
|
251
368
|
the gate that watches activation. It is still far above a collapse: if the
|
|
@@ -339,22 +456,95 @@ gates:
|
|
|
339
456
|
min_scanned: 8
|
|
340
457
|
corpus: "declared human-authored suppression surfaces (10 at baseline)"
|
|
341
458
|
status: enforced
|
|
459
|
+
no_canary_reason: >-
|
|
460
|
+
cross-file: a suppression is a violation only against the declared surface that authorises it, so the pair is the unit.
|
|
342
461
|
note: >
|
|
343
462
|
The denominator is the INVENTORY, not the entry count — the gate's job is
|
|
344
463
|
that every suppression surface is accounted for, and a surface list that
|
|
345
464
|
collapsed to nothing must not read as "no suppressions to check".
|
|
346
465
|
|
|
466
|
+
- id: lint_adr_sweep_routing
|
|
467
|
+
argv: []
|
|
468
|
+
min_scanned: 20
|
|
469
|
+
corpus: "candidate rows (REVIEW-NOW / SUPERSEDE (candidate)) across docs/decisions/adr-evidence-sweep-*.md (26 at baseline, in one artifact)"
|
|
470
|
+
status: enforced
|
|
471
|
+
canary:
|
|
472
|
+
class: unrouted-candidate
|
|
473
|
+
path: docs/decisions/adr-evidence-sweep-zz-canary-probe.md
|
|
474
|
+
content: |
|
|
475
|
+
# ADR evidence sweep — canary probe
|
|
476
|
+
|
|
477
|
+
| Record | Disposition | Why |
|
|
478
|
+
|---|---|---|
|
|
479
|
+
| ADR-9999 | REVIEW-NOW | canary probe row |
|
|
480
|
+
|
|
481
|
+
## Candidate routing
|
|
482
|
+
|
|
483
|
+
| Record | Disposition | Route | Dated follow-up |
|
|
484
|
+
|---|---|---|---|
|
|
485
|
+
| ADR-9999 | REVIEW-NOW | council | when we get to it |
|
|
486
|
+
note: >
|
|
487
|
+
The floor is 20 rather than 26 because a candidate LEAVING the population
|
|
488
|
+
is the point of the sweep: every disposition that lands takes its row out
|
|
489
|
+
of the count, so a tight floor would red on the gate working. It is far
|
|
490
|
+
above a collapse — a scan that stopped seeing the artifact reports 0.
|
|
491
|
+
|
|
492
|
+
- id: check_requirements_trace
|
|
493
|
+
argv: []
|
|
494
|
+
min_scanned: 15
|
|
495
|
+
corpus: "roadmap files at the top level of agents/roadmaps/ (25 at registration, 2026-08-22)"
|
|
496
|
+
status: enforced
|
|
497
|
+
no_canary_reason: >-
|
|
498
|
+
this gate is a LISTING, not an enforcement: `main()` returns 0 on every
|
|
499
|
+
path and `process.exit(main())` is its only exit, so no planted file can
|
|
500
|
+
make it red and the harness's "caught the planted defect (exit 1)"
|
|
501
|
+
observation is unreachable by construction. Verified, not assumed — a probe
|
|
502
|
+
roadmap carrying an unresolved acceptance-criteria ref left the exit code at
|
|
503
|
+
0. It is registered for its `scanned:` floor, which is the one thing about
|
|
504
|
+
it that CAN break, and that floor is the negative control here.
|
|
505
|
+
note: >
|
|
506
|
+
A LISTING gate: it exits 0 always, including on a dangling `[AC:]` ref and
|
|
507
|
+
on an empty corpus. Registered here for its `scanned:` floor rather than
|
|
508
|
+
for a pass/fail verdict — the floor is the only thing about it that can
|
|
509
|
+
break, and a scan that stops seeing agents/roadmaps/ would otherwise
|
|
510
|
+
report an empty inventory as a clean one. Floor 15 against 25 at
|
|
511
|
+
registration: the active estate is being drained deliberately and is
|
|
512
|
+
expected to shrink, so a tight floor would red on the drain working.
|
|
513
|
+
|
|
514
|
+
- id: check_council_pin_staleness
|
|
515
|
+
argv: []
|
|
516
|
+
min_scanned: 3
|
|
517
|
+
corpus: "council members carrying a `model:` in agents/templates/.ai-council.yml.example (5 at registration, 2026-08-22)"
|
|
518
|
+
status: enforced
|
|
519
|
+
no_canary_reason: >-
|
|
520
|
+
the harness is create-only and this gate reads ONE fixed path
|
|
521
|
+
(agents/templates/.ai-council.yml.example), so no planted file lands inside
|
|
522
|
+
its scan scope — making it red means EDITING that template, which the
|
|
523
|
+
harness does not do. Discrimination is proven by the gate's own
|
|
524
|
+
`--self-test` instead: 10 cases across the fresh, stale, future-date,
|
|
525
|
+
malformed, unstamped and vendor-sentinel branches.
|
|
526
|
+
note: >
|
|
527
|
+
Floor 3 against 5 at registration: the template's member list is a shipped
|
|
528
|
+
artifact rather than a draining corpus, but an exact floor would red on a
|
|
529
|
+
legitimate trim of one member. Collapse is covered more strictly from the
|
|
530
|
+
other side — `reportScanned` raises DeadScopeError at 0 members, before
|
|
531
|
+
this floor is consulted at all.
|
|
532
|
+
|
|
347
533
|
- id: lint_trigger_collisions
|
|
348
534
|
argv: []
|
|
349
535
|
min_scanned: 90
|
|
350
536
|
corpus: "src/rules/*.md frontmatters (111 at baseline)"
|
|
351
537
|
status: enforced
|
|
538
|
+
no_canary_reason: >-
|
|
539
|
+
pairwise: a collision needs two rules, and which two is the finding — a single planted file collides with nothing.
|
|
352
540
|
|
|
353
541
|
- id: lint_rule_skill_pack_reach
|
|
354
542
|
argv: ["--quiet"]
|
|
355
543
|
min_scanned: 90
|
|
356
544
|
corpus: "src/rules/*.md frontmatters joined against src/skills packs and the pack registry (116 rules at baseline)"
|
|
357
545
|
status: enforced
|
|
546
|
+
no_canary_reason: >-
|
|
547
|
+
join: rule frontmatter against the skills tree and the pack registry; a planted rule needs a matching planted pack graph to be judged.
|
|
358
548
|
note: >
|
|
359
549
|
Advisory on findings, enforced on COVERAGE: the gate exits 0 while its
|
|
360
550
|
unreachable-route set is non-empty (12 at introduction), so only this
|
|
@@ -367,6 +557,8 @@ gates:
|
|
|
367
557
|
min_scanned: 380
|
|
368
558
|
corpus: "src/ ↔ dist/agent-src/ .md pairs (429 at baseline: 111 rules + 318 skills)"
|
|
369
559
|
status: enforced
|
|
560
|
+
no_canary_reason: >-
|
|
561
|
+
byte-equality between src/ and dist/agent-src/ pairs — the property is a relation between two trees, not a file.
|
|
370
562
|
|
|
371
563
|
- id: check_augment_description_cap
|
|
372
564
|
argv: []
|
|
@@ -477,6 +669,8 @@ gates:
|
|
|
477
669
|
min_scanned: 340
|
|
478
670
|
corpus: "CI + local gate invocations parsed from .github/workflows + taskfiles (360 measured 2026-08-13: 109 CI + 251 local)"
|
|
479
671
|
status: enforced
|
|
672
|
+
no_canary_reason: >-
|
|
673
|
+
whole-graph: it parses every workflow and taskfile invocation and reports gates present in one set and absent from the other.
|
|
480
674
|
note: >
|
|
481
675
|
Registered 2026-08-02. It already emitted the contract line on every path,
|
|
482
676
|
including the failing one — it was simply never listed, the same omission
|
|
@@ -524,6 +718,8 @@ gates:
|
|
|
524
718
|
unavailable_exit: 2
|
|
525
719
|
corpus: "built HTML pages under site/dist (25 content sources at baseline)"
|
|
526
720
|
status: enforced
|
|
721
|
+
no_canary_reason: >-
|
|
722
|
+
needs the BUILT site under site/dist, which does not exist until a build runs; already reported `unavailable` when absent.
|
|
527
723
|
note: >
|
|
528
724
|
Registered 2026-07-30 after it was caught reporting green over a stale build —
|
|
529
725
|
6 pages against 25 content sources, every source newer than the newest page.
|
|
@@ -553,6 +749,8 @@ gates:
|
|
|
553
749
|
min_scanned: 1200
|
|
554
750
|
corpus: "all .md under src/ + dist/agent-src/ plus the shipped root files (1,566 at baseline)"
|
|
555
751
|
status: enforced
|
|
752
|
+
no_canary_reason: >-
|
|
753
|
+
a planted file would be judged, but the gate is a broad scan whose baseline is the corpus size — a single red proves the matcher fires, which its own fixtures already do.
|
|
556
754
|
note: >
|
|
557
755
|
SCAN_DIRS named the retired authoring root, so the entire src/ tree —
|
|
558
756
|
more than half the corpus — was skipped and an identifier authored there
|
|
@@ -563,6 +761,8 @@ gates:
|
|
|
563
761
|
min_scanned: 800
|
|
564
762
|
corpus: ".md under the scanned roots plus memory YAML (1,043 at baseline)"
|
|
565
763
|
status: enforced
|
|
764
|
+
no_canary_reason: >-
|
|
765
|
+
a planted broken reference is judged, but every target must exist in the real tree for the resolver to be faithful; an isolated fixture makes every reference broken.
|
|
566
766
|
note: >
|
|
567
767
|
src/ was absent from every reference-resolution candidate list, so a link
|
|
568
768
|
resolvable only under the source of truth was reported BROKEN. The
|
|
@@ -574,6 +774,8 @@ gates:
|
|
|
574
774
|
min_scanned: 400
|
|
575
775
|
corpus: "src/rules + src/skills + src/agent-src/commands + docs/guidelines .md (533 at baseline)"
|
|
576
776
|
status: enforced
|
|
777
|
+
no_canary_reason: >-
|
|
778
|
+
thresholds are computed across the whole corpus; a single planted artefact has no population to exceed.
|
|
577
779
|
note: >
|
|
578
780
|
A collapse below the floor would mean the gate stopped reading the tree
|
|
579
781
|
that states extraction thresholds, so a bare or diverging threshold
|
|
@@ -584,6 +786,8 @@ gates:
|
|
|
584
786
|
min_scanned: 5
|
|
585
787
|
corpus: "src/agent-src/profiles/*.yml (6 seed profiles at baseline)"
|
|
586
788
|
status: enforced
|
|
789
|
+
no_canary_reason: >-
|
|
790
|
+
join: a profile is judged against the persona set it names, so both sides are needed.
|
|
587
791
|
note: >
|
|
588
792
|
Fewer than 5 profiles scanned would mean the gate stopped reading the
|
|
589
793
|
seed-profile dir, so a defaults.personas id that resolves to no persona
|
|
@@ -594,6 +798,8 @@ gates:
|
|
|
594
798
|
min_scanned: 200
|
|
595
799
|
corpus: "src/skills/*/SKILL.md (288 at baseline)"
|
|
596
800
|
status: enforced
|
|
801
|
+
no_canary_reason: >-
|
|
802
|
+
ratio gate: the 15% rich-skill cap is a property of the corpus, so one planted skill cannot cross it.
|
|
597
803
|
note: >
|
|
598
804
|
A collapse below the floor would mean the gate stopped reading the skills
|
|
599
805
|
tree, so a rich-tagged skill without its justification section (or a cap
|
|
@@ -604,6 +810,8 @@ gates:
|
|
|
604
810
|
min_scanned: 350
|
|
605
811
|
corpus: "skills / rules / commands .md actually judged (368 of 438 enumerated; the rest carry a declared exemption the ledger names)"
|
|
606
812
|
status: enforced
|
|
813
|
+
no_canary_reason: >-
|
|
814
|
+
the allowlist is line-keyed against real files, so a planted file has no allowlist anchor and the exemption path goes untested.
|
|
607
815
|
note: >
|
|
608
816
|
Its human summary prints "N hits across M files", where M is files WITH
|
|
609
817
|
HITS — 0 on a clean run. Reading that as coverage is precisely how a
|
|
@@ -617,6 +825,8 @@ gates:
|
|
|
617
825
|
min_scanned: 1
|
|
618
826
|
corpus: "ready roadmap files under agents/roadmaps/ top level (6 as of 2026-08-21; 19 at the original baseline: 14 grandfathered + 4 draft-exempt + 1 carrying a live register)"
|
|
619
827
|
status: enforced
|
|
828
|
+
no_canary_reason: >-
|
|
829
|
+
a planted roadmap is judged, but the gate reads the ready-roadmap population to decide scope; an isolated file changes what it scans.
|
|
620
830
|
note: >
|
|
621
831
|
Gate R1 (docs/contracts/plan-review-gates.md § 1). The count is READY
|
|
622
832
|
FILES INSPECTED incl. grandfathered/draft-exempt ones — exemptions are
|
|
@@ -704,6 +914,8 @@ gates:
|
|
|
704
914
|
min_scanned: 1
|
|
705
915
|
corpus: "findings artefacts under agents/evidence/reviews/ + the current-diff evaluation (1 at baseline — the evaluation itself; artefact count grows with gated PRs)"
|
|
706
916
|
status: enforced
|
|
917
|
+
no_canary_reason: >-
|
|
918
|
+
git-dependent: it evaluates the current diff against a base ref.
|
|
707
919
|
note: >
|
|
708
920
|
Gate R2 (docs/contracts/plan-review-gates.md § 2). HONEST LIMIT, stated
|
|
709
921
|
because a floor that cannot fail is exactly the false green this file
|
|
@@ -731,6 +943,8 @@ gates:
|
|
|
731
943
|
min_scanned: 7
|
|
732
944
|
corpus: "archived round records — `*-review.md` under agents/evidence/reviews/, excluding live `*.findings.md` (9 at baseline)"
|
|
733
945
|
status: enforced
|
|
946
|
+
no_canary_reason: >-
|
|
947
|
+
git-dependent in effect: it reads archived round records whose identity comes from the committed tree, and its own scan-scope guard fails on an empty corpus.
|
|
734
948
|
note: >
|
|
735
949
|
Contract § 2.7. Unlike the R2 entry above, this floor is genuinely
|
|
736
950
|
trippable: the corpus is 9 frozen records and archived records are not
|
|
@@ -760,6 +974,8 @@ gates:
|
|
|
760
974
|
min_scanned: 250
|
|
761
975
|
corpus: "src/skills/*/SKILL.md (288 at baseline)"
|
|
762
976
|
status: enforced
|
|
977
|
+
no_canary_reason: >-
|
|
978
|
+
join: a handoff is a link from one skill to another, so the target skill must exist to judge the link.
|
|
763
979
|
note: >
|
|
764
980
|
The argv here is load-bearing, not decoration. Taskfile injects `--quiet`
|
|
765
981
|
(QUIET_FLAG) and this gate read `args[0]` as a positional path, so the CI
|
|
@@ -774,6 +990,8 @@ gates:
|
|
|
774
990
|
min_scanned: 540
|
|
775
991
|
corpus: "names across src/rules + src/skills + src/agent-src + src/domains/**/command.md (621 at baseline)"
|
|
776
992
|
status: enforced
|
|
993
|
+
no_canary_reason: >-
|
|
994
|
+
collision gate across four roots at once; one planted name collides with nothing.
|
|
777
995
|
note: >
|
|
778
996
|
Counts NAMES, not files — the scan-scope census counts files under the same
|
|
779
997
|
roots, so the two artefacts legitimately report different numbers here.
|
|
@@ -783,12 +1001,16 @@ gates:
|
|
|
783
1001
|
min_scanned: 540
|
|
784
1002
|
corpus: "artefacts carrying frontmatter across the discovery roots (619 at baseline)"
|
|
785
1003
|
status: enforced
|
|
1004
|
+
no_canary_reason: >-
|
|
1005
|
+
a planted artefact is judged, but the gate reports adoption across the discovery roots, so the number rather than a red is the output.
|
|
786
1006
|
|
|
787
1007
|
- id: audit_skill_overlap
|
|
788
1008
|
argv: ["--quiet", "--print-table", "--strict"]
|
|
789
1009
|
min_scanned: 250
|
|
790
1010
|
corpus: "src/skills/*/SKILL.md compared pairwise (288 at baseline)"
|
|
791
1011
|
status: enforced
|
|
1012
|
+
no_canary_reason: >-
|
|
1013
|
+
pairwise over 288 skills; overlap needs a corpus, and which pair is the finding.
|
|
792
1014
|
note: >
|
|
793
1015
|
`--strict` is part of the CI invocation and can exit non-zero on a real
|
|
794
1016
|
overlap finding. The guard reads the count independently of the exit code —
|
|
@@ -799,6 +1021,8 @@ gates:
|
|
|
799
1021
|
min_scanned: 90
|
|
800
1022
|
corpus: "src/rules/*.md (111 at baseline)"
|
|
801
1023
|
status: enforced
|
|
1024
|
+
no_canary_reason: >-
|
|
1025
|
+
a planted rule IS judgeable — this entry is a genuine authoring gap rather than a structural one, and is the first candidate if the mode is ever built.
|
|
802
1026
|
note: >
|
|
803
1027
|
Emits on stderr, not stdout: `--format json` owns this gate's stdout and a
|
|
804
1028
|
count written there would corrupt the payload. The guard reads both streams.
|
|
@@ -820,6 +1044,8 @@ gates:
|
|
|
820
1044
|
min_scanned: 3
|
|
821
1045
|
corpus: "the three named inputs it cross-checks — src/cli/registry.ts, src/config/evaluator-budgets.json, internal/bench/reports/evaluator-measurements.json"
|
|
822
1046
|
status: enforced
|
|
1047
|
+
no_canary_reason: >-
|
|
1048
|
+
git-dependent cross-check of three named committed inputs; the property is their agreement, not any one file.
|
|
823
1049
|
note: >
|
|
824
1050
|
Registered because its count became REAL, not to pad the manifest. The
|
|
825
1051
|
gate always printed a hardcoded `scanned: 3`; hardening derived it from
|
|
@@ -833,6 +1059,8 @@ gates:
|
|
|
833
1059
|
min_scanned: 100
|
|
834
1060
|
corpus: "leaf keys in src/config/agent-settings.template.yml (140 at baseline)"
|
|
835
1061
|
status: enforced
|
|
1062
|
+
no_canary_reason: >-
|
|
1063
|
+
the only possible violation is a MODIFICATION of two tracked files (a key added to the template, or a row removed from the contract) and the canary harness is create-only by design. Discrimination is proven by the gate's own `--self-test` instead — six rejecting cases including the dead-scan-root one.
|
|
836
1064
|
note: >
|
|
837
1065
|
Floor set well below the live 140 so retiring a settings key does not red
|
|
838
1066
|
the change that retires it, but high enough that the collapse this file
|
|
@@ -1032,6 +1260,8 @@ gates:
|
|
|
1032
1260
|
min_scanned: 1
|
|
1033
1261
|
corpus: "rows of the `docs/MIGRATION.md` scheduled-deprecations table (3 at baseline)"
|
|
1034
1262
|
status: enforced
|
|
1263
|
+
no_canary_reason: >-
|
|
1264
|
+
discrimination is proven by the gate's own `--self-test` (10 cases, 6 rejecting) driving the real binary, which covers the due-at-the-cut case a create-only canary could not express.
|
|
1035
1265
|
note: >
|
|
1036
1266
|
`argv` carries `--quiet` because that is what the task passes: the
|
|
1037
1267
|
Taskfile resolves `{{.QUIET_FLAG}}` to `--quiet` unless
|
|
@@ -1061,6 +1291,8 @@ gates:
|
|
|
1061
1291
|
min_scanned: 900
|
|
1062
1292
|
corpus: "TypeScript sources — src/**/*.ts excluding *.d.ts and *.test.ts, the same two kinds _lib/gate_population excludes (1,063 at baseline)"
|
|
1063
1293
|
status: enforced
|
|
1294
|
+
no_canary_reason: >-
|
|
1295
|
+
the canary contract is create-only and this gate's violation is a MODIFICATION — a file crossing its line ceiling. Discrimination is proven by the gate's own `--self-test`, including a boundary case and a dead scan root.
|
|
1064
1296
|
# No `canary:` recipe, and the reason is the canary contract's own shape
|
|
1065
1297
|
# rather than a gap. The violation this gate detects is a file OVER 1,500
|
|
1066
1298
|
# lines, so a create-only recipe would have to inline 1,501 lines of content
|
|
@@ -1075,6 +1307,32 @@ gates:
|
|
|
1075
1307
|
# last case is what pins the metric as excess lines rather than a file count;
|
|
1076
1308
|
# a count-based ratchet passes it, and this gate must not.
|
|
1077
1309
|
|
|
1310
|
+
- id: check_no_stub_inventory_table
|
|
1311
|
+
argv: ["--quiet"]
|
|
1312
|
+
min_scanned: 1
|
|
1313
|
+
corpus: "the guarded watch list — agents/roadmaps/stubs/README.md (1 file; the whole scope, not a sample)"
|
|
1314
|
+
status: enforced
|
|
1315
|
+
no_canary_reason: >-
|
|
1316
|
+
the guarded path already EXISTS, so a create-only canary cannot plant the violation. Discrimination is proven by the gate's own `--self-test`.
|
|
1317
|
+
# No `canary:` recipe: the guarded path already EXISTS, and the canary
|
|
1318
|
+
# contract is create-only. A recipe would have to mutate a tracked file
|
|
1319
|
+
# rather than plant one, which the contract does not express. The gate
|
|
1320
|
+
# reports UNPROVEN there rather than green, which is the honest state.
|
|
1321
|
+
#
|
|
1322
|
+
# Discrimination is proven by the gate's own `--self-test` instead, and the
|
|
1323
|
+
# five cases are the sabotage probes it was verified with before landing:
|
|
1324
|
+
# a restored transfer table, the inventory header alone, a DEAD watch list
|
|
1325
|
+
# (the `check_safety_floor_untouched` shape — it must red, never report
|
|
1326
|
+
# clean), plus two accepting cases that pin the narrowness review asked for
|
|
1327
|
+
# — a glossary table and a table citing parent roadmaps one directory up
|
|
1328
|
+
# must both pass. A blanket ban on markdown tables in the file would trade
|
|
1329
|
+
# one regression for a permanent block on legitimate documentation.
|
|
1330
|
+
#
|
|
1331
|
+
# `min_scanned: 1` is the true corpus, not a weak floor: the scope is one
|
|
1332
|
+
# known file. The collapse this file's rule 3 guards against is covered by
|
|
1333
|
+
# `assertWatchlistResolves`, which refuses to report clean when the path
|
|
1334
|
+
# does not resolve — so a rename reds the gate instead of retiring it.
|
|
1335
|
+
|
|
1078
1336
|
# check_new_adr_evidence is DELIBERATELY NOT REGISTERED here, following this
|
|
1079
1337
|
# file's own two precedents rather than breaking them.
|
|
1080
1338
|
#
|