@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,213 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * The runnable share of `verify:` clauses, per roadmap.
4
+ *
5
+ * A `verify:` clause names a command and never names what the command must
6
+ * produce, so a step can be flipped on a command that cannot fail. Two numbers
7
+ * say how bad that is, and neither had a producing command before this script:
8
+ * how many clauses name a COMMAND at all (the runnable share), and how many
9
+ * name an EXPECTATION (the falsifiable share).
10
+ *
11
+ * THIS IS A READER, NOT A GATE. It exits 0 on every corpus, including one where
12
+ * both shares are zero. That is a property of the reader, not a description of
13
+ * the tree: measured 2026-09-29, the tree carried 230 clauses, 93 naming a
14
+ * command and 6 naming an expectation — neither share is zero, and the
15
+ * commissioning roadmap's claim that the second one was is the first thing this
16
+ * script refuted. A ratchet needs a false-positive rate and two readings a
17
+ * quarter apart; it has neither, and a gate that reds all but a handful of
18
+ * roadmaps at once gets weakened until it finds nothing. What it buys instead
19
+ * is that the NEXT reading is a delta rather than a re-derivation.
20
+ *
21
+ * THE UNIT, stated because the figure is meaningless without it. One unit is
22
+ * one STEP BLOCK (`- [ ]`, `- [x]`, `- [~]`, `- [-]`, plus its continuation
23
+ * lines) that carries a `verify:` clause. Not one line: a clause wraps, and a
24
+ * line count would double-count a wrapped clause and count prose that merely
25
+ * mentions the token. Step blocks come from `closure_scan`'s own `units()`, so
26
+ * the two instruments agree on what a step is; that also inherits its
27
+ * exclusions — fenced code, and the `## Decisions` / `## Blockers` /
28
+ * `## Kill register` / `## Risk Register` discharge sections, where a mention
29
+ * of `verify:` is commentary rather than a step's oracle.
30
+ *
31
+ * Closed steps are counted. A `[x]` flipped on a clause that could not fail is
32
+ * the defect in its completed form, and excluding them would report the
33
+ * backlog as smaller every time someone closed one.
34
+ *
35
+ * CLI:
36
+ * ./scripts-run src/scripts/roadmap_verify_share
37
+ * ./scripts-run src/scripts/roadmap_verify_share --json
38
+ * ./scripts-run src/scripts/roadmap_verify_share --root <dir> [--recursive]
39
+ *
40
+ * Exit codes: 0 always, except 2 for bad argv or a dead scan root.
41
+ */
42
+ import * as fs from 'node:fs';
43
+ import * as path from 'node:path';
44
+ import process from 'node:process';
45
+ import { fileURLToPath } from 'node:url';
46
+
47
+ import { units } from './closure_scan.js';
48
+ import { DeadScopeError, assertScanned } from './_lib/scan_scope.js';
49
+ import { parseVerifyClause } from './_lib/verify_clause.js';
50
+
51
+ const _HERE = fileURLToPath(import.meta.url);
52
+ const _PROG = 'roadmap_verify_share';
53
+ const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
54
+ const DEFAULT_ROOT = 'agents/roadmaps';
55
+
56
+ export interface FileShare {
57
+ readonly file: string;
58
+ /** Step blocks carrying a `verify:` clause. */
59
+ readonly clauses: number;
60
+ /** Of those, the ones naming a command — the runnable share. */
61
+ readonly withCommand: number;
62
+ /** Of those, the ones naming an expectation — the falsifiable share. */
63
+ readonly withExpectation: number;
64
+ }
65
+
66
+ export interface ShareReport {
67
+ readonly root: string;
68
+ readonly files: number;
69
+ readonly clauses: number;
70
+ readonly withCommand: number;
71
+ readonly withExpectation: number;
72
+ readonly perFile: readonly FileShare[];
73
+ }
74
+
75
+ /** Count the clauses in one roadmap's text. */
76
+ export function shareOf(file: string, text: string): FileShare {
77
+ let clauses = 0;
78
+ let withCommand = 0;
79
+ let withExpectation = 0;
80
+ for (const u of units(text.split('\n'))) {
81
+ if (!u.hasVerify) continue;
82
+ const clause = parseVerifyClause(u.blockText);
83
+ if (clause === null) continue;
84
+ clauses += 1;
85
+ if (clause.command !== null) withCommand += 1;
86
+ if (clause.expect !== null) withExpectation += 1;
87
+ }
88
+ return { file, clauses, withCommand, withExpectation };
89
+ }
90
+
91
+ function markdownFiles(root: string, recursive: boolean): string[] {
92
+ const out: string[] = [];
93
+ const walk = (dir: string): void => {
94
+ let entries: fs.Dirent[];
95
+ try {
96
+ entries = fs.readdirSync(dir, { withFileTypes: true });
97
+ } catch {
98
+ return;
99
+ }
100
+ for (const e of entries) {
101
+ const full = path.join(dir, e.name);
102
+ if (e.isDirectory()) {
103
+ if (recursive) walk(full);
104
+ continue;
105
+ }
106
+ if (e.name.endsWith('.md')) out.push(full);
107
+ }
108
+ };
109
+ walk(root);
110
+ return out.sort();
111
+ }
112
+
113
+ export function report(rootAbs: string, rootLabel: string, recursive: boolean): ShareReport {
114
+ const files = markdownFiles(rootAbs, recursive);
115
+ // A root that resolved to nothing is blindness, not cleanliness: the share
116
+ // would read as a clean 0/0 and the reader would believe it.
117
+ assertScanned({ gate: _PROG, scanned: files.length, units: 'roadmap(s)', roots: [rootLabel] });
118
+ const perFile = files
119
+ .map((f) => shareOf(path.relative(REPO_ROOT, f), fs.readFileSync(f, 'utf-8')))
120
+ .filter((s) => s.clauses > 0);
121
+ return {
122
+ root: rootLabel,
123
+ files: files.length,
124
+ clauses: perFile.reduce((n, s) => n + s.clauses, 0),
125
+ withCommand: perFile.reduce((n, s) => n + s.withCommand, 0),
126
+ withExpectation: perFile.reduce((n, s) => n + s.withExpectation, 0),
127
+ perFile,
128
+ };
129
+ }
130
+
131
+ function pct(n: number, of: number): string {
132
+ return of === 0 ? 'n/a' : `${((n / of) * 100).toFixed(1)}%`;
133
+ }
134
+
135
+ export function render(r: ShareReport): string {
136
+ const lines: string[] = [];
137
+ lines.push(`root: ${r.root}`);
138
+ lines.push(`roadmaps scanned: ${String(r.files)}`);
139
+ lines.push(`verify clauses: ${String(r.clauses)}`);
140
+ lines.push(` naming a command: ${String(r.withCommand)} (${pct(r.withCommand, r.clauses)})`);
141
+ lines.push(` naming an expectation: ${String(r.withExpectation)} (${pct(r.withExpectation, r.clauses)})`);
142
+ lines.push('');
143
+ lines.push('| roadmap | clauses | command | expectation |');
144
+ lines.push('|---|---:|---:|---:|');
145
+ for (const s of r.perFile) {
146
+ lines.push(
147
+ `| \`${path.basename(s.file)}\` | ${String(s.clauses)} | ${String(s.withCommand)} | ${String(s.withExpectation)} |`,
148
+ );
149
+ }
150
+ return lines.join('\n') + '\n';
151
+ }
152
+
153
+ function _usage(): string {
154
+ return (
155
+ `usage: ${_PROG} [-h] [--json] [--root <dir>] [--recursive]\n\n` +
156
+ `Report the runnable and falsifiable share of \`verify:\` clauses. Gates nothing.\n`
157
+ );
158
+ }
159
+
160
+ export function main(argv?: readonly string[]): number {
161
+ const args = argv ?? process.argv.slice(2);
162
+ let json = false;
163
+ let recursive = false;
164
+ let root = DEFAULT_ROOT;
165
+ for (let i = 0; i < args.length; i += 1) {
166
+ const a = args[i] as string;
167
+ if (a === '-h' || a === '--help') {
168
+ process.stdout.write(_usage());
169
+ return 0;
170
+ } else if (a === '--json') json = true;
171
+ else if (a === '--recursive') recursive = true;
172
+ else if (a === '--root') {
173
+ const next = args[i + 1];
174
+ if (next === undefined) {
175
+ process.stderr.write(`${_usage()}${_PROG}: error: --root needs a directory\n`);
176
+ return 2;
177
+ }
178
+ root = next;
179
+ i += 1;
180
+ } else {
181
+ process.stderr.write(`${_usage()}${_PROG}: error: unrecognized arguments: ${a}\n`);
182
+ return 2;
183
+ }
184
+ }
185
+
186
+ const rootAbs = path.isAbsolute(root) ? root : path.join(REPO_ROOT, root);
187
+ let r: ShareReport;
188
+ try {
189
+ r = report(rootAbs, root, recursive);
190
+ } catch (e) {
191
+ if (e instanceof DeadScopeError) {
192
+ process.stderr.write(`${e.message}\n`);
193
+ return 2;
194
+ }
195
+ throw e;
196
+ }
197
+
198
+ process.stdout.write(json ? JSON.stringify(r, null, 2) + '\n' : render(r));
199
+ return 0;
200
+ }
201
+
202
+ function _isCliEntry(): boolean {
203
+ if (!process.argv[1]) return false;
204
+ try {
205
+ return fs.realpathSync(_HERE) === fs.realpathSync(path.resolve(process.argv[1]));
206
+ } catch {
207
+ return false;
208
+ }
209
+ }
210
+
211
+ if (_isCliEntry() || process.argv[1] === _HERE) {
212
+ process.exitCode = main();
213
+ }
@@ -101,6 +101,29 @@
101
101
  }
