@event4u/agent-config 14.12.0 → 14.14.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 (521) 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 +118 -155
  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 +145 -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-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. 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,79 @@
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 2026-08-31, on the change that adds `lint_promotion_paths` — and the
56
+ # 2026-08-30 block above was already stale when this row landed, in BOTH numbers
57
+ # rather than only in the one this change moves. Recomputed on this tree:
58
+ # `count_gate_scripts()` returns **310** and `grep -c '^ - id:'` returns **81**
59
+ # (80 before this row), so 81/310 = 26.1 %. The script count rose without any
60
+ # recount, which is the drift the blocks below keep describing; it is recorded
61
+ # here rather than folded into the 2026-08-30 prose, because that block is a
62
+ # measurement of a tree that no longer exists.
63
+ #
64
+ # RECOUNTED ON A MERGE, 2026-08-30 — the fifth time, and the same shape as the
65
+ # 2026-08-26 blocks below: two sides each correct for their own tree (~24 % from
66
+ # the branch, ~25 % from main) meeting in one number. Recomputed rather than
67
+ # picked: `count_gate_scripts()` returns **306** and `grep -c '^ - id:'`
68
+ # returns **76** on the merged tree, so 76/306 = 24.8 % and main's side is the
69
+ # right one — arrived at by arithmetic, not by taking theirs.
70
+ #
71
+ # RECOUNTED ON A MERGE, 2026-08-26 — the fourth time this file has met the case
72
+ # the 2026-08-24 block below describes, and this one left TWO STACKED claim
73
+ # blocks rather than a conflict inside one number: 295/68 from this branch and
74
+ # 296/67 from main, each correct for its own tree. Collapsed to one recomputed
75
+ # block rather than reconciled by hand: `count_gate_scripts()` returns **296**
76
+ # and `grep -c '^ - id:'` returns **66** on the merged tree.
77
+ #
78
+ # 66 + 3 unlisted emitters (`lint_evidence_artifacts`, `adr_cite_check`,
79
+ # `check_new_adr_evidence`) = 69.
80
+ #
81
+ # RECOUNTED ON A MERGE, 2026-08-26, and the merge left TWO stacked header claims
82
+ # rather than a conflict inside one number — each branch had recounted correctly
83
+ # for its own tree, and keeping both sides produced a page asserting 294/62 and
84
+ # 295/64 four lines apart. Collapsed to one recomputed block: `count_gate_scripts()`
85
+ # returns **295** and `grep -c '^ - id:'` returns **64** on the merged tree.
86
+ #
87
+ # A paragraph that briefly stood here claimed the emitter total "cannot be
88
+ # derived by grep" and dropped it. That was true of the method it tried and
89
+ # wrong as a conclusion — every LISTED row is an emitter by construction (a row
90
+ # that did not emit could carry no floor) and the same three emitters remain
91
+ # deliberately unlisted, so 64 + 3 = 67. The figure is arithmetic over this
92
+ # file, not a grep over `src/scripts/`, and it is restored rather than left
93
+ # absent.
94
+ #
95
+ # RECOUNTED ON A MERGE, 2026-08-26 — the case the 2026-08-24 block below was
96
+ # written for, arriving again. Two branches each added one row and each recorded
97
+ # a correct population line for its own tree, so the merge put 293 and 294 side
98
+ # by side; after the merge both gates exist, so either figure describes a tree
99
+ # that no longer does. Recomputed on the merged tree rather than reconciled by
100
+ # hand: `count_gate_scripts()` returns **294** and `grep -c '^ - id:'` returns
101
+ # **63**.
102
+ #
103
+ # The emitter total moves with the listed count for the reason the 2026-08-25
104
+ # paragraph already states: every LISTED row is an emitter, because a row that
105
+ # did not emit could carry no floor, and the same three emitters remain
106
+ # deliberately unlisted (`lint_evidence_artifacts`, `adr_cite_check`,
107
+ # `check_new_adr_evidence`). 63 + 3 = 66.
108
+ #
109
+ # RECOUNTED on 2026-08-26 while adding `lint_canonical_terms`
110
+ # (road-to-canonical-terms 2.3). Recomputed, not adjusted — the two commands in
111
+ # the 2026-08-24 block below were re-run on this tree and returned 293 and 61.
112
+ # The population moved by TWO while one row was added, which is why the prose was
113
+ # not incremented by hand: a second gate script had arrived since the last count
114
+ # without a manifest row, and hand-arithmetic would have recorded 292 and been
115
+ # wrong in a way nobody could see.
54
116
  #
55
117
  # `description_route_check` is counted in the POPULATION and deliberately NOT
56
118
  # listed: it is diff-scoped, so its natural reading on most trees is zero cases,
@@ -306,10 +368,56 @@
306
368
  # in-place edit would need byte-exact restoration of a tracked file, and a canary
307
369
  # that can corrupt the tree violates the never-ships rule it inherits. The
308
370
  # consequence is a real gap — a gate whose only possible violation is a
309
- # modification of an existing tracked artefact (`check_condensation`, whose
371
+ # modification of an existing tracked artifact (`check_condensation`, whose
310
372
  # contract is `dist == rewrite(src)`; `check_ci_local_parity`, whose corpus is
311
373
  # workflow files) carries no recipe and is reported UNPROVEN, never green.
312
374
  gates:
