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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Mandrel uses **Story-centric GitHub orchestration** — GitHub Issues,
4
4
  Labels, and Projects V2 are the Single Source of Truth. Plans persist as
5
- `type::story` tickets (optionally grouped by a `plan-run::<id>` label);
5
+ `type::story` tickets ordered by `depends_on` edges;
6
6
  each Story is delivered on its own `story-<id>` branch and reaches `main`
7
7
  through its own PR.
8
8
 
@@ -40,8 +40,9 @@ From zero to shipped:
40
40
 
41
41
  `/plan` is a **single path** — there is no Epic/Story router, no
42
42
  scope-triage `epic|story` verdict, and no `deliveryShape`. All GitHub
43
- reads happen in `plan-context.js`, all writes in `plan-persist.js`, and
44
- two HITL gates bracket the authoring middle. Duplicate search targets
43
+ reads happen in `plan-context.js`, the issue-creating writes in
44
+ `plan-persist.js`, and two HITL gates bracket the authoring middle.
45
+ Duplicate search targets
45
46
  open **Stories** (`type::story`), never Epics.
46
47
 
47
48
  1. **Interrogate** — `plan-context.js` emits the single authoring
@@ -49,19 +50,29 @@ From zero to shipped:
49
50
  probe, risk heuristics, `systemPrompts.story`). Duplicate review
50
51
  folds into **gate #1**.
51
52
  2. **Author** — write `stories.json` (**one Story by default**) with a
52
- folded Tech Spec in `## Spec` / `## Slicing`, plus
53
- `risk-verdict.json` (axes + summary only — no `deliveryShape`).
53
+ folded Tech Spec in `## Spec` / `## Slicing`. There is no risk artifact
54
+ to author (Story #4542).
54
55
  Binding criteria live in top-level `acceptance[]` / `verify[]`;
55
56
  changes/references are `{ path, assumption }` objects. Split into
56
57
  N>1 only under the default-single split policy.
57
- 3. **Persist** — **gate #2** (risk-routed; typically skipped for N=1
58
- low-risk) then `plan-persist.js` runs every deterministic gate and
59
- creates Story issue(s) with `type::story` + `agent::ready` (plus a
60
- shared `plan-run::<id>` label when N>1).
58
+ 2.5. **Critics** — `plan-critics.js` evaluates the consolidation +
59
+ pre-mortem dispatch conditions against the authored draft and ledgers
60
+ every skip. This is the **only** critic gate (#4592 moved it out of
61
+ `plan-persist.js` into workflow prose), so skipping it silently skips
62
+ both critics: run it before Persist, per
63
+ [`/plan`](../workflows/plan.md) step 2.5.
64
+ 3. **Persist** — **gate #2** (raised only by an explicit `--force-review`)
65
+ then `plan-persist.js` runs every deterministic gate and
66
+ creates Story issue(s) with `type::story` + `agent::ready`, writing
67
+ each authored `depends_on` edge into the sibling body as a
68
+ `blocked by #<id>` footer when N>1.
61
69
 
62
70
  2. **Deliver the Story.** Run [`/deliver <storyId>`](../workflows/deliver.md)
63
- (or `/deliver <a> <b> …`, or `/deliver --run <planRunId>` for a
64
- multi-Story plan-run) in your IDE. `/deliver` owns input resolution and
71
+ (or `/deliver <a> <b> …` for several) in your IDE. `/deliver` takes
72
+ only Story ids and resolves their dependency graph from live state —
73
+ body edges union native GitHub `blocked_by` edges, with every blocker
74
+ checked against its real issue state, so a Story whose blocker landed in
75
+ an earlier plan run is simply ready. `/deliver` owns input resolution and
65
76
  `depends_on` sequencing only — every Story runs through
66
77
  [`helpers/deliver-story`](../workflows/helpers/deliver-story.md), the
67
78
  single v2 delivery engine. Per-Story it:
@@ -72,11 +83,12 @@ From zero to shipped:
72
83
  2. **Implement** — the agent delivers the Story in one guarded session
73
84
  against its inline `acceptance[]` / `verify[]` contract (optional
74
85
  `## Slicing` intra-session checkpoints).
