@event4u/agent-config 14.12.0 → 14.13.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.
Files changed (466) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +234 -0
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +109 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -15,17 +15,17 @@
15
15
  # THE CONTRACT (three rules, each from a real failure)
16
16
  # ----------------------------------------------------
17
17
  # 1. MACHINE-READABLE COUNT. Every listed gate emits exactly one line
18
- # `scanned: <N>` (stdout or stderr), N = artefacts it actually inspected. The
18
+ # `scanned: <N>` (stdout or stderr), N = artifacts it actually inspected. The
19
19
  # guard never parses a gate's human output — that would make the guard itself
20
20
  # fragile, and a fragile guard is the thing being replaced.
21
21
  #
22
22
  # 2. CI-IDENTICAL INVOCATION. `argv` MUST match how CI/Taskfile calls the gate.
23
23
  # A bare probe produced a false alarm during the sweep: `skill_linter` looked
24
24
  # blind when called with no arguments, but CI passes `--all` and it scans 429
25
- # artefacts. The guard must reproduce the real call or it invents defects.
25
+ # artifacts. The guard must reproduce the real call or it invents defects.
26
26
  #
27
27
  # 3. BASELINE, NOT `> 0`. `min_scanned` is a floor, not a zero-check. A gate that
28
- # drops from 428 artefacts to 3 is as broken as one that drops to 0, and `> 0`
28
+ # drops from 428 artifacts to 3 is as broken as one that drops to 0, and `> 0`
29
29
  # cannot see it. Set the floor below the true corpus (room for legitimate
30
30
  # deletions) but far above a collapse.
31
31
  #
@@ -40,17 +40,70 @@
40
40
  # visible, or it repeats the sin it exists to catch.
41
41
  # canary optional mutation recipe (Phase 7) — see CANARY below
42
42
  #
43
- # COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-25)
43
+ # COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-28)
44
44
  # ----------------------------------------------------------
45
- # 291 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
45
+ # 306 `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 on the tree carrying these rows, with `check_skill_admissions`,
48
- # `check_command_examples`, `check_routing_coverage`, `description_route_check`
49
- # and `lint_skill_trigger_corpus` counted).
50
- # **63 of them emit the machine-readable `scanned: <N>` line under their
51
- # CI-identical argv, and 60 of those 63 are listed below.** The manifest is
52
- # therefore complete with respect to its own contract for every gate that can
53
- # carry a floor, and covers ~21 % of the population.
47
+ # re-run on the tree carrying these rows, which now include the four gates the
48
+ # two runtime-cost roadmaps add: check_prefix_stable_mutation,
49
+ # check_loss_class_declared, check_benchmark_report_fields, and
50
+ # check_no_currency_in_cost_surfaces).
51
+ # **78 of them emit the machine-readable `scanned: <N>` line under their
52
+ # CI-identical argv, and 75 of those 78 are listed below.** The manifest is
53
+ # complete for every gate that can carry a floor, covering ~25 % of the population.
54
+ #
55
+ # RECOUNTED ON A MERGE, 2026-08-30 — the fifth time, and the same shape as the
56
+ # 2026-08-26 blocks below: two sides each correct for their own tree (~24 % from
57
+ # the branch, ~25 % from main) meeting in one number. Recomputed rather than
58
+ # picked: `count_gate_scripts()` returns **306** and `grep -c '^ - id:'`
59
+ # returns **76** on the merged tree, so 76/306 = 24.8 % and main's side is the
60
+ # right one — arrived at by arithmetic, not by taking theirs.
61
+ #
62
+ # RECOUNTED ON A MERGE, 2026-08-26 — the fourth time this file has met the case
63
+ # the 2026-08-24 block below describes, and this one left TWO STACKED claim
64
+ # blocks rather than a conflict inside one number: 295/68 from this branch and
65
+ # 296/67 from main, each correct for its own tree. Collapsed to one recomputed
66
+ # block rather than reconciled by hand: `count_gate_scripts()` returns **296**
67
+ # and `grep -c '^ - id:'` returns **66** on the merged tree.
68
+ #
69
+ # 66 + 3 unlisted emitters (`lint_evidence_artifacts`, `adr_cite_check`,
70
+ # `check_new_adr_evidence`) = 69.
71
+ #
72
+ # RECOUNTED ON A MERGE, 2026-08-26, and the merge left TWO stacked header claims
73
+ # rather than a conflict inside one number — each branch had recounted correctly
74
+ # for its own tree, and keeping both sides produced a page asserting 294/62 and
75
+ # 295/64 four lines apart. Collapsed to one recomputed block: `count_gate_scripts()`
76
+ # returns **295** and `grep -c '^ - id:'` returns **64** on the merged tree.
77
+ #
78
+ # A paragraph that briefly stood here claimed the emitter total "cannot be
79
+ # derived by grep" and dropped it. That was true of the method it tried and
80
+ # wrong as a conclusion — every LISTED row is an emitter by construction (a row
81
+ # that did not emit could carry no floor) and the same three emitters remain
82
+ # deliberately unlisted, so 64 + 3 = 67. The figure is arithmetic over this
83
+ # file, not a grep over `src/scripts/`, and it is restored rather than left
84
+ # absent.
85
+ #
86
+ # RECOUNTED ON A MERGE, 2026-08-26 — the case the 2026-08-24 block below was
87
+ # written for, arriving again. Two branches each added one row and each recorded
88
+ # a correct population line for its own tree, so the merge put 293 and 294 side
89
+ # by side; after the merge both gates exist, so either figure describes a tree
90
+ # that no longer does. Recomputed on the merged tree rather than reconciled by
91
+ # hand: `count_gate_scripts()` returns **294** and `grep -c '^ - id:'` returns
92
+ # **63**.
93
+ #
94
+ # The emitter total moves with the listed count for the reason the 2026-08-25
95
+ # paragraph already states: every LISTED row is an emitter, because a row that
96
+ # did not emit could carry no floor, and the same three emitters remain
97
+ # deliberately unlisted (`lint_evidence_artifacts`, `adr_cite_check`,
98
+ # `check_new_adr_evidence`). 63 + 3 = 66.
99
+ #
100
+ # RECOUNTED on 2026-08-26 while adding `lint_canonical_terms`
101
+ # (road-to-canonical-terms 2.3). Recomputed, not adjusted — the two commands in
102
+ # the 2026-08-24 block below were re-run on this tree and returned 293 and 61.
103
+ # The population moved by TWO while one row was added, which is why the prose was
104
+ # not incremented by hand: a second gate script had arrived since the last count
105
+ # without a manifest row, and hand-arithmetic would have recorded 292 and been
106
+ # wrong in a way nobody could see.
54
107
  #
55
108
  # `description_route_check` is counted in the POPULATION and deliberately NOT
56
109
  # listed: it is diff-scoped, so its natural reading on most trees is zero cases,
@@ -306,10 +359,38 @@
306
359
  # in-place edit would need byte-exact restoration of a tracked file, and a canary
307
360
  # that can corrupt the tree violates the never-ships rule it inherits. The
308
361
  # consequence is a real gap — a gate whose only possible violation is a