375
+ - id: lint_metric_consumers
376
+ argv: ["--quiet"]
377
+ min_scanned: 5
378
+ 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."
379
+ status: enforced
380
+ no_canary_reason: >-
381
+ A create-only canary cannot express this gate's violation. The corpus is
382
+ the `metrics:` list inside ONE tracked file, so a planted file lands in no
383
+ row; every violation it can have is a MODIFICATION — a field emptied, a
384
+ field replaced with boilerplate, an id duplicated. Same class as
385
+ `check_no_automerge_key` and `lint_memory_twin_parity`. Discrimination is
386
+ proven instead by the gate's own `--self-test`: 7 cases, 6 rejecting,
387
+ each driving the real CLI against a throwaway registry.
388
+ note: >
389
+ road-to-experience-loop-broadening step 0.3. Refuses a metric that does
390
+ not name its consumer, the decision it feeds, and what fails without it.
391
+ The third field is the falsifiable one: the first two are answerable for a
392
+ metric nobody needs, and if the honest answer to "what fails without it"
393
+ is nothing, the entry cannot be written. HONEST LIMIT, stated in the
394
+ gate's own docstring: it checks SHAPE, not truth — it makes the omission
395
+ impossible, not the answer correct, because telling a real consumer from a
396
+ plausible sentence is a review judgement no parser has.
397
+ - id: lint_consolidation_lineage
398
+ argv: []
399
+ min_scanned: 0
400
+ 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."
401
+ status: enforced
402
+ 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."
403
+ - id: lint_carrier_integrity
404
+ argv: []
405
+ min_scanned: 600
406
+ corpus: "every roadmap file under agents/roadmaps/archive/ and agents/roadmaps/skipped/ — 656 at the time of writing, and the count only rises because archival is one-way. The floor sits at 600 rather than near 656 because a reading below it means the walk lost a directory, not that roadmaps were un-archived. The walk direction is the design: a `[~]` carry is validated once, when the parent is archived, by a sweep that then never looks at the pair again, so the receiver can be deleted afterwards with nothing going red. Starting from the archived parent — which names its destination by slug and which nothing rewrites — makes whole-file deletion detectable on the first pass, with no registry to maintain. TWO CLASSES, and the split decides the tier: `broken-destination` (deleted, renamed, re-parented, skipped, or archived with open steps) is a HARD failure at zero with no baseline, because every member had a recorded home and lost it; `unannotated` (a bare `[~]` with no annotation at all) is ratcheted at 243 in gate-violation-baselines.json, all of it predating the annotation contract by up to three months."
407
+ status: enforced
408
+ canary:
409
+ class: contract-violation
410
+ path: agents/roadmaps/archive/zz-canary-carrier-integrity.md
411
+ content: |
412
+ ---
413
+ complexity: bounded
414
+ ---
415
+ # Canary planted by check_gate_coverage --canary; never ships.
416
+
417
+ ## Phase 1 — a phase
418
+
419
+ - [~] **1.1 A step carried to a receiver that does not exist.**
420
+ <!-- deferred-resolution: carried-to=road-to-zz-canary-receiver-that-does-not-exist -->
313
421
  - id: lint_skill_trigger_corpus
314
422
  argv: []
315
423
  min_scanned: 70
@@ -406,7 +514,7 @@ gates:
406
514
  per-class red observation lives in the gate's own `--self-test` (9 cases,
407
515
  6 rejecting), which proves every class discriminates over a synthetic
408
516
  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
517
+ register at all: `compiled-test-artifact` is excluded from the payload by
410
518
  the `files[]` negations that fixed it, so a plant never ships and never
411
519
  reds, and `source-map` needs 121 files in a BUILT tree.
412
520
 
@@ -461,7 +569,7 @@ gates:
461
569
  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
570
  status: enforced
463
571
  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.
572
+ 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
573
 
466
574
  - id: check_pack_passport_reconciliation
467
575
  argv: []
@@ -821,7 +929,7 @@ gates:
821
929
  - id: check_no_roadmap_refs
822
930
  argv: []
823
931
  min_scanned: 700
824
- corpus: "stable artefacts across src/{rules,skills,agent-src/*} + docs/ + agents/settings/contexts (872 at baseline)"
932
+ corpus: "stable artifacts across src/{rules,skills,agent-src/*} + docs/ + agents/settings/contexts (872 at baseline)"
825
933
  status: enforced
826
934
  canary:
827
935
  class: stale-reference
@@ -829,7 +937,7 @@ gates:
829
937
  content: |
830
938
  ---
831
939
  type: auto
832
- description: "Planted canary rule linking a stable artefact into the transient roadmap tree."
940
+ description: "Planted canary rule linking a stable artifact into the transient roadmap tree."
833
941
  ---
834
942
 
835
943
  See [the plan](../../agents/roadmaps/road-to-nowhere.md) — the exact
@@ -837,7 +945,7 @@ gates:
837
945
  note: >
838
946
  Retargeted 2026-07-29 from the ADR-051-emptied tree. It had been enforcing the
839
947
  no-roadmap-references rule for docs/ only while the rule + skill layer went
840
- unscanned — 0 -> 872 artefacts. No violation had slipped through (verified),
948
+ unscanned — 0 -> 872 artifacts. No violation had slipped through (verified),
841
949
  so this closed a latent gap, not a live breach.
842
950
 
843
951
  - id: check_context_paths
@@ -921,7 +1029,7 @@ gates:
921
1029
  silent-green found in the same sweep — the per-pack lint matrix, whose path was
922
1030
  a double ADR-051 casualty and which exited 0 on an empty match across 17 CI
923
1031
  shards — is NOT listed here because it was deleted rather than repaired
924
- (skill_linter --all already covers all 429 artefacts in 0.5s).
1032
+ (skill_linter --all already covers all 429 artifacts in 0.5s).
925
1033
 
926
1034
 
927
1035
  # ── Registered 2026-08-02 (road-to-renewal-foundation Phase 1) ───────────
@@ -965,7 +1073,7 @@ gates:
965
1073
  corpus: "src/rules + src/skills + src/agent-src/commands + docs/guidelines .md (533 at baseline)"
966
1074
  status: enforced
967
1075
  no_canary_reason: >-
968
- thresholds are computed across the whole corpus; a single planted artefact has no population to exceed.
1076
+ thresholds are computed across the whole corpus; a single planted artifact has no population to exceed.
969
1077
  note: >
970
1078
  A collapse below the floor would mean the gate stopped reading the tree
971
1079
  that states extraction thresholds, so a bare or diverging threshold
@@ -1071,10 +1179,45 @@ gates:
1071
1179
  or if a drop to 0 is ever traced to a scanner defect rather than to an
1072
1180
  empty corpus.
1073
1181
 
1182
+ - id: check_gate_reachability
1183
+ script: src/scripts/check_gate_reachability.ts
1184
+ min_scanned: 10
1185
+ 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."
1186
+ status: enforced
1187
+ 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."
1188
+
1189
+ # road-to-retired-claims-stay-retired 2.3. The gate was NOT in this manifest
1190
+ # before that roadmap widened it: it asserted its scope with plain
1191
+ # `assertScanned` and published no machine-readable count, so
1192
+ # check_gate_coverage could not see it at all. Widening it to read the
1193
+ # publish-surface set is exactly the moment that becomes indefensible — a
1194
+ # gate that now decides what may ship on npm should not be the one gate
1195
+ # nobody counts.
1196
+ - id: check_claims
1197
+ argv: []
1198
+ min_scanned: 60
1199
+ 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."
1200
+ status: enforced
1201
+ 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."
1202
+
1203
+ - id: check_rule_evidence_declaration
1204
+ argv: []
1205
+ min_scanned: 10
1206
+ 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."
1207
+ status: enforced
1208
+ 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."
1209
+
1210
+ - id: check_concern_admissions
1211
+ script: src/scripts/check_concern_admissions.ts
1212
+ min_scanned: 0
1213
+ 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."
1214
+ status: enforced
1215
+ 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."
1216
+
1074
1217
  - id: check_estate_count
