@event4u/agent-config 16.0.0 → 16.2.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 (382) 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 +289 -140
  5. package/CONTRIBUTING.md +9 -0
  6. package/README.md +2 -2
  7. package/dist/agent-src/commands/analyze/inbox.md +26 -0
  8. package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
  9. package/dist/agent-src/commands/challenge-me/closure.md +178 -0
  10. package/dist/agent-src/commands/challenge-me.md +9 -2
  11. package/dist/agent-src/commands/council/default.md +25 -5
  12. package/dist/agent-src/commands/feature/plan.md +28 -1
  13. package/dist/agent-src/commands/feature/roadmap.md +28 -1
  14. package/dist/agent-src/commands/implement-ticket.md +27 -0
  15. package/dist/agent-src/commands/jira-ticket.md +27 -0
  16. package/dist/agent-src/commands/pr/create.md +29 -0
  17. package/dist/agent-src/commands/pr/merge.md +60 -9
  18. package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
  19. package/dist/agent-src/commands/roadmap/create.md +74 -27
  20. package/dist/agent-src/commands/roadmap/materialize.md +27 -0
  21. package/dist/agent-src/commands/roadmap/process-full.md +123 -18
  22. package/dist/agent-src/commands/team.md +22 -0
  23. package/dist/agent-src/commands/work.md +4 -0
  24. package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
  25. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
  26. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
  27. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +19 -23
  28. package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
  29. package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
  30. package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
  31. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
  32. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
  33. package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
  34. package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
  35. package/dist/agent-src/rules/autonomous-execution.md +15 -8
  36. package/dist/agent-src/rules/delegation-policy.md +23 -45
  37. package/dist/agent-src/rules/design-fidelity.md +32 -37
  38. package/dist/agent-src/rules/evaluator-independence.md +43 -49
  39. package/dist/agent-src/rules/test-first.md +41 -0
  40. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  41. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
  42. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  43. package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
  44. package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
  45. package/dist/agent-src/skills/database/data/manifest.json +4 -4
  46. package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
  47. package/dist/agent-src/skills/design-review/SKILL.md +80 -4
  48. package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
  49. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +30 -5
  50. package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
  51. package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
  52. package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
  53. package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
  54. package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
  55. package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
  56. package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
  57. package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
  58. package/dist/agent-src/skills/ui-component-architect/SKILL.md +23 -0
  59. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
  60. package/dist/agent-src/templates/agent-settings.md +1 -1
  61. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  62. package/dist/agent-src/templates/roadmaps.md +218 -0
  63. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
  64. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
  65. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
  66. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  67. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +260 -21
  68. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  69. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  70. package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
  71. package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  72. package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  73. package/dist/cli/python/knowledge_ingest.js +1 -1
  74. package/dist/cli/python/workspace_drive.js +1 -1
  75. package/dist/cli-delegate/check_update_banner.js +40 -2
  76. package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
  77. package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-4XFP2Y3E.js} +1 -1
  78. package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
  79. package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
  80. package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
  81. package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-7XGBX6ZH.js} +973 -555
  82. package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
  83. package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-FP36SWJD.js} +587 -141
  84. package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-IGD6ERX6.js} +62 -7
  85. package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-JNMVLWLR.js} +99 -14
  86. package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
  87. package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
  88. package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
  89. package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
  90. package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
  91. package/dist/cli-delegate/{chunk-QJWAUMJW.js → chunk-YJ72UIAK.js} +730 -15
  92. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  93. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  94. package/dist/cli-delegate/cmd_conformance.js +985 -831
  95. package/dist/cli-delegate/cmd_doctor.js +7 -5
  96. package/dist/cli-delegate/cmd_explain.js +2 -2
  97. package/dist/cli-delegate/cmd_export.js +9 -7
  98. package/dist/cli-delegate/cmd_fleet.js +4 -2
  99. package/dist/cli-delegate/cmd_handoff.js +7 -7
  100. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  101. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  102. package/dist/cli-delegate/cmd_migrate.js +2 -2
  103. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  104. package/dist/cli-delegate/cmd_preflight.js +4 -2
  105. package/dist/cli-delegate/cmd_prune.js +10 -8
  106. package/dist/cli-delegate/cmd_route_audit.js +3 -3
  107. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  108. package/dist/cli-delegate/cmd_session_recycle.js +4 -4
  109. package/dist/cli-delegate/cmd_settings_get.js +28 -2
  110. package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
  111. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  112. package/dist/cli-delegate/cmd_sync.js +10 -8
  113. package/dist/cli-delegate/cmd_uninstall.js +16 -13
  114. package/dist/cli-delegate/cmd_update.js +1 -1
  115. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  116. package/dist/cli-delegate/cmd_validate.js +12 -10
  117. package/dist/cli-delegate/cmd_versions.js +1 -1
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +90 -43
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +4 -4
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +10 -8
  125. package/dist/discovery/trust-report.md +3 -3
  126. package/dist/discovery/workspaces.json +8 -6
  127. package/dist/hooks/dispatch.js +7682 -2772
  128. package/dist/hooks/dispatch.sha256 +1 -0
  129. package/dist/install/claudeRuleRewrite.js +14 -3
  130. package/dist/install/conflict.js +60 -10
  131. package/dist/install/conflictTracker.js +218 -0
  132. package/dist/install/fsPrimitives.js +54 -0
  133. package/dist/install/install.mjs +2200 -1559
  134. package/dist/install/manifestFiles.js +259 -0
  135. package/dist/install/preflight.js +14 -2
  136. package/dist/install/preserve.js +157 -0
  137. package/dist/install/recordedOwnership.js +132 -0
  138. package/dist/install/txlog.js +11 -2
  139. package/dist/mcp/registry-manifest.json +3 -3
  140. package/dist/mcp/server.json +2 -2
  141. package/dist/mcp/server.mjs +3066 -1470
  142. package/dist/router.json +1 -1
  143. package/dist/scripts/_lib/agent_settings.js +3 -2
  144. package/dist/scripts/_lib/fs_atomic.js +167 -0
  145. package/dist/scripts/_lib/installed_tools.js +460 -0
  146. package/dist/scripts/_lib/lean_projection_mode.js +3 -2
  147. package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
  148. package/dist/server/routes/install.js +8 -0
  149. package/dist/server/routes/wizard.js +9 -3
  150. package/dist/server/schemas/settings.js +40 -5
  151. package/dist/shared/missionExecution.js +97 -0
  152. package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
  153. package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
  154. package/dist/ui/index.html +2 -2
  155. package/docs/MIGRATION.md +103 -0
  156. package/docs/contracts/settings-classes.md +28 -7
  157. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
  158. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
  159. package/docs/guidelines/design-fidelity-routing.md +29 -0
  160. package/package.json +4 -4
  161. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
  162. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
  163. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
  164. package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  165. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +260 -21
  166. package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  167. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  168. package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
  169. package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  170. package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  171. package/src/config/agent-settings.template.yml +168 -27
  172. package/src/config/auto-rule-budget.json +16 -0
  173. package/src/config/ci-local-parity.yml +36 -5
  174. package/src/config/continuity-surface.json +23 -2
  175. package/src/config/gate-coverage.yml +377 -13
  176. package/src/config/gate-violation-baselines.json +10 -6
  177. package/src/config/hook-latency-budget.json +21 -0
  178. package/src/config/hook-token-budget.json +4 -2
  179. package/src/config/loop-surfaces.yaml +215 -0
  180. package/src/config/metric-registry.yml +114 -0
  181. package/src/config/placeholder-drift-budget.json +10 -0
  182. package/src/config/platform-anchor.json +3 -2
  183. package/src/config/release-gate-locality.yml +11 -0
  184. package/src/config/routing-coverage-seed.json +33 -5
  185. package/src/config/rule-enforcement-baseline.json +0 -1
  186. package/src/install/claudeRuleRewrite.ts +16 -2
  187. package/src/install/conflict.ts +65 -9
  188. package/src/install/conflictTracker.ts +299 -0
  189. package/src/install/fsPrimitives.ts +54 -0
  190. package/src/install/manifestFiles.ts +312 -0
  191. package/src/install/preflight.ts +16 -2
  192. package/src/install/preserve.ts +205 -0
  193. package/src/install/recordedOwnership.ts +149 -0
  194. package/src/install/txlog.ts +11 -2
  195. package/src/install/types.ts +19 -4
  196. package/src/scripts/_cli/cmd_conformance.ts +88 -15
  197. package/src/scripts/_cli/cmd_doctor.ts +7 -20
  198. package/src/scripts/_cli/cmd_route_explain.ts +9 -2
  199. package/src/scripts/_cli/cmd_settings_get.ts +44 -0
  200. package/src/scripts/_cli/doctor_execution.ts +173 -0
  201. package/src/scripts/_cli/doctor_network_posture.ts +226 -0
  202. package/src/scripts/_lib/activation_payload.ts +247 -0
  203. package/src/scripts/_lib/agent_settings.ts +4 -2
  204. package/src/scripts/_lib/authority_path.ts +102 -0
  205. package/src/scripts/_lib/body_portable.ts +102 -0
  206. package/src/scripts/_lib/cascade_base.ts +94 -0
  207. package/src/scripts/_lib/cc_transcript.ts +132 -1
  208. package/src/scripts/_lib/changelog_eras.ts +7 -2
  209. package/src/scripts/_lib/concern_sla_window.ts +200 -0
  210. package/src/scripts/_lib/continuation_ladder.ts +149 -2
  211. package/src/scripts/_lib/council_transport.ts +129 -0
  212. package/src/scripts/_lib/delivery_ready.ts +112 -0
  213. package/src/scripts/_lib/forge_protection.ts +381 -0
  214. package/src/scripts/_lib/forge_reader.ts +558 -0
  215. package/src/scripts/_lib/hook_platform_keys.ts +27 -0
  216. package/src/scripts/_lib/host_env_write.ts +111 -0
  217. package/src/scripts/_lib/json_python_parity.ts +127 -0
  218. package/src/scripts/_lib/lean_projection_mode.ts +14 -3
  219. package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
  220. package/src/scripts/_lib/loop_surfaces.ts +382 -0
  221. package/src/scripts/_lib/mission_record.ts +190 -0
  222. package/src/scripts/_lib/obligation_frequency.ts +217 -0
  223. package/src/scripts/_lib/obligations.ts +513 -0
  224. package/src/scripts/_lib/orchestration_record.ts +11 -20
  225. package/src/scripts/_lib/probe_inputs.ts +271 -0
  226. package/src/scripts/_lib/read_surface_scan.ts +322 -0
  227. package/src/scripts/_lib/release_highlights.ts +201 -11
  228. package/src/scripts/_lib/release_holds.ts +493 -0
  229. package/src/scripts/_lib/release_migration_gate.ts +184 -0
  230. package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
  231. package/src/scripts/_lib/rides_along.ts +102 -0
  232. package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
  233. package/src/scripts/_lib/shell_write_shapes.ts +108 -0
  234. package/src/scripts/_lib/structural_hiding.ts +622 -0
  235. package/src/scripts/_lib/test_delta.ts +166 -0
  236. package/src/scripts/_lib/test_provenance.ts +171 -0
  237. package/src/scripts/_lib/turn_end_refusals.ts +525 -4
  238. package/src/scripts/_lib/turn_end_transcript.ts +216 -0
  239. package/src/scripts/_lib/typed_op_grant.ts +246 -0
  240. package/src/scripts/_lib/typed_op_watch.ts +185 -0
  241. package/src/scripts/_lib/verification_command.ts +324 -0
  242. package/src/scripts/_lib/verification_evidence.ts +647 -0
  243. package/src/scripts/_lib/verify_clause.ts +280 -0
  244. package/src/scripts/ai_council/config.ts +8 -11
  245. package/src/scripts/ai_council/fallback_config.ts +5 -3
  246. package/src/scripts/ai_council/ownership_classes.ts +118 -0
  247. package/src/scripts/ai_team/team_dispatch.ts +4 -0
  248. package/src/scripts/ask_block_census.ts +285 -15
  249. package/src/scripts/before_complete_hook.ts +340 -23
  250. package/src/scripts/bench_hook_latency.ts +412 -5
  251. package/src/scripts/cache_realization_report.ts +61 -1
  252. package/src/scripts/check_argument_hint.ts +287 -0
  253. package/src/scripts/check_claims.ts +125 -1
  254. package/src/scripts/check_enforcement_coverage.ts +38 -9
  255. package/src/scripts/check_enforcement_matrix.ts +866 -0
  256. package/src/scripts/check_finding_dispositions.ts +22 -3
  257. package/src/scripts/check_gate_reachability.ts +173 -10
  258. package/src/scripts/check_generator_sync.ts +1025 -0
  259. package/src/scripts/check_host_docs_digest.ts +786 -0
  260. package/src/scripts/check_host_format_column.ts +559 -0
  261. package/src/scripts/check_input_references.ts +228 -0
  262. package/src/scripts/check_inputs_parity.ts +235 -0
  263. package/src/scripts/check_kernel_edit_ratified.ts +47 -5
  264. package/src/scripts/check_kill_switch_table.ts +294 -0
  265. package/src/scripts/check_placeholder_drift.ts +221 -0
  266. package/src/scripts/check_preamble_payload_budget.ts +75 -2
  267. package/src/scripts/check_read_surface_coverage.ts +515 -0
  268. package/src/scripts/check_release_highlights.ts +33 -1
  269. package/src/scripts/check_release_holds.ts +568 -0
  270. package/src/scripts/check_routing_coverage.ts +378 -11
  271. package/src/scripts/check_rule_projection_integrity.ts +22 -12
  272. package/src/scripts/check_static_parity.ts +17 -0
  273. package/src/scripts/check_test_delta.ts +294 -0
  274. package/src/scripts/check_test_weakening.ts +299 -0
  275. package/src/scripts/ci_settle.ts +145 -19
  276. package/src/scripts/closure_scan.ts +447 -0
  277. package/src/scripts/compile_hook_manifest.ts +102 -18
  278. package/src/scripts/council_record_shape.ts +209 -0
  279. package/src/scripts/external_sources_denylist.json +29 -4
  280. package/src/scripts/hook_manifest.json +1 -1
  281. package/src/scripts/hook_manifest.yaml +127 -11
  282. package/src/scripts/hooks/block_config_weakening.ts +229 -4
  283. package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
  284. package/src/scripts/hooks/block_plumbing_writes.ts +314 -0
  285. package/src/scripts/hooks/bundle_integrity.ts +291 -0
  286. package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
  287. package/src/scripts/hooks/code_graph_context_hook.ts +1 -2
  288. package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
  289. package/src/scripts/hooks/concern_registry.ts +6 -0
  290. package/src/scripts/hooks/concern_timings.ts +94 -0
  291. package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
  292. package/src/scripts/hooks/design_pass_hook.ts +221 -5
  293. package/src/scripts/hooks/design_slop_hook.ts +1 -2
  294. package/src/scripts/hooks/dispatch_hook.ts +25 -19
  295. package/src/scripts/hooks/edit_shape_hook.ts +1 -2
  296. package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
  297. package/src/scripts/hooks/evidence_independence.ts +97 -2
  298. package/src/scripts/hooks/exit_codes.ts +128 -0
  299. package/src/scripts/hooks/host_lowering.json +1 -0
  300. package/src/scripts/hooks/host_lowering.ts +128 -3
  301. package/src/scripts/hooks/host_lowering.yaml +262 -46
  302. package/src/scripts/hooks/host_semantics.ts +30 -2
  303. package/src/scripts/hooks/injection_budget.ts +9 -2
  304. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
  305. package/src/scripts/hooks/journal_record_hook.ts +1 -2
  306. package/src/scripts/hooks/memory_recall_hook.ts +539 -0
  307. package/src/scripts/hooks/obligation_settle_hook.ts +328 -0
  308. package/src/scripts/hooks/one_question_per_ask_hook.ts +25 -4
  309. package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
  310. package/src/scripts/hooks/permission_gate.ts +1 -2
  311. package/src/scripts/hooks/push_settle_hook.ts +1 -3
  312. package/src/scripts/hooks/replay_hook.ts +2 -1
  313. package/src/scripts/hooks/reread_guard_hook.ts +1 -2
  314. package/src/scripts/hooks/review_baseline_hook.ts +1 -2
  315. package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
  316. package/src/scripts/hooks/rule_inject_hook.ts +55 -4
  317. package/src/scripts/hooks/run_continuation_hook.ts +30 -35
  318. package/src/scripts/hooks/skill_route_hook.ts +1 -2
  319. package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
  320. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
  321. package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
  322. package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
  323. package/src/scripts/hooks/table_fingerprint.ts +49 -0
  324. package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
  325. package/src/scripts/hooks/telemetry_usage_hook.ts +1 -2
  326. package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
  327. package/src/scripts/hooks/turn_end_gate_hook.ts +337 -324
  328. package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
  329. package/src/scripts/hooks_doctor.ts +85 -0
  330. package/src/scripts/hooks_status.ts +19 -0
  331. package/src/scripts/install.ts +109 -210
  332. package/src/scripts/janitor.ts +7 -0
  333. package/src/scripts/lint_decision_classes.ts +464 -0
  334. package/src/scripts/lint_deny_text.ts +419 -0
  335. package/src/scripts/lint_exit_codes.ts +262 -0
  336. package/src/scripts/lint_hook_manifest.ts +66 -0
  337. package/src/scripts/lint_major_migration_sections.ts +450 -0
  338. package/src/scripts/lint_plan_risk_register.ts +47 -3
  339. package/src/scripts/lint_roadmap_blockers.ts +139 -12
  340. package/src/scripts/lint_roadmap_producers.ts +202 -0
  341. package/src/scripts/lint_skill_descriptions.ts +1 -1
  342. package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
  343. package/src/scripts/mcp_server/prompts.ts +142 -1
  344. package/src/scripts/measure_rule_budget.ts +101 -5
  345. package/src/scripts/measure_skill_ranker_baseline.ts +305 -51
  346. package/src/scripts/measure_turn_end_gate.ts +193 -0
  347. package/src/scripts/memory_lookup.ts +1 -1
  348. package/src/scripts/new_roadmap.ts +37 -0
  349. package/src/scripts/orchestration_record.ts +0 -5
  350. package/src/scripts/prepack-check.mjs +53 -0
  351. package/src/scripts/release.ts +14 -98
  352. package/src/scripts/release_drill.ts +267 -1
  353. package/src/scripts/release_publication.ts +64 -1
  354. package/src/scripts/report_enforcement_drift.ts +566 -0
  355. package/src/scripts/report_host_injection_effect.ts +3 -11
  356. package/src/scripts/report_invocation_surface.ts +383 -0
  357. package/src/scripts/report_obligation_carriers.ts +699 -0
  358. package/src/scripts/report_obligation_writer_split.ts +236 -0
  359. package/src/scripts/report_skill_menu_census.ts +208 -0
  360. package/src/scripts/report_standing_payload_by_host.ts +26 -152
  361. package/src/scripts/roadmap_verify_share.ts +213 -0
  362. package/src/scripts/schemas/agent-settings.schema.json +23 -0
  363. package/src/scripts/schemas/command.schema.json +48 -0
  364. package/src/scripts/schemas/review-findings.schema.json +4 -0
  365. package/src/scripts/schemas/skill.schema.json +44 -0
  366. package/src/scripts/scope_growth.ts +219 -0
  367. package/src/scripts/self_review_gate.ts +359 -10
  368. package/src/scripts/semantic_parity_census.ts +314 -0
  369. package/src/scripts/session_eol_report.ts +54 -1
  370. package/src/scripts/sweep_dead_scan_roots.ts +1 -1
  371. package/src/scripts/trigger_eval_grandfather.json +0 -3
  372. package/src/scripts/trigger_eval_rotation.ts +122 -27
  373. package/src/scripts/ui_conformance_probe.ts +774 -0
  374. package/src/scripts/update_prices.ts +85 -3
  375. package/src/scripts/write_bundle_digest.mjs +74 -0
  376. package/src/server/schemas/settings.ts +62 -7
  377. package/src/shared/missionExecution.ts +126 -0
  378. package/src/templates/consumer-settings/ONBOARDING.md +1 -0
  379. package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
  380. package/dist/ui/assets/index-D0jaCRPM.js +0 -29
  381. package/dist/ui/assets/index-jSfMW8_t.css +0 -1
  382. /package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-7RQP4UDH.js} +0 -0
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * obligation-settle — the reader the delivered-obligation record never had.
4
+ *
5
+ * The injector has always known which rules it delivered into a session. Until
6
+ * this concern, nothing asked whether the turn that received them discharged
7
+ * any. This is that question, asked at turn-end, and — for now — asked out
8
+ * loud and answered with nothing.
9
+ *
10
+ * SHADOW ONLY. IT REFUSES NOTHING, AND THAT IS NOT A PLACEHOLDER.
11
+ * It computes the verdict a future armed detector would reach, records it, and
12
+ * returns allow on every path. Arming is gated on a bar pre-registered in
13
+ * `docs/CLAIMS.md` BEFORE any code able to refuse exists, so that the bar
14
+ * cannot be chosen to fit the numbers the shadow window happened to produce.
15
+ * The estate already has one blocking turn-end concern and the first-ranked
16
+ * risk against this work is that a second one refuses a clean turn and an
17
+ * operator disables the carrier for good.
18
+ *
19
+ * THE TOUCHED SET COMES FROM THE DIFF, NOT FROM TOOL EVENTS.
20
+ * A tool event carries the path the tool was given. A shell heredoc writing
21
+ * three files reports one Bash call and no paths at all, so a detector reading
22
+ * tool events is blind to exactly the turns that wrote the most. `git diff
23
+ * --numstat HEAD` plus `git ls-files --others` sees the tree as it actually
24
+ * is, which is the only description that cannot be evaded by how the write was
25
+ * spelled. The helpers are the end-review concern's own, imported rather than
26
+ * re-derived.
27
+ *
28
+ * IT REFUSES ONLY ON CLASSES THAT COULD HAVE A DISCHARGE.
29
+ * `hook`, `validator` and `test` name carriers that run and leave traces.
30
+ * `observer`, `instruction-only` and `none` do not, so demanding a discharge
31
+ * for one would demand evidence nobody can produce — and 69 of 97 delivered
32
+ * rules on the frozen corpus are class `none`.
33
+ *
34
+ * IT IS SILENT WHILE A SUBAGENT DISPATCH IS OPEN.
35
+ * Three of the turn-end gate's six detectors are gated this way and three are
36
+ * not; the difference is whether the finding could be about work a dispatch is
37
+ * still doing. This one could — a subagent writing UI files is the canonical
38
+ * case — so it takes the gated side.
39
+ */
40
+
41
+ import path from 'node:path';
42
+ import process from 'node:process';
43
+
44
+ import { readHookStdin } from './hook_stdin.js';
45
+ // The WRITER's own root resolver, imported rather than re-derived. A second
46
+ // spelling of "which tree is this" is how a reader comes to address a ledger
47
+ // the writer never wrote — which is the defect this whole file is repairing,
48
+ // one field over.
49
+ import { workspaceRoot as writerWorkspaceRoot } from './rule_inject_hook.js';
50
+
51
+ import { may_refuse_on } from '../_lib/obligation_frequency.js';
52
+ import { appendShadow, readDelivered, readDischarged, stamp } from '../_lib/obligations.js';
53
+ import { loadRouter, matchTierRules } from '../_lib/rule_injection.js';
54
+ import { gitNumstatRows, isDocPath, untrackedNonDocFiles } from './end_review_nudge_hook.js';
55
+ import { openRecordStats } from './subagent_ledger_hook.js';
56
+ import { EXIT_ALLOW } from './exit_codes.js';
57
+
58
+ /**
59
+ * Every non-doc path this turn wrote, tracked or not.
60
+ *
61
+ * Doc paths are excluded on the same grounds the end-review concern excludes
62
+ * them: a markdown edit is not the kind of change whose obligations this
63
+ * detector can speak to, and including them would make almost every turn a
64
+ * candidate.
65
+ */
66
+ export function touchedPaths(cwd: string): string[] {
67
+ const tracked = gitNumstatRows(cwd)
68
+ .map((r) => r.path)
69
+ .filter((p) => p !== '' && !isDocPath(p));
70
+ const untracked = untrackedNonDocFiles(cwd);
71
+ return [...new Set([...tracked, ...untracked])];
72
+ }
73
+
74
+ export interface SettleVerdict {
75
+ /** Non-doc paths this turn wrote. */
76
+ readonly touched: string[];
77
+ /** Delivered rules whose path triggers match something touched. */
78
+ readonly candidates: string[];
79
+ /** Candidates with no recorded discharge, and a class that could have one. */
80
+ readonly missing: string[];
81
+ /** True when a subagent dispatch is open — every other field is then advisory only. */
82
+ readonly dispatchOpen: boolean;
83
+ }
84
+
85
+ /**
86
+ * What an armed detector would conclude, computed without refusing anything.
87
+ *
88
+ * Exported whole rather than as a boolean so the shadow row, the tests and any
89
+ * later armed path all read the SAME computation. A detector whose shadow
90
+ * measurement and live behaviour come from different code measures nothing.
91
+ */
92
+ export function computeVerdict(root: string, session: string): SettleVerdict {
93
+ const dispatchOpen = (() => {
94
+ try {
95
+ return openRecordStats(root).open_count > 0;
96
+ } catch {
97
+ // An unreadable ledger is not a reason to change the verdict.
98
+ return false;
99
+ }
100
+ })();
101
+
102
+ const touched = touchedPaths(root);
103
+ if (touched.length === 0) {
104
+ return { touched, candidates: [], missing: [], dispatchOpen };
105
+ }
106
+
107
+ const delivered = readDelivered(root, session);
108
+ if (delivered.length === 0) {
109
+ return { touched, candidates: [], missing: [], dispatchOpen };
110
+ }
111
+
112
+ let pathMatched = new Set<string>();
113
+ try {
114
+ const router = loadRouter(root);
115
+ // Empty prompt, so only PATH triggers can fire. A turn's file writes
116
+ // are not a restatement of the user's request and must not re-fire
117
+ // keyword rules — the same reasoning the injector applies on its own
118
+ // tool slot.
119
+ pathMatched = new Set(matchTierRules(router, '', touched, null).map((m) => m.id));
120
+ } catch {
121
+ return { touched, candidates: [], missing: [], dispatchOpen };
122
+ }
123
+
124
+ const candidates = delivered
125
+ .filter((r) => pathMatched.has(r.rule) && may_refuse_on(r.cls))
126
+ .map((r) => r.rule);
127
+
128
+ const discharged = new Set(readDischarged(root, session).map((r) => r.rule));
129
+ const missing = candidates.filter((id) => !discharged.has(id));
130
+ return { touched, candidates: [...new Set(candidates)], missing: [...new Set(missing)] , dispatchOpen };
131
+ }
132
+
133
+ /**
134
+ * Whether this reading should force a continuation, were anything armed.
135
+ *
136
+ * An UNCHANGED missing set on a second reading means the previous nudge moved
137
+ * nothing, so nudging again would loop rather than progress. The obligations
138
+ * stay OPEN — that is the whole point, and it is the side of the source set's
139
+ * self-contradiction this ships. A budget running out is a fact about the
140
+ * budget; letting it write a policy verdict is how an unmet obligation becomes
141
+ * a satisfied one with nobody deciding, and an exhausted budget is exactly the
142
+ * moment the obligation is least likely to have been met.
143
+ *
144
+ * There is therefore no `waived` state anywhere in this file, and no code path
145
+ * that writes one.
146
+ */
147
+ export function shouldContinue(attempt: number): boolean {
148
+ return attempt <= 1;
149
+ }
150
+
151
+ /**
152
+ * The session and root this reading is about, resolved the way the WRITER does.
153
+ *
154
+ * THE DEFECT THIS EXISTS TO CLOSE. This hook used to read
155
+ * `CLAUDE_CODE_SESSION_ID` out of the process environment and return allow when
156
+ * it was empty. The dispatcher sets no such variable — it hands each concern
157
+ * the envelope on stdin and `AGENT_CONFIG_PACKAGE_ROOT` in the environment,
158
+ * nothing else — so on every dispatched stop event the reader looked for a
159
+ * ledger under a key the writer never used. Measured 2026-09-29 on this
160
+ * machine's own ledgers: 187 delivered rows, 0 shadow rows, across 8 sessions.
161
+ *
162
+ * WHY THE ORDER IS ENVELOPE-THEN-ENVIRONMENT AND NOT THE REVERSE. The envelope
163
+ * id is the key `rule_inject_hook.ts` wrote the delivered rows under, so it is
164
+ * not merely the better source — it is the ONLY one that can find them. The
165
+ * environment fallback survives for a raw invocation that carries no envelope
166
+ * at all (a maintainer piping nothing, a host shim that skips the dispatcher),
167
+ * which is a case where guessing wrong costs a missing reading rather than a
168
+ * wrong one.
169
+ *
170
+ * THE ROOT IS PART OF THE SAME JOIN, not a second change riding along. A ledger
171
+ * is addressed by root AND session; reading the session from the envelope while
172
+ * taking the root from `process.cwd()` would leave the pair half-joined, and the
173
+ * two disagree exactly on the hosts whose shim does not chdir. `cwd` stays the
174
+ * fallback because that is what the dispatcher sets it to.
175
+ *
176
+ * Both spellings of each key are accepted because the injector accepts both.
177
+ */
178
+ export function resolveSettleContext(
179
+ envelope: Record<string, unknown>,
180
+ payload: Record<string, unknown>,
181
+ env: Record<string, string | undefined>,
182
+ ): { root: string; session: string } {
183
+ const str = (...values: unknown[]): string => {
184
+ for (const v of values) {
185
+ if (typeof v === 'string' && v.trim() !== '') return v.trim();
186
+ }
187
+ return '';
188
+ };
189
+ return {
190
+ // `workspaceRoot` is the INJECTOR's function, not a copy of it. It reads
191
+ // `workspace` / `cwd` / `project_dir`; this file used to read
192
+ // `workspace_root` / `workspace` / `cwd`, so the two key sets overlapped
193
+ // without matching and the pair was joined on the session only. It
194
+ // happened to agree on both real envelope shapes — the dispatcher sets
195
+ // `workspace_root` and chdirs concerns to it, a native wiring passes
196
+ // `cwd` — which made the asymmetry a property of today's envelopes
197
+ // rather than of the code. `workspace_root` is appended ahead of the
198
+ // shared resolver because the dispatcher is the only producer that sets
199
+ // it and nothing else reads it.
200
+ root:
201
+ str(envelope['workspace_root'])
202
+ || writerWorkspaceRoot(envelope as Parameters<typeof writerWorkspaceRoot>[0]),
203
+ session: str(
204
+ envelope['session_id'],
205
+ envelope['sessionId'],
206
+ payload['session_id'],
207
+ payload['sessionId'],
208
+ // The one pre-existing source, kept as the last resort and NOT
209
+ // joined by siblings: adding a name the writer never keys on
210
+ // would address a ledger that cannot exist.
211
+ env['CLAUDE_CODE_SESSION_ID'],
212
+ ),
213
+ };
214
+ }
215
+
216
+ /**
217
+ * The session id the WRITER would have used, for the ledger nobody reads.
218
+ *
219
+ * `rule_inject_hook.ts` defaults an unnamed session to the literal `unknown`
220
+ * and writes delivered rows there; this reader used to return `''` and allow, so
221
+ * that population was invisible to every reading of the bar. Reported rather
222
+ * than silently joined: a shared `unknown` bucket aggregates unrelated sessions,
223
+ * so reading it as one session's turn would be worse than not reading it. The
224
+ * constant is exported so a future census can count what is sitting there.
225
+ */
226
+ export const WRITER_UNNAMED_SESSION = 'unknown';
227
+
228
+ /** The envelope on stdin, or an empty object when there is none to read. */
229
+ function readEnvelope(): { envelope: Record<string, unknown>; payload: Record<string, unknown> } {
230
+ let envelope: Record<string, unknown> = {};
231
+ try {
232
+ const raw = readHookStdin();
233
+ const parsed: unknown = raw.trim() === '' ? {} : JSON.parse(raw);
234
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
235
+ envelope = parsed as Record<string, unknown>;
236
+ }
237
+ } catch {
238
+ // A malformed envelope is not a reason to refuse, and this concern
239
+ // refuses nothing anyway. It is a reason to read nothing from it.
240
+ }
241
+ const nested = envelope['payload'];
242
+ const payload =
243
+ typeof nested === 'object' && nested !== null && !Array.isArray(nested)
244
+ ? (nested as Record<string, unknown>)
245
+ : envelope;
246
+ return { envelope, payload };
247
+ }
248
+
249
+ /**
250
+ * The resolver as it stood BEFORE the join fix, kept reachable for one test.
251
+ *
252
+ * A reproduction that cannot run the old code is not a reproduction — it is an
253
+ * assertion about the new function's behavior on inputs nobody sends, and
254
+ * `tests/hooks/obligation_settle.test.ts` carried exactly that until an
255
+ * independent review named it. This function is dead on every production path
256
+ * (nothing but the fixture calls it) and exists so the defect stays executable:
257
+ * environment-only resolution, allow when empty, root from the cwd.
258
+ */
259
+ export function resolveSettleContextPreFix(
260
+ _envelope: Record<string, unknown>,
261
+ _payload: Record<string, unknown>,
262
+ env: Record<string, string | undefined>,
263
+ ): { root: string; session: string } {
264
+ // Same arity as the live resolver ON PURPOSE. A narrower signature would let
265
+ // the fixture pass the envelope in as `env`, where the lookup misses for the
266
+ // wrong reason and the test goes green without exercising the defect.
267
+ return { root: process.cwd(), session: (env['CLAUDE_CODE_SESSION_ID'] ?? '').trim() };
268
+ }
269
+
270
+ /**
271
+ * Which context resolver this reading uses — the seam the pre-fix fixture needs.
272
+ *
273
+ * It is NOT a parameter of `main()`, and that is a contract rather than a
274
+ * preference: `concern_main_signature` requires every concern's `main()` to take
275
+ * argv first or nothing, because the dispatcher calls `main(argv)` — so a
276
+ * resolver in first position would receive an argv array at runtime and resolve
277
+ * a session from it. Caught by that test, which is the reason this indirection
278
+ * exists instead of the obvious default parameter.
279
+ */
280
+ export type SettleResolver = (
281
+ envelope: Record<string, unknown>,
282
+ payload: Record<string, unknown>,
283
+ env: Record<string, string | undefined>,
284
+ ) => { root: string; session: string };
285
+
286
+ export function runSettle(resolve: SettleResolver = resolveSettleContext): number {
287
+ const { envelope, payload } = readEnvelope();
288
+ const { root, session } = resolve(envelope, payload, process.env);
289
+ if (session === '') return EXIT_ALLOW;
290
+
291
+ let verdict: SettleVerdict;
292
+ try {
293
+ verdict = computeVerdict(root, session);
294
+ } catch {
295
+ // A detector that cannot compute has nothing to say. It never has a
296
+ // refusal to withhold, so there is no safe-vs-unsafe choice here.
297
+ return EXIT_ALLOW;
298
+ }
299
+
300
+ // Silent while a dispatch is open: the files may be a subagent's, still
301
+ // being written, and a shadow row claiming otherwise would poison the very
302
+ // corpus the arming decision is measured against.
303
+ if (verdict.dispatchOpen) return EXIT_ALLOW;
304
+ if (verdict.missing.length === 0) return EXIT_ALLOW;
305
+
306
+ const attempt = appendShadow(root, session, verdict.missing, stamp());
307
+ if (attempt === 0) return EXIT_ALLOW;
308
+
309
+ // ONE line for the whole missing set, never one per obligation — the same
310
+ // aggregation the row itself uses, for the same reason.
311
+ process.stderr.write(
312
+ `obligation-settle (shadow, refusing nothing): ${verdict.missing.length} `
313
+ + `obligation(s) with no recorded discharge after writing `
314
+ + `${verdict.touched.length} file(s): ${verdict.missing.join(', ')}`
315
+ + `${shouldContinue(attempt) ? '' : ' — unchanged since the last reading; still open'}\n`,
316
+ );
317
+ return EXIT_ALLOW;
318
+ }
319
+
320
+ /** The dispatcher entry point. Argv-shaped, per `concern_main_signature`. */
321
+ export function main(_argv: readonly string[] = process.argv.slice(2)): number {
322
+ return runSettle();
323
+ }
324
+
325
+ // Bundle-safety: never auto-run when inlined into an esbuild bundle.
326
+ if (process.argv[1] !== undefined && path.basename(process.argv[1]).startsWith('obligation_settle')) {
327
+ process.exit(main());
328
+ }
@@ -16,10 +16,31 @@
16
16
  *
