@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
@@ -42,6 +42,7 @@ import * as path from 'node:path';
42
42
  import { fileURLToPath, pathToFileURL } from 'node:url';
43
43
 
44
44
  import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
45
+ import { GateLedger } from './_lib/gate_ledger.js';
45
46
  import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
46
47
 
47
48
  const _HERE = fileURLToPath(import.meta.url);
@@ -292,6 +293,40 @@ function main(argv?: readonly string[]): number {
292
293
  return 1;
293
294
  }
294
295
  const { readings, malformed } = parseStore(text);
296
+
297
+ // Per-line accounting. `malformed` is a COUNT, and a count cannot say WHICH
298
+ // lines were dropped — a store whose last 40 appends were malformed reads
299
+ // the same as one with 40 fewer readings, which is the "looked at almost
300
+ // nothing" case. The ledger names each dropped line.
301
+ const ledger = new GateLedger('check_composite_arming');
302
+ const storeLines = text.split('\n').map((l, i) => ({ n: i + 1, t: l.trim() })).filter((l) => l.t !== '');
303
+ ledger.plan(storeLines.map((l) => `line:${String(l.n)}`));
304
+ let parsedSeen = 0;
305
+ for (const l of storeLines) {
306
+ let ok = false;
307
+ try {
308
+ const o = JSON.parse(l.t) as { session?: unknown };
309
+ ok = typeof o.session === 'string' && 'composite_ms' in (o as object);
310
+ } catch {
311
+ ok = false;
312
+ }
313
+ if (ok) {
314
+ parsedSeen += 1;
315
+ ledger.complete(`line:${String(l.n)}`);
316
+ } else {
317
+ ledger.skip(`line:${String(l.n)}`, 'precondition_unmet');
318
+ }
319
+ }
320
+ ledger.report();
321
+ /* c8 ignore next 6 */
322
+ if (parsedSeen !== readings.length) {
323
+ process.stderr.write(
324
+ `❌ check_composite_arming: ledger counted ${String(parsedSeen)} parseable line(s) but ` +
325
+ `parseStore returned ${String(readings.length)} reading(s) — the accounting and the ` +
326
+ 'parser disagree, which means one of them is wrong about what was read.\n',
327
+ );
328
+ return 2;
329
+ }
295
330
  if (malformed > 0 && readings.length === 0) {
296
331
  process.stderr.write(
297
332
  `❌ ${path.relative(REPO_ROOT, store)}: ${String(malformed)} malformed line(s) and no usable ` +
@@ -0,0 +1,365 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Every hook concern added from here on carries a recorded answer — or fails.
4
+ *
5
+ * The sibling of `check_skill_admissions.ts`, same shape and same reasons, with
6
+ * one structural difference that changes the mechanism rather than the policy.
7
+ *
8
+ * ## Forward-only, and why the scope is computed differently
9
+ *
10
+ * A skill is a FILE, so its gate reads `git diff --diff-filter=A` and the 299
11
+ * already in the tree are grandfathered by construction. A concern is a KEY
12
+ * INSIDE ONE FILE — `src/scripts/hook_manifest.yaml` — so a file-level diff
13
+ * says only "the manifest changed", which is true of every concern edit and
14
+ * discriminates nothing.
15
+ *
16
+ * The scope here is therefore a SET DIFFERENCE over the parsed ids: the
17
+ * concerns at HEAD minus the concerns at the base ref. Both sides go through
18
+ * the same scoped parser (`_lib/concern_estate.ts`), for the reason that module
19
+ * exists — two readings of one corpus is how a gate comes to compare a number
20
+ * against a differently-derived number.
21
+ *
22
+ * The grandfathering is identical in effect: the 55 already in the tree need no
23
+ * ledger row and cannot be forgotten off one.
24
+ *
25
+ * ## The questions are NOT the skill questions
26
+ *
27
+ * They are derived from `docs/contracts/hook-architecture-v1.md`, because what
28
+ * makes a concern risky is different from what makes a skill risky. A concern
29
+ * binds to a slot, on hosts that may or may not honour a deny, inside a
30
+ * per-event budget — and none of that has a skill analogue.
31
+ *
32
+ * ## A rejected row is first-class
33
+ *
34
+ * `decision: rejected` records a visible "no", and a rejected row naming a
35
+ * concern that EXISTS is itself a failure: it means the refusal was recorded
36
+ * and then overridden without the row being updated, which is worse than no
37
+ * record at all.
38
+ */
39
+
40
+ import * as fs from 'node:fs';
41
+ import * as path from 'node:path';
42
+ import { spawnSync } from 'node:child_process';
43
+
44
+ import { CONCERN_MANIFEST_POSIX, concernIds } from './_lib/concern_estate.js';
45
+
46
+ const REPO_ROOT = process.cwd();
47
+
48
+ export const LEDGER_REL = 'agents/decisions/concern-admissions.jsonl';
49
+
50
+ /**
51
+ * The five answers, each a non-empty sentence.
52
+ *
53
+ * Every one is a question `hook-architecture-v1.md` makes answerable and a
54
+ * reviewer would otherwise have to reconstruct from the manifest by hand.
55
+ */
56
+ export const REQUIRED_ANSWERS = [
57
+ /** Which lifecycle slot it binds — `pre_tool_use`, `stop`, and so on. */
58
+ 'slot',
59
+ /** Which hosts actually BIND it, as opposed to which declare the slot. */
60
+ 'binding_hosts',
61
+ /** What it does where the host ignores a deny — the honest-coverage answer. */
62
+ 'behaviour_where_deny_ignored',
63
+ /** Why an existing concern cannot carry this. */
64
+ 'why_not_extend',
65
+ /** What it costs against the per-(platform,event) budget. */
66
+ 'per_event_budget_impact',
67
+ ] as const;
68
+
69
+ export const DECISIONS = ['admitted', 'rejected'] as const;
70
+ export type Decision = (typeof DECISIONS)[number];
71
+
72
+ export interface AdmissionRow {
73
+ concern: string;
74
+ decision: Decision;
75
+ date: string;
76
+ slot?: string;
77
+ binding_hosts?: string;
78
+ behaviour_where_deny_ignored?: string;
79
+ why_not_extend?: string;
80
+ per_event_budget_impact?: string;
81
+ /** Free-form; only meaningful on a `rejected` row. */
82
+ instead?: string;
83
+ }
84
+
85
+ export interface Finding {
86
+ concern: string;
87
+ kind: 'missing_row' | 'incomplete_row' | 'rejected_but_present' | 'bad_decision' | 'duplicate_row';
88
+ message: string;
89
+ }
90
+
91
+ function isRow(v: unknown): v is AdmissionRow {
92
+ return typeof v === 'object' && v !== null && typeof (v as AdmissionRow).concern === 'string';
93
+ }
94
+
95
+ export function readLedger(root = REPO_ROOT): AdmissionRow[] {
96
+ const p = path.join(root, LEDGER_REL);
97
+ if (!fs.existsSync(p)) {
98
+ // An absent ledger is not an empty corpus: it is a gate with nothing to
99
+ // read, and the forward-only scope means an absent ledger only matters
100
+ // once something has been added.
101
+ return [];
102
+ }
103
+ const out: AdmissionRow[] = [];
104
+ let n = 0;
105
+ for (const line of fs.readFileSync(p, 'utf-8').split('\n')) {
106
+ n += 1;
107
+ const t = line.trim();
108
+ if (t === '') continue;
109
+ let parsed: unknown;
110
+ try {
111
+ parsed = JSON.parse(t);
112
+ } catch {
113
+ throw new Error(
114
+ `${LEDGER_REL}:${String(n)} is not valid JSON. A malformed ledger is a hard ` +
115
+ 'failure, never a skipped line — a gate that silently drops rows admits by accident.',
116
+ );
117
+ }
118
+ if (isRow(parsed)) out.push(parsed);
119
+ }
120
+ return out;
121
+ }
122
+
123
+ /** Concern ids declared at a git ref, or `null` when the manifest is unreadable there. */
124
+ export function concernsAt(root: string, ref: string): Set<string> | null {
125
+ const res = spawnSync('git', ['show', `${ref}:${CONCERN_MANIFEST_POSIX}`], {
126
+ cwd: root,
127
+ encoding: 'utf-8',
128
+ maxBuffer: 32 * 1024 * 1024,
129
+ });
130
+ if (res.status !== 0) return null;
131
+ return new Set(concernIds(res.stdout ?? ''));
132
+ }
133
+
134
+ /** Concern ids in the working tree. */
135
+ export function liveConcerns(root = REPO_ROOT): Set<string> {
136
+ const p = path.join(root, CONCERN_MANIFEST_POSIX);
137
+ if (!fs.existsSync(p)) return new Set();
138
+ return new Set(concernIds(fs.readFileSync(p, 'utf-8')));
139
+ }
140
+
141
+ /**
142
+ * Concerns ADDED since `baseRef` — the forward-only scope.
143
+ *
144
+ * A set difference rather than a file diff, because a concern is a key inside
145
+ * one file. `null` from `concernsAt` means the manifest could not be read at
146
+ * the base, in which case NOTHING is treated as added: a ref that predates the
147
+ * file must not retroactively demand a row for all 55.
148
+ */
149
+ export function addedConcerns(root: string, baseRef: string): string[] {
150
+ const base = concernsAt(root, baseRef);
151
+ if (base === null) return [];
152
+ return [...liveConcerns(root)].filter((id) => !base.has(id)).sort();
153
+ }
154
+
155
+ export function evaluate(root = REPO_ROOT, baseRef: string | null): Finding[] {
156
+ const findings: Finding[] = [];
157
+ const rows = readLedger(root);
158
+ const live = liveConcerns(root);
159
+
160
+ const seen = new Map<string, number>();
161
+ for (const r of rows) {
162
+ seen.set(r.concern, (seen.get(r.concern) ?? 0) + 1);
163
+ if (!(DECISIONS as readonly string[]).includes(r.decision)) {
164
+ findings.push({
165
+ concern: r.concern,
166
+ kind: 'bad_decision',
167
+ message: `decision must be one of ${DECISIONS.join(' | ')}, got ${JSON.stringify(r.decision)}`,
168
+ });
169
+ continue;
170
+ }
171
+ if (r.decision === 'rejected' && live.has(r.concern)) {
172
+ findings.push({
173
+ concern: r.concern,
174
+ kind: 'rejected_but_present',
175
+ message:
176
+ 'the ledger records a REJECTION and the concern exists in the manifest. A refusal that ' +
177
+ 'was later overridden without updating its row is worse than no record at all.',
178
+ });
179
+ }
180
+ }
181
+ for (const [id, n] of seen) {
182
+ if (n > 1) {
183
+ findings.push({
184
+ concern: id,
185
+ kind: 'duplicate_row',
186
+ message: `${String(n)} rows name this concern; one decision per concern, amended in place`,
187
+ });
188
+ }
189
+ }
190
+
191
+ if (baseRef === null) return findings;
192
+
193
+ const admitted = new Map(rows.filter((r) => r.decision === 'admitted').map((r) => [r.concern, r]));
194
+ for (const id of addedConcerns(root, baseRef)) {
195
+ const row = admitted.get(id);
196
+ if (row === undefined) {
197
+ findings.push({
198
+ concern: id,
199
+ kind: 'missing_row',
200
+ message: `added since ${baseRef} with no \`admitted\` row in ${LEDGER_REL}`,
201
+ });
202
+ continue;
203
+ }
204
+ const blank = REQUIRED_ANSWERS.filter((k) => {
205
+ const v = row[k];
206
+ return typeof v !== 'string' || v.trim() === '';
207
+ });
208
+ if (blank.length > 0) {
209
+ findings.push({
210
+ concern: id,
211
+ kind: 'incomplete_row',
212
+ message: `row is missing a real answer for: ${blank.join(', ')}`,
213
+ });
214
+ }
215
+ }
216
+ return findings;
217
+ }
218
+
219
+ // ---------------------------------------------------------------------------
220
+ // CLI
221
+ // ---------------------------------------------------------------------------
222
+
223
+ import { reportScanned } from './_lib/scan_scope.js';
224
+ import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
225
+ import * as os from 'node:os';
226
+
227
+ function resolveBase(root: string): string | null {
228
+ for (const ref of ['origin/main', 'main']) {
229
+ const r = spawnSync('git', ['rev-parse', '--verify', '--quiet', ref], { cwd: root, encoding: 'utf-8' });
230
+ if (r.status === 0) return ref;
231
+ }
232
+ return null;
233
+ }
234
+
235
+ const MANIFEST = (ids: readonly string[]): string =>
236
+ ['concerns:', ...ids.map((i) => ` ${i}:\n severity: advisory`), 'roles:', ' dev:', ''].join('\n');
237
+
238
+ const ROW = (concern: string, decision: Decision, blank?: string): string =>
239
+ JSON.stringify({
240
+ concern,
241
+ decision,
242
+ date: '2026-08-30',
243
+ ...Object.fromEntries(REQUIRED_ANSWERS.map((k) => [k, k === blank ? '' : `a real answer for ${k}`])),
244
+ });
245
+
246
+ function selfTest(): number {
247
+ const roots: string[] = [];
248
+ const script = path.join('src', 'scripts', 'check_concern_admissions.ts');
249
+
250
+ /** A throwaway repo with a base commit and a working-tree change on top. */
251
+ const fixture = (opts: { base: readonly string[]; head: readonly string[]; ledger?: string }): number => {
252
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ca-selftest-'));
253
+ roots.push(dir);
254
+ const g = (...a: string[]): void => {
255
+ spawnSync('git', a, { cwd: dir, encoding: 'utf-8' });
256
+ };
257
+ const put = (rel: string, body: string): void => {
258
+ fs.mkdirSync(path.join(dir, path.dirname(rel)), { recursive: true });
259
+ fs.writeFileSync(path.join(dir, rel), body, 'utf-8');
260
+ };
261
+ g('init', '-q', '-b', 'main');
262
+ g('config', 'user.email', 'selftest@local');
263
+ g('config', 'user.name', 'selftest');
264
+ put(CONCERN_MANIFEST_POSIX, MANIFEST(opts.base));
265
+ put(LEDGER_REL, '');
266
+ g('add', '-A');
267
+ g('commit', '-q', '-m', 'base');
268
+ put(CONCERN_MANIFEST_POSIX, MANIFEST(opts.head));
269
+ if (opts.ledger !== undefined) put(LEDGER_REL, `${opts.ledger}\n`);
270
+ // repoRoot locates tsx AND resolves the relative script path, so it is
271
+ // THIS checkout; cwd and --root are the fixture.
272
+ return runGateCli(REPO_ROOT, script, ['--base', 'main', '--root', dir], dir);
273
+ };
274
+
275
+ const cases: SelfTestCase[] = [
276
+ {
277
+ name: 'no concern added → accept',
278
+ expect: 'accept',
279
+ run: () => fixture({ base: ['one'], head: ['one'] }),
280
+ },
281
+ {
282
+ name: 'a concern added with no ledger row → reject',
283
+ expect: 'reject',
284
+ run: () => fixture({ base: ['one'], head: ['one', 'two'] }),
285
+ },
286
+ {
287
+ name: 'a concern added WITH a complete admitted row → accept',
288
+ expect: 'accept',
289
+ run: () => fixture({ base: ['one'], head: ['one', 'two'], ledger: ROW('two', 'admitted') }),
290
+ },
291
+ {
292
+ // A row that exists but answers nothing is the shape a gate is
293
+ // easiest to satisfy dishonestly, so it is tested explicitly.
294
+ name: 'an admitted row with a blank answer → reject',
295
+ expect: 'reject',
296
+ run: () =>
297
+ fixture({ base: ['one'], head: ['one', 'two'], ledger: ROW('two', 'admitted', 'why_not_extend') }),
298
+ },
299
+ {
300
+ name: 'a rejected row naming a LIVE concern → reject',
301
+ expect: 'reject',
302
+ run: () => fixture({ base: ['one', 'two'], head: ['one', 'two'], ledger: ROW('two', 'rejected') }),
303
+ },
304
+ {
305
+ // The grandfathering, asserted rather than assumed: pre-existing
306
+ // concerns must never demand a row.
307
+ name: 'the pre-existing set needs no rows → accept',
308
+ expect: 'accept',
309
+ run: () => fixture({ base: ['a', 'b', 'c'], head: ['a', 'b', 'c'] }),
310
+ },
311
+ ];
312
+
313
+ try {
314
+ return runSelfTest({ gate: 'check_concern_admissions', cases, minCases: 5, minRejectCases: 3 });
315
+ } finally {
316
+ for (const d of roots) fs.rmSync(d, { recursive: true, force: true });
317
+ }
318
+ }
319
+
320
+ export function main(argv: string[] = process.argv.slice(2), rootIn = REPO_ROOT): number {
321
+ if (argv.includes('--self-test')) return selfTest();
322
+ const i = argv.indexOf('--base');
323
+ const j = argv.indexOf('--root');
324
+ const root = j >= 0 && argv[j + 1] !== undefined ? path.resolve(argv[j + 1] as string) : rootIn;
325
+ const baseRef = i >= 0 ? (argv[i + 1] as string) : resolveBase(root);
326
+
327
+ const rows = readLedger(root);
328
+ const added = baseRef === null ? [] : addedConcerns(root, baseRef);
329
+ reportScanned({
330
+ gate: 'check_concern_admissions',
331
+ scanned: rows.length + added.length,
332
+ units: 'admission row(s) + added concern(s)',
333
+ roots: [LEDGER_REL, CONCERN_MANIFEST_POSIX],
334
+ // The state this ships in: 55 concerns are grandfathered by the
335
+ // forward-only set-difference scope, so the first row arrives with the
336
+ // first new concern. `readLedger` throws on a MALFORMED ledger, so
337
+ // "moved" and "empty" stay different verdicts.
338
+ allowEmpty:
339
+ 'EMPTY_VALID: no concern has been admitted or refused through this ledger yet — the ' +
340
+ 'pre-existing 55 are grandfathered by the forward-only set-difference scope, and a ' +
341
+ 'malformed ledger is a separate hard error in readLedger()',
342
+ });
343
+
344
+ const findings = evaluate(root, baseRef);
345
+ if (baseRef === null) {
346
+ process.stdout.write(
347
+ ' ⏭️ no base ref resolved — the added-concern scope could not be computed; ' +
348
+ 'ledger consistency was still checked\n',
349
+ );
350
+ }
351
+ if (findings.length === 0) {
352
+ process.stdout.write(
353
+ `✅ check_concern_admissions: ${String(added.length)} concern(s) added since ` +
354
+ `${baseRef ?? '<no base>'}, each carrying a recorded answer.\n`,
355
+ );
356
+ return 0;
357
+ }
358
+ process.stderr.write(`❌ check_concern_admissions: ${String(findings.length)} finding(s):\n`);
359
+ for (const f of findings) process.stderr.write(` 🔴 ${f.concern} [${f.kind}] — ${f.message}\n`);
360
+ return 1;
361
+ }
362
+
363
+ if (process.argv[1] !== undefined && process.argv[1].includes('check_concern_admissions')) {
364
+ process.exit(main());
365
+ }
@@ -852,6 +852,34 @@ function main(argv: string[]): number {
852
852
  }
853
853
  const base = JSON.parse(fs.readFileSync(BASELINE, 'utf-8')).summary as Summary;
854
854
  const regressions: string[] = [];
855
+
856
+ // `undeclared` is the only counter here that is a TRUE shrink-only
857
+ // ratchet, and the asymmetry is worth stating because the two below it
858
+ // are not.
859
+ //
860
+ // A rule with no declaration has no carrier, so it can contribute to
861
+ // neither `frequency_gap` nor `local_only`. DECLARING one truthfully can
862
+ // therefore only RAISE both — the gap and the taskfile-only reach were
863
+ // always there, and the declaration is what made them computable. Both
864
+ // checks compare a number against a baseline taken when the rule was
865
+ // invisible, so an honest declaring change reds them by construction.
866
+ //
867
+ // Measured 2026-08-27, landing 14 declarations from
868
+ // `road-to-undeclared-obligation-disposition` Phase 1.3:
869
+ // `frequency gaps rose: 9 → 14` and `validators fell back to
870
+ // taskfile-only: 0 → 3`. Nothing fell back and no carrier fired less
871
+ // often. Both readings were new visibility.
872
+ //
873
+ // The sanctioned response is the one the failure message already names —
874
+ // regenerate the baseline — and the obligation this comment adds is that
875
+ // a change doing so SAYS WHY, because a regenerated baseline and a
876
+ // hidden regression look identical in a diff.
877
+ if (summary.undeclared > (base.undeclared ?? Number.POSITIVE_INFINITY)) {
878
+ regressions.push(
879
+ `undeclared rules rose: ${base.undeclared} → ${summary.undeclared} ` +
880
+ `(a rule lost its enforced_by, or a new rule landed without one)`,
881
+ );
882
+ }
855
883
  if (summary.blocking < base.blocking) {
856
884
  regressions.push(`blocking coverage fell: ${base.blocking} → ${summary.blocking}`);
857
885
  }