1075
1218
  argv: []
1076
1219
  min_scanned: 20
1077
- corpus: "active + parked roadmap files (81 at baseline: 38 active, 43 in later/)"
1220
+ 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
1221
  status: enforced
1079
1222
  canary:
1080
1223
  class: contract-violation
@@ -1099,17 +1242,45 @@ gates:
1099
1242
  cannot survive a collapse: at that point the gate's own `reportScanned`
1100
1243
  fires first. (Set to 50 in the first version, corrected on an R2 finding.)
1101
1244
 
1245
+ - id: check_static_parity
1246
+ argv: ["--quiet"]
1247
+ min_scanned: 20
1248
+ 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."
1249
+ status: enforced
1250
+ no_canary_reason: >-
1251
+ No plantable violation: the gate's finding is a DIVERGENCE between two
1252
+ whole-suite runs, not a pattern in a file. Planting one would mean making
1253
+ the collector behave differently under the two runs, i.e. writing the bug
1254
+ it exists to detect.
1255
+ note: >
1256
+ road-to-supervised-telemetry-collector step 4.2 (AC-7). Runs the
1257
+ dispatcher-reaching suite twice — collector present-but-off, then aliased
1258
+ away entirely — and compares per-test verdicts rather than declaring each
1259
+ run green. Two green runs are not the assertion; a test that silently
1260
+ turns from `passed` to `skipped` keeps both suites green and only the
1261
+ per-test comparison sees it.
1262
+
1263
+ SELF-TEST EXEMPT, with the reason rather than the omission: a
1264
+ `--self-test` here would have to spawn two full vitest runs over a fixture
1265
+ repository, minutes per invocation, to prove a comparator that is already
1266
+ unit-tested with a REJECTING case —
1267
+ `tests/scripts/check_static_parity.test.ts` drives `compare()` through the
1268
+ `passed → skipped` divergence a length-only check would miss, plus both
1269
+ only-in-one-run directions. The discrimination is proven; what is skipped
1270
+ is proving it a second time through the slowest possible harness. The
1271
+ marker the self-test ratchet reads lives in the gate's own source, beside
1272
+ `main` — this note explains it; that line is what is counted.
1102
1273
  - id: check_completion_review
1103
1274
  argv: ["--advisory", "--base", "origin/main"]
1104
1275
  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)"
1276
+ corpus: "findings artifacts under agents/evidence/reviews/ + the current-diff evaluation (1 at baseline — the evaluation itself; artifact count grows with gated PRs)"
1106
1277
  status: enforced
1107
1278
  no_canary_reason: >-
1108
1279
  git-dependent: it evaluates the current diff against a base ref.
1109
1280
  note: >
1110
1281
  Gate R2 (docs/contracts/plan-review-gates.md § 2). HONEST LIMIT, stated
1111
1282
  because a floor that cannot fail is exactly the false green this file
1112
- exists to prevent: scanned = artefacts inspected + 1 for the diff
1283
+ exists to prevent: scanned = artifacts inspected + 1 for the diff
1113
1284
  evaluation, so on any run that REACHES the count `min_scanned: 1` cannot
1114
1285
  trip. It is not unreachable in principle — a moved reviews root exits
1115
1286
  before the inventory and reports `scanned: 0`, which the guard does read —
@@ -1141,7 +1312,7 @@ gates:
1141
1312
  deleted, so a drop to 7 means the reviews root moved or the naming
1142
1313
  convention drifted — not that the work went clean. That is precisely the
1143
1314
  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
1315
+ selects only artifacts in the CURRENT review scope, so a superseded round
1145
1316
  renamed out of the `*.findings.md` glob is read by nothing at all — two
1146
1317
  findings sat recorded as `open` in this repo's own corpus for a day
1147
1318
  through exactly that gap.
@@ -1184,15 +1355,15 @@ gates:
1184
1355
  collision gate across four roots at once; one planted name collides with nothing.
1185
1356
  note: >
1186
1357
  Counts NAMES, not files — the scan-scope census counts files under the same
1187
- roots, so the two artefacts legitimately report different numbers here.
1358
+ roots, so the two artifacts legitimately report different numbers here.
1188
1359
 
1189
1360
  - id: lint_artefact_frontmatter
1190
1361
  argv: ["--quiet"]
1191
1362
  min_scanned: 540
1192
- corpus: "artefacts carrying frontmatter across the discovery roots (619 at baseline)"
1363
+ corpus: "artifacts carrying frontmatter across the discovery roots (619 at baseline)"
1193
1364
  status: enforced
1194
1365
  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.
1366
+ 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
1367
 
1197
1368
  - id: audit_skill_overlap
1198
1369
  argv: ["--quiet", "--print-table", "--strict"]
@@ -1410,7 +1581,7 @@ gates:
1410
1581
  note: >
1411
1582
  The plant needs a slug that already carries a `prompt_hash` but no committed
1412
1583
  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
1584
+ artifact without a package is deliberately out of scope. `zcs-closure` is a
1414
1585
  closed round, so it will not gain a real package and the plant cannot
1415
1586
  collide with one. The two planted failures the roadmap asked for (a one-byte
1416
1587
  prompt edit, a pre-loaded verdict) are pinned in
@@ -1469,7 +1640,7 @@ gates:
1469
1640
  That case is the gate's own subject, so it is pinned by a test fixture
1470
1641
  too (`a table that parses to zero rows reds rather than exiting green`).
1471
1642
  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
1643
+ a tracked artifact (`docs/MIGRATION.md`), and the canary contract is
1473
1644
  create-only, so it reports UNPROVEN rather than green. Discrimination is
1474
1645
  proven instead by paired fixtures in
1475
1646
  `tests/scripts/lint_scheduled_deprecations.test.ts`, verified by mutation:
@@ -1600,7 +1771,7 @@ gates:
1600
1771
  # cmd_settings_check), forcing them into the ledger contract and reddening
1601
1772
  # the completeness ratchet for work nobody asked for;
1602
1773
  # - renaming the script to `check_adr_citations.ts` is the convention-conform
1603
- # answer and touches 26 files, including archived review artefacts and a
1774
+ # answer and touches 26 files, including archived review artifacts and a
1604
1775
  # committed diff.patch that must not be rewritten;