309
- # modification of an existing tracked artefact (`check_condensation`, whose
362
+ # modification of an existing tracked artifact (`check_condensation`, whose
310
363
  # contract is `dist == rewrite(src)`; `check_ci_local_parity`, whose corpus is
311
364
  # workflow files) carries no recipe and is reported UNPROVEN, never green.
312
365
  gates:
366
+ - id: lint_metric_consumers
367
+ argv: ["--quiet"]
368
+ min_scanned: 5
369
+ corpus: "entries in src/config/metric-registry.yml (7 at the time of writing). The floor is 5, not 1: the registry's failure shape is a scan that reads a truncated or renamed file, and a single surviving entry would still pass a `> 0` check while the other six went unchecked."
370
+ status: enforced
371
+ no_canary_reason: >-
372
+ A create-only canary cannot express this gate's violation. The corpus is
373
+ the `metrics:` list inside ONE tracked file, so a planted file lands in no
374
+ row; every violation it can have is a MODIFICATION — a field emptied, a
375
+ field replaced with boilerplate, an id duplicated. Same class as
376
+ `check_no_automerge_key` and `lint_memory_twin_parity`. Discrimination is
377
+ proven instead by the gate's own `--self-test`: 7 cases, 6 rejecting,
378
+ each driving the real CLI against a throwaway registry.
379
+ note: >
380
+ road-to-experience-loop-broadening step 0.3. Refuses a metric that does
381
+ not name its consumer, the decision it feeds, and what fails without it.
382
+ The third field is the falsifiable one: the first two are answerable for a
383
+ metric nobody needs, and if the honest answer to "what fails without it"
384
+ is nothing, the entry cannot be written. HONEST LIMIT, stated in the
385
+ gate's own docstring: it checks SHAPE, not truth — it makes the omission
386
+ impossible, not the answer correct, because telling a real consumer from a
387
+ plausible sentence is a review judgement no parser has.
388
+ - id: lint_consolidation_lineage
389
+ argv: []
390
+ min_scanned: 0
391
+ corpus: "every agents/roadmaps/*.md, counted as FILES rather than as declarations. THE FLOOR WAS RETIRED ON 2026-08-30 AND REPLACED WITH AN ENUMERATION ASSERTION IN THE LINTER ITSELF (AI council, anthropic + openai, convergent on option b). It sat at 5 over a population under deliberate drawdown to ZERO, so it went red the day the drain succeeded — 6 active roadmaps to 4 in one afternoon — and the only available move was lowering the number again, a treadmill ending at a floor of 0, which is no floor. What guards the scope now is `lint_consolidation_lineage` refusing outright when a declared root is missing, is not a directory, or cannot be enumerated; that check lives in the PRODUCTION linter rather than here on purpose, because an independent existsSync in this gate would observe a directory without proving the linter enumerated it. Honest limit, named rather than implied: it catches a missing or renamed root, not a glob narrowed to match nothing, not enumeration in the wrong working directory, and not roadmaps moved into nested directories the walk no longer traverses. Today none of them carries a `consolidates:` field, so the finding count is legitimately zero while the scanned count is not — that split is the point: a declaration-count floor would be a zero-check wearing a ratchet's name, and would go green the moment the scan root moved. The floor sits at 5 rather than near the present 12 because the active estate is under deliberate drawdown (one-in-one-out plus an explicit drain), so a falling count is expected work rather than a collapse; below 5 the estate would be smaller than any point in its recorded history. NO CANARY, deliberately: the council decision that admitted this gate (2026-08-27, 2/2 convergent, E1=b/E2=report) fixed it in REPORT mode, so it exits 0 on findings by design and a planted violation could not turn it red. Its ability to go red is proven instead by `--self-test`, which the same decision required: six declaration spellings must parse identically, all four finding types must fire, and a complete folder must stay silent."
392
+ status: enforced
393
+ no_canary_reason: "A report-mode gate cannot be turned red by a planted file. The council decision that admitted this gate (2026-08-27, 2/2 convergent, E1=b/E2=report) fixed it in report mode deliberately: the four measured failures come from a high-noise drafting context and do not establish precision on the tracked estate, so blocking is earned by tracked-scope evidence rather than assumed. A canary here would either be planted and ignored (proving nothing) or force `--strict` into CI, which would decide E2 by wiring instead of by evidence. The negative control is `--self-test` instead, required by the same decision and stronger than a single planted file: six declaration spellings must parse to an identical parent set, all four finding types must fire, and a complete folder must stay silent — the third arm being what stops a checker that returned every code unconditionally from passing the second. Revisit together with E2: when the tracked half is promoted to blocking, it owes a canary."
313
394
  - id: lint_skill_trigger_corpus
314
395
  argv: []
315
396
  min_scanned: 70
@@ -406,7 +487,7 @@ gates:
406
487
  per-class red observation lives in the gate's own `--self-test` (9 cases,
407
488
  6 rejecting), which proves every class discriminates over a synthetic
408
489
  payload with no pack run. Two of the four cannot be planted through the
409
- register at all: `compiled-test-artefact` is excluded from the payload by
490
+ register at all: `compiled-test-artifact` is excluded from the payload by
410
491
  the `files[]` negations that fixed it, so a plant never ships and never
411
492
  reds, and `source-map` needs 121 files in a BUILT tree.
412
493
 
@@ -461,7 +542,7 @@ gates:
461
542
  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"
462
543
  status: enforced
463
544
  no_canary_reason: >-
464
- 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.
545
+ the violation is a MODIFICATION, not a creation: this gate reds when package.json `files[]` or `.npmignore` changes and the committed artifact 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.
465
546
 
466
547
  - id: check_pack_passport_reconciliation
467
548
  argv: []
@@ -821,7 +902,7 @@ gates:
821
902
  - id: check_no_roadmap_refs
822
903
  argv: []
823
904
  min_scanned: 700
824
- corpus: "stable artefacts across src/{rules,skills,agent-src/*} + docs/ + agents/settings/contexts (872 at baseline)"
905
+ corpus: "stable artifacts across src/{rules,skills,agent-src/*} + docs/ + agents/settings/contexts (872 at baseline)"
825
906
  status: enforced
826
907
  canary:
827
908
  class: stale-reference
@@ -829,7 +910,7 @@ gates:
829
910
  content: |
830
911
  ---
831
912
  type: auto
832
- description: "Planted canary rule linking a stable artefact into the transient roadmap tree."
913
+ description: "Planted canary rule linking a stable artifact into the transient roadmap tree."
833
914
  ---
834
915
 
835
916
  See [the plan](../../agents/roadmaps/road-to-nowhere.md) — the exact
@@ -837,7 +918,7 @@ gates:
837
918
  note: >
838
919
  Retargeted 2026-07-29 from the ADR-051-emptied tree. It had been enforcing the
839
920
  no-roadmap-references rule for docs/ only while the rule + skill layer went
840
- unscanned — 0 -> 872 artefacts. No violation had slipped through (verified),
921
+ unscanned — 0 -> 872 artifacts. No violation had slipped through (verified),
841
922
  so this closed a latent gap, not a live breach.
842
923
 
843
924
  - id: check_context_paths
@@ -921,7 +1002,7 @@ gates:
921
1002
  silent-green found in the same sweep — the per-pack lint matrix, whose path was
922
1003
  a double ADR-051 casualty and which exited 0 on an empty match across 17 CI