75
- 3. **Acceptance self-eval** — a bounded, risk-routed critic loop scores
76
- the working diff against each acceptance item before close (see
86
+ 3. **Acceptance self-eval** — a bounded critic loop scores the
87
+ caller-injected change set against each acceptance item before close (see
77
88
  [`helpers/acceptance-self-eval`](../workflows/helpers/acceptance-self-eval.md)).
78
- 4. **Ceremony** — risk-routed acceptance critics, review depth, and
79
- audit lenses (`ceremony-routing.js`).
89
+ 4. **Ceremony** — acceptance critic mode and review depth, both routed off
90
+ the change level derived from the Story's own diff
91
+ (`review-depth.js#deriveChangeLevel` → `ceremony-routing.js`).
80
92
  5. **Close** (`single-story-close.js`) — runs close-validation gates,
81
93
  the maker-blind Story-scope code review, pushes `story-<id>`, opens
82
94
  a PR to `main`, and (under the default `delivery.ci.autoMerge:
@@ -88,7 +100,7 @@ From zero to shipped:
88
100
  `MERGED` PR the Story flips to `agent::done`; local branch cleanup
89
101
  and Projects-v2 Status re-assert run out-of-band.
90
102
 
91
- For a multi-Story plan-run, `/deliver` sequences ready Stories by
103
+ For a multi-Story run, `/deliver` sequences ready Stories by
92
104
  `depends_on` and runs the per-run epilogue (audit roster · follow-up
93
105
  roll-up · sibling coherence) once after the last Story lands.
94
106
 
@@ -105,8 +117,8 @@ rather than re-documenting the ceremony they own.
105
117
  - **Layered state stores with explicit precedence.** Ticket status lives
106
118
  in GitHub Issues and Labels; the lifecycle bus
107
119
  (`temp/run-<id>/lifecycle.ndjson`) is the canonical resume target for
108
- in-flight runs; structured comments (`story-run-progress`,
109
- `verification-results`, retro) are the operator-visible rollup. The
120
+ in-flight runs; structured comments (`verification-results`, retro) are
121
+ the operator-visible rollup. The
110
122
  stores, their owners, and their conflict-resolution rules are listed in
111
123
  [§ State stores](#state-stores) — that matrix is the single source of
112
124
  truth for "who owns which write."
@@ -149,9 +161,8 @@ on-disk layout resolved by
149
161
  | State Store | Owner (canonical writer) | Mutation API | Idempotency key | Conflict resolution |
150
162
  | --- | --- | --- | --- | --- |
151
163
  | GitHub labels | `transitionTicketState` via `ticketing.js` | `gh issue edit --add-label / --remove-label`, wrapped in `update-ticket-state.js` | `(ticketId, label-set)` — set-equality before write | Authoritative for current ticket lifecycle state; if a label disagrees with the lifecycle ledger, the **ledger wins on resume** and the label is re-derived. |
152
- | `story-run-progress` comment | `story-phase.js` (per Story, per phase transition) | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='story-run-progress')` | Authoritative for Story-level phase progress. |
153
164
  | `verification-results` comment | `lib/orchestration/code-review.js` | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='verification-results')` | Authoritative for the Story-scope review + lens findings; critical findings block close. |
154
- | Lifecycle ledger NDJSON | `lifecycle-emit.js` (single append-only writer per run) | Append-only line write to `temp/run-<id>/lifecycle.ndjson` | `(runId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived. |
165
+ | Lifecycle ledger NDJSON | `LedgerWriter` (`lib/orchestration/lifecycle/ledger-writer.js`, registered as the first listener on every bus event — single append-only writer per run) | Append-only line write to `temp/run-<id>/lifecycle.ndjson` | `(runId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived. |
155
166
  | Validation evidence cache | `evidence-gate.js` | JSON cache file under the run temp tree, keyed by HEAD SHA | `(gate, git rev-parse HEAD)` | Pure cache: a missing entry triggers a re-run; presence is a fast-path skip. Cache eviction is safe. |
156
167
  | PR / auto-merge state | `single-story-close.js` (sole authorized caller of `gh pr merge`) | `gh pr merge --auto --squash --delete-branch`; PR open via the close pipeline's `gh pr create` | `(prNumber, head-branch SHA)` — `gh pr list --head` probes before create | GitHub is authoritative for PR + auto-merge arming state; the ledger records the *intent* to arm, GitHub records the outcome. |
157
168
  | Worktree cleanup state | `WorktreeManager.reap` (via `single-story-close.js` / `git-cleanup.js`) | `git worktree remove` + on-disk pending-cleanup JSON under the run temp tree | `(storyId, worktree-path)` | Filesystem is authoritative for "is the worktree gone?"; the pending-cleanup JSON only tracks stale-registry entries needing a follow-up sweep. |
@@ -180,12 +191,12 @@ graph LR
180
191
  A["👤 /plan --seed | --seed-file | --tickets"]:::manual
181
192
  B["🤖 interrogate → author → persist"]:::agentic
182
193
  A --> B
183
- B -.-> B_Art["📄 type::story issue(s)<br/>(+ optional plan-run::&lt;id&gt;)"]:::artifact
194
+ B -.-> B_Art["📄 type::story issue(s)<br/>(+ depends_on edges)"]:::artifact
184
195
  end
185
196
 
186
197
  subgraph Phase2 ["Phase 2: Deliver"]
187
198
  direction TB
188
- E["👤 /deliver &lt;storyId&gt;<br/>(or --run &lt;planRunId&gt;)"]:::manual
199
+ E["👤 /deliver &lt;storyId&gt; [&lt;storyId&gt;…]"]:::manual
189
200
  F["🤖 deliver-story: story-&lt;id&gt; from main<br/>implement → self-eval → ceremony → close"]:::agentic
190
201
  G["🤖 close-validation → code-review → open PR"]:::agentic
191
202
  E --> F --> G
@@ -267,7 +278,7 @@ the SDLC depends on:
267
278
  - **One Story by default.** `/plan` authors a single `type::story` issue
268
279
  whose body carries a folded `## Spec` (inline only — never spilled to
269
280
  `docs/`) plus top-level `acceptance[]` / `verify[]`. It splits into N>1
270
- siblings (sharing a `plan-run::<id>` label + `depends_on` edges) **only**
281
+ siblings (ordered by `depends_on` edges) **only**
271
282
  under the default-single split policy: near-zero overlap or a genuine
272
283
  architectural seam. Coupled work stays one Story and is decomposed inside
273
284
  `## Slicing` as intra-session checkpoints, not sibling tickets.
@@ -278,8 +289,7 @@ the SDLC depends on:
278
289
  `assertAcceptancePartition` so every acceptance criterion belongs to
279
290
  exactly one Story.
280
291
  - **Handoff.** Persist creates the Story issue(s) at `agent::ready` and
281
- names the delivery command: `/deliver <storyId>` (or `/deliver --run
282
- <planRunId>`).
292
+ names the delivery command: `/deliver <storyId> [<storyId> ...]`.
283
293
 
284
294
  Optional split advisory notes come from
285
295
  [`core/scope-triage`](../skills/core/scope-triage/SKILL.md); there is no
@@ -308,8 +318,7 @@ self-eval, ceremony, close, CI watch, confirm-merge, cleanup) lives in the
308
318
  | Mode | Entry point | When to use |
309
319
  | --- | --- | --- |
