@event4u/agent-config 16.1.0 → 16.3.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 (467) 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 +98 -257
  5. package/README.md +14 -12
  6. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  7. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  8. package/dist/agent-src/commands/bug/fix.md +17 -2
  9. package/dist/agent-src/commands/feature/plan.md +1 -1
  10. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  11. package/dist/agent-src/commands/fix/ci.md +1 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/jira-ticket.md +1 -1
  14. package/dist/agent-src/commands/roadmap/create.md +1 -1
  15. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  16. package/dist/agent-src/commands/roadmap/process-full.md +5 -5
  17. package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
  18. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  19. package/dist/agent-src/commands/roadmap.md +18 -4
  20. package/dist/agent-src/commands/tests/create.md +17 -3
  21. package/dist/agent-src/commands/tests/execute.md +22 -5
  22. package/dist/agent-src/commands/work.md +4 -0
  23. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  24. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  25. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
  26. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
  27. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
  28. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  29. package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
  30. package/dist/agent-src/rules/active-remediation.md +1 -1
  31. package/dist/agent-src/rules/autonomous-execution.md +1 -0
  32. package/dist/agent-src/rules/broken-access-control.md +1 -0
  33. package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
  34. package/dist/agent-src/rules/context-hygiene.md +1 -1
  35. package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
  36. package/dist/agent-src/rules/design-fidelity.md +13 -16
  37. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
  38. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
  39. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  40. package/dist/agent-src/rules/domain-safety-retention.md +1 -0
  41. package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
  42. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  43. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
  44. package/dist/agent-src/rules/finance-safety-floor.md +1 -0
  45. package/dist/agent-src/rules/git-history-discipline.md +1 -0
  46. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
  47. package/dist/agent-src/rules/legal-safety-floor.md +3 -2
  48. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
  49. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  50. package/dist/agent-src/rules/media-governance-routing.md +14 -17
  51. package/dist/agent-src/rules/persona-governance.md +2 -2
  52. package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
  53. package/dist/agent-src/rules/question-not-instruction.md +1 -0
  54. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  55. package/dist/agent-src/rules/runtime-safety.md +1 -0
  56. package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
  57. package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
  58. package/dist/agent-src/rules/session-canary.md +8 -62
  59. package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
  60. package/dist/agent-src/rules/source-confidentiality.md +1 -0
  61. package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
  62. package/dist/agent-src/rules/tool-safety.md +1 -0
  63. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  64. package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
  65. package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
  66. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  67. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  68. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  69. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
  70. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
  71. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  72. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  73. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  74. package/dist/agent-src/skills/design-review/SKILL.md +30 -4
  75. package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
  76. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  77. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
  78. package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
  79. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  80. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  81. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  82. package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
  83. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  84. package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
  85. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  86. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  87. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  88. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  89. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
  90. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  91. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  92. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  93. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  94. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  95. package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
  96. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  97. package/dist/agent-src/templates/roadmaps.md +30 -0
  98. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  99. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  100. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  101. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  102. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  103. package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
  104. package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  105. package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  106. package/dist/cli/python/knowledge_ingest.js +1 -1
  107. package/dist/cli/python/workspace_drive.js +1 -1
  108. package/dist/cli/registry.js +1 -1
  109. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  110. package/dist/cli-delegate/check_update_banner.js +12 -1
  111. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  112. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  113. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  114. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
  115. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  116. package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
  117. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
  118. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  119. package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
  120. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
  121. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  122. package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
  123. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
  124. package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
  125. package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
  126. package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
  127. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  128. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  129. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
  130. package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
  131. package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
  132. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
  133. package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
  134. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  135. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  136. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  137. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  138. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  139. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  140. package/dist/cli-delegate/cmd_conformance.js +1862 -809
  141. package/dist/cli-delegate/cmd_doctor.js +13 -6
  142. package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
  143. package/dist/cli-delegate/cmd_explain.js +5 -5
  144. package/dist/cli-delegate/cmd_export.js +11 -8
  145. package/dist/cli-delegate/cmd_fleet.js +3 -3
  146. package/dist/cli-delegate/cmd_handoff.js +10 -7
  147. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  148. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  149. package/dist/cli-delegate/cmd_migrate.js +2 -2
  150. package/dist/cli-delegate/cmd_packs_active.js +3 -3
  151. package/dist/cli-delegate/cmd_preflight.js +6 -6
  152. package/dist/cli-delegate/cmd_prune.js +11 -8
  153. package/dist/cli-delegate/cmd_refresh.js +2 -1
  154. package/dist/cli-delegate/cmd_route_audit.js +8 -6
  155. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  156. package/dist/cli-delegate/cmd_session_recycle.js +4 -3
  157. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  158. package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
  159. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  160. package/dist/cli-delegate/cmd_sync.js +11 -8
  161. package/dist/cli-delegate/cmd_uninstall.js +11 -8
  162. package/dist/cli-delegate/cmd_update.js +1 -1
  163. package/dist/cli-delegate/cmd_upgrade.js +3 -2
  164. package/dist/cli-delegate/cmd_validate.js +11 -8
  165. package/dist/cli-delegate/cmd_versions.js +1 -1
  166. package/dist/cli-delegate/deferral_carry.js +16 -0
  167. package/dist/cli-delegate/gate_execute.js +2 -2
  168. package/dist/cli-delegate/roadmap_gates.js +5 -5
  169. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  170. package/dist/discovery/deprecation-report.md +1 -1
  171. package/dist/discovery/discovery-manifest.json +132 -80
  172. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  173. package/dist/discovery/discovery-manifest.summary.md +3 -3
  174. package/dist/discovery/dormancy-report.md +1 -1
  175. package/dist/discovery/orphan-report.md +1 -1
  176. package/dist/discovery/packs.json +7 -5
  177. package/dist/discovery/trust-report.md +2 -2
  178. package/dist/discovery/workspaces.json +6 -4
  179. package/dist/hooks/dispatch.js +7972 -5186
  180. package/dist/hooks/dispatch.sha256 +1 -0
  181. package/dist/install/claudePathsPlan.js +47 -6
  182. package/dist/install/claudeRuleRewrite.js +7 -0
  183. package/dist/install/emit_host_rules_cli.js +39 -36
  184. package/dist/install/globalRuleScope.js +87 -0
  185. package/dist/install/host_rule_ownership.js +160 -0
  186. package/dist/install/install.mjs +2226 -1055
  187. package/dist/install/installThinLayer.js +261 -0
  188. package/dist/install/installedRuleLinks.js +176 -0
  189. package/dist/install/wizard-plan.js +24 -0
  190. package/dist/mcp/registry-manifest.json +3 -3
  191. package/dist/mcp/server.json +2 -2
  192. package/dist/mcp/server.mjs +40913 -34865
  193. package/dist/scripts/_lib/agent_settings.js +11 -0
  194. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  195. package/dist/scripts/_lib/installed_layer.js +378 -0
  196. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  197. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  198. package/dist/scripts/_lib/rule_injection.js +67 -10
  199. package/dist/scripts/_lib/rule_law_section.js +122 -0
  200. package/dist/scripts/_lib/thin_rules.js +458 -0
  201. package/dist/scripts/_lib/windsurf_render.js +60 -0
  202. package/dist/scripts/condense.js +14 -26
  203. package/dist/scripts/project_thin_rules.js +14 -294
  204. package/dist/server/schemas/settings.js +29 -0
  205. package/dist/shared/skillRanking.js +74 -13
  206. package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
  207. package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
  208. package/dist/ui/index.html +2 -2
  209. package/docs/contracts/settings-classes.md +10 -6
  210. package/package.json +4 -4
  211. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  212. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  213. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  214. package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  215. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  216. package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  217. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  218. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  219. package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
  220. package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  221. package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  222. package/src/config/agent-settings.template.yml +91 -22
  223. package/src/config/ci-local-parity.yml +18 -0
  224. package/src/config/continuity-surface.json +9 -2
  225. package/src/config/evaluator-budgets.json +4 -4
  226. package/src/config/gate-coverage.yml +327 -3
  227. package/src/config/gate-violation-baselines.json +21 -9
  228. package/src/config/hook-bundle-budget.json +25 -0
  229. package/src/config/hook-latency-budget.json +21 -0
  230. package/src/config/hook-token-budget.json +8 -3
  231. package/src/config/host-instruction-limits.json +33 -0
  232. package/src/config/metric-registry.yml +114 -0
  233. package/src/config/placeholder-drift-budget.json +10 -0
  234. package/src/config/routing-coverage-seed.json +38 -3
  235. package/src/config/rule-activation-census.json +7 -3
  236. package/src/config/rule-consequence-class.json +161 -0
  237. package/src/config/rule-law-ceilings.json +99 -0
  238. package/src/install/claudePathsPlan.ts +46 -4
  239. package/src/install/claudeRuleRewrite.ts +10 -1
  240. package/src/install/emit_host_rules_cli.ts +43 -34
  241. package/src/install/globalRuleScope.ts +109 -0
  242. package/src/install/host_rule_ownership.ts +170 -0
  243. package/src/install/installThinLayer.ts +312 -0
  244. package/src/install/installedRuleLinks.ts +220 -0
  245. package/src/install/wizard-plan.ts +24 -0
  246. package/src/scripts/_cli/cmd_doctor.ts +28 -90
  247. package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
  248. package/src/scripts/_cli/doctor_execution.ts +100 -17
  249. package/src/scripts/_cli/doctor_network_posture.ts +226 -0
  250. package/src/scripts/_dispatch.bash +16 -2
  251. package/src/scripts/_lib/agent_settings.ts +11 -0
  252. package/src/scripts/_lib/body_portable.ts +102 -0
  253. package/src/scripts/_lib/cc_transcript.ts +132 -1
  254. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  255. package/src/scripts/_lib/concern_sla_window.ts +200 -0
  256. package/src/scripts/_lib/estate_offsets.ts +241 -0
  257. package/src/scripts/_lib/exemption_shape.ts +143 -0
  258. package/src/scripts/_lib/fnv.ts +23 -0
  259. package/src/scripts/_lib/foreign_scan.ts +106 -0
  260. package/src/scripts/_lib/forge_protection.ts +114 -0
  261. package/src/scripts/_lib/forge_reader.ts +558 -0
  262. package/src/scripts/_lib/gitignore_block.ts +314 -0
  263. package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
  264. package/src/scripts/_lib/graph_feeder_record.ts +214 -0
  265. package/src/scripts/_lib/hook_settings.ts +73 -0
  266. package/src/scripts/_lib/host_capability.ts +40 -19
  267. package/src/scripts/_lib/host_env_write.ts +111 -0
  268. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  269. package/src/scripts/_lib/installed_layer.ts +538 -0
  270. package/src/scripts/_lib/json_merge.ts +82 -0
  271. package/src/scripts/_lib/json_pointers.ts +93 -11
  272. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  273. package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
  274. package/src/scripts/_lib/machine_wake.ts +16 -3
  275. package/src/scripts/_lib/neighbour_census.ts +760 -0
  276. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  277. package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
  278. package/src/scripts/_lib/obligations.ts +119 -8
  279. package/src/scripts/_lib/probe_inputs.ts +271 -0
  280. package/src/scripts/_lib/prompt_shape.ts +46 -0
  281. package/src/scripts/_lib/read_surface_scan.ts +322 -0
  282. package/src/scripts/_lib/release_highlights.ts +2 -1
  283. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  284. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  285. package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
  286. package/src/scripts/_lib/review_coverage.ts +134 -0
  287. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  288. package/src/scripts/_lib/rule_injection.ts +130 -10
  289. package/src/scripts/_lib/rule_law_section.ts +147 -0
  290. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  291. package/src/scripts/_lib/shell_write_shapes.ts +108 -0
  292. package/src/scripts/_lib/skill_origin.ts +254 -0
  293. package/src/scripts/_lib/structural_hiding.ts +622 -0
  294. package/src/scripts/_lib/structured_ask.ts +64 -21
  295. package/src/scripts/_lib/thin_rules.ts +540 -0
  296. package/src/scripts/_lib/touched_file_quality.ts +434 -0
  297. package/src/scripts/_lib/turn_end_refusals.ts +600 -4
  298. package/src/scripts/_lib/turn_end_transcript.ts +216 -0
  299. package/src/scripts/_lib/verification_command.ts +324 -0
  300. package/src/scripts/_lib/verification_evidence.ts +647 -0
  301. package/src/scripts/_lib/verify_clause.ts +280 -0
  302. package/src/scripts/_lib/windsurf_render.ts +63 -0
  303. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  304. package/src/scripts/ai_council/clients.ts +26 -57
  305. package/src/scripts/ai_council/config.ts +1 -1
  306. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  307. package/src/scripts/ai_team/team_dispatch.ts +4 -0
  308. package/src/scripts/audit_skill_overlap.ts +261 -0
  309. package/src/scripts/before_complete_hook.ts +573 -25
  310. package/src/scripts/bench_hook_latency.ts +412 -5
  311. package/src/scripts/bench_touched_file_quality.ts +238 -0
  312. package/src/scripts/cache_realization_report.ts +61 -1
  313. package/src/scripts/check_argument_hint.ts +287 -0
  314. package/src/scripts/check_claims.ts +125 -1
  315. package/src/scripts/check_enforcement_coverage.ts +38 -9
  316. package/src/scripts/check_enforcement_matrix.ts +621 -22
  317. package/src/scripts/check_estate_count.ts +130 -153
  318. package/src/scripts/check_finding_dispositions.ts +138 -7
  319. package/src/scripts/check_generator_sync.ts +71 -0
  320. package/src/scripts/check_hook_bundle_composition.ts +370 -0
  321. package/src/scripts/check_host_docs_digest.ts +786 -0
  322. package/src/scripts/check_host_format_column.ts +559 -0
  323. package/src/scripts/check_input_references.ts +228 -0
  324. package/src/scripts/check_inputs_parity.ts +235 -0
  325. package/src/scripts/check_kernel_edit_ratified.ts +89 -9
  326. package/src/scripts/check_kill_switch_table.ts +294 -0
  327. package/src/scripts/check_memory.ts +7 -1
  328. package/src/scripts/check_placeholder_drift.ts +221 -0
  329. package/src/scripts/check_read_surface_coverage.ts +515 -0
  330. package/src/scripts/check_release_highlights.ts +10 -0
  331. package/src/scripts/check_release_holds.ts +2 -1
  332. package/src/scripts/check_release_pr_shape.ts +38 -15
  333. package/src/scripts/check_routing_coverage.ts +378 -11
  334. package/src/scripts/check_standing_rule_delivery.ts +33 -13
  335. package/src/scripts/check_static_parity.ts +17 -0
  336. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  337. package/src/scripts/ci_settle.ts +145 -19
  338. package/src/scripts/closure_scan.ts +115 -1
  339. package/src/scripts/code_graph/detect.ts +127 -7
  340. package/src/scripts/code_graph/foreign.ts +194 -0
  341. package/src/scripts/code_graph/query.ts +217 -4
  342. package/src/scripts/code_graph/types.ts +26 -2
  343. package/src/scripts/code_graph/validate.ts +3 -1
  344. package/src/scripts/code_graph/verbs.ts +103 -0
  345. package/src/scripts/compile_hook_manifest.ts +90 -14
  346. package/src/scripts/condense.ts +14 -27
  347. package/src/scripts/estate_exemption_shape.ts +202 -0
  348. package/src/scripts/external_sources_denylist.json +29 -4
  349. package/src/scripts/generate_host_cost_table.ts +1 -1
  350. package/src/scripts/hook_manifest.json +1 -1
  351. package/src/scripts/hook_manifest.yaml +192 -14
  352. package/src/scripts/hooks/block_config_weakening.ts +294 -4
  353. package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
  354. package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
  355. package/src/scripts/hooks/bundle_integrity.ts +291 -0
  356. package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
  357. package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
  358. package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
  359. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  360. package/src/scripts/hooks/concern_registry.ts +2 -0
  361. package/src/scripts/hooks/concern_timings.ts +94 -0
  362. package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
  363. package/src/scripts/hooks/design_pass_hook.ts +100 -9
  364. package/src/scripts/hooks/design_slop_hook.ts +1 -2
  365. package/src/scripts/hooks/dispatch_hook.ts +77 -71
  366. package/src/scripts/hooks/edit_shape_hook.ts +1 -2
  367. package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
  368. package/src/scripts/hooks/evidence_independence.ts +1 -2
  369. package/src/scripts/hooks/exit_codes.ts +129 -0
  370. package/src/scripts/hooks/host_lowering.json +1 -0
  371. package/src/scripts/hooks/host_lowering.ts +146 -3
  372. package/src/scripts/hooks/host_lowering.yaml +262 -46
  373. package/src/scripts/hooks/host_semantics.ts +30 -2
  374. package/src/scripts/hooks/injection_budget.ts +9 -2
  375. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
  376. package/src/scripts/hooks/journal_record_hook.ts +1 -2
  377. package/src/scripts/hooks/memory_recall_hook.ts +1 -2
  378. package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
  379. package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
  380. package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
  381. package/src/scripts/hooks/payload_stub.ts +10 -1
  382. package/src/scripts/hooks/permission_gate.ts +1 -2
  383. package/src/scripts/hooks/push_settle_hook.ts +1 -3
  384. package/src/scripts/hooks/replay_hook.ts +2 -1
  385. package/src/scripts/hooks/reread_guard_hook.ts +1 -2
  386. package/src/scripts/hooks/review_baseline_hook.ts +1 -2
  387. package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
  388. package/src/scripts/hooks/rule_inject_hook.ts +765 -68
  389. package/src/scripts/hooks/run_continuation_hook.ts +13 -15
  390. package/src/scripts/hooks/skill_route_hook.ts +1 -2
  391. package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
  392. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
  393. package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
  394. package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
  395. package/src/scripts/hooks/table_fingerprint.ts +70 -0
  396. package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
  397. package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
  398. package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
  399. package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
  400. package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
  401. package/src/scripts/hooks_status.ts +112 -0
  402. package/src/scripts/injection_scan_hook.ts +7 -0
  403. package/src/scripts/install.ts +75 -189
  404. package/src/scripts/installed_layer_report.ts +103 -0
  405. package/src/scripts/language_mirror_hook.ts +15 -6
  406. package/src/scripts/learning_sidecar.ts +119 -8
  407. package/src/scripts/lint_deny_text.ts +419 -0
  408. package/src/scripts/lint_exit_codes.ts +262 -0
  409. package/src/scripts/lint_hook_manifest.ts +108 -0
  410. package/src/scripts/lint_major_migration_sections.ts +156 -26
  411. package/src/scripts/lint_pack_boundaries.ts +63 -5
  412. package/src/scripts/lint_roadmap_blockers.ts +78 -12
  413. package/src/scripts/lint_rule_law_section.ts +517 -0
  414. package/src/scripts/lint_skill_descriptions.ts +1 -1
  415. package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
  416. package/src/scripts/lint_workflow_security.ts +161 -5
  417. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  418. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  419. package/src/scripts/mcp_server/prompts.ts +142 -1
  420. package/src/scripts/measure_routing_signal.ts +54 -16
  421. package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
  422. package/src/scripts/measure_turn_end_gate.ts +193 -0
  423. package/src/scripts/memory_learn_hook.ts +91 -6
  424. package/src/scripts/memory_lookup.ts +1 -1
  425. package/src/scripts/model_rule_injection.ts +52 -5
  426. package/src/scripts/prepack-check.mjs +53 -0
  427. package/src/scripts/project_thin_rules.ts +34 -327
  428. package/src/scripts/release_publication.ts +13 -1
  429. package/src/scripts/report_evidence_temperature.ts +657 -0
  430. package/src/scripts/report_installed_rule_links.ts +157 -0
  431. package/src/scripts/report_invocation_surface.ts +383 -0
  432. package/src/scripts/report_label_agreement.ts +233 -0
  433. package/src/scripts/report_obligation_carriers.ts +699 -0
  434. package/src/scripts/report_obligation_mechanism.ts +230 -0
  435. package/src/scripts/report_obligation_writer_split.ts +236 -0
  436. package/src/scripts/report_single_token_triggers.ts +277 -0
  437. package/src/scripts/report_skill_menu_census.ts +208 -0
  438. package/src/scripts/report_skill_ranker_confusion.ts +442 -0
  439. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  440. package/src/scripts/report_verification_record_coverage.ts +306 -0
  441. package/src/scripts/roadmap_verify_share.ts +213 -0
  442. package/src/scripts/rule_activation_census.ts +5 -2
  443. package/src/scripts/rule_trigger_eval.ts +9 -9
  444. package/src/scripts/schemas/command.schema.json +44 -0
  445. package/src/scripts/schemas/review-findings.schema.json +7 -2
  446. package/src/scripts/schemas/rule.schema.json +5 -0
  447. package/src/scripts/schemas/skill.schema.json +44 -0
  448. package/src/scripts/self_review_gate.ts +421 -17
  449. package/src/scripts/semantic_parity_census.ts +314 -0
  450. package/src/scripts/session_eol_report.ts +54 -1
  451. package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
  452. package/src/scripts/sweep_dead_scan_roots.ts +1 -1
  453. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  454. package/src/scripts/sync_gitignore.ts +29 -235
  455. package/src/scripts/trigger_eval_grandfather.json +0 -7
  456. package/src/scripts/trigger_eval_rotation.ts +122 -27
  457. package/src/scripts/ui_conformance_probe.ts +156 -4
  458. package/src/scripts/update_prices.ts +85 -3
  459. package/src/scripts/write_bundle_digest.mjs +74 -0
  460. package/src/server/schemas/settings.ts +41 -0
  461. package/src/shared/skillRanking.ts +117 -11
  462. package/src/templates/consumer-settings/ONBOARDING.md +1 -0
  463. package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
  464. package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
  465. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  466. package/dist/ui/assets/index-DH1xc62v.js +0 -29
  467. package/dist/ui/assets/index-jSfMW8_t.css +0 -1