1605
1776
  # - manifest-driven classification is explicitly rejected by
1606
1777
  # gate_population.ts's own header (a new gate lands before anyone
@@ -1623,7 +1794,7 @@ gates:
1623
1794
  the gate correctly stays green. Measured on a previous attempt, where the
1624
1795
  gate was then mis-reported as dead. Same class as `check_condensation` and
1625
1796
  `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
1797
+ an existing tracked artifact. The red is proven instead by the committed
1627
1798
  violating fixture `tests/fixtures/automerge-key/` plus two recorded
1628
1799
  sabotage probes in `tests/scripts/check_no_automerge_key.test.ts`.
1629
1800
  note: >
@@ -1632,7 +1803,7 @@ gates:
1632
1803
  lands OUTSIDE the corpus and the gate correctly stays green — measured on a
1633
1804
  previous attempt at this gate, where it was then mis-reported as dead. The
1634
1805
  only violation this gate can have is a modification of an existing tracked
1635
- artefact, which is the same class as `check_condensation` and
1806
+ artifact, which is the same class as `check_condensation` and
1636
1807
  `check_ci_local_parity`, and the CANARY section above already states that
1637
1808
  such a gate carries no recipe and is reported UNPROVEN rather than green.
1638
1809
 
@@ -1750,42 +1921,54 @@ gates:
1750
1921
  ADR whose dated record must not be rewritten, and a bare rule count with no
1751
1922
  enforcement sense ("2 rules" in a concepts page) which must not be a finding.
1752
1923
 
1924
+ - id: check_supervision_claim_atomicity
1925
+ argv: []
1926
+ min_scanned: 6
1927
+ 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"
1928
+ status: enforced
1929
+ no_canary_reason: >-
1930
+ A create-only canary cannot express this gate's violation. The corpus is a
1931
+ committed CONSTANT (`PUBLIC_SURFACES`), so a planted file lands in no row —
1932
+ the eight rows exist whatever the filesystem holds. The violation is a
1933
+ present-tense supervision claim appearing INSIDE one of those tracked
1934
+ pages, which is a modification. Same class as `check_score_contract`,
1935
+ `check_no_automerge_key` and `check_condensation`.
1936
+ Discrimination is proven instead by the gate's own `--self-test`, which is
1937
+ the step that created it: road-to-runtime-governance-flip 3.4 required
1938
+ seeded negatives to be OBSERVED red, not asserted. **7/7, 5 rejecting**,
1939
+ each building a throwaway git repo so the revision check is real and each
1940
+ driving the real CLI. The rejecting cases: no evidence at all; an emptied
1941
+ suite whose cases all skipped; a result recorded against a different
1942
+ revision; a suite that did not exercise real processes; and a non-integer
1943
+ case count. Two accepting controls: sufficient evidence lets the claim
1944
+ through, and a DENIAL of supervision needs no evidence at all.
1945
+ The refusals are separate because a suite that ran on a parent commit, one
1946
+ that skipped everything, and one that mocked the process layer are three
1947
+ different lies, and a file-presence check catches none of them.
1948
+ **Grown from 4/4 by a neutral council review of the code**, which found the
1949
+ docstring advertising a mocked-process negative the case list did not
1950
+ contain, and — worse — that the pattern matched `is NOT supervised`, so the
1951
+ gate would have refused a truthful denial. Both are closed with regression
1952
+ cases; the second is the `denial` accepting control above.
1753
1953
  - id: check_score_contract
1754
1954
  argv: ["--quiet"]
1755
1955
  min_scanned: 20
1756
1956
  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
1957
  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
1958
+ no_canary_reason: >-
1959
+ Create-only canary cannot reach this corpus. Measured 2026-08-26: the row
1960
+ declared one, and `check_gate_coverage --canary` reported the gate DEAD —
1961
+ it stayed green over the plant. The gate is not dead; the recipe was
1962
+ unreachable. `check_score_contract` reads ONE file (`DEFAULT_REL`, or
1963
+ `--file`), so a newly created `ac-capability-scorecard-zz-canary.yaml`
1964
+ sits outside the corpus by construction and the gate correctly ignores it.
1965
+ Same class as `check_no_automerge_key` and `check_condensation`: the only
1966
+ violation this gate can have is a MODIFICATION of the one tracked
1967
+ scorecard, which a create-only canary cannot express. Discrimination is
1968
+ proven instead by the gate's own `--self-test` (8 cases, 6 of them
1969
+ pointing at the committed twins under `tests/fixtures/score-contract/twins/`)
1970
+ and by `tests/scripts/check_score_contract.test.ts`, which asserts each
1971
+ twin reds on exactly one finding CODE rather than merely on a non-zero exit.
1789
1972
  note: >
1790
1973
  The floor is 20 against a live corpus of 23, and the gap is deliberately
1791
1974
  narrow because this corpus does not grow by ordinary work: a row is added
@@ -1805,3 +1988,486 @@ gates:
1805
1988
  `tests/scripts/check_score_contract.test.ts` asserts each reds on exactly
1806
1989
  one finding CODE — not merely on a non-zero exit, which would let a twin
1807
1990
  keep passing while testing the wrong defect.
1991
+ - id: check_beta_review_markers
1992
+ argv: []
1993
+ min_scanned: 100
1994
+ 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."
1995
+ status: enforced
1996
+ canary:
1997
+ class: contract-violation
1998
+ path: docs/contracts/zz-canary-beta-lapse.md
1999
+ content: |
2000
+ ---
2001
+ stability: beta
2002
+ keep-beta-until: 2026-01-01
2003
+ ---
2004
+
2005
+ # ZZ canary — a beta contract whose review deadline lapsed
2006
+
2007
+ Planted by `check_gate_coverage --canary`; never ships. The date is far
2008
+ in the past, so this is a FRESH lapse rather than one inside the frozen
2009
+ 2026-08-25 baseline — the distinction is the whole point of the gate,
2010
+ because an inherited lapse warns and a new one must fail.
2011
+ - id: lint_canonical_terms
2012
+ argv: []
2013
+ min_scanned: 1200
2014
+ 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."
2015
+ status: enforced
2016
+ canary:
2017
+ class: contract-violation
2018
+ path: src/skills/zz-canary-canonical-terms/SKILL.md
2019
+ content: |
2020
+ ---
2021
+ name: zz-canary-canonical-terms
2022
+ description: Canary planted by check_gate_coverage --canary; never ships.
2023
+ ---
2024
+
2025
+ # Canary
2026
+
2027
+ This sentence describes the observed behaviour of an artifact, in prose,
2028
+ outside any fence — two non-canonical spellings the house dialect
2029
+ recorded in `src/config/canonical-terms.yml` decided against. The gate
2030
+ must red on it, because a ratchet that cannot see a NEW occurrence is a
2031
+ ratchet that only records history.
2032
+ - id: lint_host_portability
2033
+ argv: []
2034
+ min_scanned: 600
2035
+ 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."
2036
+ status: enforced
2037
+ canary:
2038
+ class: contract-violation
2039
+ path: src/skills/zz-canary-host-portability/SKILL.md
2040
+ content: |
2041
+ ---
2042
+ name: zz-canary-host-portability
2043
+ description: Canary planted by check_gate_coverage --canary; never ships.
2044
+ execution:
2045
+ type: assisted
2046
+ handler: internal
2047
+ allowed_tools: ["FileWriterTool"]
2048
+ ---
2049
+
2050
+ # Canary
2051
+
2052
+ The grant above names a tool no host in this tree is known to honour. A
2053
+ loader IGNORES an unrecognised key, so this artifact reads as restricted
2054
+ and is not — which is the whole defect class the gate exists to refuse.
2055
+ - id: check_host_loadability
2056
+ argv: ["--reach", "--root", "."]
2057
+ min_scanned: 6
2058
+ 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."
2059
+ status: enforced
2060
+ 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."
2061
+ 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."
2062
+ - id: lint_eval_specs
2063
+ argv: []
2064
+ min_scanned: 120
2065
+ 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."
2066
+ status: enforced
2067
+ canary:
2068
+ class: contract-violation
2069
+ path: src/skills/zz-canary-eval-specs/evals/evals.json
2070
+ content: |
2071
+ {
2072
+ "skill": "zz-canary-eval-specs",
2073
+ "scenarios": [
2074
+ { "id": "x", "prompt": "planted by check_gate_coverage --canary; never ships", "assertions": [{ "kind": "tool-choice" }] }
2075
+ ]
2076
+ }
2077
+ - id: lint_memory_twin_parity
2078
+ argv: []
2079
+ min_scanned: 7
2080
+ 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."
2081
+ status: enforced
2082
+ no_canary_reason: >-
2083
+ Create-only canary cannot reach this corpus. The gate's population is the
2084
+ `twins:` list inside one tracked config file, and every violation it can
2085
+ have is a MODIFICATION — a twin drifting, a verdict deleted, a ceiling
2086
+ exceeded. A newly created file lands outside the list by construction and
2087
+ the gate correctly ignores it. Same class as `check_no_automerge_key`,
2088
+ `check_condensation` and `check_ci_local_parity`. Discrimination is proven
2089
+ instead by the gate's own `--self-test`: 5 cases, 3 rejecting, including
2090
+ the two states the roadmap's verify clause names by hand — a one-line
2091
+ behavioural divergence must RED, and a comment-only divergence must stay
2092
+ GREEN.
2093
+ - id: lint_skill_link_reach
2094
+ argv: []
2095
+ min_scanned: 200
2096
+ 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."
2097
+ status: enforced
2098
+ canary:
2099
+ class: contract-violation
2100
+ path: dist/agent-src/skills/zz-canary-link-reach/SKILL.md
2101
+ content: |
2102
+ ---
2103
+ name: zz-canary-link-reach
2104
+ description: Canary planted by check_gate_coverage --canary; never ships.
2105
+ ---
2106
+
2107
+ # Canary
2108
+
2109
+ This body links to [a skill that is not delivered](../zz-canary-absent-target/SKILL.md).
2110
+ The gate must red on it: a consumer following that link gets a 404, and a
2111
+ link checker that reads only `src/` cannot see the difference between a
2112
+ missing file and a file that exists but did not ship.
2113
+ - id: lint_composition_review
2114
+ argv: []
2115
+ min_scanned: 380
2116
+ corpus: "the skill + rule corpus — every src/skills/*/SKILL.md and src/rules/*.md (419 at baseline: 299 skills + 120 rules)"
2117
+ status: enforced
2118
+ canary:
2119
+ class: contract-violation
2120
+ path: src/rules/__canary_composition_review__.md
2121
+ content: |
2122
+ ---
2123
+ name: __canary_composition_review__
2124
+ composition_review:
2125
+ - candidate: rule:this-rule-does-not-exist
2126
+ disposition: create_separate
2127
+ rationale: a canary record naming an incumbent that is not in the tree
2128
+ ---
2129
+
2130
+ # canary
2131
+ note: >
2132
+ road-to-composition-before-creation Phase 4.1. Two halves with different
2133
+ teeth, on purpose. The STRUCTURAL half is hard: a present record whose
2134
+ candidate resolves to nothing, whose `none`/`none_found` pair disagrees,
2135
+ whose disposition is off-enum, which repeats a candidate, which is empty,
2136
+ or which uses a YAML block scalar, exits 1. The PRESENCE half is advisory
2137
+ and exits 0: an artifact added without a record is reported by path and
2138
+ never blocks. Flipping that to a block needs a false-positive rate from at
2139
+ least one release of advisory operation, which the roadmap records as not
2140
+ yet measured and does not pre-authorise.
2141
+
2142
+ WHAT IT CERTIFIES, narrowed after an independent review (2 seats, both
2143
+ raising it): REFERENTIAL CONSISTENCY, never that a search happened. An
2144
+ author can name any existing artifact, write `create_separate` and a
2145
+ sixteen-character rationale, and pass. The earlier wording here said a
2146
+ record pointing at a non-existent incumbent "reads as evidence of a search
2147
+ that cannot have happened", which reads as a claim about the search — it is
2148
+ not one, and the module docstring makes the same narrowing. What the hard
2149
+ half buys is that a record cannot point at nothing; whether it points at
2150
+ the RIGHT thing is a reviewer's judgement, and the roadmap's own Risk 1 is
2151
+ that the field becomes a pro-forma line.
2152
+
2153
+ DISCRIMINATION is carried by `--self-test` (8 cases, 5 rejecting), not by
2154
+ the canary. The canary is one create-only recipe by design and exercises
2155
+ the unresolvable-candidate door only; the other five hard doors and the
2156
+ advisory path are covered by the self-test and by
2157
+ tests/scripts/lint_composition_review.test.ts, including a real-git
2158
+ fixture for the untracked-addition union.
2159
+
2160
+ COMPATIBILITY: this is a new HARD whole-corpus gate, so a pre-existing
2161
+ malformed record anywhere in the tree would fail every later PR. Measured
2162
+ at landing: 419 artifacts scanned, 0 records malformed, because zero
2163
+ artifacts carry the field at all — the hard half can only fire on a record
2164
+ that EXISTS, so a corpus with none cannot fail it. The first record written
2165
+ is the first thing that can.
2166
+
2167
+ `{{.QUIET_FLAG}}` in the taskfile against `argv: []` here: `--quiet`
2168
+ suppresses per-finding lines only. Verified — `scanned: 419` and the exit
2169
+ code are byte-identical with and without it, so the coverage measurement
2170
+ and the CI invocation cannot diverge.
2171
+
2172
+ The floor is 380 against a live 419 — room for real deletions, far above
2173
+ a collapse. The corpus is the whole estate rather than the diff precisely
2174
+ so the floor can be honest: `lint_evidence_artifacts` declines
2175
+ registration here because a diff-scoped gate legitimately scans 0, and
2176
+ this gate narrows to the diff only for the advisory half.
2177
+
2178
+ - id: check_prefix_stable_mutation
2179
+ argv: []
2180
+ min_scanned: 35
2181
+ corpus: "hook-manifest concerns bound on at least one mid-session slot, whose script exists (45 at baseline, across 45 mid-session concerns)"
2182
+ status: enforced
2183
+ canary:
2184
+ class: contract-violation
2185
+ path: src/scripts/__canary_prefix_stable__.ts
2186
+ content: |
2187
+ // A canary hook that writes a prefix-stable surface mid-session.
2188
+ // The gate reads the MANIFEST, so this file alone cannot trip it —
2189
+ // which is why DISCRIMINATION is carried by --self-test, not here.
2190
+ import * as fs from 'node:fs';
2191
+ fs.writeFileSync('dist/agent-src/rules/__canary__.md', 'x');
2192
+ note: >
2193
+ road-to-runtime-context-floors step 1.2 — the RUNTIME half of prefix
2194
+ stability. `check_kernel_prefix_stability` guards the kernel prefix at
2195
+ authoring time against a committed snapshot, and `_lib/payload_hash_drift`
2196
+ measures churn after the fact from an audit ledger; neither can see a hook
2197
+ rewriting a prefix-stable surface DURING a session, which invalidates the
2198
+ prompt cache for the rest of it.
2199
+
2200
+ THE SURFACE LIST IS LOADED, NOT RESTATED. Both this gate and
2201
+ `check_preamble_payload_budget` import `PREFIX_STABLE_SURFACES` from
2202
+ `_lib/prefix_stable_surfaces.ts`. That refactor is part of the same change:
2203
+ the budget gate previously stated its three roots twice inside its own
2204
+ file, and a third statement here would be the drift shape this repository
2205
+ already pays for elsewhere.
2206
+
2207
+ DISCRIMINATION is carried by `--self-test` (7 cases, 2 rejecting), NOT by
2208
+ the canary. The gate's corpus is the hook manifest, so a planted script
2209
+ that no manifest binds is invisible to it by construction — the canary
2210
+ above documents the violating SHAPE for a reader and is honestly not the
2211
+ discriminator. The self-test plants a manifest as well as a script, which
2212
+ is what actually proves the red path: a fixture concern on `post_tool_use`
2213
+ writing `dist/agent-src/rules/` fails, and the same concern with
2214
+ `re_arm: pre_compact` passes.
2215
+
2216
+ FAIL-CLOSED on an undecidable target, per the council that resolved
2217
+ `which-surfaces-are-prefix-stable` (2026-08-28, 2/2): a write whose target
2218
+ is computed at runtime, in a file that ALSO carries a literal resolving
2219
+ into a declared surface, fails. Narrow on purpose — a dynamic write in a
2220
+ file with no such literal is not reported, because a gate that flagged
2221
+ every dynamic write in every hook is one nobody can keep green.
2222
+
2223
+ The floor is 35 against a live 45: room for real concern deletions, far
2224
+ above a collapse. `{{.QUIET_FLAG}}` against `argv: []` is safe here —
2225
+ `--quiet` suppresses only the success line, and `scanned:` is emitted
2226
+ outside that guard.
2227
+
2228
+ - id: check_loss_class_declared
2229
+ argv: []
2230
+ min_scanned: 45
2231
+ corpus: "every hook-manifest concern whose script exists (53 at baseline); of those, the model-facing lossy subset is the gated population"
2232
+ status: enforced
2233
+ canary:
2234
+ class: contract-violation
2235
+ path: src/scripts/__canary_loss_class__.ts
2236
+ content: |
2237
+ // A model-facing lossy transform with no loss_class declaration.
2238
+ // As with the sibling gate, the manifest is the corpus, so the
2239
+ // discriminator is --self-test rather than this plant.
2240
+ const WORD_CAP = 400;
2241
+ export function run() {
2242
+ return { context: redactLines(body).slice(0, WORD_CAP).join('\n') };
2243
+ }
2244
+ note: >
2245
+ road-to-runtime-context-floors step 3.2. Strictness was decided, not
2246
+ assumed: council 2026-08-28 (2/2 convergent) resolved
2247
+ `how-strict-the-loss-class-lint-is` as option (b) — FAIL on transforms
2248
+ whose output reaches the model, WARN elsewhere. Option (a) (fail
2249
+ everywhere in `src/`) buys a first-run backlog whose usual answer is a
2250
+ broad allowlist, which this repository has measured emptying a gate;
2251
+ option (c) (warn everywhere, ratchet later) is the shape this repository
2252
+ has measurably never ratcheted. Both seats added the refinement adopted
2253
+ here: unknown reachability is classified as model-reaching.
2254
+
2255
+ MEASURED AT LANDING: **1** module qualifies — `hot_context_hook`, which is
2256
+ exactly the `ephemeral-lossy` exemplar `docs/contracts/loss-classes.md`
2257
+ classifies. A gated population of one is the honest state of this tree,
2258
+ not a broken detector, and it is why the floor below is set on the SCANNED
2259
+ corpus (53 hook scripts) rather than on the gated subset.
2260
+
2261
+ THE DETECTOR READS CODE, NOT PROSE. Its first cut matched `truncat` inside
2262
+ three docblocks that describe truncation without performing any and
2263
+ reported a corpus of four; three of those four were comments. Comments are
2264
+ stripped before matching, and one self-test case pins that direction
2265
+ ("prose about truncation is not truncation"), because a gate that fires on
2266
+ writing about a defect is how a real corpus of one becomes a pro-forma
2267
+ corpus of four.
2268
+
2269
+ DISCRIMINATION: `--self-test`, 8 cases, 3 rejecting — including the two
2270
+ that matter beyond "missing declaration": a `recoverable-lossy` with no
2271
+ `loss_recovery` locator (without it the class is indistinguishable from
2272
+ `ephemeral-lossy`) and a misspelled class name.
2273
+
2274
+ - id: check_benchmark_report_fields
2275
+ argv: []
2276
+ min_scanned: 4
2277
+ corpus: "committed benchmark reports under internal/bench/reports/ that announce a schema_version and a corpus/selection block (6 at baseline)"
2278
+ status: enforced
2279
+ canary:
2280
+ class: contract-violation
2281
+ path: internal/bench/reports/__canary_missing_cache__.json
2282
+ content: |
2283
+ {
2284
+ "schema_version": 1,
2285
+ "corpus": { "id": "__canary__" },
2286
+ "selection": { "top_k": 3 }
2287
+ }
2288
+ note: >
2289
+ road-to-runtime-context-floors step 4.1. `cache.read_write_ratio` and
2290
+ `cache.stable_prefix_share` are REQUIRED fields; a report that cannot
2291
+ compute one emits `{ unavailable: "<reason>" }` rather than omitting the
2292
+ key or emitting a zero. A blank reads as "no cache activity" and a zero
2293
+ reads as "the worst possible ratio" — both are claims, and neither is the
2294
+ claim "this was not measured".
2295
+
2296
+ The canary IS the discriminator here, unlike its two siblings: this gate's
2297
+ corpus is a directory of files, so a planted report is genuinely in scope
2298
+ and a create-only plant exercises the real red path. `--self-test` adds 7
2299
+ cases (5 rejecting) covering the forms a plant cannot reach — a blank
2300
+ `unavailable` reason, and a share above 1.
2301
+
2302
+ COMPATIBILITY: six committed reports predate the requirement, and all six
2303
+ were backfilled in the landing change with a stated reason rather than a
2304
+ fabricated number — additively, 48 insertions and 0 deletions, so no
2305
+ historical measurement moved.
2306
+
2307
+ The floor is 4 against a live 6. `allowEmpty` is declared
2308
+ (`OPTIONAL_INPUT:`) because benchmark reports are run artefacts rather
2309
+ than source and a checkout may legitimately carry none; the floor applies
2310
+ whenever any are present.
2311
+
2312
+ - id: check_no_currency_in_cost_surfaces
2313
+ argv: []
2314
+ min_scanned: 4
2315
+ corpus: "the four cost surfaces road-to-delivered-cost-truth built (4 at baseline) — a named watchlist, not a tree walk"
2316
+ status: enforced
2317
+ canary:
2318
+ class: contract-violation
2319
+ path: src/scripts/__canary_currency__.ts
2320
+ content: |
2321
+ // A planted file is NOT in this gate's corpus by construction — the
2322
+ // watchlist is four named files. Discrimination is --self-test's job.
2323
+ out.push(`total: $42`);
2324
+ note: >
2325
+ road-to-delivered-cost-truth AC-7. The suite does not know a consumer's
2326
+ contract — subscription, per-token, committed spend, a reseller rate — so
2327
+ any monetary figure it printed would be extrapolated from a rate it
2328
+ invented. That is worse than no number, because it is actionable and wrong,
2329
+ and it is exactly the thing someone reasonably adds back later on the
2330
+ grounds that a cost report should show cost.
2331
+
2332
+ SCOPE IS A NAMED LIST, NOT A PATTERN, and that is the load-bearing choice.
2333
+ `cache_realization_report` legitimately carries a `cost_usd` block for
2334
+ back-compat with downstream consumers; a gate sweeping `src/scripts/*cost*`
2335
+ would fail on it and be neutered with an allowlist inside a release. The
2336
+ watchlist is asserted by `assertWatchlistResolves`, so a renamed surface is
2337
+ a dead scope (exit 2) rather than a silent pass.
2338
+
2339
+ THE DETECTOR TOOK TWO CORRECTIONS, BOTH FROM ITS OWN SELF-TEST, and both
2340
+ are pinned as accepting cases so a future widening cannot reintroduce them:
2341
+ a bare `$` substring matches TEMPLATE INTERPOLATION (`${value}`), and
2342
+ excluding `${` alone still matched a REGEX END ANCHOR (`/\.md$/`). The
2343
+ shipped pattern is positive rather than subtractive — a currency `$` is
2344
+ followed by a digit or by an interpolated amount — because a gate whose
2345
+ first real run produces dozens of false positives gets an allowlist within
2346
+ a release and then guards nothing.
2347
+
2348
+ DISCRIMINATION: `--self-test`, 9 cases, 4 rejecting. The canary above
2349
+ documents the violating shape for a reader and is honestly NOT the
2350
+ discriminator, because a created file lands outside a four-name watchlist.
2351
+
2352
+ - id: lint_promotion_paths
2353
+ argv: ["--quiet"]
2354
+ min_scanned: 1800
2355
+ corpus: "every .ts file under src/ and tests/ (2812 at baseline). The floor is 1800, not 1: this gate's failure shape is a walk that stops at a renamed root or a skip-list that grows, and a partial walk certifies exactly the coverage it did not perform."
2356
+ status: enforced
2357
+ canary:
2358
+ class: contract-violation
2359
+ path: src/scripts/__canary_promotion_bypass__.ts
2360
+ content: |
2361
+ import { parseCandidateRecord } from './_lib/candidate_record.js';
2362
+ const promoted = { ...parseCandidateRecord, lifecycle: 'promoted' };
2363
+ fs.writeFileSync(path.join(REPO_ROOT, 'src', 'rules', 'x.md'), promoted);
2364
+ note: >
2365
+ road-to-harness-promotion-bridge — discharge route 1 of the carried
2366
+ blocking condition. The condition covers "a verb, a state transition into
2367
+ `promoted`, or any write into `src/` derived from a candidate", and the AI
2368
+ council of 2026-08-31 ruled it NOT DISCHARGED because only the first two
2369
+ were gated. This gate inventories all three limbs across the whole
2370
+ authored tree and fails when a promotion-capable write bypasses the single
2371
+ guarded capability in `src/scripts/_lib/promotion_capability.ts`.
2372
+
2373
+ THE CAPABILITY IS UNOBTAINABLE WHILE `blocker: merge-authority` IS OPEN,
2374
+ and R0 proves that by CALLING it rather than by reading it — a text match
2375
+ would pass over a refusal edited into a no-op. Sensitivity of R0 was
2376
+ observed: neutralising the refusal makes the gate red with
2377
+ "capability obtainable while the blocker is open".
2378
+
2379
+ ANTI-VACUITY IS THE POINT, not a bonus. The condition's own text says a
2380
+ check over a population of zero discharges nothing, so three floors are
2381
+ asserted separately — 400 files, 4 candidate-derived modules, 10
2382
+ filesystem-write sites inside them — each via `assertScanned`, each exiting
2383
+ 2 rather than green. Live values at baseline: 2812 / 16 / 66.
2384
+
2385
+ THE CANARY IS A GENUINE DISCRIMINATOR here: the corpus is a tree walk, so
2386
+ a planted file is in scope and a create-only plant exercises the real red
2387
+ path on all three limbs at once. `--self-test` adds 15 cases (9 rejecting)
2388
+ covering the forms a single plant cannot reach — the interface-declaration
2389
+ accepting pole, a two-argument `assertTransition`, a candidate-derived
2390
+ write into a CLONE's `src/` (out of scope: a clone is a candidate's own
2391
+ sandbox, already gated by `bench_ab_integrity`'s allowed-delta-path check),
2392
+ a candidate-derived READ of `src/`, and prose in a block comment.
2393
+
2394
+ TWO DEFECTS WERE FOUND BY RUNNING IT, both pinned as cases: a substitution
2395
+ that rewrote identifiers INSIDE string literals (`cand` in `'ac-cand-'`),
2396
+ and an expansion that DESTROYED the `REPO_ROOT` token the rule keys on
2397
+ because `REPO_ROOT` is itself a `const`. The first produced a false
2398
+ positive on a tmpdir removal; the second silently dropped the R3 half of a
2399
+ planted three-limb bypass, which is the failure direction that matters.
2400
+
2401
+ - id: lint_code_comments
2402
+ argv: ["--base", "origin/main"]
2403
+ min_scanned: 0
2404
+ corpus: >
2405
+ the source files a change touches, measured against the base ref — a DIFF,
2406
+ not a tree walk. The floor is 0 deliberately: a docs-only or config-only
2407
+ change legitimately carries no source file, and a floor above 0 would red
2408
+ exactly those commits. The scan-scope failure this class exists to catch
2409
+ cannot occur here, because there is no committed path list that can go
2410
+ stale — the root is `git diff`, and git answers for its own range.
2411
+ status: enforced
2412
+ canary:
2413
+ class: contract-violation
2414
+ path: src/scripts/__canary_comment_discipline__.ts
2415
+ content: |
2416
+ // Hier stehen nur die Werte, die Bedeutung tragen und nicht mehr.
2417
+ export const canary = 1;
2418
+ note: >
2419
+ The carrier `code-comment-discipline` never had, and the one the "Code
2420
+ comments English" clause of `language-and-tone` claimed via a `.md`-only
2421
+ validator (`check_md_language.ts:175` rejects every other path).
2422
+
2423
+ THE CANARY IS A GENUINE DISCRIMINATOR: the corpus is a diff, a newly
2424
+ created file is in it by construction, and the planted content trips the
2425
+ `de-comment` class on two function words with no umlaut — the
2426
+ transliterated form the real incident was written in, not the easy case.
2427
+
2428
+ DISCRIMINATION IS ALSO PINNED BY FIXTURE, in both directions, because a
2429
+ language heuristic is only usable if its near-misses are known:
2430
+ `tests/scripts/lint_code_comments.test.ts` asserts silence on an umlauted
2431
+ proper name, a non-ASCII sample value inside a code span, a `Ü2` step
2432
+ label, and a German user quotation spanning two comment lines — the four
2433
+ shapes this repository's own hooks actually contain. Measured over 402
2434
+ source files here: zero findings. Measured over the 45 changed files of
2435
+ the consumer repository that prompted the gate: 530.
2436
+
2437
+ SENSITIVITY WAS OBSERVED, not assumed: neutralising the German predicate
2438
+ turns 4 of the 20 table cases red and restoring it turns them green. (The
2439
+ earlier wording said "4 of the 22" and described the inline vitest corpus
2440
+ that the fixture-table refactor replaced; a completion review caught the
2441
+ stale denominator.)
2442
+
2443
+ THE GATE ALSO CARRIES ITS OWN `--self-test` (20 cases, 11 rejecting),
2444
+ which drives the real binary rather than the imported classifier — argv
2445
+ parsing, scan-scope assertion and exit codes included. It does NOT reach a
2446
+ consumer checkout, and the earlier claim that it did was withdrawn after a
2447
+ completion review: `runGateCli` spawns `<repoRoot>/node_modules/.bin/tsx`
2448
+ and both `tsx` and `vitest` are devDependencies, `dist/scripts/` carries no
2449
+ compiled twin, and `scripts-run` is not in `files[]` — so where the suite
2450
+ is absent the self-test cannot run either, and where it runs the suite is
2451
+ present. What it buys is real and narrower: it exercises the CLI half that
2452
+ the vitest file cannot reach, and CI runs the gate only in diff mode,
2453
+ which exits 0 on an empty diff. It is ONE table, not a second corpus: the cases
2454
+ live in `COMMENT_CASES`, exported by the gate, and the vitest file
2455
+ enumerates the same export against `scanText` while the self-test
2456
+ enumerates it against the CLI. A second table over one classifier would
2457
+ drift, and the copy nobody runs locally drifts first. Floors are set at
2458
+ 16/8 against a real 20/11, so deleting a case to reach green fails and a
2459
+ deliberate shrink shows up as a floor edit in the diff. Sensitivity
2460
+ re-observed on the self-test the same way: neutralising the German
2461
+ predicate turns exactly 4 of the 11 rejecting cases red (the three
2462
+ German-comment shapes and the reasonless escape) while the report and
2463
+ provenance cases stay green, and restoring it returns 20/20. The block-comment
2464
+ continuation and JSX cases arrived with the two blind spots fixed on
2465
+ `origin/main` and were folded into the same table on merge, so both surfaces
2466
+ cover them rather than the vitest file alone.
2467
+
2468
+ NOTE ON THE ADOPTION RATCHET, stated because the number does not move:
2469
+ `gate-self-test:registered-non-adopters` counts manifest rows that are
2470
+ `enforced` AND carry `min_scanned >= 1`. This row's floor is 0 for the
2471
+ reason the corpus field gives, so it was never in that population and
2472
+ the count stays at 24 either side of this change. The self-test is
2473
+ therefore adopted on its merits rather than to clear a ratchet.