310
320
  | **Single Story** | `/deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
311
- | **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**); each lands through its own PR. |
312
- | **Plan-run** | `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue after the set lands. |
321
+ | **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**), resolved from live state so edges may point at Stories from earlier plan runs; each lands through its own PR, and the per-run epilogue runs after the set lands. |
313
322
  | **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/deliver`; not an operator slash command. |
314
323
 
315
324
  The single operator-facing entry point is `/deliver`. It performs no
@@ -374,14 +383,14 @@ Concurrent runs are serialised by **two distinct layers**:
374
383
  assignee; `--steal` is the only override. See
375
384
  [`README.md` § Multi-developer coordination](../README.md#multi-developer-coordination).
376
385
 
377
- ### Concurrent close — push retry
386
+ ### Concurrent close
378
387
 
379
388
  `single-story-close.js` syncs the Story branch from `origin/main` before
380
- pushing and opening/locating the PR. Bounded retry constants live in
381
- `.agents/scripts/lib/config/runners.js` (`DEFAULT_STORY_MERGE_RETRY`:
382
- 3 attempts, `[250, 500, 1000]` ms backoff). A real content conflict aborts
383
- the loop with a clear error, leaves the tree clean, and exits non-zero for
384
- manual resolution.
389
+ pushing and opening/locating the PR, so concurrent closes serialize through
390
+ their own worktrees rather than racing one shared branch. The push does not
391
+ retry: a rejected push, or a real content conflict at base-sync, aborts with
392
+ a clear error, leaves the tree clean, and exits non-zero for manual
393
+ resolution.
385
394
 
386
395
  ---
387
396
 
@@ -486,14 +495,18 @@ pass — the tiers below *are* the audit machinery.
486
495
  | --- | --- | --- | --- |
487
496
  | Tier 1 — write-time | During Story implementation | Footprint-matched **local**-lens authoring checklists threaded into the Story prompt (`checklistPath`) | advisory |
488
497
  | Tier 2 — Story-scope | `single-story-close.js` (maker-blind subprocess) | Local-tier lens roster over the Story diff (`selectLocalLenses`) + review pillars, posted as `verification-results` | blocking on 🔴 |
489
- | Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global + risk-routed lenses (`selectAudits` / `resolveAuditLenses`) over the combined landed tip | blocking |
498
+ | Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global lenses (`selectAudits`) over the combined landed tip | blocking |
490
499
 
491
500
  - **`local`** lenses (decidable from a single Story's diff) are verified at
492
501
  Tiers 1–2 and are **not** re-run at run closeout.
493
- - **`cumulative`** lenses (only decidable across a plan-run's combined diff)
502
+ - **`cumulative`** lenses (only decidable across a run's combined diff)
494
503
  and **`global`** lenses (whole-product properties) are verified at Tier 3.
495
- - **Risk-routed** lenses run regardless of tier when a high-risk axis (or a
496
- route-adding change set) demands them.
504
+
505
+ There is no risk-routed lens tier. Story #4542 deleted the risk→lens router:
506
+ it had zero callers while this document claimed it ran inside close. Lens
507
+ selection is change-set-matched (`selectAudits` / `selectLocalLenses`); the
508
+ `sensitivePaths` classes in `audit-rules.json` route review **depth**, not
509
+ lenses.
497
510
 
498
511
  The run-closeout roster is deliberately **slim**: it excludes every
499
512
  local-tier change-set lens so the outermost tier — where a fix is most
@@ -504,8 +517,8 @@ expensive — does not re-verify a concern already covered shift-left.
504
517
  The Story-scope code review runs **outside the maker's context**, inside
505
518
  the `single-story-close.js` close subprocess, over `main...story-<id>`
506
519
  (see [`helpers/code-review.md`](../workflows/helpers/code-review.md)). It
507
- walks the Story diff once, executing the risk-routed lens roster as review
508
- dimensions alongside the review pillars, and posts the unified
520
+ walks the Story diff once, executing the change-set-matched local lens roster
521
+ as review dimensions alongside the review pillars, and posts the unified
509
522
  `verification-results` comment. Remediation is tier-aware and split by
510
523
  finding class off `delivery.codeReview.autoFixSeverity` (default `medium`);
511
524
  surviving 🔴 Critical findings halt the run. The legacy `scope: epic`
@@ -513,12 +526,14 @@ Epic-branch review path was removed with the v2 cutover.
513
526
 
514
527
  ### Quality ratchets
515
528
 
516
- - **Maintainability ratchet** (`check-maintainability.js`) — fails if the
529
+ - **Maintainability ratchet** (`check-baselines.js` via
530
+ `lib/baselines/kinds/maintainability.js`) — fails if the
517
531
  composite score drops below the established baseline.
518
- - **CRAP gate** (`check-crap.js`) — per-method complexity × coverage risk
532
+ - **CRAP gate** (`check-baselines.js` via `lib/baselines/kinds/crap.js`) —
533
+ per-method complexity × coverage risk
519
534
  against `baselines/crap.json`, wired into close-validation, `ci.yml`, and
520
- `.husky/pre-push`. The `baseline-refresh:`-tagged commit convention is the
521
- project standard for baseline edits (see
535
+ `.husky/pre-push`. The `baseline-refresh: true` commit-trailer convention
536
+ is the project standard for baseline edits (see
522
537
  [`core/gates-and-baselines`](../skills/core/gates-and-baselines/SKILL.md)).
523
538
 
524
539
  ### Audits → Stories
@@ -552,7 +567,7 @@ Severity vocabulary (`eventSeverity()` derives it for state transitions):
552
567
 
553
568
  | Severity | Used for | Webhook prefix |
554
569
  | --- | --- | --- |
555
- | `low` | `story-run-progress` upserts, intermediate transitions, audit reports. | `[low]` |
570
+ | `low` | Intermediate transitions, audit reports. | `[low]` |
556
571
  | `medium` | Operator-visible milestones: Story state transitions, story merged, run complete. | `[medium]` |
557
572
  | `high` | Operator must act (HITL gates, Story blockers, autonomous-chain failures); body leads with `🚨 Action Required:`. | `[Action Required]` |
558
573
 
@@ -650,8 +665,7 @@ the ticket or re-plan the work as a v2 Story via `/plan --tickets <id>`.
650
665
  | `/plan --seed-file <path>` | Plan from on-disk notes / a plan seed (the `/audit-to-stories` handoff). |
651
666
  | `/plan --tickets <ids>` | Analyze existing issue(s) into proper Stories (prefer an N=1 rewrite). |
652
667
  | `/deliver <storyId>` | Deliver one Story via `helpers/deliver-story` — `story-<id>` → PR → `main`. |
653
- | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order; each lands through its own PR. |
654
- | `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue. |
668
+ | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (resolved from live state), then run the per-run epilogue. |
655
669
  | *helper* `helpers/deliver-story` | Per-Story engine invoked by `/deliver`; not an operator slash command. See [`deliver-story.md`](../workflows/helpers/deliver-story.md). |
656
670
  | `/audit-to-stories` | Convert audit findings into a plan seed / Stories → `/plan --seed-file`. |
657
671
  | `/qa-explore` · `/qa-assist` · `/qa-run` | Agent-led / human-led exploratory QA and the automated Gherkin harness. |