923
1004
  shards — is NOT listed here because it was deleted rather than repaired
924
- (skill_linter --all already covers all 429 artefacts in 0.5s).
1005
+ (skill_linter --all already covers all 429 artifacts in 0.5s).
925
1006
 
926
1007
 
927
1008
  # ── Registered 2026-08-02 (road-to-renewal-foundation Phase 1) ───────────
@@ -965,7 +1046,7 @@ gates:
965
1046
  corpus: "src/rules + src/skills + src/agent-src/commands + docs/guidelines .md (533 at baseline)"
966
1047
  status: enforced
967
1048
  no_canary_reason: >-
968
- thresholds are computed across the whole corpus; a single planted artefact has no population to exceed.
1049
+ thresholds are computed across the whole corpus; a single planted artifact has no population to exceed.
969
1050
  note: >
970
1051
  A collapse below the floor would mean the gate stopped reading the tree
971
1052
  that states extraction thresholds, so a bare or diverging threshold
@@ -1071,10 +1152,45 @@ gates:
1071
1152
  or if a drop to 0 is ever traced to a scanner defect rather than to an
1072
1153
  empty corpus.
1073
1154
 
1155
+ - id: check_gate_reachability
1156
+ script: src/scripts/check_gate_reachability.ts
1157
+ min_scanned: 10
1158
+ corpus: "exemption rows in src/config/gate-reachability-exemptions.json PLUS the gate-shaped task targets reachable from neither `task ci`'s transitive closure nor any workflow. Reachability is measured three ways, not two: a workflow may call `task <name>` OR the script directly, and conflating those overstated the hole 39 -> 22 on this tree."
1159
+ status: enforced
1160
+ no_canary_reason: "The negative control is the gate's own --self-test, run in CI: 4 cases, 2 rejecting, covering BOTH directions — an unreachable target with no row, and a row naming a target that is reachable. It builds throwaway task trees rather than touching this one, which is strictly better than a planted canary here: a canary would mean adding a real unreachable gate target to taskfiles/ and removing it again, and a forgotten one is the exact defect this gate exists to catch."
1161
+
1162
+ # road-to-retired-claims-stay-retired 2.3. The gate was NOT in this manifest
1163
+ # before that roadmap widened it: it asserted its scope with plain
1164
+ # `assertScanned` and published no machine-readable count, so
1165
+ # check_gate_coverage could not see it at all. Widening it to read the
1166
+ # publish-surface set is exactly the moment that becomes indefensible — a
1167
+ # gate that now decides what may ship on npm should not be the one gate
1168
+ # nobody counts.
1169
+ - id: check_claims
1170
+ argv: []
1171
+ min_scanned: 60
1172
+ corpus: "ledger entries in docs/CLAIMS.md (97 at registration: 59 backed, 30 unbacked, 8 closed). The gate's SECOND root, the five files in `PUBLISH_SURFACES`, is not summed into this count — ledger entries and files are different units and a sum of the two is a number nobody can re-derive. That root is guarded by `assertWatchlistResolves` inside the gate, which fires when every publish surface has vanished while a retired phrasing is still registered."
1173
+ status: enforced
1174
+ no_canary_reason: "The gate carries its own `--self-test` (5 cases, 3 rejecting) — so this row is an adopter, not an exemption; the reason field states why a PLANTED canary is additionally unavailable. Beyond the self-test the negative controls are the 30 mechanism tests in tests/scripts/check_claims.test.ts (17) and tests/scripts/check_claims_retired_phrasings.test.ts (13), each building a throwaway tree and running the real script in it. Twenty-one assert a REJECTION, and one publishes the LITERAL historical string (`zero runtime daemon`) that shipped in package.json and .github/about.yml while claim:no-runtime-daemon was already withdrawn. A planted canary here would mean committing a retired phrasing to a real publish surface and removing it again, and a forgotten one is precisely the defect this gate exists to catch."
1175
+
1176
+ - id: check_rule_evidence_declaration
1177
+ argv: []
1178
+ min_scanned: 10
1179
+ corpus: "the ten security / safety-floor rules named in the gate's own SCOPE constant. The floor equals the scope on purpose, unlike every other row here: the corpus is not discovered, it is DECLARED, so a count below it means a row was deleted rather than that the tree shrank. Widening the obligation means adding a row to SCOPE, which raises both numbers together."
1180
+ status: enforced
1181
+ no_canary_reason: "The gate carries its own `--self-test` (6 cases, 4 rejecting), each building a throwaway src/rules/ tree and running the real gate against it — a missing block, a valueless key, and BOTH directions of the conditional rule: an external-source block missing `normative_level` or `verified_on` must reject, and an `own-analysis` block carrying neither must ACCEPT. That pair is the load-bearing one, because a gate enforcing more than the schema would reject a rule the schema accepts. A planted canary cannot express any of them: the violation is a MODIFICATION of one of ten tracked rule files, and a newly created file lands outside the declared scope by construction. Same class as check_no_automerge_key and check_score_contract."
1182
+
1183
+ - id: check_concern_admissions
1184
+ script: src/scripts/check_concern_admissions.ts
1185
+ min_scanned: 0
1186
+ corpus: "agents/decisions/concern-admissions.jsonl rows PLUS the concerns added since the base ref (a SET DIFFERENCE over ids in src/scripts/hook_manifest.yaml, because a concern is a key inside one file rather than a file of its own). Ships at 0: the 55 pre-existing concerns are grandfathered by that forward-only scope, so the first row arrives with the first new concern, and a MALFORMED ledger is a separate hard error in readLedger() rather than an empty read."
1187
+ status: enforced
1188
+ no_canary_reason: "The negative control is the gate's own --self-test, which is stronger than a single planted canary and is run in CI: 6 cases, 3 of them rejecting, covering a concern added with no row, a row with a blank answer, and a rejected row naming a live concern — plus two ACCEPT cases that pin the grandfathering, so a gate that started failing everything would not pass either. A planted canary in the real ledger would additionally have to be removed again, and a forgotten one is a false rejection row in a decision record."
1189
+
1074
1190
  - id: check_estate_count
1075
1191
  argv: []
1076
1192
  min_scanned: 20
1077
- corpus: "active + parked roadmap files (81 at baseline: 38 active, 43 in later/)"
1193
+ corpus: "active + parked roadmap files (81 at baseline: 38 active, 43 in later/), plus src/scripts/hook_manifest.yaml for the concern axis — a single file read with `git show` at the base ref rather than a third materialised subtree"
1078
1194
  status: enforced
1079
1195
  canary:
1080
1196
  class: contract-violation
@@ -1099,17 +1215,45 @@ gates:
1099
1215
  cannot survive a collapse: at that point the gate's own `reportScanned`
1100
1216
  fires first. (Set to 50 in the first version, corrected on an R2 finding.)
1101
1217
 
