mandrel 2.0.0 → 2.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 (323) hide show
  1. package/.agents/README.md +59 -28
  2. package/.agents/agents/acceptance-critic.md +20 -9
  3. package/.agents/agents/story-worker.md +45 -48
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +60 -46
  6. package/.agents/docs/agentrc-reference.json +8 -13
  7. package/.agents/docs/configuration.md +33 -57
  8. package/.agents/docs/execution-reference.md +39 -10
  9. package/.agents/docs/quality-gates.md +17 -19
  10. package/.agents/docs/workflows.md +6 -6
  11. package/.agents/instructions.md +64 -79
  12. package/.agents/rules/ci-remediation.md +3 -3
  13. package/.agents/rules/gherkin-standards.md +10 -0
  14. package/.agents/rules/git-conventions-reference.md +42 -51
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +2 -2
  16. package/.agents/schemas/agentrc.schema.json +35 -46
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  24. package/.agents/schemas/signal-event.schema.json +3 -3
  25. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  26. package/.agents/schemas/validation-evidence.schema.json +1 -1
  27. package/.agents/scripts/acceptance-eval.js +24 -68
  28. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  29. package/.agents/scripts/bootstrap.js +3 -3
  30. package/.agents/scripts/check-dead-exports.js +43 -104
  31. package/.agents/scripts/check-doc-links.js +2 -2
  32. package/.agents/scripts/check-lifecycle-lint.js +1 -1
  33. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  34. package/.agents/scripts/deliver-recover.js +122 -0
  35. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  36. package/.agents/scripts/evidence-gate.js +20 -50
  37. package/.agents/scripts/generate-skills-index.js +17 -1
  38. package/.agents/scripts/generate-workflows-doc.js +4 -4
  39. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  40. package/.agents/scripts/lib/audit-suite/selector.js +323 -23
  41. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -11
  42. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  43. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  44. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  45. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  46. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -1
  47. package/.agents/scripts/lib/checks/index.js +1 -1
  48. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  49. package/.agents/scripts/lib/checks/state.js +17 -248
  50. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +3 -3
  51. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  52. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  53. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  54. package/.agents/scripts/lib/cli-args.js +23 -2
  55. package/.agents/scripts/lib/close-validation/gates.js +13 -13
  56. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  57. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  58. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  59. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  60. package/.agents/scripts/lib/config/acceptance-eval.js +2 -2
  61. package/.agents/scripts/lib/config/delivery-routing.js +7 -6
  62. package/.agents/scripts/lib/config/explain.js +10 -16
  63. package/.agents/scripts/lib/config/github.js +7 -5
  64. package/.agents/scripts/lib/config/limits.js +15 -25
  65. package/.agents/scripts/lib/config/quality.js +11 -14
  66. package/.agents/scripts/lib/config/runners.js +8 -21
  67. package/.agents/scripts/lib/config/temp-paths.js +18 -56
  68. package/.agents/scripts/lib/config-settings-schema-delivery.js +34 -16
  69. package/.agents/scripts/lib/config-settings-schema-quality.js +9 -2
  70. package/.agents/scripts/lib/config-settings-schema.js +48 -22
  71. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  72. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  73. package/.agents/scripts/lib/duplicate-search.js +38 -7
  74. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  75. package/.agents/scripts/lib/format-generated-json.js +97 -0
  76. package/.agents/scripts/lib/framework-version.js +19 -189
  77. package/.agents/scripts/lib/gh-exec.js +8 -0
  78. package/.agents/scripts/lib/git-branch-lifecycle.js +0 -158
  79. package/.agents/scripts/lib/git-utils.js +0 -14
  80. package/.agents/scripts/lib/json-utils.js +1 -2
  81. package/.agents/scripts/lib/label-constants.js +0 -15
  82. package/.agents/scripts/lib/label-taxonomy.js +1 -12
  83. package/.agents/scripts/lib/observability/active-story-env.js +42 -163
  84. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  85. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  86. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  87. package/.agents/scripts/lib/observability/source-classifier.js +2 -2
  88. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  89. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  90. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  91. package/.agents/scripts/lib/orchestration/ceremony-routing.js +43 -45
  92. package/.agents/scripts/lib/orchestration/change-set.js +103 -0
  93. package/.agents/scripts/lib/orchestration/code-review.js +70 -191
  94. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +3 -3
  95. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  96. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  97. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  98. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  99. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  100. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +9 -11
  101. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  102. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  103. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +7 -3
  104. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  105. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  106. package/.agents/scripts/lib/orchestration/merge-block-class.js +76 -20
  107. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  108. package/.agents/scripts/lib/orchestration/plan-context.js +116 -33
  109. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +26 -36
  110. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +31 -22
  111. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  112. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +16 -6
  113. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +173 -25
  114. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  115. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +280 -100
  116. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +472 -55
  117. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +21 -16
  118. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  119. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +230 -0
  120. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +41 -40
  121. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +1 -2
  122. package/.agents/scripts/lib/orchestration/planning/spec-authoring-grounding.js +1 -1
  123. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  124. package/.agents/scripts/lib/orchestration/retro-proposals.js +7 -7
  125. package/.agents/scripts/lib/orchestration/review-depth.js +105 -40
  126. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  127. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  128. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  129. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  130. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  131. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  132. package/.agents/scripts/lib/orchestration/run-epilogue.js +374 -16
  133. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +24 -0
  134. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  135. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  136. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +4 -13
  137. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  138. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +72 -30
  139. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  140. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  141. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +12 -8
  142. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  143. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  144. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +264 -43
  145. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  146. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  147. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +104 -279
  148. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +191 -0
  149. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +120 -0
  150. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  151. package/.agents/scripts/lib/orchestration/story-follow-ups.js +75 -14
  152. package/.agents/scripts/lib/orchestration/story-init-remote.js +12 -8
  153. package/.agents/scripts/lib/orchestration/story-plan-state.js +14 -29
  154. package/.agents/scripts/lib/orchestration/task-body-validator.js +52 -7
  155. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  156. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +119 -14
  157. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +3 -4
  158. package/.agents/scripts/lib/orchestration/ticket-validator.js +121 -18
  159. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -47
  160. package/.agents/scripts/lib/orchestration/ticketing/reads.js +19 -32
  161. package/.agents/scripts/lib/orchestration/ticketing/transition.js +61 -1
  162. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  163. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  164. package/.agents/scripts/lib/planning-corpus.js +12 -286
  165. package/.agents/scripts/lib/preflight-runner.js +2 -2
  166. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  167. package/.agents/scripts/lib/signals/index.js +4 -17
  168. package/.agents/scripts/lib/signals/read.js +35 -35
  169. package/.agents/scripts/lib/signals/schema.js +8 -11
  170. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  171. package/.agents/scripts/lib/signals/write.js +0 -1
  172. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  173. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  174. package/.agents/scripts/lib/story-adjacency.js +8 -7
  175. package/.agents/scripts/lib/story-body/story-body.js +81 -13
  176. package/.agents/scripts/lib/templates/decomposer-prompts.js +15 -16
  177. package/.agents/scripts/lib/test-env.js +14 -1
  178. package/.agents/scripts/lib/test-tiers.js +0 -3
  179. package/.agents/scripts/lib/ticket-body-sections.js +0 -14
  180. package/.agents/scripts/lib/validation-evidence.js +31 -59
  181. package/.agents/scripts/lib/wave-runner/live-probe.js +315 -0
  182. package/.agents/scripts/lib/wave-runner/ready-set.js +32 -6
  183. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  184. package/.agents/scripts/lib/worktree/lifecycle/reap.js +68 -19
  185. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  186. package/.agents/scripts/plan-context.js +38 -7
  187. package/.agents/scripts/plan-critics.js +203 -0
  188. package/.agents/scripts/plan-persist.js +145 -35
  189. package/.agents/scripts/plan-run-epilogue.js +83 -38
  190. package/.agents/scripts/post-structured-comment.js +0 -38
  191. package/.agents/scripts/pr-watch-with-update.js +43 -22
  192. package/.agents/scripts/providers/github/compose.js +0 -1
  193. package/.agents/scripts/providers/github/errors.js +0 -19
  194. package/.agents/scripts/providers/github/issues.js +1 -11
  195. package/.agents/scripts/providers/github/mappers.js +5 -0
  196. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  197. package/.agents/scripts/providers/github/tickets.js +33 -153
  198. package/.agents/scripts/providers/github.js +17 -6
  199. package/.agents/scripts/quality-preview.js +13 -6
  200. package/.agents/scripts/resolve-stories.js +236 -0
  201. package/.agents/scripts/run-coverage.js +4 -1
  202. package/.agents/scripts/run-lint.js +2 -2
  203. package/.agents/scripts/run-verify.js +31 -2
  204. package/.agents/scripts/signals-view.js +9 -10
  205. package/.agents/scripts/single-story-close.js +173 -18
  206. package/.agents/scripts/single-story-confirm-merge.js +288 -15
  207. package/.agents/scripts/single-story-init.js +6 -10
  208. package/.agents/scripts/stories-wave-tick.js +380 -53
  209. package/.agents/scripts/story-plan.js +3 -3
  210. package/.agents/scripts/update-ticket-state.js +8 -50
  211. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  212. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  213. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  214. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  215. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  216. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  217. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  218. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  219. package/.agents/skills/core/idea-refinement/SKILL.md +3 -3
  220. package/.agents/skills/core/scope-triage/SKILL.md +3 -0
  221. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  222. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  223. package/.agents/skills/skills.index.json +2 -12
  224. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  225. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  226. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  227. package/.agents/workflows/audit-architecture.md +3 -4
  228. package/.agents/workflows/audit-clean-code.md +4 -4
  229. package/.agents/workflows/audit-documentation.md +4 -5
  230. package/.agents/workflows/audit-lighthouse.md +8 -0
  231. package/.agents/workflows/audit-navigability.md +10 -0
  232. package/.agents/workflows/audit-performance.md +2 -3
  233. package/.agents/workflows/audit-quality.md +8 -9
  234. package/.agents/workflows/audit-security.md +1 -2
  235. package/.agents/workflows/audit-seo.md +10 -0
  236. package/.agents/workflows/audit-ux-ui.md +7 -0
  237. package/.agents/workflows/deliver.md +133 -45
  238. package/.agents/workflows/git-cleanup.md +2 -2
  239. package/.agents/workflows/git-deliver.md +1 -1
  240. package/.agents/workflows/helpers/acceptance-self-eval.md +34 -17
  241. package/.agents/workflows/helpers/code-quality-guardrails.md +15 -12
  242. package/.agents/workflows/helpers/code-review.md +14 -12
  243. package/.agents/workflows/helpers/deliver-story-reference.md +73 -32
  244. package/.agents/workflows/helpers/deliver-story.md +209 -118
  245. package/.agents/workflows/helpers/parallel-tooling.md +2 -2
  246. package/.agents/workflows/helpers/worktree-lifecycle.md +28 -32
  247. package/.agents/workflows/plan.md +239 -19
  248. package/.agents/workflows/qa-assist.md +6 -6
  249. package/.agents/workflows/qa-explore.md +3 -3
  250. package/.agents/workflows/qa-run.md +1 -5
  251. package/bin/mandrel.js +12 -1
  252. package/docs/CHANGELOG.md +62 -0
  253. package/lib/cli/registry.js +262 -19
  254. package/lib/cli/sync-agents.js +157 -0
  255. package/lib/cli/sync-commands.js +115 -6
  256. package/lib/cli/sync.js +168 -6
  257. package/lib/cli/update.js +105 -8
  258. package/lib/cli/version-helpers.js +131 -0
  259. package/lib/migrations/README.md +7 -5
  260. package/lib/migrations/index.js +17 -9
  261. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  262. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  263. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +154 -0
  264. package/package.json +2 -2
  265. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  266. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  267. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  268. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  269. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  270. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  271. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  272. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  273. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  274. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  275. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  276. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  277. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  278. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  279. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  280. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  281. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  282. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  283. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  284. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  285. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  286. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  287. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  288. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  289. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  290. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  291. package/.agents/schemas/risk-verdict.schema.json +0 -53
  292. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  293. package/.agents/scripts/analyze-execution.js +0 -444
  294. package/.agents/scripts/check-prepush-recovery.js +0 -90
  295. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  296. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  297. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -187
  298. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  299. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  300. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  301. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +0 -128
  302. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -273
  303. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  304. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  305. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  306. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  307. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  308. package/.agents/scripts/lib/orchestration/planning/risk-verdict.js +0 -104
  309. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  310. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  311. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  312. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -21
  313. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  314. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  315. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  316. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -397
  317. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  318. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +0 -155
  319. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  320. package/.agents/scripts/lib/orchestration/story-progress/story-run-progress-writer.js +0 -400
  321. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +0 -36
  322. package/.agents/scripts/resolve-plan-run.js +0 -117
  323. package/.agents/skills/core/analyze-execution/SKILL.md +0 -101