17
17
  * WHAT IT SEES, honestly. `_lib/structured_ask.ts` carries no observed
18
18
  * per-host tool, so this guard matches on a name SHAPE and is filtered by the
19
- * manifest's per-concern `tools:` key to the same candidate names. On every
20
- * host measured today it therefore fires on nothing — the concern exists so
21
- * that the first host to ship a picker meets the rule already in force, not
22
- * because a violation has been observed.
19
+ * manifest's per-concern `tools:` key to the same candidate names. No host's
20
+ * delivered surface has been OBSERVED in this tree carrying a question-picker
21
+ * tool, which is why `STRUCTURED_ASK_SHAPES` is empty and no per-host shape row
22
+ * exists — the same sentence `_lib/structured_ask.ts` already uses about itself.
23
+ *
24
+ * That is NARROWER than the claim this header used to make. The earlier
25
+ * sentence asserted that on every host measured today the concern therefore
26
+ * matches nothing at all, and the two are different claims with only the first
27
+ * supported. The old wording is described here rather than quoted, because
28
+ * 1.1's drift check is a grep and a grep cannot tell a refuted quotation from
29
+ * a live assertion. The measurement base is ONE row:
30
+ * `_lib/host_capability.ts`'s registry records `structured_ask: false` for
31
+ * `claude` alone, observed-absent on Claude Code 2.1.263 on 2026-09-07, and the
32
+ * other eight hosts in `docs/enforcement-by-host.md` have no row at all — never
33
+ * looked, not measured. "Every host measured" read against that table therefore
34
+ * describes one host, and a present-tense claim about what the concern matches
35
+ * turns one dated single-version reading into a standing property, which the registry's own
36
+ * comment refuses in the same breath: the observation "is not a claim that the
37
+ * vendor ships no such tool anywhere, and a later session observing one writes
38
+ * the `true` row over it".
39
+ *
40
+ * So the honest statement is about what has been looked at, not about what
41
+ * fires. The concern exists so the first host whose delivered surface carries a
42
+ * picker meets the rule already in force, not because a violation has been
43
+ * observed.
23
44
  *