1218
+ - id: check_static_parity
1219
+ argv: ["--quiet"]
1220
+ min_scanned: 20
1221
+ corpus: "test files that spell the dispatcher module name, discovered by grep over tests/ and src/. The count is deliberately not written here — it moves with the suite, and four different figures for it appeared across the rounds of this change (R2 round-5 finding 12). The floor is 20, not 1: this gate's silent-failure shape is a discovery COLLAPSE — a grep that stops matching would run two suites of one file each and report them identical, which is the 'gate that scans nothing exits green' case in its most convincing disguise."
1222
+ status: enforced
1223
+ no_canary_reason: >-
1224
+ No plantable violation: the gate's finding is a DIVERGENCE between two
1225
+ whole-suite runs, not a pattern in a file. Planting one would mean making
1226
+ the collector behave differently under the two runs, i.e. writing the bug
1227
+ it exists to detect.
1228
+ note: >
1229
+ road-to-supervised-telemetry-collector step 4.2 (AC-7). Runs the
1230
+ dispatcher-reaching suite twice — collector present-but-off, then aliased
1231
+ away entirely — and compares per-test verdicts rather than declaring each
1232
+ run green. Two green runs are not the assertion; a test that silently
1233
+ turns from `passed` to `skipped` keeps both suites green and only the
1234
+ per-test comparison sees it.
1235
+
1236
+ SELF-TEST EXEMPT, with the reason rather than the omission: a
1237
+ `--self-test` here would have to spawn two full vitest runs over a fixture
1238
+ repository, minutes per invocation, to prove a comparator that is already
1239
+ unit-tested with a REJECTING case —
1240
+ `tests/scripts/check_static_parity.test.ts` drives `compare()` through the
1241
+ `passed → skipped` divergence a length-only check would miss, plus both
1242
+ only-in-one-run directions. The discrimination is proven; what is skipped
1243
+ is proving it a second time through the slowest possible harness. The
1244
+ marker the self-test ratchet reads lives in the gate's own source, beside
1245
+ `main` — this note explains it; that line is what is counted.
1102
1246
  - id: check_completion_review
1103
1247
  argv: ["--advisory", "--base", "origin/main"]
1104
1248
  min_scanned: 1
1105
- corpus: "findings artefacts under agents/evidence/reviews/ + the current-diff evaluation (1 at baseline — the evaluation itself; artefact count grows with gated PRs)"
1249
+ corpus: "findings artifacts under agents/evidence/reviews/ + the current-diff evaluation (1 at baseline — the evaluation itself; artifact count grows with gated PRs)"
1106
1250
  status: enforced
1107
1251
  no_canary_reason: >-
1108
1252
  git-dependent: it evaluates the current diff against a base ref.
1109
1253
  note: >
1110
1254
  Gate R2 (docs/contracts/plan-review-gates.md § 2). HONEST LIMIT, stated
1111
1255
  because a floor that cannot fail is exactly the false green this file
1112
- exists to prevent: scanned = artefacts inspected + 1 for the diff
1256
+ exists to prevent: scanned = artifacts inspected + 1 for the diff
1113
1257
  evaluation, so on any run that REACHES the count `min_scanned: 1` cannot
1114
1258
  trip. It is not unreachable in principle — a moved reviews root exits
1115
1259
  before the inventory and reports `scanned: 0`, which the guard does read —
@@ -1141,7 +1285,7 @@ gates:
1141
1285
  deleted, so a drop to 7 means the reviews root moved or the naming
1142
1286
  convention drifted — not that the work went clean. That is precisely the
1143
1287
  case rule 3 exists for. The gate reads the FROZEN records because R2
1144
- selects only artefacts in the CURRENT review scope, so a superseded round
1288
+ selects only artifacts in the CURRENT review scope, so a superseded round
1145
1289
  renamed out of the `*.findings.md` glob is read by nothing at all — two
1146
1290
  findings sat recorded as `open` in this repo's own corpus for a day
1147
1291
  through exactly that gap.
@@ -1184,15 +1328,15 @@ gates:
1184
1328
  collision gate across four roots at once; one planted name collides with nothing.
1185
1329
  note: >
1186
1330
  Counts NAMES, not files — the scan-scope census counts files under the same
1187
- roots, so the two artefacts legitimately report different numbers here.
1331
+ roots, so the two artifacts legitimately report different numbers here.
1188
1332
 
1189
1333
  - id: lint_artefact_frontmatter
1190
1334
  argv: ["--quiet"]
1191
1335
  min_scanned: 540
1192
- corpus: "artefacts carrying frontmatter across the discovery roots (619 at baseline)"
1336
+ corpus: "artifacts carrying frontmatter across the discovery roots (619 at baseline)"
1193
1337
  status: enforced
1194
1338
  no_canary_reason: >-
1195
- a planted artefact is judged, but the gate reports adoption across the discovery roots, so the number rather than a red is the output.
1339
+ a planted artifact is judged, but the gate reports adoption across the discovery roots, so the number rather than a red is the output.
1196
1340
 
1197
1341
  - id: audit_skill_overlap
1198
1342
  argv: ["--quiet", "--print-table", "--strict"]
@@ -1410,7 +1554,7 @@ gates:
1410
1554
  note: >
1411
1555
  The plant needs a slug that already carries a `prompt_hash` but no committed
1412
1556
  package — a brand-new `zz-canary` slug is skipped, not caught, because an
1413
- artefact without a package is deliberately out of scope. `zcs-closure` is a
1557
+ artifact without a package is deliberately out of scope. `zcs-closure` is a
1414
1558
  closed round, so it will not gain a real package and the plant cannot
1415
1559
  collide with one. The two planted failures the roadmap asked for (a one-byte
1416
1560
  prompt edit, a pre-loaded verdict) are pinned in
@@ -1469,7 +1613,7 @@ gates:
1469
1613
  That case is the gate's own subject, so it is pinned by a test fixture
1470
1614
  too (`a table that parses to zero rows reds rather than exiting green`).
1471
1615
  No `canary:` recipe: this gate's only violation shape is a MODIFICATION of
1472
- a tracked artefact (`docs/MIGRATION.md`), and the canary contract is
1616
+ a tracked artifact (`docs/MIGRATION.md`), and the canary contract is
1473
1617
  create-only, so it reports UNPROVEN rather than green. Discrimination is
1474
1618
  proven instead by paired fixtures in
1475
1619
  `tests/scripts/lint_scheduled_deprecations.test.ts`, verified by mutation:
@@ -1600,7 +1744,7 @@ gates:
1600
1744
  # cmd_settings_check), forcing them into the ledger contract and reddening
1601
1745
  # the completeness ratchet for work nobody asked for;
1602
1746
  # - renaming the script to `check_adr_citations.ts` is the convention-conform
1603
- # answer and touches 26 files, including archived review artefacts and a
1747
+ # answer and touches 26 files, including archived review artifacts and a
1604
1748
  # committed diff.patch that must not be rewritten;
1605
1749
  # - manifest-driven classification is explicitly rejected by
1606
1750
  # gate_population.ts's own header (a new gate lands before anyone
@@ -1623,7 +1767,7 @@ gates:
1623
1767
  the gate correctly stays green. Measured on a previous attempt, where the
1624
1768
  gate was then mis-reported as dead. Same class as `check_condensation` and
1625
1769
  `check_ci_local_parity` — the only possible violation is a modification of
1626
- an existing tracked artefact. The red is proven instead by the committed
1770
+ an existing tracked artifact. The red is proven instead by the committed
1627
1771
  violating fixture `tests/fixtures/automerge-key/` plus two recorded