102
102
  }
103
103
  },
104
+ "delivery": {
105
+ "type": "object",
106
+ "additionalProperties": true,
107
+ "properties": {
108
+ "merge": {
109
+ "type": "string",
110
+ "enum": ["off", "on-green"],
111
+ "default": "off",
112
+ "description": "Whether a run may merge the pull request it produced. off (default) = the run ends at mergeable-green-and-open and says so. on-green = merge is permitted, and only when an object-bound grant covering {op: prod_merge, target: <base>} exists and the final head is required-check-green, target-current and tamper-checked (ADR-268 section 3). A precondition, never the authorisation by itself; forge auto-merge is the mechanism, so branch protection stays the gate."
113
+ },
114
+ "wait_for_ci": {
115
+ "type": "boolean",
116
+ "default": true,
117
+ "description": "Whether the run stays alive until the required checks settle. true (default) = the run drives CI and reports the settled verdict. false = the run ends once the branch is pushed and the PR is open. Independent of merge: a run may wait for CI without being allowed to merge."
118
+ },
119
+ "pr_topology": {
120
+ "type": "string",
121
+ "enum": ["single", "stacked"],
122
+ "default": "single",
123
+ "description": "How a mission's work is shaped into pull requests. single (default) = one branch, one pull request. stacked = a dependent series. stacked is never chosen by the agent and never asked about at roadmap creation — the owner plans it in roadmap frontmatter or it does not happen."
124
+ }
125
+ }
126
+ },
104
127
  "screenshots": {
105
128
  "type": "object",
106
129
  "additionalProperties": true,
@@ -8,6 +8,50 @@
8
8
  "additionalProperties": false,
9
9
  "required": ["name", "description", "disable-model-invocation"],
10
10
  "properties": {
11
+ "inputs": {
12
+ "type": "array",
13
+ "minItems": 1,
14
+ "description": "Structured declaration of the parameters this artifact takes. OPTIONAL on every artifact: one with no block validates unchanged, so nothing existing breaks and no migration is owed. Where the block IS present it is the single authority — the argument-hint and the MCP `arguments` set are derived from it, and a hand-written hint on the same artifact is a conflict rather than a merge (road-to-an-invocation-contract-that-reaches-the-wire).",
15
+ "items": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "required": ["name", "type"],
19
+ "properties": {
20
+ "name": {
21
+ "type": "string",
22
+ "pattern": "^[a-z][a-z0-9_]*$",
23
+ "description": "Parameter name. Lowercase snake_case, so it is safe both as a wire key and as an in-body ${name} reference."
24
+ },
25
+ "type": {
26
+ "enum": ["string", "number", "boolean", "enum", "path"],
27
+ "description": "Closed set on purpose: an unknown type must FAIL validation rather than reach a host that cannot interpret it."
28
+ },
29
+ "required": {
30
+ "type": "boolean",
31
+ "description": "Absent means optional."
32
+ },
33
+ "default": {
34
+ "description": "Value used when the caller supplies none. Any JSON type — it is checked against `type` by the consuming generator, not here."
35
+ },
36
+ "enum": {
37
+ "type": "array",
38
+ "minItems": 1,
39
+ "items": {
40
+ "type": "string",
41
+ "minLength": 1,
42
+ "pattern": "^[^|\\]>]+$",
43
+ "description": "A value. `|`, `]` and `>` are excluded because they are the delimiters of the derived argument-hint — permitting them would make the hint ambiguous and break the round-trip the hint gate asserts."
44
+ },
45
+ "description": "Allowed values. Only meaningful when `type` is `enum`."
46
+ },
47
+ "description": {
48
+ "type": "string",
49
+ "minLength": 1,
50
+ "description": "One line, shown to a caller choosing a value."
51
+ }
52
+ }
53
+ }
54
+ },
11
55
  "name": {
12
56
  "type": "string",
13
57
  "pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
@@ -103,6 +147,10 @@
103
147
  "pattern": "^[a-z][a-z0-9-]*$",
104
148
  "description": "Sub-command identifier within the cluster (e.g. `ci` for `/fix ci`)."
105
149
  },
150
+ "produces_roadmap": {
151
+ "type": "boolean",
152
+ "description": "This command produces a roadmap, so it ends in the plan-closure pass (`/challenge-me closure`). The declaration replaces the hard-coded entrance list that lived inside three command bodies and left the other five producers uncovered with nothing saying so. `lint_roadmap_producers` reds a command that declares it and carries no reference to the closure pass. Omit the key for commands that produce no plan."
153
+ },
106
154
  "superseded_by": {
107
155
  "type": "string",
108
156
  "pattern": "^[a-z][a-z0-9-]*( (--[a-z][a-z0-9-]*|[a-z][a-z0-9-]*))?$",
@@ -127,6 +127,10 @@
127
127
  "type": "string",
128
128
  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
129
129
  "description": "ISO calendar date of the disposition."
130
+ },
131
+ "contradicted": {
132
+ "type": "string",
133
+ "description": "The tree's mechanical disproof of the finding's premise, written by self_review_gate.annotateContradicted when a deletion claim names an artifact the range does not delete and the working tree still holds. A finding carrying this is NOT merge-blocking in either gate (self_review_gate.classifyBlocking and check_finding_dispositions.isBlocking both read it), and it is still reported so a human sees what was claimed and why it was set aside."
130
134
  }
131
135
  }