@@ -12,7 +12,9 @@
12
12
  * `urp.collect()` completion criterion, and exit code 0. snake_case kept.
13
13
  *
14
14
  * A roadmap that has reached `count_open == 0` and `count_deferred == 0` is
15
- * **complete**. This sweep moves it to `agents/roadmaps/archive/`, rewrites code-comment-allow provenance-comment -- the sweep's own operand
15
+ * **complete** — and so is one whose only `[~]` steps are bare, because the
16
+ * sweep first carries them to a follow-up (`deferral_carry.ts`; `--no-carry`
17
+ * turns that off). This sweep moves it to `agents/roadmaps/archive/`, rewrites code-comment-allow provenance-comment -- the sweep's own operand
16
18
  * inbound references (`agents/roadmaps/<x>.md` → `agents/roadmaps/archive/<x>.md`) code-comment-allow provenance-comment -- the rewrite this sweep performs
17
19
  * across tracked files so links never break, and regenerates the dashboard.
18
20
  *
@@ -63,6 +65,7 @@ import {
63
65
  collect,
64
66
  parse_blockers,
65
67
  } from './update_roadmap_progress.js';
68
+ import { BLOCK_END_RE, DEFERRED_RESOLUTION_RE, DEFERRED_STEP_RE, planCarry, type CarryPlan, type OwnerDecision } from './deferral_carry.js';
66
69
  import { guardedBaselineProblems, parseGuardedBaselines } from './guarded_baseline.js';