@@ -6,8 +6,8 @@
6
6
  * root `npm run lint` walks into the orphan tree, hits the nested config,
7
7
  * and fails. The close-time biome block is the canonical symptom.
8
8
  *
9
- * Surface: `epic-deliver` preflight, `story-close` preflight, and the
10
- * `/diagnose` CLI. Surfaced as a blocker so the operator clears the residue
9
+ * Surface: `story-close` preflight, the `/diagnose` CLI, and retro.
10
+ * Surfaced as a blocker so the operator clears the residue
11
11
  * with `rm -rf` before close re-runs the validation chain.
12
12
  *
13
13
  * AutoCorrect is `refuse-and-print`. Recursive deletion under `.worktrees/`
@@ -21,7 +21,7 @@ const ID = 'worktree-residue-biome';
21
21
  export default {
22
22
  id: ID,
23
23
  severity: 'blocker',
24
- scope: ['epic-deliver', 'story-close', 'diagnose', 'retro'],
24
+ scope: ['story-close', 'diagnose', 'retro'],
25
25
  autoCorrect: 'refuse-and-print',
26
26
  detect(state) {
27
27
  const orphans = state?.fs?.worktreeBiomeOrphans ?? [];
@@ -46,6 +46,22 @@ function optionalBooleanFlag(value) {
46
46
  return coerceBooleanFlag(value);
47
47
  }
48
48
 
49
+ /**
50
+ * Parse a positive-integer flag, preserving `undefined` when the flag is
51
+ * absent so a caller can distinguish "not supplied" (fall back to config)
52
+ * from an explicit value. A non-numeric or non-positive value is treated as
53
+ * absent rather than coerced to 0 — a `--max-wait-seconds=abc` typo must not
54
+ * silently become a zero-second wait.
55
+ *
56
+ * @param {unknown} value
57
+ * @returns {number|undefined}
58
+ */
59
+ function parsePositiveInt(value) {
60
+ if (value === undefined || value === null) return undefined;
61
+ const parsed = Number.parseInt(String(value), 10);
62
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
63
+ }
64
+
49
65
  /**
50
66
  * Standardized CLI argument parser for sprint scripts.
51
67
  * Supports options like --epic, --story, --dry-run, --skip-dashboard.
@@ -63,10 +79,12 @@ export function parseSprintArgs(args = process.argv) {
63
79
  'skip-validation': { type: 'boolean', default: false },
64
80
  'skip-sync': { type: 'boolean', default: false },
65
81
  'no-auto-merge': { type: 'boolean', default: false },
66
- 'no-full-scope-crap': { type: 'boolean', default: false },
67
82
  // No default — absent means "use delivery.routing.closeAndLand".
68
83
  'wait-merge': { type: 'boolean' },
69
84
  'no-wait-merge': { type: 'boolean', default: false },
85
+ // Story #4543 — per-run override of `delivery.mergeWatch.maxWaitSeconds`
86
+ // (the merge wait's per-invocation bound). Absent means "use the config".
87
+ 'max-wait-seconds': { type: 'string' },
70
88
  executor: { type: 'string' },
71
89
  cwd: { type: 'string' },
72
90
  'recut-of': { type: 'string' },
@@ -87,13 +105,16 @@ export function parseSprintArgs(args = process.argv) {
87
105
  skipValidation: coerceBooleanFlag(values['skip-validation']),
88
106
  skipSync: coerceBooleanFlag(values['skip-sync']),
89
107
  noAutoMerge: coerceBooleanFlag(values['no-auto-merge']),
90
- noFullScopeCrap: coerceBooleanFlag(values['no-full-scope-crap']),
91
108
  // Close-and-land: `--wait-merge` forces land-in-close; `--no-wait-merge`
92
109
  // opts out. When neither flag is present (`undefined`),
93
110
  // `parseCloseOptions` applies `delivery.routing.closeAndLand` (default
94
111
  // true) so attended and headless delivers share the same happy path.
95
112
  waitForMerge: optionalBooleanFlag(values['wait-merge']),
96
113
  noWaitForMerge: coerceBooleanFlag(values['no-wait-merge']),
114
+ // Story #4543 — raise the merge wait's per-invocation bound for a
115
+ // headless caller with no host tool-invocation ceiling, so it lands in
116
+ // one block instead of returning `pending` at the default 300s.
117
+ maxWaitSeconds: parsePositiveInt(values['max-wait-seconds']),
97
118
  executor: values.executor ?? null,
98
119
  // Resolve worktree cwd from flag or env. Empty string/whitespace → null.
99
120
  cwd:
@@ -54,22 +54,22 @@ function buildChangedFileScope(baseRef) {
54
54
  *
55
55
  * The baselines gate resolves its compare ref through `resolveScope`,
56
56
  * whose environment layer reads `BASELINE_REF`. Threading
57
- * `origin/<epicBranch>` here makes the gate diff head against the epic
57
+ * `origin/<baseBranch>` here makes the gate diff head against the epic
58
58
  * integration branch instead of the framework-default `origin/main`, so
59
59
  * drift that already landed on `main` but is outside the Story's own diff
60
60
  * does not surface as a phantom regression. The same convention
61
- * (`origin/<epicBranch>`) is used by the baseline-attribution and
61
+ * (`origin/<baseBranch>`) is used by the baseline-attribution and
62
62
  * auto-refresh paths, keeping read/compare bases aligned.
63
63
  *
64
64
  * Returns `null` when no integration branch is supplied (the gate then
65
65
  * keeps its existing default-ref / consumer-config behaviour untouched).
66
66
  *
67
- * @param {string|undefined|null} epicBranch
67
+ * @param {string|undefined|null} baseBranch
68
68
  * @returns {{ BASELINE_REF: string } | null}
69
69
  */
70
- function buildBaselinesGateEnv(epicBranch) {
71
- if (typeof epicBranch !== 'string' || epicBranch.length === 0) return null;
72
- return { BASELINE_REF: `origin/${epicBranch}` };
70
+ function buildBaselinesGateEnv(baseBranch) {
71
+ if (typeof baseBranch !== 'string' || baseBranch.length === 0) return null;
72
+ return { BASELINE_REF: `origin/${baseBranch}` };
73
73
  }
74
74
 
75
75
  /**
@@ -240,11 +240,11 @@ function probeBaselinesGate({ config, cwd, presentBaselines } = {}) {
240
240
  * shared in-process runner. The unified `check-baselines` gate is now the
241
241
  * single source of truth for per-kind regression enforcement
242
242
  * (attribution-wired floor + tolerance + schema).
243
- * The `epicBranch` parameter threads the close run's integration branch
243
+ * The `baseBranch` parameter threads the close run's integration branch
244
244
  * into two gates: the `format` gate's `changedFileScope` (existing) and —
245
245
  * since Story #3890 — the `check-baselines` gate's `BASELINE_REF` env, so
246
246
  * the baselines regression compare diffs head against the epic integration
247
- * branch (`origin/<epicBranch>`) rather than the framework-default
247
+ * branch (`origin/<baseBranch>`) rather than the framework-default
248
248
  * `origin/main`. Without this, every child Story on an `epic/<id>` branch
249
249
  * re-discovered inherited main-vs-epic drift in untouched files as phantom
250
250
  * regressions and worked around it by hand-setting `BASELINE_REF`.
@@ -268,10 +268,10 @@ function probeBaselinesGate({ config, cwd, presentBaselines } = {}) {
268
268
  * none are required, the gate is skipped with a logged reason (via `log`)
269
269
  * instead of a blocking failure.
270
270
  *
271
- * @param {{ config?: object, epicBranch?: string, cwd?: string, packageScripts?: Record<string, string>, presentBaselines?: string[]|Set<string>, log?: (message: string) => void }} [opts]
271
+ * @param {{ config?: object, baseBranch?: string, cwd?: string, packageScripts?: Record<string, string>, presentBaselines?: string[]|Set<string>, log?: (message: string) => void }} [opts]
272
272
  * `config` is the canonical resolved config (`{ project, delivery, ... }`);
273
273
  * gate commands resolve from `project.commands` and the CRAP toggle from
274
- * `delivery.quality.gates.crap.enabled`. `epicBranch` is the close run's
274
+ * `delivery.quality.gates.crap.enabled`. `baseBranch` is the close run's
275
275
  * integration branch (`epic/<id>` for Epic-attached Stories, the base
276
276
  * branch for standalone Stories). `cwd` is where the `package.json`
277
277
  * coverage-script probe and the `baselines/<kind>.json` presence probe
@@ -285,7 +285,7 @@ function probeBaselinesGate({ config, cwd, presentBaselines } = {}) {
285
285
  */
286
286
  export function buildDefaultGates({
287
287
  config,
288
- epicBranch,
288
+ baseBranch,
289
289
  cwd,
290
290
  packageScripts,
291
291
  presentBaselines,
@@ -305,9 +305,9 @@ export function buildDefaultGates({
305
305
  const formatWriteString = resolveFormatWriteCommand(config);
306
306
  const formatChangedFileScope =
307
307
  formatCheckString === FORMAT_CHECK_FALLBACK
308
- ? buildChangedFileScope(epicBranch)
308
+ ? buildChangedFileScope(baseBranch)
309
309
  : null;
310
- const baselinesGateEnv = buildBaselinesGateEnv(epicBranch);
310
+ const baselinesGateEnv = buildBaselinesGateEnv(baseBranch);
311
311
  const baselinesDecision = probeBaselinesGate({
312
312
  config,
313
313
  cwd,
@@ -3,7 +3,7 @@
3
3
  * inputs.js — shared input validator for close-validation projection helpers.
4
4
  *
5
5
  * Used by `projections/maintainability.js` (and any future projection that
6
- * shares the same `{ cwd, epicBranch, storyBranch, baselinePath }` argument
6
+ * shares the same `{ cwd, baseBranch, storyBranch, baselinePath }` argument
7
7
  * shape) to collapse the inline guard cascade into a single predicate that
8
8
  * returns a typed `reason` on failure.
9
9
  *
@@ -16,7 +16,7 @@
16
16
  /**
17
17
  * @typedef {Object} ProjectionInputs
18
18
  * @property {string} [cwd]
19
- * @property {string} [epicBranch]
19
+ * @property {string} [baseBranch]
20
20
  * @property {string} [storyBranch]
21
21
  * @property {string} [baselinePath]
22
22
  */
@@ -32,7 +32,7 @@
32
32
  /**
33
33
  * @typedef {Object} ValidationFail
34
34
  * @property {false} ok
35
- * @property {'missing-cwd'|'missing-epic-branch'|'missing-story-branch'|'missing-baseline-path'|'no-baseline'} reason
35
+ * @property {'missing-cwd'|'missing-base-branch'|'missing-story-branch'|'missing-baseline-path'|'no-baseline'} reason
36
36
  */
37
37
 
38
38
  /**
@@ -40,7 +40,7 @@
40
40
  *
41
41
  * Reason branches (in order):
42
42
  * - `missing-cwd` — cwd is falsy
43
- * - `missing-epic-branch` — epicBranch is falsy
43
+ * - `missing-base-branch` — baseBranch is falsy
44
44
  * - `missing-story-branch` — storyBranch is falsy
45
45
  * - `missing-baseline-path` — baselinePath is falsy
46
46
  * - `no-baseline` — loadBaseline returned null/undefined/empty
@@ -54,9 +54,9 @@
54
54
  * @returns {ValidationOk | ValidationFail}
55
55
  */
56
56
  export function validateProjectionInputs(inputs, opts = {}) {
57
- const { cwd, epicBranch, storyBranch, baselinePath } = inputs ?? {};
57
+ const { cwd, baseBranch, storyBranch, baselinePath } = inputs ?? {};
58
58
  if (!cwd) return { ok: false, reason: 'missing-cwd' };
59
- if (!epicBranch) return { ok: false, reason: 'missing-epic-branch' };
59
+ if (!baseBranch) return { ok: false, reason: 'missing-base-branch' };
60
60
  if (!storyBranch) return { ok: false, reason: 'missing-story-branch' };
61
61
  if (!baselinePath) return { ok: false, reason: 'missing-baseline-path' };
62
62
 
@@ -80,7 +80,7 @@ export function validateProjectionInputs(inputs, opts = {}) {
80
80
  */
81
81
  export const MISSING_ARG_REASONS = new Set([
82
82
  'missing-cwd',
83
- 'missing-epic-branch',
83
+ 'missing-base-branch',
84
84
  'missing-story-branch',
85
85
  'missing-baseline-path',
86
86
  ]);
@@ -41,18 +41,18 @@ function normaliseSkipReason(reason) {
41
41
  }
42
42
 
43
43
  /**
44
- * Refresh `origin/<epicBranch>` so the diff range resolves even when the
44
+ * Refresh `origin/<baseBranch>` so the diff range resolves even when the
45
45
  * close script hasn't reached its own pull/rebase step yet. Routed through
46
46
  * the shared `(cwd, ref, windowMs)` cache so a story-init fetch in the same
47
47
  * wave satisfies the projection without re-hitting origin.
48
48
  *
49
49
  * @param {string} cwd
50
- * @param {string} epicBranch
50
+ * @param {string} baseBranch
51
51
  * @param {{ gitSpawn: typeof defaultGitSpawn }} git
52
52
  * @returns {{ ok: true } | { ok: false, detail: string }}
53
53
  */
54
- function refreshEpicRef(cwd, epicBranch, git) {
55
- const fetchRes = cachedGitFetchSync(cwd, epicBranch, {
54
+ function refreshEpicRef(cwd, baseBranch, git) {
55
+ const fetchRes = cachedGitFetchSync(cwd, baseBranch, {
56
56
  gitSpawn: git.gitSpawn,
57
57
  });
58
58
  if (fetchRes.status !== 0) {
@@ -69,13 +69,13 @@ function refreshEpicRef(cwd, epicBranch, git) {
69
69
  * the changed-files list. Normalises Windows-style backslash paths to
70
70
  * forward slashes so the baseline lookup is platform-agnostic.
71
71
  *
72
- * @param {{ cwd: string, epicBranch: string, storyBranch: string, git: { gitSpawn: typeof defaultGitSpawn } }} opts
72
+ * @param {{ cwd: string, baseBranch: string, storyBranch: string, git: { gitSpawn: typeof defaultGitSpawn } }} opts
73
73
  * @returns {{ ok: true, files: string[] } | { ok: false, detail: string }}
74
74
  */
75
- function diffChangedFiles({ cwd, epicBranch, storyBranch, git }) {
75
+ function diffChangedFiles({ cwd, baseBranch, storyBranch, git }) {
76
76
  try {
77
77
  const files = diffNameOnly({
78
- range: `origin/${epicBranch}...${storyBranch}`,
78
+ range: `origin/${baseBranch}...${storyBranch}`,
79
79
  cwd,
80
80
  gitSpawn: git.gitSpawn,
81
81
  });
@@ -190,7 +190,7 @@ function collectRegressions({
190
190
  *
191
191
  * @param {{
192
192
  * cwd: string,
193
- * epicBranch: string,
193
+ * baseBranch: string,
194
194
  * storyBranch: string,
195
195
  * baselinePath: string,
196
196
  * tolerance?: number,
@@ -207,7 +207,7 @@ function collectRegressions({
207
207
  */
208
208
  export function projectMaintainabilityRegressions({
209
209
  cwd,
210
- epicBranch,
210
+ baseBranch,
211
211
  storyBranch,
212
212
  baselinePath,
213
213
  tolerance = DEFAULT_MI_TOLERANCE,
@@ -216,7 +216,7 @@ export function projectMaintainabilityRegressions({
216
216
  loadBaseline = getBaseline,
217
217
  } = {}) {
218
218
  const validation = validateProjectionInputs(
219
- { cwd, epicBranch, storyBranch, baselinePath },
219
+ { cwd, baseBranch, storyBranch, baselinePath },
220
220
  { loadBaseline },
221
221
  );
222
222
  if (!validation.ok) {
@@ -227,7 +227,7 @@ export function projectMaintainabilityRegressions({
227
227
  };
228
228
  }
229
229
 
230
- const fetchOutcome = refreshEpicRef(cwd, epicBranch, git);
230
+ const fetchOutcome = refreshEpicRef(cwd, baseBranch, git);
231
231
  if (!fetchOutcome.ok) {
232
232
  return {
233
233
  ok: true,
@@ -237,7 +237,7 @@ export function projectMaintainabilityRegressions({
237
237
  };
238
238
  }
239
239
 
240
- const diffOutcome = diffChangedFiles({ cwd, epicBranch, storyBranch, git });
240
+ const diffOutcome = diffChangedFiles({ cwd, baseBranch, storyBranch, git });
241
241
  if (!diffOutcome.ok) {
242
242
  return {
243
243
  ok: true,
@@ -72,21 +72,19 @@ function applyChangedFileScope({ gate, spawnCwd, log }) {
72
72
  * Worktree locality (Story #1120): when `worktreePath` is supplied, every
73
73
  * gate runner is spawned with `cwd: worktreePath` so the gate sees the
74
74
  * Story branch's post-rebase tree. Evidence reads/writes still key against
75
- * `cwd` (the main checkout) because the per-Epic temp tree lives under
76
- * the main `.git/`. Failure messages name the worktree path.
75
+ * `cwd` (the main checkout) because the temp tree lives under the main
76
+ * `.git/`. Failure messages name the worktree path.
77
77
  *
78
- * Evidence-aware: when `storyId` is provided alongside either `epicId` or
79
- * `standalone: true`, and `useEvidence !== false`, each gate consults
78
+ * Evidence-aware: when `storyId` is provided alongside `standalone: true`,
79
+ * and `useEvidence !== false`, each gate consults
80
80
  * `validation-evidence.shouldSkip()` against current HEAD + the gate's
81
81
  * command-config hash. A matching record skips the gate; a successful run
82
82
  * is recorded so the next caller in the local hot path can skip in turn.
83
83
  *
84
- * Standalone keyspace (Story #4250): the standalone path has no parent
85
- * Epic, so it passes `standalone: true` (and leaves `epicId` null) to route
86
- * the evidence file to the storyId-anchored
84
+ * Standalone keyspace (Story #4250): `standalone: true` routes the evidence
85
+ * file to the storyId-anchored
87
86
  * `<tempRoot>/standalone/stories/story-<id>/validation-evidence.json`
88
- * keyspace instead of feeding a null `epicId` into the Epic-keyed path
89
- * (which structurally disabled the cache before).
87
+ * keyspace. v2.0.0 removed the Epic tier and its Epic-keyed keyspace.
90
88
  *
91
89
  * `onGateStart` is invoked immediately before each gate's runner spawn.
92
90
  * story-close uses it to drive `phaseTimer.mark(...)` for per-gate
@@ -100,7 +98,6 @@ function applyChangedFileScope({ gate, spawnCwd, log }) {
100
98
  * log?: (m: string) => void,
101
99
  * onGateStart?: (gate: Gate) => void,
102
100
  * storyId?: number|null,
103
- * epicId?: number|null,
104
101
  * standalone?: boolean,
105
102
  * useEvidence?: boolean,
106
103
  * evidenceClock?: () => number,
@@ -118,7 +115,6 @@ export async function runCloseValidation({
118
115
  log = () => {},
119
116
  onGateStart,
120
117
  storyId = null,
121
- epicId = null,
122
118
  standalone = false,
123
119
  useEvidence = true,
124
120
  evidenceClock = () => Date.now(),
@@ -129,16 +125,12 @@ export async function runCloseValidation({
129
125
  const failed = [];
130
126
  const skipped = [];
131
127
  // Evidence is active when a Story id is present AND there is a keyspace to
132
- // anchor on: either a real Epic id (Epic path) or `standalone: true`
133
- // (Story #4250 standalone storyId-anchored keyspace). A bare `epicId:
134
- // null` without `standalone` keeps the cache off, as before.
135
- const evidenceActive =
136
- useEvidence && storyId != null && (epicId != null || standalone);
137
- // The evidence-store opts: `standalone` routes to the storyId-anchored
138
- // keyspace; otherwise the Epic-keyed path resolves under `epicId`.
139
- const evidenceStoreOpts = { cwd, epicId, standalone };
140
- // Evidence keys against the main checkout's HEAD because the per-Epic
141
- // evidence file lives under the main `.git/`. Gate spawn, in contrast,
128
+ // anchor on (`standalone: true` — Story #4250's storyId-anchored
129
+ // keyspace, now the only one).
130
+ const evidenceActive = useEvidence && storyId != null && standalone;
131
+ const evidenceStoreOpts = { cwd, standalone };
132
+ // Evidence keys against the main checkout's HEAD because the evidence
133
+ // file lives under the main `.git/`. Gate spawn, in contrast,
142
134
  // runs in the worktree when one is supplied — that's the whole point of
143
135
  // Story #1120.
144
136
  const spawnCwd = worktreePath ?? cwd;
@@ -3,19 +3,25 @@
3
3
  */
4
4
 
5
5
  import { writeFile as defaultWriteFile } from 'node:fs/promises';
6
- import { storyArtifactPath } from '../config/temp-paths.js';
6
+ import path from 'node:path';
7
+ import { storyTempDir } from '../config/temp-paths.js';
7
8
  import { getSpawnCount as defaultGetSpawnCount } from '../gh-exec.js';
8
9
 
9
10
  /**
10
11
  * Throw-away ghSpawnCount emitter (Story #1795 / Epic #1788).
11
12
  *
12
13
  * Writes the current `gh-exec` spawn counter to
13
- * `temp/epic-<eid>/stories/story-<sid>/gh-spawn-count.json` so the
14
- * `analyze-execution.js` child process can read it and emit a
15
- * `ghSpawnCount` field on the `story-perf-summary` payload. The Story-
16
- * close orchestrator calls this inside `runPostMergeClose` right before
17
- * the perf-summary phase, capturing every `gh` invocation from preflight
18
- * through the merge in one counter snapshot.
14
+ * `temp/run-<id>/stories/story-<sid>/gh-spawn-count.json`.
15
+ *
16
+ * Story #4545 its reader is gone: `analyze-execution.js` consumed this file
17
+ * to emit a `ghSpawnCount` field on the `story-perf-summary` payload, and both
18
+ * that CLI and that payload were deleted with the execution-analysis surface.
19
+ * The writer itself already had no production caller before that (the
20
+ * `runPostMergeClose` orchestrator named below went in the v2.0.0 cutover), so
21
+ * this module is production-dead and kept alive only by its own test — the
22
+ * test-importer blind spot the dead-exports ratchet cannot see. It is left in
23
+ * place rather than deleted because reviving spawn telemetry against the live
24
+ * close path is a decision, not a sweep.
19
25
  *
20
26
  * @param {object} opts
21
27
  * @param {number|string} opts.epicId
@@ -50,7 +56,10 @@ export async function emitGhSpawnCount({
50
56
  );
51
57
  return { status: 'failed', reason: 'counter-read-failed' };
52
58
  }
53
- const targetPath = storyArtifactPath(eid, sid, 'gh-spawn-count.json', config);
59
+ const targetPath = path.join(
60
+ storyTempDir(eid, sid, config),
61
+ 'gh-spawn-count.json',
62
+ );
54
63
  const payload = {
55
64
  kind: 'gh-spawn-count',
56
65
  epicId: eid,
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Resolves `.agentrc.json → delivery.acceptanceEval` into the canonical
5
5
  * shape the per-Story acceptance self-eval loop consumes. The loop scores
6
- * the working diff against each inline `acceptance[]` item, redrafts the
7
- * unmet items, and re-evaluates — capped at `maxRounds` redraft rounds,
6
+ * the caller-injected change set against each inline `acceptance[]` item,
7
+ * redrafts the unmet items, and re-evaluates — capped at `maxRounds` rounds,
8
8
  * then escalates to `agent::blocked` when criteria remain unmet.
9
9
  *
10
10
  * ## The undisableable cap
@@ -18,12 +18,13 @@
18
18
  * full-closure agent that ran before M7-B.
19
19
  *
20
20
  * `delivery.routing.freshCriticSampleRate` is the **maker-checker sampling
21
- * floor** (Epic #4478, M7-B, Part 2). Risk-routed ceremony sends a low-risk
22
- * acceptance cluster down the contract-identical *inline* critic path, but a
23
- * fraction of low-risk clusters are still forced through a *fresh-context*
24
- * critic so "low risk" never degrades to zero independent checking. The rate is
25
- * clamped into `[0, 1]`; `0` disables the floor (pure risk routing), `1` forces
26
- * every cluster fresh. The default is `0.2`. See `resolveCeremonyForRisk` in
21
+ * floor** (Epic #4478, M7-B, Part 2). Ceremony routing sends the acceptance
22
+ * clusters of a change set that touches no sensitive path down the
23
+ * contract-identical *inline* critic path, but a fraction of them are still
24
+ * forced through a *fresh-context* critic so a low derived level never degrades
25
+ * to zero independent checking. The rate is clamped into `[0, 1]`; `0` disables
26
+ * the floor (pure level routing), `1` forces every cluster fresh. The default is
27
+ * `0.2`. See `resolveCeremonyForRisk` in
27
28
  * `lib/orchestration/ceremony-routing.js`.
28
29
  *
29
30
  * Framework-defaults pattern mirrors `lib/config/ci.js#getCiDelivery`.
@@ -63,13 +63,13 @@ const SECRET_SEGMENT_PATTERNS = Object.freeze([
63
63
  const KEY_MEANINGS = Object.freeze({
64
64
  // project.*
65
65
  'project.baseBranch':
66
- 'Default base branch Epics and Stories branch from and merge back into.',
66
+ 'Default base branch Stories branch from and merge back into.',
67
67
  'project.paths.agentRoot':
68
68
  'Directory holding the distributed agent bundle (instructions, skills, scripts).',
69
69
  'project.paths.docsRoot':
70
70
  'Directory the mandatory docs-context reads resolve against.',
71
71
  'project.paths.tempRoot':
72
- 'Root for gitignored scratch output (per-Epic run state, mirrors, logs).',
72
+ 'Root for gitignored scratch output (per-run state, mirrors, logs).',
73
73
  'project.docsContextFiles':
74
74
  'Authoritative files an agent must read before starting any task.',
75
75
  'project.commands.lintBaseline':
@@ -114,10 +114,6 @@ const KEY_MEANINGS = Object.freeze({
114
114
  'Allowlist of events that fire a webhook notification.',
115
115
 
116
116
  // planning.*
117
- 'planning.context.maxBytes':
118
- 'Byte budget for the planning-context payload before summary mode kicks in.',
119
- 'planning.context.summaryMode':
120
- 'When the planner switches to a summarized context representation.',
121
117
  'planning.codebaseSnapshot.tier':
122
118
  'Depth of the structural codebase view threaded into spec authoring.',
123
119
  'planning.codebaseSnapshot.include':
@@ -149,7 +145,7 @@ const KEY_MEANINGS = Object.freeze({
149
145
  'delivery.execution.timeoutMs':
150
146
  'Per-execution timeout for orchestrated delivery steps.',
151
147
  'delivery.lease.ttlMs':
152
- 'Time-to-live for the Epic lease before a stale claim is reclaimable.',
148
+ 'Time-to-live for the delivery lease before a stale claim is reclaimable.',
153
149
  'delivery.ci.watch.pollIntervalMs':
154
150
  'Poll cadence (ms) for the merge/CI watch loop.',
155
151
  'delivery.ci.watch.maxPolls':
@@ -161,9 +157,7 @@ const KEY_MEANINGS = Object.freeze({
161
157
  'delivery.docsFreshness.paths':
162
158
  'Docs whose freshness is checked at delivery time.',
163
159
  'delivery.deliverRunner.concurrencyCap':
164
- 'Maximum Stories dispatched in parallel within one wave. Default 3 — conservative by design to keep host-quota consumption predictable. Operators running wide-wave Epics with adequate parallel-agent quota should raise this to reduce wall-clock time proportionally.',
165
- 'delivery.deliverRunner.verifyConcurrencyCap':
166
- 'Maximum verify steps run in parallel.',
160
+ 'Maximum Stories dispatched in parallel within one wave. Default 3 — conservative by design to keep host-quota consumption predictable. Operators running wide waves with adequate parallel-agent quota should raise this to reduce wall-clock time proportionally.',
167
161
  'delivery.worktreeIsolation.enabled':
168
162
  'Whether each Story runs in its own git worktree.',
169
163
  'delivery.worktreeIsolation.root':
@@ -179,9 +173,9 @@ const KEY_MEANINGS = Object.freeze({
179
173
  'delivery.worktreeIsolation.bootstrapFiles':
180
174
  'Files copied into each new worktree (e.g. .env, .mcp.json, local overrides).',
181
175
  'delivery.mergeWatch.intervalSeconds':
182
- 'Poll cadence (seconds) for MergeWatcher after epic.merge.armed.',
176
+ 'Poll cadence (seconds) for the close-and-land merge wait after the arm.',
183
177
  'delivery.mergeWatch.maxBudgetSeconds':
184
- 'Wall-clock budget (seconds) before MergeWatcher surfaces budget-exceeded.',
178
+ 'Cumulative wall-clock budget (seconds) across resumes before the merge wait gives up and blocks.',
185
179
  'delivery.codeReview.providers':
186
180
  'Ordered provider chain the code-review phase consults.',
187
181
  'delivery.codeReview.maxFixAttempts':
@@ -195,7 +189,7 @@ const KEY_MEANINGS = Object.freeze({
195
189
  'delivery.routing.freshCriticSampleRate':
196
190
  'Fraction of low-risk acceptance clusters forced through a fresh-context critic (maker-checker floor).',
197
191
  'delivery.routing.ceremonyProfile':
198
- 'Acceptance-ceremony depth: minimal (always inline), standard (risk-routed), or strict (always fresh).',
192
+ 'Acceptance-ceremony depth: minimal (always inline), standard (derived-level routed), or strict (always fresh).',
199
193
  'delivery.routing.closeAndLand':
200
194
  'When true, single-story-close lands through merge in one close (opt out with --no-wait-merge).',
201
195
  'delivery.feedbackLoop.auditResultsAutoFile':
@@ -217,7 +211,7 @@ const KEY_MEANINGS = Object.freeze({
217
211
  'delivery.acceptanceEval.maxRounds':
218
212
  'Redraft rounds the per-Story acceptance self-eval loop runs before escalating to agent::blocked (default 2; clamped to a hard ceiling that cannot be disabled).',
219
213
  'delivery.acceptanceEval.clusterCeiling':
220
- 'Max acceptance criteria one single-delivery acceptance critic scores per fresh-context pass; the Epic ACs are split into ceil(totalACs / clusterCeiling) maker-blind critic clusters (default 4; clamped to [1, 8]).',
214
+ 'Max acceptance criteria one single-delivery acceptance critic scores per fresh-context pass; the Story ACs are split into ceil(totalACs / clusterCeiling) maker-blind critic clusters (default 4; clamped to [1, 8]).',
221
215
 
222
216
  // qa.*
223
217
  'qa.featureRoot': 'Root directory holding the QA harness .feature files.',
@@ -252,7 +246,7 @@ const PREFIX_MEANINGS = Object.freeze([
252
246
  ],
253
247
  ['delivery.quality', 'Delivery-time quality configuration.'],
254
248
  ['delivery.signals', 'Threshold for a delivery friction/telemetry signal.'],
255
- ['delivery.mergeWatch', 'MergeWatcher poll cadence and wall-clock budget.'],
249
+ ['delivery.mergeWatch', 'Merge-wait poll cadence and wall-clock budget.'],
256
250
  [
257
251
  'delivery.feedbackLoop',
258
252
  'Opt-out toggles for auto-filing non-blocking findings.',
@@ -282,7 +276,7 @@ const PREFIX_MEANINGS = Object.freeze([
282
276
  const BLOCK_MEANINGS = Object.freeze({
283
277
  project: 'Project identity, paths, and command configuration.',
284
278
  github: 'GitHub provider identity and merge/notification policy.',
285
- planning: 'Inputs and guardrails for /epic-plan.',
279
+ planning: 'Inputs and guardrails for /plan.',
286
280
  delivery: 'Execution, isolation, quality, and CI settings for delivery.',
287
281
  qa: 'Agent-driven QA harness contract.',
288
282
  });
@@ -55,11 +55,13 @@ export const NOTIFICATIONS_DEFAULTS = Object.freeze({
55
55
  'operator-message',
56
56
  ]),
57
57
  webhookEvents: Object.freeze([
58
- 'epic-started',
59
- 'epic-progress',
60
- 'epic-blocked',
61
- 'epic-unblocked',
62
- 'epic-complete',
58
+ 'state-transition',
59
+ 'story-merged',
60
+ 'story-closing',
61
+ 'operator-message',
62
+ 'merge.unlanded',
63
+ 'merge.flip-failed',
64
+ 'loop.tick',
63
65
  ]),
64
66
  });
65
67
 
@@ -5,7 +5,6 @@
5
5
  * Post-reshape, the surviving operator-configurable keys are split across
6
6
  * `planning.*` and `delivery.*`:
7
7
  *
8
- * - `planning.context.{maxBytes, summaryMode}` (planning-context budget)
9
8
  * - `delivery.execution.timeoutMs` (per-process execution timeout)
10
9
  * - `delivery.lease.ttlMs` (assignee-as-lease staleness window — Story #3480)
11
10
  * - `delivery.signals.{rework, retry}` (performance-signal detector
@@ -17,7 +16,12 @@
17
16
  * Dropped entirely: `maxInstructionSteps`, `friction.*`, `executionMaxBuffer`,
18
17
  * `signals.{churn, idle}`, `delivery.preflight`, `delivery.maxTokenBudget`
19
18
  * (planning no longer sizes against a token-budget envelope; session-mass
20
- * ceilings are absolute in `DEFAULT_MODEL_CAPACITY`).
19
+ * ceilings are absolute in `DEFAULT_MODEL_CAPACITY`), and
20
+ * `planning.context.{maxBytes, summaryMode}` (Story #4541 — the `applyBudget`
21
+ * pass they fed lost its last caller in the v2 cutover, and it bounded a field
22
+ * the envelope builders discarded; the live bound on planner-context size is
23
+ * the fixed `PLAN_CONTEXT_ENVELOPE_BYTE_CEILING` in
24
+ * `lib/orchestration/plan-context.js`).
21
25
  *
22
26
  * The historic combined accessor `getLimits(config)` is preserved as a
23
27
  * compatibility surface: it returns a wrapper carrying the surviving
@@ -37,10 +41,14 @@ export const SIGNALS_DEFAULTS = Object.freeze({
37
41
 
38
42
  /**
39
43
  * Default TTL for the assignee-as-lease primitive (Story #3480). A claim
40
- * whose owner has not emitted a `story.heartbeat` within this window is
41
- * considered stale and may be reclaimed by another operator. 15 minutes
42
- * gives a healthy run comfortable headroom over the §2e idle watchdog's
43
- * 10-minute re-tick while still releasing a genuinely dead claim promptly.
44
+ * whose owner's last heartbeat is older than this window is considered stale
45
+ * and may be reclaimed by another operator.
46
+ *
47
+ * Note: no shipped caller supplies a real heartbeat the emitter was inert
48
+ * and was deleted (A22), so the guards anchor liveness to `now` and every
49
+ * foreign claim reads live (fail-closed; clear a stranded claim with
50
+ * `--steal`). This value is therefore only consulted by a caller that threads
51
+ * its own `heartbeatAt`, and is kept as the documented default for that seam.
44
52
  */
45
53
  export const LEASE_TTL_MS_DEFAULT = 900000;
46
54
 
@@ -51,10 +59,6 @@ export const LIMITS_DEFAULTS = Object.freeze({
51
59
  maxTickets: 80,
52
60
  executionTimeoutMs: 600000,
53
61
  leaseTtlMs: LEASE_TTL_MS_DEFAULT,
54
- planningContext: Object.freeze({
55
- maxBytes: 50000,
56
- summaryMode: 'auto',
57
- }),
58
62
  signals: SIGNALS_DEFAULTS,
59
63
  });
60
64
 
@@ -83,8 +87,7 @@ function mergeSignals(userSignals) {
83
87
  /**
84
88
  * Resolve the surviving limits surface against a `.agentrc.json` shape
85
89
  * (post-reshape). `maxTickets` is a framework constant (never read from
86
- * config); pulls `planningContext` from `planning.*`, pulls
87
- * `executionTimeoutMs` from `delivery.*`, pulls signals from
90
+ * config); pulls `executionTimeoutMs` from `delivery.*`, pulls signals from
88
91
  * `delivery.signals.*`.
89
92
  *
90
93
  * @param {object|undefined} config
@@ -92,23 +95,14 @@ function mergeSignals(userSignals) {
92
95
  * maxTickets: number,
93
96
  * executionTimeoutMs: number,
94
97
  * leaseTtlMs: number,
95
- * planningContext: { maxBytes: number, summaryMode: string },
96
98
  * signals: ReturnType<typeof mergeSignals>,
97
99
  * }}
98
100
  */
99
101
  export function resolveLimits(config) {
100
- const planning =
101
- config?.planning && typeof config.planning === 'object'
102
- ? config.planning
103
- : {};
104
102
  const delivery =
105
103
  config?.delivery && typeof config.delivery === 'object'
106
104
  ? config.delivery
107
105
  : {};
108
- const planningContextUser =
109
- planning.context && typeof planning.context === 'object'
110
- ? planning.context
111
- : {};
112
106
  const execution =
113
107
  delivery.execution && typeof delivery.execution === 'object'
114
108
  ? delivery.execution
@@ -120,10 +114,6 @@ export function resolveLimits(config) {
120
114
  executionTimeoutMs:
121
115
  execution.timeoutMs ?? LIMITS_DEFAULTS.executionTimeoutMs,
122
116
  leaseTtlMs: lease.ttlMs ?? LIMITS_DEFAULTS.leaseTtlMs,
123
- planningContext: {
124
- ...LIMITS_DEFAULTS.planningContext,
125
- ...planningContextUser,
126
- },
127
117
  signals: mergeSignals(delivery.signals),
128
118
  };
129
119
  }