132
136
  }
@@ -13,6 +13,50 @@
13
13
  "domain"
14
14
  ],
15
15
  "properties": {
16
+ "inputs": {
17
+ "type": "array",
18
+ "minItems": 1,
19
+ "description": "Structured declaration of the parameters this artifact takes. OPTIONAL on every artifact: one with no block validates unchanged, so nothing existing breaks and no migration is owed. Where the block IS present it is the single authority — the argument-hint and the MCP `arguments` set are derived from it, and a hand-written hint on the same artifact is a conflict rather than a merge (road-to-an-invocation-contract-that-reaches-the-wire).",
20
+ "items": {
21
+ "type": "object",
22
+ "additionalProperties": false,
23
+ "required": ["name", "type"],
24
+ "properties": {
25
+ "name": {
26
+ "type": "string",
27
+ "pattern": "^[a-z][a-z0-9_]*$",
28
+ "description": "Parameter name. Lowercase snake_case, so it is safe both as a wire key and as an in-body ${name} reference."
29
+ },
30
+ "type": {
31
+ "enum": ["string", "number", "boolean", "enum", "path"],
32
+ "description": "Closed set on purpose: an unknown type must FAIL validation rather than reach a host that cannot interpret it."
33
+ },
34
+ "required": {
35
+ "type": "boolean",
36
+ "description": "Absent means optional."
37
+ },
38
+ "default": {
39
+ "description": "Value used when the caller supplies none. Any JSON type — it is checked against `type` by the consuming generator, not here."
40
+ },
41
+ "enum": {
42
+ "type": "array",
43
+ "minItems": 1,
44
+ "items": {
45
+ "type": "string",
46
+ "minLength": 1,
47
+ "pattern": "^[^|\\]>]+$",
48
+ "description": "A value. `|`, `]` and `>` are excluded because they are the delimiters of the derived argument-hint — permitting them would make the hint ambiguous and break the round-trip the hint gate asserts."
49
+ },
50
+ "description": "Allowed values. Only meaningful when `type` is `enum`."
51
+ },
52
+ "description": {
53
+ "type": "string",
54
+ "minLength": 1,
55
+ "description": "One line, shown to a caller choosing a value."
56
+ }
57
+ }
58
+ }
59
+ },
16
60
  "name": {
17
61
  "type": "string",
18
62
  "pattern": "^[a-z][a-z0-9-]*$",
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Who owns a piece of scope growth discovered mid-mission.
4
+ *
5
+ * The size question — *is this small and aligned enough to do now* — already
6
+ * has an answer in the remediation ladder. This is the other axis, and the two
7
+ * are independent: something small and council-owned is still not the agent's
8
+ * to decide, and something agent-owned and large is still bounded by the
9
+ * smallest-diff rule.
10
+ *
11
+ * Four verdicts, and the last one is the important one:
12
+ *
13
+ * `agent` done inline, recorded as a scope delta in the PR body, never
14
+ * asked about.
15
+ * `council` routed through the ownership ladder; the verdict becomes a
16
+ * `## Decisions` row. It does NOT reach the owner, however
17
+ * consequential — a technical decision does not become
18
+ * owner-owned because it is hard.
19
+ * `owner` the work changes what the product or the business does, or it
20
+ * needs a typed op for which no grant exists. Two rows, closed.
21
+ * `follow-up` not scope growth at all. A larger unrelated opportunity
22
+ * becomes its own artifact and the mission does not expand to
23
+ * hold it — the failure that looks like diligence is a mission
24
+ * that absorbs every good idea it meets and delivers none.
25
+ *
26
+ * `unknown` is a real verdict and is deliberately NOT folded into `agent`:
27
+ * growth nothing classifies is growth nobody decided, and defaulting it to the
28
+ * cheapest rung is how an owner question becomes an agent one silently.
29
+ *
30
+ * Exit codes: 0 classified · 1 unknown · 2 bad argv.
31
+ */
32
+
33
+ import * as fs from 'node:fs';
34
+ import * as path from 'node:path';
35
+ import process from 'node:process';
36
+ import { fileURLToPath } from 'node:url';
37
+
38
+ const _HERE = fileURLToPath(import.meta.url);
39
+ const _PROG = 'scope_growth';
40
+
41
+ export type Verdict = 'agent' | 'council' | 'owner' | 'follow-up' | 'unknown';
42
+
43
+ export interface Rule {
44
+ readonly verdict: Verdict;
45
+ readonly kind: string;
46
+ readonly re: RegExp;
47
+ }
48
+
49
+ /**
50
+ * Ordered, and the order is the contract: `owner` and `follow-up` are tested
51
+ * BEFORE `agent`, so a row that matches both ("a missing test — in a subsystem
52
+ * this mission never touched") resolves to the more conservative rung rather
53
+ * than to the first cheap match.
54
+ */
55
+ export const RULES: readonly Rule[] = [
56
+ // --- owner: two rows, closed ------------------------------------------
57
+ {
58
+ verdict: 'owner',
59
+ kind: 'product-or-business-change',
60
+ re: /\b(?:new user-visible|changes what the product|changes what the business|a price|pricing|a public commitment|a policy change)\b/i,
61
+ },
62
+ {
63
+ verdict: 'owner',
64
+ kind: 'typed-op-without-grant',
65
+ re: /\b(?:needs a typed op|no grant exists|merge to main|force-push|deploy to prod(?:uction)?|rotate the secret)\b/i,
66
+ },
67
+ // --- follow-up: unrelated, however good -------------------------------
68
+ {
69
+ verdict: 'follow-up',
70
+ kind: 'larger-unrelated',
71
+ re: /\b(?:unrelated|another subsystem|a subsystem this .{0,30}never touched|out of scope|deserves its own)\b/i,
72
+ },
73
+ // --- council: technical, contested ------------------------------------
74
+ {
75
+ verdict: 'council',
76
+ kind: 'larger-internal-re-cut',
77
+ re: /\b(?:re-?cut|restructure the module|reshape the boundary)\b/i,
78
+ },
79
+ {
80
+ verdict: 'council',
81
+ kind: 'two-equal-strategies',
82
+ re: /\b(?:two equal|two valid|either strategy|no evidence between them)\b/i,
83
+ },
84
+ {
85
+ verdict: 'council',
86
+ kind: 'risky-compatibility-design',
87
+ re: /\b(?:compatibility risk|backwards[- ]incompat|breaking change)\b/i,
88
+ },
89
+ {
90
+ verdict: 'council',
91
+ kind: 'unclear-boundary',
92
+ re: /\b(?:unclear boundary|where the boundary)\b/i,
93
+ },
94
+ // --- agent: six rows, closed ------------------------------------------
95
+ {
96
+ verdict: 'agent',
97
+ kind: 'necessary-internal-refactor',
98
+ re: /\b(?:necessary (?:internal )?refactor|cannot land (?:correctly )?without)\b/i,
99
+ },
100
+ { verdict: 'agent', kind: 'missing-test', re: /\bmissing test\b/i },
101
+ {
102
+ verdict: 'agent',
103
+ kind: 'regression-on-touched-path',
104
+ re: /\bregression\b[^.]{0,60}\btouched\b|\btouched\b[^.]{0,60}\bregression\b/i,
105
+ },
106
+ {
107
+ verdict: 'agent',
108
+ kind: 'small-dependency-adjustment',
109
+ re: /\b(?:small dependency adjustment|patch bump|minor bump)\b/i,
110
+ },
111
+ {
112
+ verdict: 'agent',
113
+ kind: 'local-api-inside-defined-semantics',
114
+ re: /\b(?:inside (?:the )?(?:already-)?defined semantics|the contract does not move)\b/i,
115
+ },
116
+ {
117
+ verdict: 'agent',
118
+ kind: 'boy-scout-cleanup',
119
+ re: /\bboy[- ]scout\b/i,
120
+ },
121
+ ];
122
+
123
+ export interface Classification {
124
+ readonly verdict: Verdict;
125
+ readonly kind: string;
126
+ /** True when the verdict is done inline and recorded rather than asked. */
127
+ readonly records_scope_delta: boolean;
128
+ /** True when a person is reached at all. */
129
+ readonly asks: boolean;
130
+ }
131
+
132
+ export function classifyGrowth(text: string): Classification {
133
+ for (const r of RULES) {
134
+ if (r.re.test(text)) {
135
+ return {
136
+ verdict: r.verdict,
137
+ kind: r.kind,
138
+ records_scope_delta: r.verdict === 'agent',
139
+ asks: r.verdict === 'owner',
140
+ };
141
+ }
142
+ }
143
+ return { verdict: 'unknown', kind: 'unclassified', records_scope_delta: false, asks: false };
144
+ }
145
+
146
+ function _usage(): string {
147
+ return `usage: ${_PROG} [-h] [--self-test] [--json] <description...>\n`;
148
+ }
149
+
150
+ export function main(argv?: readonly string[]): number {
151
+ const args = argv ?? process.argv.slice(2);
152
+ let json = false;
153
+ const words: string[] = [];
154
+ for (const a of args) {
155
+ if (a === '-h' || a === '--help') {
156
+ process.stdout.write(_usage());
157
+ return 0;
158
+ }
159
+ if (a === '--self-test') return _selfTest();
160
+ if (a === '--json') {
161
+ json = true;
162
+ continue;
163
+ }
164
+ words.push(a);
165
+ }
166
+ if (!words.length) {
167
+ process.stderr.write(`${_usage()}${_PROG}: error: a description is required\n`);
168
+ return 2;
169
+ }
170
+ const c = classifyGrowth(words.join(' '));
171
+ if (json) {
172
+ process.stdout.write(JSON.stringify(c, null, 2) + '\n');
173
+ } else {
174
+ process.stdout.write(
175
+ `${c.verdict} (${c.kind}) scope-delta=${String(c.records_scope_delta)} asks=${String(c.asks)}\n`,
176
+ );
177
+ }
178
+ return c.verdict === 'unknown' ? 1 : 0;
179
+ }
180
+
181
+ function _selfTest(): number {
182
+ const cases: ReadonlyArray<readonly [string, Verdict]> = [
183
+ ['a missing test on a path this change touched', 'agent'],
184
+ ['a boy-scout cleanup, small and local', 'agent'],
185
+ ['two equal technical strategies with no evidence between them', 'council'],
186
+ ['this introduces a compatibility risk', 'council'],
187
+ ['it needs a typed op and no grant exists', 'owner'],
188
+ ['this adds new user-visible semantics', 'owner'],
189
+ ['an unrelated refactor that deserves its own roadmap', 'follow-up'],
190
+ ['something nobody wrote a rule for', 'unknown'],
191
+ // The ordering case: matches `missing test` AND `unrelated`, and the
192
+ // conservative rung must win or a follow-up silently becomes agent work.
193
+ ['a missing test in an unrelated subsystem', 'follow-up'],
194
+ ];
195
+ const failures: string[] = [];
196
+ for (const [text, want] of cases) {
197
+ const got = classifyGrowth(text).verdict;
198
+ if (got !== want) failures.push(`"${text}" → ${got}, wanted ${want}`);
199
+ }
200
+ if (failures.length) {
201
+ for (const f of failures) process.stderr.write(`❌ ${_PROG} --self-test: ${f}\n`);
202
+ return 1;
203
+ }
204
+ process.stdout.write(`✅ ${_PROG} --self-test: ${String(cases.length)} case(s) behaved\n`);
205
+ return 0;
206
+ }
207
+
208
+ function _isCliEntry(): boolean {
209
+ if (!process.argv[1]) return false;
210
+ try {
211
+ return fs.realpathSync(_HERE) === fs.realpathSync(path.resolve(process.argv[1]));
212
+ } catch {
213
+ return false;
214
+ }
215
+ }
216
+
217
+ if (_isCliEntry() || process.argv[1] === _HERE) {
218
+ process.exitCode = main();
219
+ }