@event4u/agent-config 14.12.0 → 14.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +234 -0
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +109 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -55,7 +55,30 @@ function makeBrokenRef(
55
55
  return { file, line, ref, ref_type, severity, suggestion };
56
56
  }
57
57
 
58
- const SCAN_DIRS = ['dist/agent-src', 'agents'];
58
+ // `docs/guidelines` joins the scan on 2026-08-26 (`road-to-contract-review-deadlines`
59
+ // 4.3), and the decision is the NARROW one of the three that step offered —
60
+ // widen to the SHIPPED roots only.
61
+ //
62
+ // Priced before deciding, which is what the step asked for. Measured with
63
+ // `measure_docs_dead_links`: 544 dead relative links across `docs/`, of which
64
+ // **104 sat in files `package.json:files[]` publishes** and 440 did not.
65
+ // Widening to all of `docs/` would land ~300 findings on the next unrelated pull
66
+ // request — the flood that gets a gate waived rather than adopted, and the same
67
+ // argument this roadmap's Phase 0 already accepted for the beta backlog.
68
+ // Widening to the shipped roots lands **zero**, because 4.2 repaired all 104
69
+ // first, so the gate arrives green and holds the gain instead of announcing it.
70
+ //
71
+ // The excluded class is named rather than left implicit: **297 dead links in
72
+ // NON-shipped `docs/`** — analysis notes, ADR records, architecture pages — stay
73
+ // out of scope. They cost a maintainer a confused minute; a dead link under
74
+ // `docs/guidelines/` is shipped to a consumer and is the only half that reaches
75
+ // anyone. Re-measure any time with `./scripts-run src/scripts/measure_docs_dead_links`.
76
+ //
77
+ // The three named single-file contracts in `files[]`
78
+ // (`persona-schema`, `provider-lifecycle`, `settings-classes`) are NOT added:
79
+ // a directory scan cannot express "these three files under a directory that is
80
+ // otherwise excluded", and all three measure zero dead links today.
81
+ const SCAN_DIRS = ['dist/agent-src', 'agents', 'docs/guidelines'];
59
82
  const SKIP_DIRS = [
60
83
  // Archived roadmaps have historical refs — a link to a file that existed when
61
84
  // the plan was written is not drift, so the exclusion is right on the merits.
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Provenance-declaration gate for the security and safety floors.
4
+ *
5
+ * WHY THIS SCOPE AND NOT ALL 120 RULES. `src/rules/code-provenance.md`
6
+ * § The knowledge layer states the obligation for prose: an artefact asserting
7
+ * an externally-sourced claim either cites it or labels the statement as own
8
+ * analysis, and "silence is neither". That rule also says plainly that nothing
9
+ * enforces it — `lint_harvest_provenance` validates the harvest ledger's own
10
+ * rows and "cannot see a claim nobody recorded". This gate is the structural
11
+ * half for the surface where an unsourced normative claim costs the most.
12
+ *
13
+ * road-to-retired-claims-stay-retired Phase 3.2. The roadmap picked the ten
14
+ * deliberately: holding all 120 at once is the strict-gate-fires-on-everything
15
+ * failure this repository has recorded before, and the ten are the rules whose
16
+ * normative content most plausibly came from outside.
17
+ *
18
+ * WHAT IT CHECKS. Each in-scope rule carries an `evidence:` block with
19
+ * `source_type`, `verified_on` and `normative_level`. The block's SHAPE —
20
+ * enums, the date pattern, unknown keys — is `rule.schema.json`'s job via
21
+ * `validate_frontmatter`, and is deliberately not duplicated here: two
22
+ * validators for one shape drift, and the schema is the one a rule author
23
+ * already runs. This gate owns PRESENCE within a declared scope, which the
24
+ * schema cannot express because the block is optional everywhere else.
25
+ *
26
+ * THE SCOPE IS A LIST, AND THAT IS THE POINT. There is no frontmatter marker
27
+ * that delimits "security and safety floor" — measured 2026-08-30, the ten
28
+ * span three tiers (`2a`, `2b`, `safety-floor`), two `type` values and three
29
+ * pack sets, and `packs: [engineering-base]` also holds rules that are not
30
+ * safety floors. Deriving the scope from a proxy would silently admit and drop
31
+ * rules as unrelated frontmatter moved. An explicit list is reviewable, and a
32
+ * rule joining it is a decision somebody makes rather than a side effect.
33
+ *
34
+ * Exit codes: 0 = every in-scope rule declares · 1 = a declaration is missing
35
+ * or the scope is dead · 2 = usage error.
36
+ *
37
+ * Usage:
38
+ * ./scripts-run src/scripts/check_rule_evidence_declaration
39
+ * ./scripts-run src/scripts/check_rule_evidence_declaration --root <dir>
40
+ * ./scripts-run src/scripts/check_rule_evidence_declaration --self-test
41
+ */
42
+ import * as fs from 'node:fs';
43
+ import * as os from 'node:os';
44
+ import * as path from 'node:path';
45
+ import { fileURLToPath } from 'node:url';
46
+
47
+ import { runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
48
+ import { assertWatchlistResolves, DeadScopeError, reportScanned } from './_lib/scan_scope.js';
49
+
50
+ const _FILE = fileURLToPath(import.meta.url);
51
+ const REPO_ROOT = path.resolve(path.dirname(_FILE), '..', '..');
52
+
53
+ /**
54
+ * The declared scope, with the reason each row is in it.
55
+ *
56
+ * Growing this list is the intended way to widen the obligation: adding a row
57
+ * makes the gate fail until that rule declares, which is exactly the
58
+ * "an eleventh rule added without one fails" behaviour the roadmap asked for.
59
+ */
60
+ export const SCOPE: ReadonlyArray<{ rule: string; why: string }> = [
61
+ { rule: 'security-sensitive-stop', why: 'gates every edit to an auth / tenancy / billing / secrets surface' },
62
+ { rule: 'untrusted-input-defense', why: 'the data-not-instructions boundary; cites OWASP LLM01' },
63
+ { rule: 'lethal-trifecta-guard', why: 'the three-leg exfiltration shape; cites the OWASP ASI list' },
64
+ { rule: 'secret-vcs-guard', why: 'the last gate before a credential reaches history' },
65
+ { rule: 'broken-access-control', why: 'cites OWASP A01:2021 and BOLA/IDOR, and GDPR exposure' },
66
+ { rule: 'tool-safety', why: 'Least Agency; cites OWASP ASI excessive-agency and LLM06' },
67
+ { rule: 'domain-safety-pii', why: 'cites GDPR, CCPA, HIPAA, EEO and a k-anonymity figure' },
68
+ // NOT `non-destructive-by-default`, and the reason is a real constraint on
69
+ // this scope rather than a preference. That rule is `type: "always"`, so its
70
+ // bytes are charged to the kernel budget: adding the four-line block moved
71
+ // it 9,657 -> 9,752 chars and breached `check_always_budget`'s top-3 cap
72
+ // (37,948 > 37,855). An optional frontmatter block is not free on an
73
+ // always-rule, and trimming a kernel rule to make room is a maintainer
74
+ // decision this gate has no business forcing. `domain-safety-retention`
75
+ // takes the slot: same class, `type: "auto"`, and its normative content is
76
+ // more externally sourced than most (GDPR Art. 17, tax and VAT floors).
77
+ { rule: 'domain-safety-retention', why: 'cites GDPR Art. 17 plus tax and VAT retention floors by jurisdiction' },
78
+ { rule: 'engineering-safety-floor', why: 'the production / infra / bulk-destructive floor' },
79
+ { rule: 'code-provenance', why: 'states the knowledge-layer obligation this gate enforces' },
80
+ ];
81
+
82
+ /** Keys every declaration must carry, per rule.schema.json. */
83
+ const REQUIRED_KEYS = ['source_type'] as const;
84
+
85
+ /**
86
+ * `normative_level` is required only where an external source exists.
87
+ *
88
+ * It states how binding the SOURCE is. For `own-analysis` there is no external
89
+ * source, so the field answers a question that does not arise and `informative`
90
+ * is its only coherent value — requiring it there forces a non-answer. The
91
+ * schema draws the same line with an `if`/`then`, and the two are kept in step
92
+ * deliberately rather than one being inferred from the other: a gate that
93
+ * enforced more than the schema would reject a rule the schema accepts.
94
+ */
95
+ const OWN_ANALYSIS = 'own-analysis';
96
+
97
+ export interface Finding {
98
+ rule: string;
99
+ reason: string;
100
+ }
101
+
102
+ /** Extract the frontmatter block of a markdown file, or `null`. */
103
+ function frontmatter(body: string): string | null {
104
+ if (!body.startsWith('---\n')) return null;
105
+ const end = body.indexOf('\n---', 3);
106
+ if (end === -1) return null;
107
+ return body.slice(4, end + 1);
108
+ }
109
+
110
+ /**
111
+ * The `evidence:` mapping's own lines, or `null` when the key is absent.
112
+ *
113
+ * Deliberately a line scan rather than a YAML parse: this gate runs on every
114
+ * `task ci`, the schema validator already parses the same file properly, and a
115
+ * second parser is a second thing that can disagree about the first.
116
+ */
117
+ export function evidenceLines(fm: string): string[] | null {
118
+ const lines = fm.split('\n');
119
+ const start = lines.findIndex((l) => /^evidence:\s*$/.test(l));
120
+ if (start === -1) return null;
121
+ const out: string[] = [];
122
+ for (const line of lines.slice(start + 1)) {
123
+ if (line.trim() === '') continue;
124
+ if (!/^\s+\S/.test(line)) break; // dedented — the block ended
125
+ out.push(line);
126
+ }
127
+ return out;
128
+ }
129
+
130
+ export function analyse(root = REPO_ROOT): Finding[] {
131
+ const findings: Finding[] = [];
132
+ for (const { rule } of SCOPE) {
133
+ const abs = path.join(root, 'src', 'rules', `${rule}.md`);
134
+ let body: string;
135
+ try {
136
+ body = fs.readFileSync(abs, 'utf8');
137
+ } catch {
138
+ findings.push({ rule, reason: 'in scope but the rule file does not exist — remove the row or restore the rule' });
139
+ continue;
140
+ }
141
+ const fm = frontmatter(body);
142
+ if (fm === null) {
143
+ findings.push({ rule, reason: 'no frontmatter block' });
144
+ continue;
145
+ }
146
+ const block = evidenceLines(fm);
147
+ if (block === null) {
148
+ findings.push({
149
+ rule,
150
+ reason:
151
+ 'carries no `evidence:` block — state where its normative content came from, ' +
152
+ 'or record `source_type: own-analysis`, which is a complete discharge',
153
+ });
154
+ continue;
155
+ }
156
+ const has = (key: string): boolean =>
157
+ block.some((l) => new RegExp(`^\\s+${key}:\\s*\\S`).test(l));
158
+ for (const key of REQUIRED_KEYS) {
159
+ if (!has(key)) findings.push({ rule, reason: `evidence block is missing \`${key}\`` });
160
+ }
161
+ const ownAnalysis = block.some((l) => l.includes(`source_type: ${OWN_ANALYSIS}`));
162
+ if (!ownAnalysis && has('source_type')) {
163
+ for (const key of ['normative_level', 'verified_on'] as const) {
164
+ if (has(key)) continue;
165
+ findings.push({
166
+ rule,
167
+ reason:
168
+ `evidence block names an external source but no \`${key}\` — both are real ` +
169
+ 'questions wherever a source exists, and neither is where one does not',
170
+ });
171
+ }
172
+ }
173
+ }
174
+ return findings;
175
+ }
176
+
177
+ function runGate(root: string): number {
178
+ try {
179
+ assertWatchlistResolves({
180
+ gate: 'check_rule_evidence_declaration',
181
+ candidates: SCOPE.map((s) => `src/rules/${s.rule}.md`),
182
+ repoRoot: root,
183
+ });
184
+ } catch (exc) {
185
+ if (!(exc instanceof DeadScopeError)) throw exc;
186
+ process.stderr.write(`❌ ${exc.message}\n`);
187
+ return 1;
188
+ }
189
+ reportScanned({
190
+ gate: 'check_rule_evidence_declaration',
191
+ scanned: SCOPE.length,
192
+ units: 'in-scope rule(s)',
193
+ roots: ['src/rules/'],
194
+ });
195
+ const findings = analyse(root);
196
+ if (findings.length > 0) {
197
+ process.stderr.write(
198
+ `❌ check_rule_evidence_declaration: ${String(findings.length)} finding(s):\n`,
199
+ );
200
+ for (const f of findings) process.stderr.write(` src/rules/${f.rule}.md — ${f.reason}\n`);
201
+ process.stderr.write(
202
+ ' → the block is documented at `evidence` in src/scripts/schemas/rule.schema.json.\n',
203
+ );
204
+ return 1;
205
+ }
206
+ process.stdout.write(
207
+ `✅ check_rule_evidence_declaration: ${String(SCOPE.length)} security/safety rule(s) declare their provenance.\n`,
208
+ );
209
+ return 0;
210
+ }
211
+
212
+ function selfTest(): number {
213
+ const roots: string[] = [];
214
+ const fixture = (frontmatterBody: string, rules = [SCOPE[0]!.rule]): number => {
215
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rule-evidence-'));
216
+ roots.push(dir);
217
+ fs.mkdirSync(path.join(dir, 'src', 'rules'), { recursive: true });
218
+ // Every in-scope rule must exist or the run fails for the wrong reason;
219
+ // the ones not under test get a well-formed block.
220
+ const good = ['evidence:', ' source_type: own-analysis'].join('\n');
221
+ for (const { rule } of SCOPE) {
222
+ const fm = rules.includes(rule) ? frontmatterBody : good;
223
+ fs.writeFileSync(
224
+ path.join(dir, 'src', 'rules', `${rule}.md`),
225
+ `---\ntype: "auto"\n${fm}\n---\n\n# ${rule}\n`,
226
+ );
227
+ }
228
+ return runGate(dir);
229
+ };
230
+
231
+ const EXT = ['evidence:', ' source_type: external-standard', ' verified_on: 2026-08-30', ' normative_level: recommended'];
232
+ const OWN = ['evidence:', ' source_type: own-analysis'];
233
+
234
+ const cases: SelfTestCase[] = [
235
+ {
236
+ name: 'every in-scope rule declares → accept',
237
+ expect: 'accept',
238
+ run: () => fixture(EXT.join('\n')),
239
+ },
240
+ {
241
+ name: 'an in-scope rule with NO evidence block → reject',
242
+ expect: 'reject',
243
+ run: () => fixture('description: "a rule with no provenance"'),
244
+ },
245
+ {
246
+ // The conditional rule, in the direction that must REJECT: an
247
+ // external source is named, so how binding it is and when it was
248
+ // last checked are both real questions.
249
+ name: 'an external-source block missing normative_level → reject',
250
+ expect: 'reject',
251
+ run: () => fixture(['evidence:', ' source_type: external-standard', ' verified_on: 2026-08-30'].join('\n')),
252
+ },
253
+ {
254
+ name: 'an external-source block missing verified_on → reject',
255
+ expect: 'reject',
256
+ run: () => fixture(['evidence:', ' source_type: external-standard', ' normative_level: recommended'].join('\n')),
257
+ },
258
+ {
259
+ name: 'a source_type present but valueless → reject',
260
+ expect: 'reject',
261
+ run: () => fixture(['evidence:', ' source_type:'].join('\n')),
262
+ },
263
+ {
264
+ // The same shape in the direction that must ACCEPT. `own-analysis`
265
+ // names no external source, so neither field has a question to
266
+ // answer — requiring them there would force a non-answer, and a
267
+ // gate that rejected this would reject what the schema accepts.
268
+ name: 'an own-analysis block with neither field → accept',
269
+ expect: 'accept',
270
+ run: () => fixture(OWN.join('\n')),
271
+ },
272
+ ];
273
+
274
+ try {
275
+ return runSelfTest({
276
+ gate: 'check_rule_evidence_declaration',
277
+ cases,
278
+ minCases: 6,
279
+ minRejectCases: 4,
280
+ });
281
+ } finally {
282
+ for (const d of roots) fs.rmSync(d, { recursive: true, force: true });
283
+ }
284
+ }
285
+
286
+ export function main(argv: string[] = process.argv.slice(2)): number {
287
+ if (argv.includes('--self-test')) return selfTest();
288
+ let root = REPO_ROOT;
289
+ for (let i = 0; i < argv.length; i += 1) {
290
+ const a = argv[i]!;
291
+ if (a === '--root') {
292
+ const v = argv[i + 1];
293
+ if (v === undefined) {
294
+ process.stderr.write('check_rule_evidence_declaration: --root needs a directory\n');
295
+ return 2;
296
+ }
297
+ root = path.resolve(v);
298
+ i += 1;
299
+ } else if (a === '--quiet') {
300
+ continue;
301
+ } else if (a === '-h' || a === '--help') {
302
+ process.stdout.write(
303
+ 'usage: check_rule_evidence_declaration [--root DIR] [--quiet] [--self-test]\n',
304
+ );
305
+ return 0;
306
+ } else {
307
+ process.stderr.write(`check_rule_evidence_declaration: unrecognized argument: ${a}\n`);
308
+ return 2;
309
+ }
310
+ }
311
+ return runGate(root);
312
+ }
313
+
314
+ if (process.argv[1] !== undefined && process.argv[1].includes('check_rule_evidence_declaration')) {
315
+ process.exit(main());
316
+ }
@@ -6,10 +6,20 @@
6
6
  * WHY THIS GATE EXISTS (road-to-conformance-round5 Phase 1, measured 2026-08-07)
7
7
  * ---------------------------------------------------------------------------
8
8
  * `docs/contracts/rule-router.md` (§ "The router earns its place as a
9
- * **compile-time** artifact", measured: zero consumers under
10
- * `src/scripts/hooks/`) states that nothing loads
11
- * `dist/router.json` at runtime, so **projection is the only reach mechanism
12
- * there is**: a non-kernel rule activates by the model's judgment over text
9
+ * **compile-time** artifact") states that under every shipped default nothing
10
+ * loads `dist/router.json` at runtime, so **projection is the only reach
11
+ * mechanism there is**:
12
+ *
13
+ * CORRECTED 2026-08-26. This docblock used to cite that section's "measured:
14
+ * zero consumers under `src/scripts/hooks/`", and that measurement is stale: the
15
+ * `rule-inject` concern reads the router via `_lib/rule_injection.ts:76-79` and
16
+ * is bound on three slots. The gate's rationale survives the correction because
17
+ * the concern is DEFAULT-OFF and returns before reading the router unless
18
+ * `lean_projection.mode: delivery` is set — so on a shipped default, projection
19
+ * IS still the only reach mechanism. What no longer holds is the stronger claim
20
+ * that no such mechanism exists. Stated here rather than quietly re-worded,
21
+ * because a gate whose stated reason rests on a refuted premise is exactly the
22
+ * decoration ADR-127 rejects: a non-kernel rule activates by the model's judgment over text
13
23
  * already in context, and the per-tool rule tree is what puts it there. That
14
24
  * makes the state of the projection load-bearing, and it was broken:
15
25
  *
@@ -63,6 +63,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
63
63
  import * as os from 'node:os';
64
64
  import { parse as parseYaml } from 'yaml';
65
65
  import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
66
+ import { GateLedger } from './_lib/gate_ledger.js';
66
67
 
67
68
  const _FILE = fileURLToPath(import.meta.url);
68
69
  const REPO = path.resolve(path.dirname(_FILE), '..', '..');
@@ -323,37 +324,57 @@ export function checkRubric(rubric: Row, rowCount: number, ids: string[]): Findi
323
324
 
324
325
  /* ── driver ────────────────────────────────────────────────────────────────── */
325
326
 
326
- export function check(rel: string): Finding[] {
327
+ export function check(rel: string, ledger?: GateLedger): Finding[] {
327
328
  // An absolute `--file` must be honoured as given. path.join(REPO, '/abs')
328
329
  // silently produces REPO + '/abs', which reports `missing_file` for a file
329
330
  // that exists — the shape a test using a temp copy hits first.
330
331
  const abs = path.isAbsolute(rel) ? rel : path.join(REPO, rel);
331
332
  if (!fs.existsSync(abs)) {
333
+ ledger?.plan([rel]);
334
+ ledger?.fail(rel, 'scorecard does not exist');
332
335
  return [{ where: rel, code: 'missing_file', detail: 'scorecard does not exist' }];
333
336
  }
334
337
  let doc: unknown;
335
338
  try {
336
339
  doc = parseYaml(fs.readFileSync(abs, 'utf8'));
337
340
  } catch (exc) {
341
+ ledger?.plan([rel]);
342
+ ledger?.fail(rel, 'unparseable YAML');
338
343
  return [{ where: rel, code: 'unparseable', detail: String(exc) }];
339
344
  }
340
345
  if (doc === null || typeof doc !== 'object') {
346
+ ledger?.plan([rel]);
347
+ ledger?.fail(rel, 'top level is not a mapping');
341
348
  return [{ where: rel, code: 'unparseable', detail: 'top level is not a mapping' }];
342
349
  }
343
350
  const top = doc as Row;
344
351
  const rubric = top['rubric'];
345
352
  const cats = top['categories'];
346
353
  if (rubric === undefined || typeof rubric !== 'object' || rubric === null) {
354
+ ledger?.plan([rel]);
355
+ ledger?.fail(rel, 'no `rubric:` block');
347
356
  return [{ where: rel, code: 'missing_field', detail: 'no `rubric:` block' }];
348
357
  }
349
358
  if (!Array.isArray(cats)) {
359
+ ledger?.plan([rel]);
360
+ ledger?.fail(rel, '`categories:` must be a list');
350
361
  return [{ where: rel, code: 'missing_field', detail: '`categories:` must be a list' }];
351
362
  }
352
363
  const rows = cats as Row[];
353
364
  const ids = rows.map((r) => String(r['category'] ?? '<unnamed>'));
365
+ // Per-row accounting. Every early return above aborts BEFORE any row is
366
+ // read, and until this ledger existed those aborts produced a one-line
367
+ // finding indistinguishable, in the coverage record, from a full pass over
368
+ // 23 rows. The ledger separates "checked every row and found one problem"
369
+ // from "never reached a row".
370
+ ledger?.plan(ids.map((id, i) => `${id}#${String(i)}`));
354
371
  const findings = [...checkRubric(rubric as Row, rows.length, ids)];
355
372
  rows.forEach((r, i) => {
356
- findings.push(...checkRow(r, `${rel} → ${ids[i] ?? `row ${i}`}`));
373
+ const target = `${ids[i] ?? '<unnamed>'}#${String(i)}`;
374
+ const rowFindings = checkRow(r, `${rel} → ${ids[i] ?? `row ${i}`}`);
375
+ findings.push(...rowFindings);
376
+ if (rowFindings.length > 0) ledger?.fail(target, `${String(rowFindings.length)} finding(s)`);
377
+ else ledger?.complete(target);
357
378
  });
358
379
  return findings;
359
380
  }
@@ -450,7 +471,9 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
450
471
  process.stderr.write('usage: check_score_contract [--quiet] [--file <path>]\n');
451
472
  return 2;
452
473
  }
453
- const findings = check(rel);
474
+ const ledger = new GateLedger('check_score_contract');
475
+ const findings = check(rel, ledger);
476
+ ledger.report(quiet ? () => undefined : undefined);
454
477
  // Rule 1 of the gate-coverage contract: exactly one `scanned: <N>` line,
455
478
  // emitted on the red path too — a gate that only reports coverage when it
456
479
  // passes cannot be caught going blind at the moment it matters.