1628
1772
  sabotage probes in `tests/scripts/check_no_automerge_key.test.ts`.
1629
1773
  note: >
@@ -1632,7 +1776,7 @@ gates:
1632
1776
  lands OUTSIDE the corpus and the gate correctly stays green — measured on a
1633
1777
  previous attempt at this gate, where it was then mis-reported as dead. The
1634
1778
  only violation this gate can have is a modification of an existing tracked
1635
- artefact, which is the same class as `check_condensation` and
1779
+ artifact, which is the same class as `check_condensation` and
1636
1780
  `check_ci_local_parity`, and the CANARY section above already states that
1637
1781
  such a gate carries no recipe and is reported UNPROVEN rather than green.
1638
1782
 
@@ -1750,42 +1894,54 @@ gates:
1750
1894
  ADR whose dated record must not be rewritten, and a bare rule count with no
1751
1895
  enforcement sense ("2 rules" in a concepts page) which must not be a finding.
1752
1896
 
1897
+ - id: check_supervision_claim_atomicity
1898
+ argv: []
1899
+ min_scanned: 6
1900
+ corpus: "public surfaces a reader lands on — README.md plus seven docs/ pages (8 at baseline, 2026-08-27); the floor is 6 so a page being renamed does not silently shrink the scan to nothing"
1901
+ status: enforced
1902
+ no_canary_reason: >-
1903
+ A create-only canary cannot express this gate's violation. The corpus is a
1904
+ committed CONSTANT (`PUBLIC_SURFACES`), so a planted file lands in no row —
1905
+ the eight rows exist whatever the filesystem holds. The violation is a
1906
+ present-tense supervision claim appearing INSIDE one of those tracked
1907
+ pages, which is a modification. Same class as `check_score_contract`,
1908
+ `check_no_automerge_key` and `check_condensation`.
1909
+ Discrimination is proven instead by the gate's own `--self-test`, which is
1910
+ the step that created it: road-to-runtime-governance-flip 3.4 required
1911
+ seeded negatives to be OBSERVED red, not asserted. **7/7, 5 rejecting**,
1912
+ each building a throwaway git repo so the revision check is real and each
1913
+ driving the real CLI. The rejecting cases: no evidence at all; an emptied
1914
+ suite whose cases all skipped; a result recorded against a different
1915
+ revision; a suite that did not exercise real processes; and a non-integer
1916
+ case count. Two accepting controls: sufficient evidence lets the claim
1917
+ through, and a DENIAL of supervision needs no evidence at all.
1918
+ The refusals are separate because a suite that ran on a parent commit, one
1919
+ that skipped everything, and one that mocked the process layer are three
1920
+ different lies, and a file-presence check catches none of them.
1921
+ **Grown from 4/4 by a neutral council review of the code**, which found the
1922
+ docstring advertising a mocked-process negative the case list did not
1923
+ contain, and — worse — that the pattern matched `is NOT supervised`, so the
1924
+ gate would have refused a truthful denial. Both are closed with regression
1925
+ cases; the second is the `denial` accepting control above.
1753
1926
  - id: check_score_contract
1754
1927
  argv: ["--quiet"]
1755
1928
  min_scanned: 20
1756
1929
  corpus: "rows in `agents/evidence/ac-capability-scorecard.yaml` — one per rubric category recoverable from the tracked tree (23 at baseline, 2026-08-24)"
1757
1930
  status: enforced
1758
- canary:
1759
- class: contract-violation
1760
- path: agents/evidence/ac-capability-scorecard-zz-canary.yaml
1761
- content: |
1762
- # zz canary probe: a scorecard awarding `ten` with an empty required
1763
- # evidence class, which is the one thing this gate exists to refuse.
1764
- # Create-only, so it is expressible as a canary — unlike the MODIFICATION
1765
- # shapes (a redeclared `state: complete`, a count edited to match an
1766
- # added row) that most of this file's ratchets detect.
1767
- schema_version: 1
1768
- rubric:
1769
- state: incomplete
1770
- authority: unavailable-external-review
1771
- reported_category_count: 32
1772
- recovered_category_count: 1
1773
- missing_category_count: 31
1774
- manifest_version: baseline_v1
1775
- recovery_source: agents/roadmaps/road-to-ten-across-the-board.md
1776
- excluded_from_manifest: []
1777
- categories:
1778
- - category: release-integrity
1779
- baseline: 9.2
1780
- claim: "canary"
1781
- closing_path: "canary"
1782
- mechanism_evidence: ["src/scripts/check_score_contract.ts"]
1783
- adoption_evidence: ["src/scripts/check_score_contract.ts"]
1784
- negative_control_evidence: []
1785
- production_window: src/scripts/check_score_contract.ts
1786
- outcome_evidence: ["src/scripts/check_score_contract.ts"]
1787
- non_regression_evidence: ["src/scripts/check_score_contract.ts"]
1788
- status: ten
1931
+ no_canary_reason: >-
1932
+ Create-only canary cannot reach this corpus. Measured 2026-08-26: the row
1933
+ declared one, and `check_gate_coverage --canary` reported the gate DEAD —
1934
+ it stayed green over the plant. The gate is not dead; the recipe was
1935
+ unreachable. `check_score_contract` reads ONE file (`DEFAULT_REL`, or
1936
+ `--file`), so a newly created `ac-capability-scorecard-zz-canary.yaml`
1937
+ sits outside the corpus by construction and the gate correctly ignores it.
1938
+ Same class as `check_no_automerge_key` and `check_condensation`: the only
1939
+ violation this gate can have is a MODIFICATION of the one tracked
1940
+ scorecard, which a create-only canary cannot express. Discrimination is
1941
+ proven instead by the gate's own `--self-test` (8 cases, 6 of them
1942
+ pointing at the committed twins under `tests/fixtures/score-contract/twins/`)
1943
+ and by `tests/scripts/check_score_contract.test.ts`, which asserts each
1944
+ twin reds on exactly one finding CODE rather than merely on a non-zero exit.
1789
1945
  note: >
1790
1946
  The floor is 20 against a live corpus of 23, and the gap is deliberately
1791
1947
  narrow because this corpus does not grow by ordinary work: a row is added
@@ -1805,3 +1961,363 @@ gates:
1805
1961
  `tests/scripts/check_score_contract.test.ts` asserts each reds on exactly
1806
1962
  one finding CODE — not merely on a non-zero exit, which would let a twin
1807
1963
  keep passing while testing the wrong defect.