67
70
 
68
71
  import { isCliEntry } from './_cli_entry.js';
@@ -403,17 +406,6 @@ export interface DeferredItem {
403
406
  destination: string | null;
404
407
  }
405
408
 
406
- /**
407
- * `<!-- deferred-resolution: carried-to=<slug> -->` — the resolved-deferral
408
- * annotation. `merged-into=<slug>` is the second accepted form.
409
- */
410
- const DEFERRED_RESOLUTION_RE = /<!--\s*deferred-resolution:\s*(carried-to|merged-into)\s*=\s*([A-Za-z0-9._-]+)\s*-->/;
411
-
412
- /** `- [~] …` — a deferred step, at any indent, with `-` or `*`. */
413
- const DEFERRED_STEP_RE = /^[ \t]*[-*][ \t]+\[~\][ \t]*(.*)$/;
414
- /** Any other checkbox, or a heading — where a step's block ends. */
415
- const BLOCK_END_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]|^#{1,6}[ \t]/;
416
-
417
409
  /** Escape a string for literal use inside a `RegExp`. */
418
410
  function _escapeRe(v: string): string {
419
411
  return v.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -590,9 +582,10 @@ export function deferralProblems(
590
582
  /** Archive every complete active roadmap: no open steps, and every `[~]` resolved. */
591
583
  function archive_completed(
592
584
  root: string,
593
- opts: { changed_only: boolean; base: string; dry_run: boolean },
585
+ opts: { changed_only: boolean; base: string; dry_run: boolean; carry?: boolean; owner_decision?: OwnerDecision; only?: string | null },
594
586
  ): ArchiveRecord[] {
595
587
  const { changed_only, base, dry_run } = opts;
588
+ const carry = opts.carry ?? true;
596
589
  const roadmap_root = path.join(root, 'agents', 'roadmaps');
597
590
  if (!_isDir(roadmap_root)) {
598
591
  return [];
@@ -617,7 +610,12 @@ function archive_completed(
617
610
  );
618
611
 
619
612
  const archived: ArchiveRecord[] = [];
613
+ // `--only`: the owner's archive answer is about ONE roadmap. Without the
614
+ // filter, `--owner-decision later` would also park every other roadmap
615
+ // still waiting on its own, unasked owner question.
616
+ const only = opts.only ? opts.only.replace(/^.*\//, '').replace(/\.md$/, '') + '.md' : null;
620
617
  for (const stats of collect(roadmap_root)) {
618
+ if (only !== null && stats.rel !== only) continue;
621
619
  // `guarded-baseline` is INCOMPLETE by construction (council 2026-08-31,
622
620
  // 2/2 convergent) — checked BEFORE the open-step test on purpose. A
623
621
  // well-formed record keeps its box `[ ]` and would be skipped silently as
@@ -625,7 +623,7 @@ function archive_completed(
625
623
  // and invisible in a sweep that only reports what it moved; a MALFORMED
626
624
  // one on `[x]` would otherwise archive with an annotation claiming the
627
625
  // opposite. Both are named here instead.
628
- const roadmapText = fs.readFileSync(path.join(roadmap_root, stats.rel), 'utf-8');
626
+ let roadmapText = fs.readFileSync(path.join(roadmap_root, stats.rel), 'utf-8');
629
627
  const guarded = parseGuardedBaselines(roadmapText);
630
628
  if (guarded.length > 0) {
631
629
  process.stderr.write(
@@ -644,13 +642,54 @@ function archive_completed(
644
642
  // A `[~]` no longer blocks unconditionally: it blocks unless it carries a
645
643
  // validated resolution annotation. See `deferralProblems` for why, and
646
644
  // for every way that check fails closed.
645
+ const old_rel = `agents/roadmaps/${stats.rel}`;
646
+ let open_blockers = stats.open_blockers.map((b) => b.id);
647
647
  if (stats.deferred !== 0) {
648
648
  const abs = path.join(roadmap_root, stats.rel);
649
649
  // The source's own slug is removed: it is trivially in `sweepSet`,
650
650
  // and self-reference is reported by its own, clearer message.
651
651
  const others = new Set(sweepSet);
652
652
  others.delete(stats.rel.replace(/\.md$/, ''));
653
- const problems = deferralProblems(root, stats.rel, fs.readFileSync(abs, 'utf-8'), others);
653
+ // Bare `[~]` steps are carried to a follow-up first, then validated
654
+ // like any hand-written carry — see `deferral_carry.ts`. Only for a
655
+ // roadmap this sweep would actually archive, so a `--changed-only`
656
+ // run never writes a follow-up for someone else's roadmap.
657
+ const inScope = !changed_only || (touched as Set<string>).has(old_rel);
658
+ const bare = parseDeferredItems(roadmapText).some((d) => d.kind === null);
659
+ if (carry && inScope && bare) {
660
+ const outcome = planCarry(root, stats.rel, roadmapText, open_blockers, _today(), opts.owner_decision ?? 'ask');
661
+ if ('refused' in outcome) {
662
+ process.stderr.write(` ⚠️ ${stats.rel}: deferrals not carried — ${outcome.refused}.\n`);
663
+ } else if (outcome.plan.ownerBlockers.length > 0 && !outcome.plan.parked) {
664
+ // The steps wait on the OWNER. Nothing is written: whether
665
+ // to park them or work them is the owner's call, and the
666
+ // step-by-step offer needs the first step on screen.
667
+ process.stdout.write(_ownerDecisionBlock(stats.rel, outcome.plan));
668
+ continue;
669
+ } else {
670
+ const { plan } = outcome;
671
+ process.stdout.write(
672
+ ` ↪ ${stats.rel}: carried ${plan.carried} deferred step(s)` +
673
+ (plan.movedBlockers.length > 0 ? ` and blocker(s) ${plan.movedBlockers.join(', ')}` : '') +
674
+ ` → ${plan.destRel}\n`,
675
+ );
676
+ if (dry_run) {
677
+ // Nothing was written, so the validation below would
678
+ // read the old file; report the move it would make.
679
+ archived.push({ roadmap: old_rel, archived_to: `agents/roadmaps/archive/${stats.rel}`, refs_migrated: [] });
680
+ continue;
681
+ }
682
+ fs.mkdirSync(path.dirname(path.join(root, plan.destRel)), { recursive: true });
683
+ fs.writeFileSync(path.join(root, plan.destRel), plan.destText, 'utf-8');
684
+ fs.writeFileSync(abs, plan.sourceText, 'utf-8');
685
+ // Staged so the blocker-divergence check below compares the
686
+ // carry against itself, not against the pre-carry index.
687
+ _run(['git', 'add', '--', plan.destRel, old_rel], root);
688
+ roadmapText = plan.sourceText;
689
+ open_blockers = open_blockers.filter((id) => !plan.movedBlockers.includes(id));
690
+ }
691
+ }
692
+ const problems = deferralProblems(root, stats.rel, roadmapText, others);
654
693
  if (problems.length > 0) {
655
694
  process.stderr.write(
656
695
  ` ⚠️ ${stats.rel}: ${problems.length} unresolved deferral(s) — not archived.\n`,
@@ -666,9 +705,8 @@ function archive_completed(
666
705
  // predicted shipped in the 9.36.0 changelog head. Same discipline
667
706
  // `roadmap-progress-sync` Iron Law 3 applies to `[~]` steps: a roadmap
668
707
  // carrying an open decision stays visible until the decision is made.
669
- const open_blockers = stats.open_blockers;
670
708
  if (open_blockers.length > 0) {
671
- const ids = open_blockers.map((b) => b.id).join(', ');
709
+ const ids = open_blockers.join(', ');
672
710
  process.stderr.write(
673
711
  ` ⚠️ ${stats.rel}: all steps closed but ${open_blockers.length} ` +
674
712
  `blocker(s) still open (${ids}) — not archived. Resolve them, ` +
@@ -676,7 +714,6 @@ function archive_completed(
676
714
  );
677
715
  continue;
678
716
  }
679
- const old_rel = `agents/roadmaps/${stats.rel}`;
680
717
  if (changed_only && !(touched as Set<string>).has(old_rel)) {
681
718
  continue; // complete, but not this branch's work
682
719
  }
@@ -722,6 +759,38 @@ function archive_completed(
722
759
  return archived;
723
760
  }
724
761
 
762
+ /**
763
+ * The owner question, rendered for a human AND forwarded verbatim by a
764
+ * subagent: the trailing `OWNER-DECISION` line is one JSON object, so an
765
+ * orchestrator can re-present the decision without re-deriving it. A subagent
766
+ * never answers it and never re-runs with `--owner-decision later` itself.
767
+ */
768
+ function _ownerDecisionBlock(rel: string, plan: CarryPlan): string {
769
+ const ids = plan.ownerBlockers.join(', ');
770
+ const park = `agents/roadmaps/later/${plan.destSlug}.md`;
771
+ const step = plan.firstStep.split('\n').map((l) => ` ${l}`).join('\n');
772
+ const record = {
773
+ roadmap: `agents/roadmaps/${rel}`,
774
+ owner_blockers: plan.ownerBlockers,
775
+ deferred_steps: plan.carried,
776
+ park_to: park,
777
+ archive_command: `./agent-config roadmap:archive --all --owner-decision later --only ${rel}`,
778
+ first_step: plan.firstStep,
779
+ };
780
+ return (
781
+ ` ❓ ${rel}: ${plan.carried} deferred step(s) wait on owner blocker(s) ${ids} — not archived; the owner decides:\n` +
782
+ ` 1. Archive it — the steps and their blockers park in ${park}\n` +
783
+ ` (${record.archive_command})\n` +
784
+ ' 2. Work them step by step, starting with:\n' +
785
+ `${step}\n` +
786
+ ` OWNER-DECISION ${JSON.stringify(record)}\n`
787
+ );
788
+ }
789
+
790
+ function _today(): string {
791
+ return new Date().toISOString().slice(0, 10);
792
+ }
793
+
725
794
  function _isDir(p: string): boolean {
726
795
  try {
727
796
  return fs.statSync(p).isDirectory();
@@ -824,13 +893,16 @@ function _runTwin(root: string, script: string): void {
824
893
  const _PROG = 'archive_completed_roadmaps.py';
825
894
 
826
895
  function _usage(): string {
827
- return `usage: ${_PROG} [-h] [--all] [--base BASE] [--dry-run] [--repo-root REPO_ROOT]\n`;
896
+ return `usage: ${_PROG} [-h] [--all] [--base BASE] [--dry-run] [--no-carry] [--owner-decision later] [--only ROADMAP] [--repo-root REPO_ROOT]\n`;
828
897
  }
829
898
 
830
899
  interface Args {
831
900
  all: boolean;
832
901
  base: string;
833
902
  dry_run: boolean;
903
+ carry: boolean;
904
+ owner_decision: OwnerDecision;
905
+ only: string | null;
834
906
  repo_root: string | null;
835
907
  }
836
908
 
@@ -838,6 +910,9 @@ function _parseArgs(argv: readonly string[]): Args {
838
910
  let all = false;
839
911
  let base = 'origin/main';
840
912
  let dry_run = false;
913
+ let carry = true;
914
+ let owner_decision: OwnerDecision = 'ask';
915
+ let only: string | null = null;
841
916
  let repo_root: string | null = null;
842
917
  const emitError = (msg: string): never => {
843
918
  process.stderr.write(_usage());
@@ -856,6 +931,23 @@ function _parseArgs(argv: readonly string[]): Args {
856
931
  } else if (tok === '--dry-run') {
857
932
  dry_run = true;
858
933
  i += 1;
934
+ } else if (tok === '--no-carry') {
935
+ carry = false;
936
+ i += 1;
937
+ } else if (tok === '--only' || tok.startsWith('--only=')) {
938
+ const val = tok.includes('=') ? tok.slice(tok.indexOf('=') + 1) : argv[i + 1];
939
+ if (val === undefined || val === '') {
940
+ emitError('argument --only: expected one argument');
941
+ }
942
+ only = val as string;
943
+ i += tok.includes('=') ? 1 : 2;
944
+ } else if (tok === '--owner-decision' || tok.startsWith('--owner-decision=')) {
945
+ const val = tok.includes('=') ? tok.slice(tok.indexOf('=') + 1) : argv[i + 1];
946
+ if (val !== 'later' && val !== 'ask') {
947
+ emitError("argument --owner-decision: expected 'later' or 'ask'");
948
+ }
949
+ owner_decision = val as OwnerDecision;
950
+ i += tok.includes('=') ? 1 : 2;
859
951
  } else if (tok === '--base') {
860
952
  const val = argv[i + 1];
861
953
  if (val === undefined) {
@@ -880,7 +972,7 @@ function _parseArgs(argv: readonly string[]): Args {
880
972
  emitError(`unrecognized arguments: ${tok}`);
881
973
  }
882
974
  }
883
- return { all, base, dry_run, repo_root };
975
+ return { all, base, dry_run, carry, owner_decision, only, repo_root };
884
976
  }
885
977
 
886
978
  function main(argv?: readonly string[]): number {
@@ -894,6 +986,9 @@ function main(argv?: readonly string[]): number {
894
986
  changed_only: !ns.all,
895
987
  base: ns.base,
896
988
  dry_run: ns.dry_run,
989
+ carry: ns.carry,
990
+ owner_decision: ns.owner_decision,
991
+ only: ns.only,
897
992
  });
898
993
  if (archived.length === 0) {
899
994
  process.stdout.write(' ℹ️ No completed roadmaps to archive.\n');
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Auto-carry for the archival sweep: a finished roadmap whose only obstacle is
3
+ * bare `[~]` steps hands them to a follow-up roadmap and then archives.
4
+ *
5
+ * WHY. The dashboard renders a roadmap with zero open steps as 100 %, deferred
6
+ * steps included, while the sweep refused every bare `[~]` and waited for a
7
+ * human to write the `carried-to` annotation by hand. Nobody did: measured
8
+ * 2026-10-02, five roadmaps sat at 100 % in the active tree with fourteen
9
+ * unannotated deferrals between them, and `/roadmap:process-full` — which ends
10
+ * non-interactively — had no step that could resolve one. "Finished" and
11
+ * "archived" had silently come apart.
12
+ *
13
+ * The disposition this module executes is the one `roadmap-progress-sync`
14
+ * Iron Law 3 already routes to the council without the owner: carry the item
15
+ * AND its blocker into a named follow-up created in the SAME change. It keeps
16
+ * every criterion alive in the active estate, so it is the preserving branch of
17
+ * the preservation test, never a drop. The owner decided on 2026-10-02 that the
18
+ * sweep performs it automatically instead of waiting for a menu.
19
+ *
20
+ * What the carry does, so the archived parent and the live child agree:
21
+ *
22
+ * - every bare `[~]` block is copied verbatim into the child as an OPEN `[ ]`
23
+ * step — open, not `[~]`, because a child at 100 % on arrival would be
24
+ * carried again by the next sweep, forever;
25
+ * - the parent's step gets `<!-- deferred-resolution: carried-to=<child> -->`,
26
+ * and the child gets `parent_roadmap: <parent>`, which is the pair
27
+ * `deferralProblems` and `lint_deferral_integrity` validate from both ends;
28
+ * - every OPEN blocker a carried step names via `blocked-by: <id>` moves with
29
+ * it: copied verbatim into the child's `## Blockers`, and closed in the
30
+ * parent with a status line naming where it went. The open-blocker count is
31
+ * unchanged, it only changes file.
32
+ *
33
+ * NOT automatic when a moved blocker waits on the OWNER (owner decision
34
+ * 2026-10-02): the sweep then writes nothing and asks — archive with the steps
35
+ * parked in `later/` (`--owner-decision later`), or work them step by step with
36
+ * the first one on screen. The procedure lives in `roadmap-process-loop` § 6a.
37
+ *
38
+ * Refused, so nothing is written, when the parent would still not archive
39
+ * afterwards: an open blocker no carried step names is a decision the parent
40
+ * itself raised, and carrying around it would strand the child with steps that
41
+ * have no reason to exist apart from the parent. A human-written annotation
42
+ * that fails validation is also left alone — fixing someone's wrong carry is
43
+ * not this module's call.
44
+ */
45
+
46
+ import * as fs from 'node:fs';
47
+ import * as path from 'node:path';
48
+
49
+ /**
50
+ * `<!-- deferred-resolution: carried-to=<slug> -->` — the resolved-deferral
51
+ * annotation. `merged-into=<slug>` is the second accepted form.
52
+ */
53
+ export const DEFERRED_RESOLUTION_RE =
54
+ /<!--\s*deferred-resolution:\s*(carried-to|merged-into)\s*=\s*([A-Za-z0-9._-]+)\s*-->/;
55
+
56
+ /** `- [~] …` — a deferred step, at any indent, with `-` or `*`. */
57
+ export const DEFERRED_STEP_RE = /^[ \t]*[-*][ \t]+\[~\][ \t]*(.*)$/;
58
+
59
+ /** Any other checkbox, or a heading — where a step's block ends. */
60
+ export const BLOCK_END_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]|^#{1,6}[ \t]/;
61
+
62
+ const BLOCKED_BY_RE = /blocked-by:\s*([A-Za-z0-9._-]+)/g;
63
+ const BLOCKER_HEAD_RE = /^###[ \t]+blocker:[ \t]*(.+?)[ \t]*$/i;
64
+ const STATUS_LINE_RE = /^([ \t]*-[ \t]+\*\*Status:\*\*[ \t]*)(.*)$/;
65
+ const AC_HEADING_RE = /^##[ \t]+acceptance/i;
66
+ const OWNER_LINE_RE = /^[ \t]*-[ \t]+\*\*Owner:\*\*[ \t]*`?([A-Za-z]+)/;
67
+
68
+ /**
69
+ * Blocker owners that are NOT the human owner. Everything else — `maintainer`,
70
+ * `user`, `owner`, and any value this list does not name — is owner-dependent:
71
+ * in doubt it is the owner's decision, so an unrecognised owner fails closed.
72
+ */
73
+ const AGENT_SIDE_OWNERS: ReadonlySet<string> = new Set(['implementer', 'council', 'agent', 'ai']);
74
+
75
+ /**
76
+ * What happens to deferrals whose blockers wait on the owner.
77
+ *
78
+ * `ask` (default): nothing is written; the sweep reports the decision instead —
79
+ * archive with the steps parked in `later/`, or work them step by step.
80
+ * `later`: the owner chose to archive; the carry lands in `later/`.
81
+ */
82
+ export type OwnerDecision = 'ask' | 'later';
83
+
84
+ /** The lightweight cap `lint_roadmap_complexity` enforces, with margin. */
85
+ const LIGHTWEIGHT_LINE_BUDGET = 500;
86
+
87
+ const DISPOSITION_DIRS: readonly string[] = ['', 'later', 'archive', 'skipped'];
88
+
89
+ interface BareStep {
90
+ /** Line index of the `[~]` line in the parent. */
91
+ line: number;
92
+ /** The step line plus its continuation block, dedented to the step. */
93
+ block: string[];
94
+ isAcceptance: boolean;
95
+ blockerIds: string[];
96
+ }
97
+
98
+ interface BlockerSpan {
99
+ id: string;
100
+ start: number;
101
+ end: number;
102
+ open: boolean;
103
+ ownerDependent: boolean;
104
+ }
105
+
106
+ export interface CarryPlan {
107
+ destSlug: string;
108
+ destRel: string;
109
+ destText: string;
110
+ sourceText: string;
111
+ carried: number;
112
+ movedBlockers: string[];
113
+ /** Moved blockers only the owner can resolve. Non-empty ⇒ the owner decides. */
114
+ ownerBlockers: string[];
115
+ /** The first carried step, verbatim, for the step-by-step offer. */
116
+ firstStep: string;
117
+ /** True when the carry targets `later/` (owner chose to archive). */
118
+ parked: boolean;
119
+ }
120
+
121
+ export type CarryOutcome = { plan: CarryPlan } | { refused: string };
122
+
123
+ function _bareSteps(lines: readonly string[]): BareStep[] {
124
+ const out: BareStep[] = [];
125
+ let inAcceptance = false;
126
+ // No fence skipping, on purpose: `parseDeferredItems` does not skip fences
127
+ // either, and a step this module did not see but the sweep's validation does
128
+ // would be written, then refused.
129
+ for (let i = 0; i < lines.length; i++) {
130
+ const line = lines[i] as string;
131
+ if (/^##[ \t]/.test(line)) inAcceptance = AC_HEADING_RE.test(line);
132
+ const m = DEFERRED_STEP_RE.exec(line);
133
+ if (m === null) continue;
134
+ let end = i + 1;
135
+ while (end < lines.length && !BLOCK_END_RE.test(lines[end] as string)) end++;
136
+ const raw = lines.slice(i, end);
137
+ if (DEFERRED_RESOLUTION_RE.test(raw.join('\n'))) continue;
138
+ while (raw.length > 1 && (raw[raw.length - 1] as string).trim() === '') raw.pop();
139
+ const indent = (/^[ \t]*/.exec(line) as RegExpExecArray)[0].length;
140
+ const block = raw.map((l) => (l.slice(0, indent).trim() === '' ? l.slice(indent) : l));
141
+ const ids = new Set<string>();
142
+ for (const b of raw) for (const hit of b.matchAll(BLOCKED_BY_RE)) ids.add(hit[1] as string);
143
+ out.push({ line: i, block, isAcceptance: inAcceptance, blockerIds: [...ids] });
144
+ }
145
+ return out;
146
+ }
147
+
148
+ function _blockerSpans(lines: readonly string[]): BlockerSpan[] {
149
+ const start = lines.findIndex((l) => /^##[ \t]+Blockers[ \t]*$/i.test(l));
150
+ if (start === -1) return [];
151
+ let sectionEnd = lines.length;
152
+ for (let i = start + 1; i < lines.length; i++) {
153
+ if (/^##[ \t]+\S/.test(lines[i] as string)) {
154
+ sectionEnd = i;
155
+ break;
156
+ }
157
+ }
158
+ const spans: BlockerSpan[] = [];
159
+ for (let i = start + 1; i < sectionEnd; i++) {
160
+ const m = BLOCKER_HEAD_RE.exec(lines[i] as string);
161
+ if (m === null) continue;
162
+ let end = i + 1;
163
+ while (end < sectionEnd && !/^###?[ \t]/.test(lines[end] as string)) end++;
164
+ const status = lines
165
+ .slice(i, end)
166
+ .map((l) => STATUS_LINE_RE.exec(l))
167
+ .find((s) => s !== null);
168
+ const value = (status?.[2] ?? 'open').trim().toLowerCase();
169
+ const owner = lines
170
+ .slice(i, end)
171
+ .map((l) => OWNER_LINE_RE.exec(l))
172
+ .find((o) => o !== null);
173
+ spans.push({
174
+ id: (m[1] as string).trim(),
175
+ start: i,
176
+ end,
177
+ open: !/^resolved\b/.test(value),
178
+ ownerDependent: !AGENT_SIDE_OWNERS.has((owner?.[1] ?? '').toLowerCase()),
179
+ });
180
+ }
181
+ return spans;
182
+ }
183
+
184
+ function _plusDays(date: string, days: number): string {
185
+ const d = new Date(`${date}T00:00:00Z`);
186
+ d.setUTCDate(d.getUTCDate() + days);
187
+ return d.toISOString().slice(0, 10);
188
+ }
189
+
190
+ /** The first `<base>-carried[-N]` slug no roadmap directory already holds. */
191
+ export function nextCarrySlug(root: string, sourceSlug: string): string {
192
+ const base = sourceSlug.replace(/-carried(-\d+)?$/, '');
193
+ for (let n = 1; ; n++) {
194
+ const slug = n === 1 ? `${base}-carried` : `${base}-carried-${n}`;
195
+ const taken = DISPOSITION_DIRS.some((d) =>
196
+ fs.existsSync(path.join(root, 'agents', 'roadmaps', d, `${slug}.md`)),
197
+ );
198
+ if (!taken) return slug;
199
+ }
200
+ }
201
+
202
+ function _title(sourceText: string, sourceSlug: string): string {
203
+ const h1 = /^#[ \t]+(.+?)[ \t]*$/m.exec(sourceText.replace(/^---\n[\s\S]*?\n---\n/, ''));
204
+ return h1 !== null ? (h1[1] as string) : sourceSlug.replace(/-/g, ' ');
205
+ }
206
+
207
+ /**
208
+ * Plan the carry for one roadmap. Pure apart from reading which slugs exist, so
209
+ * the sweep can decide before it writes anything.
210
+ *
211
+ * @param openBlockerIds every OPEN blocker the parent carries, as `collect()`
212
+ * counts them — the source of truth for "would it archive afterwards".
213
+ */
214
+ export function planCarry(
215
+ root: string,
216
+ rel: string,
217
+ text: string,
218
+ openBlockerIds: readonly string[],
219
+ date: string,
220
+ ownerDecision: OwnerDecision = 'ask',
221
+ ): CarryOutcome {
222
+ const sourceSlug = rel.replace(/\.md$/, '');
223
+ const lines = text.split('\n');
224
+ const steps = _bareSteps(lines);
225
+ if (steps.length === 0) return { refused: 'no bare `[~]` step to carry' };
226
+
227
+ const named = new Set(steps.flatMap((s) => s.blockerIds));
228
+ const stranded = openBlockerIds.filter((id) => !named.has(id));
229
+ if (stranded.length > 0) {
230
+ return {
231
+ refused:
232
+ `open blocker(s) no deferred step names (${stranded.join(', ')}) — ` +
233
+ 'carrying around them would not let this roadmap archive',
234
+ };
235
+ }
236
+ const moved = _blockerSpans(lines).filter((b) => b.open && named.has(b.id));
237
+ const ownerBlockers = moved.filter((b) => b.ownerDependent).map((b) => b.id);
238
+ const parked = ownerBlockers.length > 0 && ownerDecision === 'later';
239
+
240
+ const destSlug = nextCarrySlug(root, sourceSlug);
241
+ const annotation = `<!-- deferred-resolution: carried-to=${destSlug} -->`;
242
+
243
+ const out = [...lines];
244
+ for (const b of moved) {
245
+ for (let i = b.start; i < b.end; i++) {
246
+ const s = STATUS_LINE_RE.exec(out[i] as string);
247
+ if (s === null) continue;
248
+ out[i] =
249
+ `${s[1] as string}resolved — carried, still open, to \`${destSlug}\` ` +
250
+ `with the steps it blocks (was: ${(s[2] as string).trim()})`;
251
+ break;
252
+ }
253
+ }
254
+ for (const s of steps) out[s.line] = `${out[s.line] as string} ${annotation}`;
255
+
256
+ const toOpen = (block: readonly string[]): string =>
257
+ block.map((l, i) => (i === 0 ? l.replace(/\[~\]/, '[ ]') : l)).join('\n');
258
+ const phaseSteps = steps.filter((s) => !s.isAcceptance).map((s) => toOpen(s.block));
259
+ const acSteps = steps.filter((s) => s.isAcceptance).map((s) => toOpen(s.block));
260
+ const phaseName = `Deferred steps carried from ${sourceSlug}`;
261
+ const blockerText = moved.map((b) => lines.slice(b.start, b.end).join('\n').trimEnd());
262
+
263
+ const body = [
264
+ `# ${_title(text, sourceSlug)} — carried`,
265
+ '',
266
+ `> **Source:** carried by the archival sweep on ${date} from`,
267
+ `> [\`${sourceSlug}\`](${parked ? '../' : ''}archive/${sourceSlug}.md), which closed every other step.`,
268
+ '> Each step below was `[~]` there and is restated verbatim as open work, so',
269
+ '> archiving the parent buried nothing. Blockers the steps name moved with them.',
270
+ '',
271
+ '## Goal',
272
+ '',
273
+ `Every step ${sourceSlug} deferred is either done here or explicitly disposed`,
274
+ 'of — a step that still cannot run is re-deferred with its reason, never',
275
+ 'left to read as finished.',
276
+ '',
277
+ `## Phase 1 — ${phaseName}`,
278
+ '',
279
+ phaseSteps.length > 0
280
+ ? phaseSteps.join('\n')
281
+ : '- [ ] **1.1 Close the carried acceptance criteria below.** The parent deferred\n' +
282
+ ' only acceptance criteria; this step is done when each is checked or disposed of.\n' +
283
+ ' verify: every criterion under `## Acceptance Criteria` is `[x]` or `[-]`',
284
+ '',
285
+ ...(blockerText.length > 0 ? ['## Blockers', '', blockerText.join('\n\n'), ''] : []),
286
+ '## Risk Register',
287
+ `<!-- risk-review: v1 | reviewed: ${date} | reviewer: archive-sweep/auto-carry -->`,
288
+ '',
289
+ '| Rank | Item | Risk type | Description | Mitigation | Anchored under |',
290
+ '|------|------|-----------|-------------|------------|----------------|',
291
+ '| 1 | Carried steps stay blocked indefinitely | implementation | A step deferred ' +
292
+ 'once for elapsed time or a decision can sit here as long as it sat in the parent | ' +
293
+ 'It now counts as open work in the dashboard instead of as 100 %, and its blocker ' +
294
+ `is listed where the estate gates count it | Phase 1 — ${phaseName} |`,
295
+ '',
296
+ '## Acceptance Criteria',
297
+ '',
298
+ acSteps.length > 0
299
+ ? acSteps.join('\n')
300
+ : `- [ ] AC-1 — No step carried from \`${sourceSlug}\` is still \`[ ]\` without a recorded disposition.`,
301
+ '',
302
+ ].join('\n');
303
+ const complexity = body.split('\n').length > LIGHTWEIGHT_LINE_BUDGET ? 'structural' : 'lightweight';
304
+ // Parked: `status: later` plus the three-part `entry_condition:` mapping
305
+ // `lint_roadmap_later_disposition` requires, and the growth claim the
306
+ // `later_roadmaps` count needs — a new file in `later/` is not a parking
307
+ // move, so no allowance covers it otherwise.
308
+ const ids = ownerBlockers.join(', ');
309
+ const parkedKeys = parked
310
+ ? 'entry_condition:\n' +
311
+ ` what: the owner resolves blocker(s) ${ids}\n` +
312
+ ' when: whenever the owner takes the next step\n' +
313
+ ' who: owner\n' +
314
+ // `lint_roadmap_later_disposition` rule C: a park with no review date
315
+ // reads exactly like an abandonment.
316
+ `review_by: ${_plusDays(date, 90)}\n` +
317
+ `estate_growth_exempt: >-\n Owner-chosen archive of ${sourceSlug}: its deferred steps wait on owner\n` +
318
+ ` blocker(s) ${ids} and are parked here instead of left active. The parent\n` +
319
+ ' is archived in the same change, so the active count drops by one.\n'
320
+ : '';
321
+ const destText =
322
+ `---\ncomplexity: ${complexity}\nstatus: ${parked ? 'later' : 'ready'}\nexecution:\n mode: phase-checkpoints\n` +
323
+ `parent_roadmap: ${sourceSlug}\n${parkedKeys}---\n${body}`;
324
+ const destRel = parked ? `agents/roadmaps/later/${destSlug}.md` : `agents/roadmaps/${destSlug}.md`;
325
+
326
+ return {
327
+ plan: {
328
+ destSlug,
329
+ destRel,
330
+ destText,
331
+ sourceText: out.join('\n'),
332
+ carried: steps.length,
333
+ movedBlockers: moved.map((b) => b.id),
334
+ ownerBlockers,
335
+ firstStep: (steps[0] as BareStep).block.join('\n'),
336
+ parked,
337
+ },
338
+ };
339
+ }
@@ -1351,7 +1351,10 @@ function main(argv?: readonly string[]): number {
1351
1351
  // leaves behind rather than the one it found. `--check` never archives: a
1352
1352
  // gate that mutates the tree it is checking cannot be trusted by CI.
1353
1353
  let sweep_out = '';
1354
- if (!args.check && args.archive && unarchived_complete(collect(roadmap_root)).length > 0) {
1354
+ // `pending_iron_law_3` too: a 100 % roadmap with bare `[~]` steps is what the
1355
+ // sweep's carry exists for, and gating on `deferred === 0` never spawned it.
1356
+ const before = collect(roadmap_root);
1357
+ if (!args.check && args.archive && unarchived_complete(before).length + pending_iron_law_3(before).length > 0) {
1355
1358
  const swept = run_archival_sweep(repo_root);
1356
1359
  sweep_out = swept.stdout;
1357
1360
  if (swept.stderr) {
@@ -11,8 +11,9 @@
11
11
  *
12
12
  * The gate is **scoped to the greenfield-scaffold path only**. It acts only
13
13
  * when `state.ui_audit` records `greenfield == True` and
14
- * `greenfield_decision == "scaffold"`. Every other UI flow sees this slot as a
15
- * clean `SUCCESS` no-op, so those flows stay byte-identical.
14
+ * `greenfield_decision` ∈ `{scaffold, granularity_convention}`. Every other
15
+ * UI flow sees this slot as a clean `SUCCESS` no-op, so those flows stay
16
+ * byte-identical.
16
17
  */
17
18
  import {
18
19
  type Any,
@@ -21,6 +22,7 @@ import {
21
22
  StepResult,
22
23
  agent_directive,
23
24
  } from '../../delivery_state.js';
25
+ import { GRANULARITY_CONVENTION } from '../../state.js';
24
26
 
25
27
  /** Declared ambiguity surfaces for this step. */
26
28
  export const AMBIGUITIES: ReadonlyArray<Record<string, string>> = [
@@ -112,14 +114,18 @@ export function run(state: DeliveryState): StepResult {
112
114
  * The gate is inert for every other flow: improve-existing, the `bare` /
113
115
  * `external_reference` greenfield picks, and the `diff` / `file` envelopes all
114
116
  * leave `ui_audit` without the `greenfield == True` +
115
- * `greenfield_decision == "scaffold"` pair.
117
+ * `greenfield_decision` ∈ `{scaffold, granularity_convention}` pair.
116
118
  */
117
119
  function _is_greenfield_scaffold(state: DeliveryState): boolean {
118
120
  const audit = state.ui_audit;
119
121
  if (!_isDict(audit)) return false;
122
+ // `granularity_convention` is option 4 — a scaffold that additionally
123
+ // organises what it creates under a named convention, so it takes the same
124
+ // grounding pass. Kept in step with the identical guard in `scaffold`.
120
125
  return (
121
126
  audit['greenfield'] === true &&
122
- audit['greenfield_decision'] === 'scaffold'
127
+ (audit['greenfield_decision'] === 'scaffold' ||
128
+ audit['greenfield_decision'] === GRANULARITY_CONVENTION)
123
129
  );
124
130
  }
125
131