24
45
  * ENFORCEMENT REACH, also honestly. `fail_closed: false` and the exit-1 deny
25
46
  * are only a deny where the host both binds `pre_tool_use` AND honours the
@@ -72,8 +72,7 @@ import { buildOrchestrationLine, type RecordInput } from '../_lib/orchestration_
72
72
  import { DEFAULT_DIR } from '../orchestration_record.js';
73
73
  import { is_replay_mode } from './state_io.js';
74
74
  import { readHookStdin } from './hook_stdin.js';
75
-
76
- const EXIT_ALLOW = 0;
75
+ import { EXIT_ALLOW } from './exit_codes.js';
77
76
 
78
77
  type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
79
78
  type JsonObject = { [k: string]: JsonValue };
@@ -20,6 +20,7 @@ import {
20
20
  type PermissionDecision,
21
21
  type PermissionEmission,
22
22
  } from "./host_semantics.js";
23
+ import { EXIT_ALLOW, EXIT_BLOCK } from './exit_codes.js';
23
24
 
24
25
  type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
25
26
  type JsonObject = { [k: string]: JsonValue };
@@ -29,8 +30,6 @@ function _isObject(v: unknown): v is JsonObject {
29
30
  }
30
31
 
31
32
  /** Mirrors `dispatch_hook.EXIT_ALLOW` / `EXIT_BLOCK`; imported would be a cycle. */