1964
+ - id: check_beta_review_markers
1965
+ argv: []
1966
+ min_scanned: 100
1967
+ corpus: "every `stability: beta` contract under docs/contracts/ — 121 at the time this row landed. The floor sits at 100 because the beta population shrinks as contracts promote to stable, so a slow decline is expected and a drop below 100 is a scan-root collapse rather than a promotion wave."
1968
+ status: enforced
1969
+ canary:
1970
+ class: contract-violation
1971
+ path: docs/contracts/zz-canary-beta-lapse.md
1972
+ content: |
1973
+ ---
1974
+ stability: beta
1975
+ keep-beta-until: 2026-01-01
1976
+ ---
1977
+
1978
+ # ZZ canary — a beta contract whose review deadline lapsed
1979
+
1980
+ Planted by `check_gate_coverage --canary`; never ships. The date is far
1981
+ in the past, so this is a FRESH lapse rather than one inside the frozen
1982
+ 2026-08-25 baseline — the distinction is the whole point of the gate,
1983
+ because an inherited lapse warns and a new one must fail.
1984
+ - id: lint_canonical_terms
1985
+ argv: []
1986
+ min_scanned: 1200
1987
+ corpus: "every markdown file under src/ and docs/, tracked and untracked. 1,577 exist in the shipped tree; the floor sits at 1,200 so a legitimate documentation prune cannot red it while a scan-root collapse still can. Untracked files are IN the corpus deliberately — the canary below is create-only by contract, so a tracked-only listing would leave the gate green on its own canary."
1988
+ status: enforced
1989
+ canary:
1990
+ class: contract-violation
1991
+ path: src/skills/zz-canary-canonical-terms/SKILL.md
1992
+ content: |
1993
+ ---
1994
+ name: zz-canary-canonical-terms
1995
+ description: Canary planted by check_gate_coverage --canary; never ships.
1996
+ ---
1997
+
1998
+ # Canary
1999
+
2000
+ This sentence describes the observed behaviour of an artifact, in prose,
2001
+ outside any fence — two non-canonical spellings the house dialect
2002
+ recorded in `src/config/canonical-terms.yml` decided against. The gate
2003
+ must red on it, because a ratchet that cannot see a NEW occurrence is a
2004
+ ratchet that only records history.
2005
+ - id: lint_host_portability
2006
+ argv: []
2007
+ min_scanned: 600
2008
+ corpus: "every .md under src/skills, src/agent-src, src/domains and src/subagents — 717 today. The floor sits at 600 because the artifact estate only grows by ordinary work and a reading below it means a scan root moved, not that 117 artifacts were deleted."
2009
+ status: enforced
2010
+ canary:
2011
+ class: contract-violation
2012
+ path: src/skills/zz-canary-host-portability/SKILL.md
2013
+ content: |
2014
+ ---
2015
+ name: zz-canary-host-portability
2016
+ description: Canary planted by check_gate_coverage --canary; never ships.
2017
+ execution:
2018
+ type: assisted
2019
+ handler: internal
2020
+ allowed_tools: ["FileWriterTool"]
2021
+ ---
2022
+
2023
+ # Canary
2024
+
2025
+ The grant above names a tool no host in this tree is known to honour. A
2026
+ loader IGNORES an unrecognised key, so this artifact reads as restricted
2027
+ and is not — which is the whole defect class the gate exists to refuse.
2028
+ - id: check_host_loadability
2029
+ argv: ["--reach", "--root", "."]
2030
+ min_scanned: 6
2031
+ corpus: "the six host surfaces in HOST_SURFACES (claude-code, cursor, cline, windsurf, gemini-cli, copilot). The floor is the full set rather than a fraction: the surface list is a committed constant, so a reading below 6 means a row was dropped from the constant, never that a projection is legitimately smaller. An ABSENT host tool is a ledger SKIP with its detection signal named, not a missing row."
2032
+ status: enforced
2033
+ no_canary_reason: "Create-only canary cannot reach this corpus, and the reason is structural rather than incidental. The corpus is a committed CONSTANT (HOST_SURFACES in _lib/host_projection_reach.ts), so a planted FILE lands in no row: the six rows exist whatever the filesystem holds. The violation this gate can have is an installed host tool whose projection directory is EMPTY \u2014 a state a create-only plant is the opposite of. Discrimination is proven instead by the measurement itself, which reports 6/6 present and projecting with per-host artifact counts (claude-code 13, cursor 228, cline 14, windsurf 215, gemini-cli 1, copilot 1); a dead projection reads as `empty-projection` and a missing tool as `skipped-tool-absent`, and those two verdicts being DIFFERENT is the whole point of the mode."
2034
+ argv_note: "The `--reach` argv, not the default. The default mode checks that two projections PARSE and emits no coverage line; reach accounts for every host surface and is the mode that carries a corpus. Registered on the argv that emits, per this manifest\u0027s own CI-identical-argv rule \u2014 and note that `--reach` is declared LOCAL-ONLY in ci-local-parity.yml, because a CI runner has no host tool installed and every row would resolve `skipped-tool-absent`, which is the empty-scope false green this manifest exists to refuse."
2035
+ - id: lint_eval_specs
2036
+ argv: []
2037
+ min_scanned: 120
2038
+ corpus: "every eval specification under src/skills/*/evals/, src/domains/*/evals/ and src/agent-src/commands/evals/ — 175 at the time this row landed. The floor sits at 120 because the corpus grows as skills gain evals and shrinks only when a skill is archived; a drop below 120 is a scan-root collapse rather than a pruning wave."
2039
+ status: enforced
2040
+ canary:
2041
+ class: contract-violation
2042
+ path: src/skills/zz-canary-eval-specs/evals/evals.json
2043
+ content: |
2044
+ {
2045
+ "skill": "zz-canary-eval-specs",
2046
+ "scenarios": [
2047
+ { "id": "x", "prompt": "planted by check_gate_coverage --canary; never ships", "assertions": [{ "kind": "tool-choice" }] }
2048
+ ]
2049
+ }
2050
+ - id: lint_memory_twin_parity
2051
+ argv: []
2052
+ min_scanned: 7
2053
+ corpus: "the twins declared in src/config/memory-twin-verdicts.yml — 7 today. The floor is the exact count rather than a lower bound: this list does not grow by ordinary work (a twin is added only when a script is duplicated into the template tree, which is a deliberate act), and a DROP means a verdict was deleted rather than earned. A new twin raises the floor in the same commit."
2054
+ status: enforced
2055
+ no_canary_reason: >-
2056
+ Create-only canary cannot reach this corpus. The gate's population is the
2057
+ `twins:` list inside one tracked config file, and every violation it can
2058
+ have is a MODIFICATION — a twin drifting, a verdict deleted, a ceiling
2059
+ exceeded. A newly created file lands outside the list by construction and
2060
+ the gate correctly ignores it. Same class as `check_no_automerge_key`,
2061
+ `check_condensation` and `check_ci_local_parity`. Discrimination is proven
2062
+ instead by the gate's own `--self-test`: 5 cases, 3 rejecting, including
2063
+ the two states the roadmap's verify clause names by hand — a one-line
2064
+ behavioural divergence must RED, and a comment-only divergence must stay
2065
+ GREEN.
2066
+ - id: lint_skill_link_reach
2067
+ argv: []
2068
+ min_scanned: 200
2069
+ corpus: "every skill directory under dist/agent-src/skills — the tree the installer deploys. 299 at the time this row landed, and the floor sits at 200 because the delivered set shrinks when a skill is archived and a scoped projection can legitimately deliver fewer, while a reading below 200 means the projection is broken rather than smaller."
2070
+ status: enforced
2071
+ canary:
2072
+ class: contract-violation
2073
+ path: dist/agent-src/skills/zz-canary-link-reach/SKILL.md
2074
+ content: |
2075
+ ---
2076
+ name: zz-canary-link-reach
2077
+ description: Canary planted by check_gate_coverage --canary; never ships.
2078
+ ---
2079
+
2080
+ # Canary
2081
+
2082
+ This body links to [a skill that is not delivered](../zz-canary-absent-target/SKILL.md).
2083
+ The gate must red on it: a consumer following that link gets a 404, and a
2084
+ link checker that reads only `src/` cannot see the difference between a
2085
+ missing file and a file that exists but did not ship.
2086
+ - id: lint_composition_review
2087
+ argv: []
2088
+ min_scanned: 380
2089
+ corpus: "the skill + rule corpus — every src/skills/*/SKILL.md and src/rules/*.md (419 at baseline: 299 skills + 120 rules)"
2090
+ status: enforced
2091
+ canary:
2092
+ class: contract-violation
2093
+ path: src/rules/__canary_composition_review__.md
2094
+ content: |
2095
+ ---
2096
+ name: __canary_composition_review__
2097
+ composition_review:
2098
+ - candidate: rule:this-rule-does-not-exist
2099
+ disposition: create_separate
2100
+ rationale: a canary record naming an incumbent that is not in the tree
2101
+ ---
2102
+
2103
+ # canary
2104
+ note: >
2105
+ road-to-composition-before-creation Phase 4.1. Two halves with different
2106
+ teeth, on purpose. The STRUCTURAL half is hard: a present record whose
2107
+ candidate resolves to nothing, whose `none`/`none_found` pair disagrees,
2108
+ whose disposition is off-enum, which repeats a candidate, which is empty,
2109
+ or which uses a YAML block scalar, exits 1. The PRESENCE half is advisory
2110
+ and exits 0: an artifact added without a record is reported by path and
2111
+ never blocks. Flipping that to a block needs a false-positive rate from at
2112
+ least one release of advisory operation, which the roadmap records as not
2113
+ yet measured and does not pre-authorise.
2114
+
2115
+ WHAT IT CERTIFIES, narrowed after an independent review (2 seats, both
2116
+ raising it): REFERENTIAL CONSISTENCY, never that a search happened. An
2117
+ author can name any existing artifact, write `create_separate` and a
2118
+ sixteen-character rationale, and pass. The earlier wording here said a
2119
+ record pointing at a non-existent incumbent "reads as evidence of a search
2120
+ that cannot have happened", which reads as a claim about the search — it is
2121
+ not one, and the module docstring makes the same narrowing. What the hard
2122
+ half buys is that a record cannot point at nothing; whether it points at
2123
+ the RIGHT thing is a reviewer's judgement, and the roadmap's own Risk 1 is
2124
+ that the field becomes a pro-forma line.
2125
+
2126
+ DISCRIMINATION is carried by `--self-test` (8 cases, 5 rejecting), not by
2127
+ the canary. The canary is one create-only recipe by design and exercises
2128
+ the unresolvable-candidate door only; the other five hard doors and the
2129
+ advisory path are covered by the self-test and by
2130
+ tests/scripts/lint_composition_review.test.ts, including a real-git
2131
+ fixture for the untracked-addition union.
2132
+
2133
+ COMPATIBILITY: this is a new HARD whole-corpus gate, so a pre-existing
2134
+ malformed record anywhere in the tree would fail every later PR. Measured
2135
+ at landing: 419 artifacts scanned, 0 records malformed, because zero
2136
+ artifacts carry the field at all — the hard half can only fire on a record
2137
+ that EXISTS, so a corpus with none cannot fail it. The first record written
2138
+ is the first thing that can.
2139
+
2140
+ `{{.QUIET_FLAG}}` in the taskfile against `argv: []` here: `--quiet`
2141
+ suppresses per-finding lines only. Verified — `scanned: 419` and the exit
2142
+ code are byte-identical with and without it, so the coverage measurement
2143
+ and the CI invocation cannot diverge.
2144
+
2145
+ The floor is 380 against a live 419 — room for real deletions, far above
2146
+ a collapse. The corpus is the whole estate rather than the diff precisely
2147
+ so the floor can be honest: `lint_evidence_artifacts` declines
2148
+ registration here because a diff-scoped gate legitimately scans 0, and
2149
+ this gate narrows to the diff only for the advisory half.
2150
+
2151
+ - id: check_prefix_stable_mutation
2152
+ argv: []
2153
+ min_scanned: 35
2154
+ corpus: "hook-manifest concerns bound on at least one mid-session slot, whose script exists (45 at baseline, across 45 mid-session concerns)"
2155
+ status: enforced
2156
+ canary:
2157
+ class: contract-violation
2158
+ path: src/scripts/__canary_prefix_stable__.ts
2159
+ content: |
2160
+ // A canary hook that writes a prefix-stable surface mid-session.
2161
+ // The gate reads the MANIFEST, so this file alone cannot trip it —
2162
+ // which is why DISCRIMINATION is carried by --self-test, not here.
2163
+ import * as fs from 'node:fs';
2164
+ fs.writeFileSync('dist/agent-src/rules/__canary__.md', 'x');
2165
+ note: >
2166
+ road-to-runtime-context-floors step 1.2 — the RUNTIME half of prefix
2167
+ stability. `check_kernel_prefix_stability` guards the kernel prefix at
2168
+ authoring time against a committed snapshot, and `_lib/payload_hash_drift`
2169
+ measures churn after the fact from an audit ledger; neither can see a hook
2170
+ rewriting a prefix-stable surface DURING a session, which invalidates the
2171
+ prompt cache for the rest of it.
2172
+
2173
+ THE SURFACE LIST IS LOADED, NOT RESTATED. Both this gate and
2174
+ `check_preamble_payload_budget` import `PREFIX_STABLE_SURFACES` from
2175
+ `_lib/prefix_stable_surfaces.ts`. That refactor is part of the same change:
2176
+ the budget gate previously stated its three roots twice inside its own
2177
+ file, and a third statement here would be the drift shape this repository
2178
+ already pays for elsewhere.
2179
+
2180
+ DISCRIMINATION is carried by `--self-test` (7 cases, 2 rejecting), NOT by
2181
+ the canary. The gate's corpus is the hook manifest, so a planted script
2182
+ that no manifest binds is invisible to it by construction — the canary
2183
+ above documents the violating SHAPE for a reader and is honestly not the
2184
+ discriminator. The self-test plants a manifest as well as a script, which
2185
+ is what actually proves the red path: a fixture concern on `post_tool_use`
2186
+ writing `dist/agent-src/rules/` fails, and the same concern with
2187
+ `re_arm: pre_compact` passes.
2188
+
2189
+ FAIL-CLOSED on an undecidable target, per the council that resolved
2190
+ `which-surfaces-are-prefix-stable` (2026-08-28, 2/2): a write whose target
2191
+ is computed at runtime, in a file that ALSO carries a literal resolving
2192
+ into a declared surface, fails. Narrow on purpose — a dynamic write in a
2193
+ file with no such literal is not reported, because a gate that flagged
2194
+ every dynamic write in every hook is one nobody can keep green.
2195
+
2196
+ The floor is 35 against a live 45: room for real concern deletions, far
2197
+ above a collapse. `{{.QUIET_FLAG}}` against `argv: []` is safe here —
2198
+ `--quiet` suppresses only the success line, and `scanned:` is emitted
2199
+ outside that guard.
2200
+
2201
+ - id: check_loss_class_declared
2202
+ argv: []
2203
+ min_scanned: 45
2204
+ corpus: "every hook-manifest concern whose script exists (53 at baseline); of those, the model-facing lossy subset is the gated population"
2205
+ status: enforced
2206
+ canary:
2207
+ class: contract-violation
2208
+ path: src/scripts/__canary_loss_class__.ts
2209
+ content: |
2210
+ // A model-facing lossy transform with no loss_class declaration.
2211
+ // As with the sibling gate, the manifest is the corpus, so the
2212
+ // discriminator is --self-test rather than this plant.
2213
+ const WORD_CAP = 400;
2214
+ export function run() {
2215
+ return { context: redactLines(body).slice(0, WORD_CAP).join('\n') };
2216
+ }
2217
+ note: >
2218
+ road-to-runtime-context-floors step 3.2. Strictness was decided, not
2219
+ assumed: council 2026-08-28 (2/2 convergent) resolved
2220
+ `how-strict-the-loss-class-lint-is` as option (b) — FAIL on transforms
2221
+ whose output reaches the model, WARN elsewhere. Option (a) (fail
2222
+ everywhere in `src/`) buys a first-run backlog whose usual answer is a
2223
+ broad allowlist, which this repository has measured emptying a gate;
2224
+ option (c) (warn everywhere, ratchet later) is the shape this repository
2225
+ has measurably never ratcheted. Both seats added the refinement adopted
2226
+ here: unknown reachability is classified as model-reaching.
2227
+
2228
+ MEASURED AT LANDING: **1** module qualifies — `hot_context_hook`, which is
2229
+ exactly the `ephemeral-lossy` exemplar `docs/contracts/loss-classes.md`
2230
+ classifies. A gated population of one is the honest state of this tree,
2231
+ not a broken detector, and it is why the floor below is set on the SCANNED
2232
+ corpus (53 hook scripts) rather than on the gated subset.
2233
+
2234
+ THE DETECTOR READS CODE, NOT PROSE. Its first cut matched `truncat` inside
2235
+ three docblocks that describe truncation without performing any and
2236
+ reported a corpus of four; three of those four were comments. Comments are
2237
+ stripped before matching, and one self-test case pins that direction
2238
+ ("prose about truncation is not truncation"), because a gate that fires on
2239
+ writing about a defect is how a real corpus of one becomes a pro-forma
2240
+ corpus of four.
2241
+
2242
+ DISCRIMINATION: `--self-test`, 8 cases, 3 rejecting — including the two
2243
+ that matter beyond "missing declaration": a `recoverable-lossy` with no
2244
+ `loss_recovery` locator (without it the class is indistinguishable from
2245
+ `ephemeral-lossy`) and a misspelled class name.
2246
+
2247
+ - id: check_benchmark_report_fields
2248
+ argv: []
2249
+ min_scanned: 4
2250
+ corpus: "committed benchmark reports under internal/bench/reports/ that announce a schema_version and a corpus/selection block (6 at baseline)"
2251
+ status: enforced
2252
+ canary:
2253
+ class: contract-violation
2254
+ path: internal/bench/reports/__canary_missing_cache__.json
2255
+ content: |
2256
+ {
2257
+ "schema_version": 1,
2258
+ "corpus": { "id": "__canary__" },
2259
+ "selection": { "top_k": 3 }
2260
+ }
2261
+ note: >
2262
+ road-to-runtime-context-floors step 4.1. `cache.read_write_ratio` and
2263
+ `cache.stable_prefix_share` are REQUIRED fields; a report that cannot
2264
+ compute one emits `{ unavailable: "<reason>" }` rather than omitting the
2265
+ key or emitting a zero. A blank reads as "no cache activity" and a zero
2266
+ reads as "the worst possible ratio" — both are claims, and neither is the
2267
+ claim "this was not measured".
2268
+
2269
+ The canary IS the discriminator here, unlike its two siblings: this gate's
2270
+ corpus is a directory of files, so a planted report is genuinely in scope
2271
+ and a create-only plant exercises the real red path. `--self-test` adds 7
2272
+ cases (5 rejecting) covering the forms a plant cannot reach — a blank
2273
+ `unavailable` reason, and a share above 1.
2274
+
2275
+ COMPATIBILITY: six committed reports predate the requirement, and all six
2276
+ were backfilled in the landing change with a stated reason rather than a
2277
+ fabricated number — additively, 48 insertions and 0 deletions, so no
2278
+ historical measurement moved.
2279
+
2280
+ The floor is 4 against a live 6. `allowEmpty` is declared
2281
+ (`OPTIONAL_INPUT:`) because benchmark reports are run artefacts rather
2282
+ than source and a checkout may legitimately carry none; the floor applies
2283
+ whenever any are present.
2284
+
2285
+ - id: check_no_currency_in_cost_surfaces
2286
+ argv: []
2287
+ min_scanned: 4
2288
+ corpus: "the four cost surfaces road-to-delivered-cost-truth built (4 at baseline) — a named watchlist, not a tree walk"
2289
+ status: enforced
2290
+ canary:
2291
+ class: contract-violation
2292
+ path: src/scripts/__canary_currency__.ts
2293
+ content: |
2294
+ // A planted file is NOT in this gate's corpus by construction — the
2295
+ // watchlist is four named files. Discrimination is --self-test's job.
2296
+ out.push(`total: $42`);
2297
+ note: >
2298
+ road-to-delivered-cost-truth AC-7. The suite does not know a consumer's
2299
+ contract — subscription, per-token, committed spend, a reseller rate — so
2300
+ any monetary figure it printed would be extrapolated from a rate it
2301
+ invented. That is worse than no number, because it is actionable and wrong,
2302
+ and it is exactly the thing someone reasonably adds back later on the
2303
+ grounds that a cost report should show cost.
2304
+
2305
+ SCOPE IS A NAMED LIST, NOT A PATTERN, and that is the load-bearing choice.
2306
+ `cache_realization_report` legitimately carries a `cost_usd` block for
2307
+ back-compat with downstream consumers; a gate sweeping `src/scripts/*cost*`
2308
+ would fail on it and be neutered with an allowlist inside a release. The
2309
+ watchlist is asserted by `assertWatchlistResolves`, so a renamed surface is
2310
+ a dead scope (exit 2) rather than a silent pass.
2311
+
2312
+ THE DETECTOR TOOK TWO CORRECTIONS, BOTH FROM ITS OWN SELF-TEST, and both
2313
+ are pinned as accepting cases so a future widening cannot reintroduce them:
2314
+ a bare `$` substring matches TEMPLATE INTERPOLATION (`${value}`), and
2315
+ excluding `${` alone still matched a REGEX END ANCHOR (`/\.md$/`). The
2316
+ shipped pattern is positive rather than subtractive — a currency `$` is
2317
+ followed by a digit or by an interpolated amount — because a gate whose
2318
+ first real run produces dozens of false positives gets an allowlist within
2319
+ a release and then guards nothing.
2320
+
2321
+ DISCRIMINATION: `--self-test`, 9 cases, 4 rejecting. The canary above
2322
+ documents the violating shape for a reader and is honestly NOT the
2323
+ discriminator, because a created file lands outside a four-name watchlist.