@@ -56,19 +56,17 @@
56
56
  "mentionOperator": false,
57
57
  "commentEvents": ["state-transition", "story-merged", "operator-message"],
58
58
  "webhookEvents": [
59
- "epic-started",
60
- "epic-progress",
61
- "epic-blocked",
62
- "epic-unblocked",
63
- "epic-complete"
59
+ "state-transition",
60
+ "story-merged",
61
+ "story-closing",
62
+ "operator-message",
63
+ "merge.unlanded",
64
+ "merge.flip-failed",
65
+ "loop.tick"
64
66
  ]
65
67
  }
66
68
  },
67
69
  "planning": {
68
- "context": {
69
- "maxBytes": 50000,
70
- "summaryMode": "auto"
71
- },
72
70
  "codebaseSnapshot": {
73
71
  "tier": "skinny",
74
72
  "include": [
@@ -131,8 +129,7 @@
131
129
  "paths": ["README.md"]
132
130
  },
133
131
  "deliverRunner": {
134
- "concurrencyCap": 3,
135
- "verifyConcurrencyCap": 4
132
+ "concurrencyCap": 3
136
133
  },
137
134
  "worktreeIsolation": {
138
135
  "enabled": true,
@@ -336,12 +333,10 @@
336
333
  "codingGuardrails": {
337
334
  "cyclomaticFlag": 8,
338
335
  "cyclomaticMustFix": 12,
339
- "miDropMustRefactor": 1.5,
340
336
  "requireSiblingTest": false
341
337
  },
342
338
  "autoRefresh": {
343
339
  "enabled": true,
344
- "miDropCap": 1.5,
345
340
  "crapJumpCap": 5,
346
341
  "scope": "diff"
347
342
  },
@@ -97,9 +97,6 @@ top-level keys are validation errors.
97
97
  | Key | Required | Type | Default | Description |
98
98
  | --- | --- | --- | --- | --- |
99
99
  | `riskHeuristics` | No | `string[]` or `{ append?, prepend? }` | — | — |
100
- | `context` | No | `object` | — | Nested configuration block. |
101
- | `context.maxBytes` | No | `integer` | — | — |
102
- | `context.summaryMode` | No | `"auto"` \| `"always"` \| `"never"` | — | — |
103
100
  | `codebaseSnapshot` | No | `object` | — | Nested configuration block. |
104
101
  | `codebaseSnapshot.tier` | No | `"skinny"` \| `"medium"` | — | — |
105
102
  | `codebaseSnapshot.include` | No | `array<string>` | — | — |
@@ -121,13 +118,12 @@ top-level keys are validation errors.
121
118
  | --- | --- | --- | --- | --- |
122
119
  | `execution` | No | `object` | — | Nested configuration block. |
123
120
  | `execution.timeoutMs` | No | `integer` | — | — |
124
- | `lease` | No | `object` | — | Story #3480 (Epic #3457). Assignee-as-lease primitive. ttlMs is the staleness window — a ticket claim whose owner has not emitted a story.heartbeat within this many milliseconds is reclaimable by another operator. Defaults to 900000 (15 min) in lib/config/limits.js. |
121
+ | `lease` | No | `object` | — | Story #3480 (Epic #3457). Assignee-as-lease primitive. ttlMs is the staleness window — a ticket claim whose owner's last heartbeat is older than this many milliseconds is reclaimable by another operator. Defaults to 900000 (15 min) in lib/config/limits.js. Note the shipped guards fail closed (there is no live heartbeat source), so a stranded claim is cleared with --steal rather than by TTL expiry. |
125
122
  | `lease.ttlMs` | No | `integer` | — | — |
126
123
  | `docsFreshness` | No | `object` | — | Nested configuration block. |
127
124
  | `docsFreshness.paths` | No | `array` | — | — |
128
125
  | `deliverRunner` | No | `object` | — | Nested configuration block. |
129
126
  | `deliverRunner.concurrencyCap` | No | `integer` | — | Maximum ready Stories dispatched by /deliver at once. Default 3. Moderate by design — keeps host-quota consumption predictable while allowing a small ready-set fan-out. Set 1 for strictly sequential delivery; raise further on hosts with adequate parallel-agent quota. See deliver.md for the sequencing model and throughput tradeoff. |
130
- | `deliverRunner.verifyConcurrencyCap` | No | `integer` | — | Bounded-concurrency cap for the per-wave verifyWaveResults loop (Epic #3019 Tech Spec §1.4). Separate from the wave-execution `concurrencyCap` so operators can tune ticket-verification parallelism independently of Story dispatch parallelism. Default 4. |
131
127
  | `worktreeIsolation` | No | `object` | — | Nested configuration block. |
132
128
  | `worktreeIsolation.enabled` | No | `boolean` | — | — |
133
129
  | `worktreeIsolation.root` | No | `string` | — | — |
@@ -235,11 +231,9 @@ top-level keys are validation errors.
235
231
  | `quality.codingGuardrails` | No | `object` | — | Nested configuration block. |
236
232
  | `quality.codingGuardrails.cyclomaticFlag` | No | `integer` | — | — |
237
233
  | `quality.codingGuardrails.cyclomaticMustFix` | No | `integer` | — | — |
238
- | `quality.codingGuardrails.miDropMustRefactor` | No | `number` | — | — |
239
234
  | `quality.codingGuardrails.requireSiblingTest` | No | `boolean` | — | — |
240
235
  | `quality.autoRefresh` | No | `object` | — | Nested configuration block. |
241
236
  | `quality.autoRefresh.enabled` | No | `boolean` | — | — |
242
- | `quality.autoRefresh.miDropCap` | No | `number` | — | — |
243
237
  | `quality.autoRefresh.crapJumpCap` | No | `number` | — | — |
244
238
  | `quality.autoRefresh.scope` | No | `"diff"` \| `"full"` | — | — |
245
239
  | `quality.baselineEpsilon` | No | `object` | — | Per-kind epsilon for s-stability-epsilon (Story #1964). Sub-epsilon row deltas resolve to prior bytes so env variance does not rewrite the on-disk baseline. |
@@ -252,13 +246,15 @@ top-level keys are validation errors.
252
246
  | `quality.baselineEpsilon.bundle-size` | No | `number` | — | — |
253
247
  | `quality.baselineEpsilon.duplication` | No | `number` | — | — |
254
248
  | `quality.requireBaselines` | No | `boolean` | — | Story #4495. Fail-closed baseline-enforcement policy for the unified check-baselines close-validation gate. When false (default), a consumer that enables baseline gates (crap/maintainability/…) but has not committed the corresponding baseline artifacts under baselines/ gets a clean skip-with-reason instead of a deterministic first-try close failure. Set true to keep the gate registered so an absent baseline artifact fails close-validation with a preflight hint naming the fix (the fail-closed posture). |
255
- | `quality.navigability` | No | `object` | — | Navigability lens + journey-suite config (Epic #4131, F2/F3/F1/F4). Read by audit-suite/selector.js (route globs) and /deliver's risk-routed ceremony (journey suite). Opt-in: absent or empty routeGlobs degrades to a silent no-op. |
249
+ | `quality.navigability` | No | `object` | — | Navigability lens + journey-suite config (Epic #4131, F2/F3/F1/F4). Read by audit-suite/selector.js (route globs) and /deliver's per-Story ceremony (journey suite). Opt-in: absent or empty routeGlobs degrades to a silent no-op. |
256
250
  | `quality.navigability.routeGlobs` | No | `array<string>` | — | Glob patterns (pages/**, app/**/route.ts) marking paths that add a user-facing route — the route-tree SSOT the navigability lens enumerates and the route-added routing predicate matches against. |
257
251
  | `quality.navigability.navRegistry` | No | `array<string>` | — | Tokens identifying the nav-registry SSOT the navigability lens checks every route resolves a nav door against. |
258
- | `quality.navigability.journeySuite` | No | `string` | — | Path or command for the per-persona journey suite /deliver's risk-routed ceremony runs. |
259
- | `mergeWatch` | No | `object` | — | Knobs consumed by the MergeWatcher lifecycle listener (Story #2896, Epic #2880). `intervalSeconds` is the poll cadence between `gh pr view --json mergeCommit,mergedAt` probes after epic.merge.armed; `maxBudgetSeconds` is the total wall-clock budget before the watcher surfaces `agent::blocked` with reason `budget-exceeded`. |
260
- | `mergeWatch.intervalSeconds` | No | `integer` | `30` | Seconds between MergeWatcher polls. Default 30. |
261
- | `mergeWatch.maxBudgetSeconds` | No | `integer` | `3600` | Total wall-clock budget (seconds) for the MergeWatcher poll loop. Default 3600 (60 minutes). |
252
+ | `quality.navigability.journeySuite` | No | `string` | — | Path or command for the per-persona journey suite /deliver's per-Story ceremony runs. |
253
+ | `mergeWatch` | No | `object` | — | Knobs consumed by the close-and-land merge wait (Story #4543; defaults in `lib/orchestration/merge-poll.js`). `intervalSeconds` is the poll cadence between `gh pr view` probes after the arm. `maxWaitSeconds` bounds ONE invocation of the merge wait and its expiry returns a resumable `pending` terminal with no label mutation; `maxBudgetSeconds` bounds the CUMULATIVE wait across resumes (anchored at the PR's createdAt, so a resume does not restart the clock) and exhausting it is the genuine give-up that classifies and blocks. `updateAttempts` caps the bounded update of a behind-the-base PR. |
254
+ | `mergeWatch.intervalSeconds` | No | `integer` | `30` | Seconds between merge-wait polls. Default 30. |
255
+ | `mergeWatch.maxWaitSeconds` | No | `integer` | `300` | Per-invocation merge-wait bound (seconds). Default 300 (5 minutes) — chosen to fit inside a single host tool invocation (~10 min ceiling) alongside the close gates that precede the wait. Expiry yields `pending` (exit 3), never a block. Headless callers with no host ceiling raise this to land in one block. |
256
+ | `mergeWatch.maxBudgetSeconds` | No | `integer` | `3600` | Cumulative wall-clock budget (seconds) across merge-wait resumes, anchored at the PR's createdAt. Default 3600 (60 minutes). Exhausting this classifies the block and transitions the Story to agent::blocked. |
257
+ | `mergeWatch.updateAttempts` | No | `integer` | `3` | Maximum times the merge wait will bring a behind-the-base PR up to date before giving up on the branch. Default 3. Set 0 to disable the update. |
262
258
  | `codeReview` | No | `object` | — | Nested configuration block. |
263
259
  | `codeReview.providers[]` | No | `array<object>` | — | Review-provider chain (Story #2871). When unset or empty, defaults to [{ name: "native" }]. The orchestrator iterates inline entries in declaration order and merges their Finding[] before posting one structured comment; manual-prompt entries (e.g. ultrareview) contribute a trailing 'Manual review suggestions' section. Selecting an adapter whose probe fails hard-fails at factory construction unless declared `optional: true` in the chain. Each item has: name, scopes, optional, manualPrompt, when. |
264
260
  | `codeReview.providerConfig` | No | `object` | — | Optional escape hatch for adapter-specific configuration. No documented keys in Epic #2815; reserved so future adapters can be configured without another schema migration. |
@@ -267,7 +263,7 @@ top-level keys are validation errors.
267
263
  | `codeReview.autoFixSeverity` | No | `"high"` \| `"medium"` | `"medium"` | Severity threshold for on-branch remediation in /deliver Phase 5 (code-review). `medium` (default) routes 🔴/🟠/🟡 findings into the host-LLM focused-fix routing (Mediums batched per lens: one commit per lens, a single validation + rescan at the end) while 🟢 suggestions still graduate to follow-up issues; `high` reproduces the pre-4399 Critical/High-only routing. Hard cutover — no back-compat flag. |
268
264
  | `refactorStage` | No | `object` | — | Opt-in, config-gated post-green refactor checkpoint wired into story-deliver (Story #3430, Epic #3418). Strictly additive and default-OFF: when disabled, story-deliver behaves exactly as before. Advisory only — never changes existing close-validation gate semantics. |
269
265
  | `refactorStage.enabled` | No | `boolean` | `false` | When true, story-deliver runs an advisory post-green refactor stage (core/code-review-and-quality skill, Post-Green Refactor Pass) after the suite is green. Default false — when unset the stage is skipped and close-validation gate semantics are unchanged. |
270
- | `acceptanceEval` | No | `object` | — | Story #3819. Bounded per-Story acceptance self-eval loop. After the implementation commits land and before the Story-implementation phase flips to `closing`, an independent (fresh-context) critic pass scores the working diff against each inline `acceptance[]` item, redrafts the unmet items, and re-evaluates — capped at `maxRounds` redraft rounds, then escalates to `agent::blocked` when criteria remain unmet. There is no `enabled` flag: the loop is a hard cutover (always on). |
266
+ | `acceptanceEval` | No | `object` | — | Story #3819. Bounded per-Story acceptance self-eval loop. After the implementation commits land and before the Story-implementation phase flips to `closing`, an independent (fresh-context) critic pass scores the caller-injected change set against each inline `acceptance[]` item, redrafts the unmet items, and re-evaluates — capped at `maxRounds` redraft rounds, then escalates to `agent::blocked` when criteria remain unmet. There is no `enabled` flag: the loop is a hard cutover (always on). |
271
267
  | `acceptanceEval.maxRounds` | No | `integer` | — | Maximum number of redraft rounds before escalation. Default 2; clamped into [1, hard ceiling] by lib/config/acceptance-eval.js so the cap can never be disabled (maxRounds: 0 clamps up to 1). |
272
268
  | `acceptanceEval.clusterCeiling` | No | `integer` | — | Epic #4475 (M4-B). Max acceptance criteria one single-delivery acceptance critic scores in a single fresh-context pass. Single delivery clusters the Epic ## Acceptance Table ACs into ceil(totalACs / clusterCeiling) groups and spawns one maker-blind critic per cluster, restoring the distributed acceptance coverage the per-Story critic fan-out gave for free. Default 4; clamped into [1, 8] by lib/config/acceptance-eval.js so a large value cannot collapse the fan-out to a single diluted critic. Ignored on the fan-out route. |
273
269
  | `ci` | No | `object` | — | Nested configuration block. |
@@ -278,11 +274,11 @@ top-level keys are validation errors.
278
274
  | `ci.autoMerge` | No | `"trust-ci"` \| `"strict"` | — | Story #4356 (Epic #4355). Merge posture. 'trust-ci' (default) merges once required checks pass; 'strict' additionally requires a clean review gate. |
279
275
  | `routing` | No | `object` | — | v2 delivery-spawn routing: role-scoped boot contexts and maker-checker sampling. The v1 singleDelivery epic-route kill-switch was removed in Stage 6. |
280
276
  | `routing.roleScopedAgents` | No | `boolean` | — | Epic #4478 (M7-B). Kill-switch for the role-scoped boot contexts. When true (default), a converted delivery spawn (`story-worker`, `acceptance-critic`) boots on its own `.claude/agents/<role>.md` system prompt instead of re-paying the full CLAUDE.md @-import closure (≈50KB → ≈8KB per spawn — the payoff of the context diet). When false, every converted spawn falls back to `subagent_type: general-purpose` — the instant, code-rollback-free per-consumer revert, and the universal escape for hosts that ignore `.claude/agents/`. The fallback is the full-closure agent that ran before M7-B, so flipping it off never drops a gate. |
281
- | `routing.freshCriticSampleRate` | No | `number` | — | Epic #4478 (M7-B, Part 2). Maker-checker sampling floor. Risk-routed ceremony sends a low-risk acceptance cluster down the contract-identical inline critic path, but this fraction of low-risk clusters is still forced through a fresh-context critic so low risk never means zero independent checking. Clamped to [0, 1]; 0 disables the floor, 1 forces every cluster fresh. Default 0.2. Consumed by resolveCeremonyForRisk (lib/orchestration/ceremony-routing.js). |
282
- | `routing.ceremonyProfile` | No | `"minimal"` \| `"standard"` \| `"strict"` | — | Acceptance-ceremony depth. minimal = always inline critic; strict = always fresh-context critic; standard (default) = risk-routed with the maker-checker sampling floor. |
277
+ | `routing.freshCriticSampleRate` | No | `number` | — | Epic #4478 (M7-B, Part 2). Maker-checker sampling floor. Under the standard profile, a change set touching no sensitive path routes its acceptance clusters down the contract-identical inline critic path, but this fraction of them is still forced through a fresh-context critic so a low derived level never means zero independent checking. Clamped to [0, 1]; 0 disables the floor, 1 forces every cluster fresh. Default 0.2. Consumed by resolveCeremonyForRisk (lib/orchestration/ceremony-routing.js). |
278
+ | `routing.ceremonyProfile` | No | `"minimal"` \| `"standard"` \| `"strict"` | — | Acceptance-ceremony depth. minimal = always inline critic; strict = always fresh-context critic; standard (default) = routed off the change level derived from the Story diff, with the maker-checker sampling floor. |
283
279
  | `routing.closeAndLand` | No | `boolean` | — | When true (default), single-story-close lands through merge in one close. Opt out per-run with --no-wait-merge. |
284
280
  | `feedbackLoop` | No | `object` | — | Nested configuration block. |
285
- | `feedbackLoop.auditResultsAutoFile` | No | `boolean` | `true` | When true (default), the Epic finalize listener auto-files non-blocking audit-results findings as follow-up issues routed by source classification. Set to false to suppress auto-filing; findings remain accessible in the structured comments on the Epic. |
281
+ | `feedbackLoop.auditResultsAutoFile` | No | `boolean` | `true` | When true (default), the close-time audit-results graduator auto-files non-blocking audit-results findings as follow-up issues routed by source classification. Set to false to suppress auto-filing; findings remain accessible in the structured comments on the Story. |
286
282
  | `feedbackLoop.retroProposals` | No | `boolean` | `true` | When true (default), the retro auto-files its actionable routed proposals as meta::<framework-gap\|consumer-improvement> + friction::<category> issues via the graduator pre-parsed-findings seam, and the rendered retro sections list the filed issue numbers instead of paste-ready gh command stanzas. Set to false to fall back to the command stanzas. |
287
283
 
288
284
  <!-- END GENERATED:agentrc -->
@@ -405,15 +401,13 @@ Repository-level merge-method allowlist applied by bootstrap.
405
401
  | ----------------- | -------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
406
402
  | `mentionOperator` | No | `false` | When `true`, friction comments @-mention `operatorHandle` for `medium`-severity dispatches (high always @mentions). |
407
403
  | `commentEvents` | No | `["state-transition", "story-merged", "operator-message"]` | Allowlist of event names that reach the GitHub ticket comment channel. |
408
- | `webhookEvents` | No | `["epic-started", "epic-progress", "epic-blocked", "epic-unblocked", "epic-complete"]` | Allowlist of event names that reach `NOTIFICATION_WEBHOOK_URL`. The webhook channel is curated for the epic narrative; story-level events are excluded. |
404
+ | `webhookEvents` | No | `["state-transition", "story-merged", "story-closing", "operator-message", "merge.unlanded", "merge.flip-failed", "loop.tick"]` | Allowlist of event names that reach `NOTIFICATION_WEBHOOK_URL`. The vocabulary mirrors the events the v2 runtime actually emits through `notify()`. |
409
405
 
410
406
  Both fields' enums are pinned in the schema and rejected if extended. To
411
407
  suppress a channel entirely, set its array to `[]`.
412
408
 
413
- > **Severity assignment.** Task transitions and `story-run-progress` upserts
414
- > fire `low` (frequency-driven). Story state transitions, `wave-run-progress`,
415
- > `epic-run-progress`, and epic-completion fire `medium`. Epic blockers and
416
- > HITL gates fire `high` (webhook prefix `[Action Required]` when an
409
+ > **Severity assignment.** Story state transitions fire `medium`. Blockers
410
+ > and HITL gates fire `high` (webhook prefix `[Action Required]` when an
417
411
  > allowlisted blocker event reaches the webhook).
418
412
 
419
413
  ---
@@ -456,17 +450,6 @@ is `soft` (visible to the planner, does not trip re-decompose). Set a
456
450
  explicit `--allow-large-fan-out` operator flag for very large delete blasts;
457
451
  that is separate from Story sizing.
458
452
 
459
- ### `planning.context`
460
-
461
- Caps the size of `--emit-context` JSON payloads emitted during `/plan`
462
- so a runaway Epic body (with its folded Tech Spec sections) can't blow the
463
- planning agent's context budget.
464
-
465
- | Field | Required | Default | Purpose |
466
- | ------------- | -------- | -------- | --------------------------------------------------------------------------------------------- |
467
- | `maxBytes` | No | `50000` | Hard ceiling on the JSON payload size (bytes). Truncation is summary-mode-aware. |
468
- | `summaryMode` | No | `'auto'` | `'auto'` truncates intelligently; `'never'` errors over the cap; `'always'` always summarizes. |
469
-
470
453
  ### `planning.codebaseSnapshot`
471
454
 
472
455
  Controls the codebase-snapshot fetcher that grounds Tech Spec / Story authoring.
@@ -536,8 +519,7 @@ fall back to documented defaults (or are no-ops when omitted).
536
519
 
537
520
  | Field | Required | Default | Purpose |
538
521
  | --------------------------- | -------- | ------- | ------------------------------------------------ |
539
- | `concurrencyCap` | No | `3` | Max parallel Story sub-agents per wave. |
540
- | `verifyConcurrencyCap` | No | `4` | Max parallel verify steps per wave. |
522
+ | `concurrencyCap` | No | `3` | Max ready Stories dispatched by `/deliver` at once. |
541
523
 
542
524
  ### `delivery.worktreeIsolation`
543
525
 
@@ -666,7 +648,6 @@ for `BUNDLE_SIZE_REFRESH=1` usage.
666
648
  | ---------------------- | -------- | ------- | ------------------------------------------------------------------ |
667
649
  | `cyclomaticFlag` | No | (none) | Cyclomatic-complexity value at which the engineer should refactor. |
668
650
  | `cyclomaticMustFix` | No | (none) | Cyclomatic-complexity value that hard-fails the gate. |
669
- | `miDropMustRefactor` | No | (none) | MI drop that mandates a refactor. |
670
651
  | `requireSiblingTest` | No | (none) | When `true`, a new function requires a sibling test file. |
671
652
 
672
653
  #### `delivery.quality.autoRefresh`
@@ -676,7 +657,6 @@ Controls Story-close auto-baseline-refresh for gated metrics.
676
657
  | Field | Required | Default | Purpose |
677
658
  | ------------- | -------- | ------- | -------------------------------------------------------- |
678
659
  | `enabled` | No | (none) | Master switch. |
679
- | `miDropCap` | No | (none) | Max MI drop the auto-refresher will absorb before failing. |
680
660
  | `crapJumpCap` | No | (none) | Max CRAP jump the auto-refresher will absorb before failing. |
681
661
  | `scope` | No | (none) | One of `'diff'` or `'full'`. |
682
662
 
@@ -791,22 +771,6 @@ Paths are configured in `delivery.quality.gates.<tier>.baselinePath`. The
791
771
  default values match the canonical layout above; override only when a
792
772
  project genuinely stores baselines elsewhere.
793
773
 
794
- ### Per-wave drift snapshots — `.agents/state/`
795
-
796
- The Epic runner's progress reporter writes wave-start snapshots so that a
797
- resumed run can detect intra-wave drift without re-reading the canonical
798
- baseline (which may have been refreshed mid-Epic).
799
-
800
- | File | Owner | Lifecycle |
801
- | --------------------------------------- | ---------------------------------------------------- | ----------------------------------------------- |
802
- | `.agents/state/wave-mi-snapshot.json` | `progress-signals/maintainability-drift.js` | Captured at wave-start; overwritten next wave. |
803
- | `.agents/state/wave-crap-snapshot.json` | `progress-signals/crap-drift.js` | Captured at wave-start; overwritten next wave. |
804
-
805
- These are **not** ratchet baselines and must not be committed as such. The
806
- filenames intentionally differ from the canonical files so a repo-wide grep
807
- for `baselines/maintainability.json` or `baselines/crap.json` only ever hits
808
- the canonical paths.
809
-
810
774
  The `.agents/state/` directory itself is created on demand by the progress
811
775
  reporter; the framework does not require it to exist ahead of time and does
812
776
  not commit its contents.
@@ -867,7 +831,7 @@ git.
867
831
  per-contributor value with two jobs: the `@`-handle the framework @mentions on
868
832
  friction comments, **and** the lease owner the workflow guards
869
833
  ([`ticket-lease.js`](../scripts/lib/orchestration/ticket-lease.js))
870
- assign to a ticket so two contributors cannot drive the same Epic/Story
834
+ assign to a ticket so two contributors cannot drive the same Story
871
835
  concurrently. Because the lease must distinguish *your* run from *another
872
836
  person's*, a shared committed handle would defeat it — everyone would coordinate
873
837
  under one identity. So each contributor sets their own in `.agentrc.local.json`:
@@ -1063,15 +1027,27 @@ mandrel explain --json # JSON report for scripting
1063
1027
 
1064
1028
  ### `mandrel sync-commands`
1065
1029
 
1066
- Regenerates the flat `.claude/commands/` tree from `.agents/workflows/`. The
1067
- bootstrap wires a `UserPromptSubmit` hook so this runs automatically on every
1068
- Claude Code prompt; manual invocations are only needed when the hook is absent
1069
- or the commands/ tree is manually deleted.
1030
+ Regenerates the flat `.claude/commands/` tree from `.agents/workflows/`. Runs
1031
+ automatically at install time (via `prepare`) and as part of `mandrel
1032
+ sync`/`update`; manual invocations are only needed when the commands/ tree is
1033
+ manually deleted or edited by hand. Refuses to project when the materialized
1034
+ `.agents/` tree doesn't match the running CLI's own version.
1070
1035
 
1071
1036
  ```bash
1072
1037
  mandrel sync-commands
1073
1038
  ```
1074
1039
 
1040
+ ### `mandrel sync-agents`
1041
+
1042
+ Regenerates the flat `.claude/agents/` tree from `.agents/agents/` — the
1043
+ role-scoped boot contexts `delivery.routing.roleScopedAgents` (default
1044
+ `true`) dispatches spawns against. Same wiring and version-match refusal as
1045
+ `mandrel sync-commands` above.
1046
+
1047
+ ```bash
1048
+ mandrel sync-agents
1049
+ ```
1050
+
1075
1051
  ### `mandrel uninstall`
1076
1052
 
1077
1053
  Reverses a recorded install using the install ledger
@@ -19,12 +19,13 @@ validated.
19
19
 
20
20
  - **Canonical record + schema validation**: `diagnose-friction.js` appends one
21
21
  `kind: friction` record, validated write-time against
22
- `signal-event.schema.json`, to the per-Epic/per-Story `signals.ndjson`
23
- stream on local disk. The retro roll-up reads that stream back to aggregate
22
+ `signal-event.schema.json`, to the per-run/per-Story `signals.ndjson`
23
+ stream on local disk (under `temp/run-<id>/`). The retro roll-up reads that
24
+ stream back to aggregate
24
25
  friction into routed proposals; nothing is posted to the GitHub ticket at
25
26
  capture time.
26
- - **No-Epic context**: Outside an Epic/Story loop there is no per-Epic stream
27
- to anchor to, so the record lands on the **standalone signal stream**
27
+ - **Standalone context**: Outside a delivery run there is no `temp/run-<id>/`
28
+ stream to anchor to, so the record lands on the **standalone signal stream**
28
29
  (`temp/standalone/stories/story-<sid>/signals.ndjson`) under the same
29
30
  canonical schema.
30
31
  - **Never silently dropped**: The signal is never silently dropped — a
@@ -57,12 +58,40 @@ schema mechanics are in [§ Friction telemetry](#friction-telemetry) above.
57
58
 
58
59
  ## FinOps & token budgeting (economic guardrails)
59
60
 
60
- Mandrel does **not** enforce live LLM spend from response metadata. The
61
- framework limits **hydrated prompt size** via section-aware elision
62
- (`elideEnvelope`) and optional **pre-dispatch estimates**; your host
63
- runtime (editor / CLI) owns session quota and hard stops. Consult this
64
- section when reasoning about why a task prompt was elided or why `/deliver`
65
- refused a fan-out on budget grounds.
61
+ Mandrel does **not** enforce live LLM spend from response metadata. It bounds
62
+ two things, both **fixed framework constants** rather than operator knobs, and
63
+ both **fail closed**: the assembled `/plan` context envelope, and plan-time
64
+ Story sizing. Your host runtime (editor / CLI) owns session quota and hard
65
+ stops. Consult this section when reasoning about why `/plan` refused an
66
+ over-ceiling envelope or an over-budget Story count.
67
+
68
+ > **There is no configurable context budget.** `planning.context.maxBytes` /
69
+ > `summaryMode` were removed outright in Story #4541, along with the
70
+ > `applyBudget` pass they fed: that pass lost its last caller in the v2
71
+ > cutover, and it was already bounding a field the envelope builders discarded
72
+ > before shipping the raw seed anyway. The schema now **rejects**
73
+ > `planning.context`, so a config carrying it fails loudly rather than silently
74
+ > capping nothing. The ceiling below is the replacement and the only live bound
75
+ > on planner-context size. Separately, `elideEnvelope` in
76
+ > `lib/orchestration/context-envelope.js` — which this section used to credit
77
+ > with limiting hydrated prompt size — has no production caller either (it is
78
+ > carried in `baselines/dead-exports-production.json`). Only `estimateTokens`
79
+ > from that module is live.
80
+
81
+ ### Planner-context envelope (`/plan`)
82
+
83
+ - **`PLAN_CONTEXT_ENVELOPE_BYTE_CEILING`** (`lib/orchestration/plan-context.js`):
84
+ 256 KB (≈64K tokens at the ≈4-chars/token estimate) on the serialized
85
+ envelope `buildPlanContext` assembles, checked at the single choke point
86
+ every mode returns through. Measured envelopes on this repo land at ~42 KB,
87
+ so the ceiling is >2× headroom over a worst-case seed plus a medium-tier
88
+ codebase snapshot.
89
+ - **On refusal**, the error names the envelope's largest fields. Trim the seed,
90
+ plan fewer `--tickets` source issues in one run, or narrow
91
+ `planning.codebaseSnapshot`. The seed is carried **verbatim** by design — it
92
+ is the operator's request, and summarizing it silently would degrade planning
93
+ quality precisely when the input is richest — so there is no elision path to
94
+ fall back on. Raising the ceiling needs a measured justification.
66
95
 
67
96
  ### Session-mass capacity (plan-time sizing)
68
97