32
- const EXIT_ALLOW = 0;
33
- const EXIT_BLOCK = 1;
34
33
 
35
34
  /** The host's `tool_name`, or `""` when the event carries none. */
36
35
  export function _payload_tool_name(envelope: JsonObject): string {
@@ -54,9 +54,7 @@ import path from "node:path";
54
54
  import { execFileSync } from "node:child_process";
55
55
  import { fileURLToPath, pathToFileURL } from "node:url";
56
56
  import { readHookStdin } from "./hook_stdin.js";
57
-
58
- const EXIT_ALLOW = 0;
59
- const EXIT_WARN = 2;
57
+ import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
60
58
 
61
59
  type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
62
60
  type JsonObject = { [k: string]: JsonValue };
@@ -36,6 +36,7 @@ import { spawnSync } from "node:child_process";
36
36
  import fs from "node:fs";
37
37
  import path from "node:path";
38
38
  import { fileURLToPath, pathToFileURL } from "node:url";
39
+ import { EXIT_USAGE } from './exit_codes.js';
39
40
 
40
41
  // src/scripts/hooks/replay_hook.ts → parents[3] is the repo root.
41
42
  const REPO_ROOT = path.resolve(
@@ -175,7 +176,7 @@ function _parse_args(argv: string[]): ReplayArgs {
175
176
  process.stderr.write(
176
177
  `replay_hook: the following arguments are required: ${missing.join(", ")}\n`,
177
178
  );
178
- process.exit(2);
179
+ process.exit(EXIT_USAGE);
179
180
  }
180
181
  return args;
181
182
  }
@@ -69,12 +69,11 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
69
69
  import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
70
70
  import { readHookStdin } from './hook_stdin.js';
71
71
  import { atomic_write_json } from './state_io.js';
72
+ import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
72
73
 
73
- const EXIT_ALLOW = 0;
74
74
  // Severity is taken from the EXIT CODE, not from the `decision` field — see
75
75
  // the file header for why this never blocks on `claude`. This concern never
76
76
  // returns exit 1 on any path.
77
- const EXIT_WARN = 2;
78
77
 
79
78
  /**
80
79
  * Committed exemption list — deliberately duplicated from
@@ -49,8 +49,7 @@ import { deriveSessionKey, totalNonDocMutatedLinesWithMeasure } from './end_revi
49
49
  import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
50
50
  import { readHookStdin } from './hook_stdin.js';
51
51
  import { atomic_write_json } from './state_io.js';
52
-
53
- const EXIT_OK = 0;
52
+ import { EXIT_ALLOW as EXIT_OK } from './exit_codes.js';
54
53
 
55
54
  export function buildBaseline(workspaceRoot: string, now: Date = new Date()): ReviewBaseline {
56
55
  const measured = totalNonDocMutatedLinesWithMeasure(workspaceRoot);
@@ -63,10 +63,9 @@ import {
63
63
  } from "./block_no_verify.js";
64
64
  import { readHookStdin } from "./hook_stdin.js";
65
65
  import { detectRtkCached } from "../../install/rtkDetection.js";
66
+ import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
66
67
 
67
68
  const SETTINGS_FILE = ".agent-settings.yml";
68
- const EXIT_ALLOW = 0;
69
- const EXIT_WARN = 2;
70
69
 
71
70
  type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
72
71
  type JsonObject = { [k: string]: JsonValue };
@@ -11,7 +11,14 @@
11
11
  * the 36.2 %-against-48 % run at `docs/CLAIMS.md:188-189`. Whatever that
12
12
  * instrument's flaws — and ADR-202 closed it — it points one way.
13
13
  *
14
- * SHIPPED ON FOR CLAUDE CODE SINCE ADR-265 — corrected 2026-09-08 (R2 finding
14
+ * SHIPPED ON FOR CLAUDE CODE SINCE ADR-267 — the delivery-default record, and
15
+ * the citation is corrected here (2026-09-13) from ADR-265, which decides
16
+ * something else entirely: whether the iron-law reserve is activated, answered
17
+ * no, with the verifier kept inside the change. Nothing in it ships a
18
+ * projection mode. ADR-267 `delivery-default-for-claude-code` is the record
19
+ * that turns this concern on for this host, and it is the one whose
20
+ * `review_trigger` fires if a rule stops arriving. Previously corrected
21
+ * 2026-09-08 (R2 finding
15
22
  * 4), because this paragraph read "DEFAULT OFF, AND OFF MEANS ZERO BYTES …
16
23
  * under every shipped default it emits nothing … there is no measured emission
17
24
  * to register yet" and all four clauses became false in the same change that
@@ -94,6 +101,13 @@ import {
94
101
  normalizeLeanProjectionMode,
95
102
  resolveLeanProjectionHosts,
96
103
  } from '../_lib/lean_projection_mode.js';
104
+ import { enforcement_class_from_frontmatter } from '../_lib/obligation_frequency.js';
105
+ import {
106
+ appendDelivered,
107
+ stamp,
108
+ type DeliveredRow,
109
+ type WriterInput,
110
+ } from '../_lib/obligations.js';
97
111
  import {
98
112
  loadRuleBody,
99
113
  loadRouter,
@@ -101,9 +115,7 @@ import {
101
115
  selectForInjection,
102
116
  } from '../_lib/rule_injection.js';
103
117
  import { readHookStdin } from './hook_stdin.js';
104
-
105
- const EXIT_ALLOW = 0;
106
- const EXIT_WARN = 2;
118
+ import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
107
119
 
108
120
  /**
109
121
  * Per-prompt injection ceiling, in UTF-8 BYTES.
@@ -237,6 +249,44 @@ export interface Injection {
237
249
  body: string;
238
250
  }
239
251
 
252
+ /**
253
+ * Record what this fire delivered, so something can later ask whether the turn
254
+ * discharged it.
255
+ *
256
+ * The write happens HERE and not in a later slot because this is the only
257
+ * place that knows the answer. By the time a turn ends, the selection that
258
+ * produced these ids is gone — the router would have to be re-run against a
259
+ * prompt nobody kept, which is a different computation that could disagree.
260
+ *
261
+ * EMITTER RECORD, NEVER A COMPLIANCE ONE. A row says a body was emitted into
262
+ * this slot. It does not say the model read it, and the ledger's own header
263
+ * carries the council lock that forbids reading it that way.
264
+ *
265
+ * Best-effort by construction: every failure path inside `appendDelivered`
266
+ * returns rather than throws, and this wrapper adds one more guard so a
267
+ * ledger problem can never turn a successful injection into a failed hook.
268
+ * A missed reading is cheaper than a refused turn, and this concern has no
269
+ * refusal to offer anyway.
270
+ */
271
+ export function recordDelivered(root: string, session: string, ruleIds: string[]): number {
272
+ try {
273
+ const now = stamp();
274
+ const rows: WriterInput<DeliveredRow>[] = ruleIds.map((id) => {
275
+ const body = loadRuleBody(root, id);
276
+ return {
277
+ rule: id,
278
+ // A rule with no projected body declares nothing this can read,
279
+ // which is `none` — the same answer as a body declaring none.
280
+ cls: body === null ? 'none' : enforcement_class_from_frontmatter(body),
281
+ at: now,
282
+ };
283
+ });
284
+ return appendDelivered(root, session, rows);
285
+ } catch {
286
+ return 0;
287
+ }
288
+ }
289
+
240
290
  /**
241
291
  * Build the injection for one event, or `null` for silence.
242
292
  *
@@ -371,6 +421,7 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
371
421
 
372
422
  for (const id of injection.rules) seen.add(id);
373
423
  writeSeen(root, session, seen);
424
+ recordDelivered(root, session, injection.rules);
374
425
 
375
426
  process.stdout.write(
376
427
  `${JSON.stringify({