mandrel 2.0.0 → 2.1.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 (311) hide show
  1. package/.agents/README.md +59 -28
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +41 -46
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +51 -44
  6. package/.agents/docs/agentrc-reference.json +8 -13
  7. package/.agents/docs/configuration.md +32 -56
  8. package/.agents/docs/execution-reference.md +39 -10
  9. package/.agents/docs/quality-gates.md +14 -16
  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/git-conventions-reference.md +42 -51
  14. package/.agents/schemas/agentrc.schema.json +34 -45
  15. package/.agents/schemas/audit-rules.json +59 -1
  16. package/.agents/schemas/audit-rules.schema.json +33 -1
  17. package/.agents/schemas/lifecycle/README.md +1 -2
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  20. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  21. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  22. package/.agents/schemas/signal-event.schema.json +3 -3
  23. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  24. package/.agents/schemas/validation-evidence.schema.json +1 -1
  25. package/.agents/scripts/acceptance-eval.js +22 -66
  26. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  27. package/.agents/scripts/bootstrap.js +3 -3
  28. package/.agents/scripts/check-dead-exports.js +43 -104
  29. package/.agents/scripts/check-doc-links.js +2 -2
  30. package/.agents/scripts/check-lifecycle-lint.js +1 -1
  31. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  32. package/.agents/scripts/deliver-recover.js +122 -0
  33. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  34. package/.agents/scripts/evidence-gate.js +20 -50
  35. package/.agents/scripts/generate-skills-index.js +17 -1
  36. package/.agents/scripts/generate-workflows-doc.js +4 -4
  37. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  38. package/.agents/scripts/lib/audit-suite/selector.js +323 -23
  39. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -11
  40. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  41. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  42. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  43. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  44. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -1
  45. package/.agents/scripts/lib/checks/index.js +1 -1
  46. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  47. package/.agents/scripts/lib/checks/state.js +17 -248
  48. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +3 -3
  49. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  50. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  51. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  52. package/.agents/scripts/lib/cli-args.js +23 -2
  53. package/.agents/scripts/lib/close-validation/gates.js +13 -13
  54. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  55. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  56. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  57. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  58. package/.agents/scripts/lib/config/delivery-routing.js +7 -6
  59. package/.agents/scripts/lib/config/explain.js +10 -16
  60. package/.agents/scripts/lib/config/github.js +7 -5
  61. package/.agents/scripts/lib/config/limits.js +15 -25
  62. package/.agents/scripts/lib/config/quality.js +11 -14
  63. package/.agents/scripts/lib/config/runners.js +8 -21
  64. package/.agents/scripts/lib/config/temp-paths.js +18 -56
  65. package/.agents/scripts/lib/config-settings-schema-delivery.js +31 -13
  66. package/.agents/scripts/lib/config-settings-schema-quality.js +9 -2
  67. package/.agents/scripts/lib/config-settings-schema.js +48 -22
  68. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  69. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  70. package/.agents/scripts/lib/duplicate-search.js +38 -7
  71. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  72. package/.agents/scripts/lib/format-generated-json.js +97 -0
  73. package/.agents/scripts/lib/framework-version.js +19 -189
  74. package/.agents/scripts/lib/gh-exec.js +8 -0
  75. package/.agents/scripts/lib/git-branch-lifecycle.js +0 -158
  76. package/.agents/scripts/lib/git-utils.js +0 -14
  77. package/.agents/scripts/lib/json-utils.js +1 -2
  78. package/.agents/scripts/lib/label-constants.js +0 -15
  79. package/.agents/scripts/lib/label-taxonomy.js +1 -12
  80. package/.agents/scripts/lib/observability/active-story-env.js +42 -163
  81. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  82. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  83. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  84. package/.agents/scripts/lib/observability/source-classifier.js +2 -2
  85. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  86. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  87. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  88. package/.agents/scripts/lib/orchestration/ceremony-routing.js +43 -45
  89. package/.agents/scripts/lib/orchestration/code-review.js +58 -168
  90. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +3 -3
  91. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  92. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  93. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  94. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  95. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  96. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +9 -11
  97. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  98. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  99. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +7 -3
  100. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  101. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  102. package/.agents/scripts/lib/orchestration/merge-block-class.js +76 -20
  103. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  104. package/.agents/scripts/lib/orchestration/plan-context.js +114 -24
  105. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  106. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +3 -7
  107. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  108. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +16 -6
  109. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +173 -25
  110. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  111. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +280 -75
  112. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +472 -55
  113. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +21 -16
  114. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  115. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +41 -40
  116. package/.agents/scripts/lib/orchestration/planning/spec-authoring-grounding.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  118. package/.agents/scripts/lib/orchestration/retro-proposals.js +7 -7
  119. package/.agents/scripts/lib/orchestration/review-depth.js +105 -40
  120. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  121. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  122. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  124. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  125. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  126. package/.agents/scripts/lib/orchestration/run-epilogue.js +374 -16
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +24 -0
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  130. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +3 -12
  131. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  132. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +72 -30
  133. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  134. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  135. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +12 -8
  136. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  137. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  138. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +264 -43
  139. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  140. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  141. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -32
  142. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  143. package/.agents/scripts/lib/orchestration/story-follow-ups.js +75 -14
  144. package/.agents/scripts/lib/orchestration/story-init-remote.js +12 -8
  145. package/.agents/scripts/lib/orchestration/story-plan-state.js +14 -29
  146. package/.agents/scripts/lib/orchestration/task-body-validator.js +52 -7
  147. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  148. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +119 -14
  149. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +3 -4
  150. package/.agents/scripts/lib/orchestration/ticket-validator.js +121 -18
  151. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -47
  152. package/.agents/scripts/lib/orchestration/ticketing/reads.js +19 -32
  153. package/.agents/scripts/lib/orchestration/ticketing/transition.js +61 -1
  154. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  155. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  156. package/.agents/scripts/lib/planning-corpus.js +12 -286
  157. package/.agents/scripts/lib/preflight-runner.js +2 -2
  158. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  159. package/.agents/scripts/lib/signals/index.js +4 -17
  160. package/.agents/scripts/lib/signals/read.js +35 -35
  161. package/.agents/scripts/lib/signals/schema.js +8 -11
  162. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  163. package/.agents/scripts/lib/signals/write.js +0 -1
  164. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  165. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  166. package/.agents/scripts/lib/story-adjacency.js +8 -7
  167. package/.agents/scripts/lib/story-body/story-body.js +6 -5
  168. package/.agents/scripts/lib/templates/decomposer-prompts.js +7 -3
  169. package/.agents/scripts/lib/test-env.js +14 -1
  170. package/.agents/scripts/lib/test-tiers.js +0 -3
  171. package/.agents/scripts/lib/ticket-body-sections.js +0 -14
  172. package/.agents/scripts/lib/validation-evidence.js +31 -59
  173. package/.agents/scripts/lib/wave-runner/ready-set.js +32 -6
  174. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  175. package/.agents/scripts/lib/worktree/lifecycle/reap.js +68 -19
  176. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  177. package/.agents/scripts/plan-context.js +38 -6
  178. package/.agents/scripts/plan-persist.js +145 -35
  179. package/.agents/scripts/plan-run-epilogue.js +83 -38
  180. package/.agents/scripts/post-structured-comment.js +0 -38
  181. package/.agents/scripts/pr-watch-with-update.js +43 -22
  182. package/.agents/scripts/providers/github/compose.js +0 -1
  183. package/.agents/scripts/providers/github/errors.js +0 -19
  184. package/.agents/scripts/providers/github/issues.js +1 -11
  185. package/.agents/scripts/providers/github/mappers.js +5 -0
  186. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  187. package/.agents/scripts/providers/github/tickets.js +33 -153
  188. package/.agents/scripts/providers/github.js +17 -6
  189. package/.agents/scripts/resolve-stories.js +236 -0
  190. package/.agents/scripts/run-coverage.js +4 -1
  191. package/.agents/scripts/run-lint.js +2 -2
  192. package/.agents/scripts/run-verify.js +31 -2
  193. package/.agents/scripts/signals-view.js +9 -10
  194. package/.agents/scripts/single-story-close.js +173 -18
  195. package/.agents/scripts/single-story-confirm-merge.js +288 -15
  196. package/.agents/scripts/single-story-init.js +6 -10
  197. package/.agents/scripts/stories-wave-tick.js +79 -4
  198. package/.agents/scripts/story-plan.js +3 -3
  199. package/.agents/scripts/update-ticket-state.js +8 -50
  200. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  201. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  202. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  203. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  204. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  205. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  206. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  207. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  208. package/.agents/skills/core/idea-refinement/SKILL.md +3 -3
  209. package/.agents/skills/core/scope-triage/SKILL.md +3 -0
  210. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  211. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  212. package/.agents/skills/skills.index.json +2 -12
  213. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  214. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  215. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  216. package/.agents/workflows/audit-architecture.md +3 -4
  217. package/.agents/workflows/audit-clean-code.md +4 -4
  218. package/.agents/workflows/audit-documentation.md +4 -5
  219. package/.agents/workflows/audit-lighthouse.md +8 -0
  220. package/.agents/workflows/audit-navigability.md +10 -0
  221. package/.agents/workflows/audit-performance.md +2 -3
  222. package/.agents/workflows/audit-quality.md +8 -9
  223. package/.agents/workflows/audit-security.md +1 -2
  224. package/.agents/workflows/audit-seo.md +10 -0
  225. package/.agents/workflows/audit-ux-ui.md +7 -0
  226. package/.agents/workflows/deliver.md +98 -45
  227. package/.agents/workflows/git-cleanup.md +2 -2
  228. package/.agents/workflows/git-deliver.md +1 -1
  229. package/.agents/workflows/helpers/acceptance-self-eval.md +21 -13
  230. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  231. package/.agents/workflows/helpers/code-review.md +12 -10
  232. package/.agents/workflows/helpers/deliver-story-reference.md +73 -32
  233. package/.agents/workflows/helpers/deliver-story.md +193 -118
  234. package/.agents/workflows/helpers/parallel-tooling.md +2 -2
  235. package/.agents/workflows/helpers/worktree-lifecycle.md +28 -32
  236. package/.agents/workflows/plan.md +184 -19
  237. package/.agents/workflows/qa-assist.md +6 -6
  238. package/.agents/workflows/qa-explore.md +3 -3
  239. package/.agents/workflows/qa-run.md +1 -5
  240. package/bin/mandrel.js +12 -1
  241. package/docs/CHANGELOG.md +40 -0
  242. package/lib/cli/registry.js +262 -19
  243. package/lib/cli/sync-agents.js +157 -0
  244. package/lib/cli/sync-commands.js +115 -6
  245. package/lib/cli/sync.js +168 -6
  246. package/lib/cli/update.js +105 -8
  247. package/lib/cli/version-helpers.js +131 -0
  248. package/lib/migrations/README.md +7 -5
  249. package/lib/migrations/index.js +12 -9
  250. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  251. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  252. package/package.json +1 -1
  253. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  254. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  255. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  256. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  257. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  258. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  259. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  260. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  261. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  262. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  263. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  264. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  265. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  266. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  267. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  268. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  269. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  270. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  271. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  272. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  273. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  274. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  275. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  276. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  277. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  278. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  279. package/.agents/schemas/risk-verdict.schema.json +0 -53
  280. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  281. package/.agents/scripts/analyze-execution.js +0 -444
  282. package/.agents/scripts/check-prepush-recovery.js +0 -90
  283. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  284. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  285. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -187
  286. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  287. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  288. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  289. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +0 -128
  290. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -273
  291. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  292. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  293. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  294. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  295. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  296. package/.agents/scripts/lib/orchestration/planning/risk-verdict.js +0 -104
  297. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  298. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  299. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  300. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -21
  301. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  302. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  303. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  304. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -397
  305. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  306. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +0 -155
  307. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  308. package/.agents/scripts/lib/orchestration/story-progress/story-run-progress-writer.js +0 -400
  309. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +0 -36
  310. package/.agents/scripts/resolve-plan-run.js +0 -117
  311. package/.agents/skills/core/analyze-execution/SKILL.md +0 -101
@@ -4,27 +4,51 @@
4
4
  * plan-persist.js — flat Story GitHub-write surface for v2 `/plan`
5
5
  * (Stage 3 — `docs/roadmap.md`).
6
6
  *
7
- * Given the author-written planning artifacts (`stories.json` +
8
- * `risk-verdict.json`, optional shared Tech Spec), this CLI validates and
9
- * creates Story issue(s) directly:
7
+ * Given the author-written planning artifacts (`stories.json`, optional shared
8
+ * Tech Spec), this CLI validates and creates Story issue(s) directly:
10
9
  *
11
- * risk-verdict → ticket validator / DAG / capacity → reachability →
10
+ * ticket validator / DAG / capacity → reachability →
12
11
  * split-policy partition → fold/spill Spec into each Story body →
13
- * createIssue(s) with type::story + agent::ready risk-verdict +
14
- * story-plan-state on every Story; plan-summary on the primary → temp
15
- * cleanup.
12
+ * createIssue(s) with type::story, resumably by plan fingerprint (NOT
13
+ * agent::ready) → story-plan-state on every Story;
14
+ * plan-summary on the primary → flip every Story to agent::ready →
15
+ * comment + close superseded source tickets → temp cleanup + stale reap.
16
+ *
17
+ * Story #4542 retired the authored risk verdict: persist neither requires nor
18
+ * accepts one, and no plan-time step produces one. Review depth and the
19
+ * acceptance-critic mode are derived from the diff at close time
20
+ * (`review-depth.js#deriveChangeLevel`). `--force-review` is the only review
21
+ * gate the planner still carries, and it is an explicit operator flag.
16
22
  *
17
23
  * CLI:
18
- * --stories <file> Required Story ticket array (default length 1)
19
- * --risk-verdict <file> Required risk verdict (no deliveryShape)
20
- * --tech-spec <file> Optional shared Tech Spec folded into each Story
21
- * --plan-dir <dir> Optional temp dir deleted at terminal success
22
- * --plan-acceptance <file> Optional JSON string[] for partition coverage
23
- * --plan-run-id <id> Optional plan-run token when N>1
24
- * --dry-run Assemble + validate without GitHub writes
25
- * --force-review Record operator-forced review routing
24
+ * --stories <file> Required Story ticket array (default length 1)
25
+ * --tech-spec <file> Optional shared Tech Spec folded into each Story
26
+ * --plan-dir <dir> Optional temp dir deleted at terminal success.
27
+ * Also where the `plan-context.json` envelope is
28
+ * auto-discovered from (see --plan-context)
29
+ * --plan-context <file> Optional explicit path to the `plan-context.js`
30
+ * envelope. Its `sourceTickets[]` is what makes
31
+ * `--tickets` superseding work without a flag
32
+ * --plan-acceptance <file> Optional JSON string[] for partition coverage
33
+ * --source-tickets <ids> Explicit OVERRIDE of the envelope-derived source
34
+ * ids, for hand-driven runs. Each id must be
35
+ * claimed by exactly one Story's `supersedes[]`;
36
+ * they are commented on and closed as superseded
37
+ * --no-close-superseded Keep the source tickets open (no comment, no
38
+ * close) — for a genuinely partial supersede
39
+ * --dry-run Assemble + validate without GitHub writes
40
+ * --force-review Operator-forced review stop before persist lands
26
41
  * --allow-over-budget / --allow-large-fan-out
27
42
  *
43
+ * Run `--dry-run` first. It exercises every gate — validator, DAG, capacity,
44
+ * budget, reachability, split/supersede partition, Spec fold — write-free, so
45
+ * an authoring mistake surfaces before a single issue exists.
46
+ *
47
+ * stdout is reserved for the JSON result (Story #2278 discipline, extended to
48
+ * this CLI by Story #4541): `routeAllOutputToStderr()` runs before any
49
+ * pipeline code so a headless driver can `JSON.parse` stdout unconditionally.
50
+ * Human-readable log lines go to stderr, matching the sibling `plan-context`.
51
+ *
28
52
  * Exit codes: 0 success; 1 fatal; 3 reachability orphans (nothing mutated).
29
53
  */
30
54
 
@@ -38,13 +62,17 @@ import {
38
62
  resolveConfig,
39
63
  validateOrchestrationConfig,
40
64
  } from './lib/config-resolver.js';
41
- import { Logger } from './lib/Logger.js';
65
+ import { Logger, routeAllOutputToStderr } from './lib/Logger.js';
42
66
  import {
43
67
  readPlanMetrics,
44
68
  recordPlanInvocation,
45
69
  renderPlanMetricsSummaryLine,
46
70
  summarizePlanMetrics,
47
71
  } from './lib/orchestration/plan-metrics.js';
72
+ import {
73
+ loadPlanContextEnvelope,
74
+ resolvePlanContextPath,
75
+ } from './lib/orchestration/plan-persist/plan-context-source.js';
48
76
  import {
49
77
  runPlanPersist,
50
78
  writeCheckpointV2,
@@ -54,7 +82,7 @@ import {
54
82
  buildWaveTable,
55
83
  PLAN_SUMMARY_COMMENT_TYPE,
56
84
  } from './lib/orchestration/plan-persist/summary.js';
57
- import { loadRiskVerdict } from './lib/orchestration/planning/risk-verdict.js';
85
+ import { resolveSourceTicketIds } from './lib/orchestration/plan-persist/supersede-ops.js';
58
86
  import { createProvider } from './lib/provider-factory.js';
59
87
 
60
88
  export {
@@ -67,11 +95,13 @@ export {
67
95
 
68
96
  const CLI_OPTIONS = {
69
97
  stories: { type: 'string' },
70
- 'risk-verdict': { type: 'string' },
71
98
  'tech-spec': { type: 'string' },
72
99
  'plan-dir': { type: 'string' },
100
+ 'plan-context': { type: 'string' },
73
101
  'plan-acceptance': { type: 'string' },
74
- 'plan-run-id': { type: 'string' },
102
+ 'source-tickets': { type: 'string' },
103
+ 'close-superseded': { type: 'boolean', default: true },
104
+ 'no-close-superseded': { type: 'boolean', default: false },
75
105
  'dry-run': { type: 'boolean', default: false },
76
106
  'force-review': { type: 'boolean', default: false },
77
107
  'allow-over-budget': { type: 'boolean', default: false },
@@ -79,9 +109,11 @@ const CLI_OPTIONS = {
79
109
  };
80
110
 
81
111
  const USAGE =
82
- 'Usage: plan-persist.js --stories <file> --risk-verdict <file> ' +
83
- '[--tech-spec <file>] [--plan-dir <dir>] [--plan-acceptance <file>] ' +
84
- '[--plan-run-id <id>] [--dry-run] [--force-review] ' +
112
+ 'Usage: plan-persist.js --stories <file> ' +
113
+ '[--tech-spec <file>] [--plan-dir <dir>] [--plan-context <file>] ' +
114
+ '[--plan-acceptance <file>] ' +
115
+ '[--source-tickets <ids>] [--no-close-superseded] ' +
116
+ '[--dry-run] [--force-review] ' +
85
117
  '[--allow-over-budget] [--allow-large-fan-out]';
86
118
 
87
119
  async function readOptional(filePath, { required }) {
@@ -104,22 +136,28 @@ async function readJsonFile(filePath, label) {
104
136
  }
105
137
  }
106
138
 
107
- function resolveInputPaths(values) {
139
+ /**
140
+ * Resolve every input path the CLI accepts, including where the
141
+ * `plan-context.js` envelope is discovered from. Exported for tests.
142
+ *
143
+ * @param {object} values Parsed `parseArgs` values.
144
+ */
145
+ export function resolveInputPaths(values) {
146
+ const planDir = values['plan-dir'] ? path.resolve(values['plan-dir']) : null;
108
147
  return {
109
148
  storiesPath: path.resolve(values.stories),
110
- riskVerdictPath: path.resolve(values['risk-verdict']),
111
149
  techSpecPath: values['tech-spec']
112
150
  ? path.resolve(values['tech-spec'])
113
151
  : null,
114
152
  planAcceptancePath: values['plan-acceptance']
115
153
  ? path.resolve(values['plan-acceptance'])
116
154
  : null,
117
- planDir: values['plan-dir'] ? path.resolve(values['plan-dir']) : null,
155
+ planDir,
156
+ planContextPath: resolvePlanContextPath(values['plan-context'], planDir),
118
157
  };
119
158
  }
120
159
 
121
160
  async function loadArtifacts(paths) {
122
- const riskVerdict = loadRiskVerdict(paths.riskVerdictPath);
123
161
  const stories = await readJsonFile(paths.storiesPath, 'stories');
124
162
  const techSpecContent = paths.techSpecPath
125
163
  ? await readOptional(paths.techSpecPath, { required: true })
@@ -127,23 +165,61 @@ async function loadArtifacts(paths) {
127
165
  const planAcceptance = paths.planAcceptancePath
128
166
  ? await readJsonFile(paths.planAcceptancePath, 'plan-acceptance')
129
167
  : null;
168
+ const planContextEnvelope = await loadPlanContextEnvelope(
169
+ paths.planContextPath,
170
+ );
130
171
 
131
- return { stories, riskVerdict, techSpecContent, planAcceptance };
172
+ return {
173
+ stories,
174
+ techSpecContent,
175
+ planAcceptance,
176
+ planContextEnvelope,
177
+ };
132
178
  }
133
179
 
134
- function buildPersistOptions(values, paths) {
180
+ /**
181
+ * Assemble the `runPlanPersist` opts bag from parsed CLI values.
182
+ *
183
+ * Exported for tests: this is the join where the envelope-derived source ids
184
+ * meet the persist engine, so a regression here silently un-wires
185
+ * `/plan --tickets` superseding (Story #4554).
186
+ *
187
+ * @param {object} values Parsed `parseArgs` values.
188
+ * @param {ReturnType<typeof resolveInputPaths>} paths
189
+ * @param {object|null} planContextEnvelope
190
+ * @returns {object} opts for `runPlanPersist`.
191
+ */
192
+ export function buildPersistOptions(values, paths, planContextEnvelope) {
193
+ const source = resolveSourceTicketIds({
194
+ explicitIds: values['source-tickets'],
195
+ envelope: planContextEnvelope,
196
+ });
197
+
135
198
  return {
136
199
  forceReview: values['force-review'],
137
200
  allowOverBudget: values['allow-over-budget'],
138
201
  allowLargeFanOut: values['allow-large-fan-out'],
139
202
  dryRun: values['dry-run'],
140
- planRunId: values['plan-run-id'],
141
203
  planDir: paths.planDir,
142
204
  skipCleanup: values['dry-run'],
205
+ sourceTicketIds: source.ids,
206
+ sourceTicketOrigin: source.origin,
207
+ // Default-on: `--no-close-superseded` is the explicit escape and always
208
+ // wins over the (default `true`) `--close-superseded`.
209
+ closeSuperseded:
210
+ values['no-close-superseded'] === true
211
+ ? false
212
+ : values['close-superseded'] !== false,
143
213
  };
144
214
  }
145
215
 
146
- async function runPersistInvocation({ values, config, provider, artifacts }) {
216
+ async function runPersistInvocation({
217
+ values,
218
+ config,
219
+ provider,
220
+ artifacts,
221
+ metricsSince,
222
+ }) {
147
223
  const paths = resolveInputPaths(values);
148
224
  const settings = {
149
225
  baseBranch: config.project?.baseBranch,
@@ -164,14 +240,37 @@ async function runPersistInvocation({ values, config, provider, artifacts }) {
164
240
  artifacts,
165
241
  config,
166
242
  settings,
167
- opts: buildPersistOptions(values, paths),
243
+ opts: {
244
+ ...buildPersistOptions(values, paths, artifacts.planContextEnvelope),
245
+ metricsSince,
246
+ },
168
247
  }),
169
248
  );
170
249
  }
171
250
 
172
- async function attachPlanMetrics(result, config) {
251
+ /**
252
+ * Attach the plan-metrics roll-up for **this** invocation.
253
+ *
254
+ * Two Story #4541 fixes meet here. `readPlanMetrics` is declared
255
+ * `(epicId, config)` but was called with `config` first, so it threw its
256
+ * `epicId` guard on every run and the catch below turned that into a
257
+ * silently missing summary — v2 persist is always Epic-less, hence the
258
+ * explicit `null`. And the Epic-less ledger is shared across every plan the
259
+ * repo has ever run, so `since` scopes the counts to the current invocation
260
+ * instead of reporting lifetime totals under an invocation-shaped line.
261
+ *
262
+ * This runs *after* `recordPlanInvocation` has appended this run's own
263
+ * record, so the summary always has at least that one entry to report.
264
+ *
265
+ * @param {object} result Mutated in place with `planMetrics`.
266
+ * @param {object} config
267
+ * @param {string} since ISO-8601 instant this invocation started.
268
+ */
269
+ async function attachPlanMetrics(result, config, since) {
173
270
  try {
174
- const summary = summarizePlanMetrics(await readPlanMetrics(config));
271
+ const summary = summarizePlanMetrics(await readPlanMetrics(null, config), {
272
+ since,
273
+ });
175
274
  if (summary) {
176
275
  result.planMetrics = summary;
177
276
  Logger.info(`[plan-persist] ${renderPlanMetricsSummaryLine(summary)}`);
@@ -184,10 +283,20 @@ async function attachPlanMetrics(result, config) {
184
283
  async function main() {
185
284
  const { values } = parseArgs({ options: CLI_OPTIONS });
186
285
 
187
- if (!values.stories || !values['risk-verdict']) {
286
+ if (!values.stories) {
188
287
  throw new Error(USAGE);
189
288
  }
190
289
 
290
+ // stdout is reserved for the JSON result: flip every Logger sink that could
291
+ // land on stdout to stderr BEFORE any pipeline code runs (Story #2278
292
+ // discipline, extended here by Story #4541 — this CLI interleaved Logger
293
+ // lines with its own JSON, so a headless driver could not parse stdout).
294
+ routeAllOutputToStderr();
295
+
296
+ // Boundary for this invocation's plan-metrics roll-up — stamped before any
297
+ // ledger-writing work so every record this run appends falls inside it.
298
+ const metricsSince = new Date().toISOString();
299
+
191
300
  let config;
192
301
  try {
193
302
  config = resolveConfig();
@@ -206,6 +315,7 @@ async function main() {
206
315
  config,
207
316
  provider,
208
317
  artifacts,
318
+ metricsSince,
209
319
  });
210
320
  } catch (err) {
211
321
  if (err?.code === 'PLAN_REACHABILITY_ORPHANS') {
@@ -216,7 +326,7 @@ async function main() {
216
326
  throw err;
217
327
  }
218
328
 
219
- await attachPlanMetrics(result, config);
329
+ await attachPlanMetrics(result, config, metricsSince);
220
330
 
221
331
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
222
332
  }
@@ -1,17 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * plan-run-epilogue.js — execute the real per-run closeout for
4
- * `/deliver --run <planRunId>` and positional multi-Story delivers.
3
+ * plan-run-epilogue.js — execute the real per-run closeout for a
4
+ * multi-Story `/deliver`.
5
5
  *
6
6
  * Usage:
7
- * node .agents/scripts/plan-run-epilogue.js --run <planRunId>
8
- * node .agents/scripts/plan-run-epilogue.js --run <planRunId> --stories 1,2,3
9
7
  * node .agents/scripts/plan-run-epilogue.js --stories 1,2,3
10
8
  *
11
- * When `--stories` is omitted, `--run` is required and the set is resolved
12
- * via plan-run labels (`state=all` so landed Stories are included).
13
- * When `--stories` is supplied without `--run`, an adhoc planRunId is
14
- * synthesized from the sorted Story ids.
9
+ * Keyed on the delivered id set: an `adhoc-<sorted-ids>` run id is
10
+ * synthesized from `--stories`. Story #4540 retired the `--run <planRunId>`
11
+ * label-resolution branch along with the `plan-run::<id>` label itself.
15
12
  */
16
13
 
17
14
  import './lib/runtime-deps/ensure-installed.js';
@@ -20,16 +17,10 @@ import { parseArgs } from 'node:util';
20
17
  import { runAsCli } from './lib/cli-utils.js';
21
18
  import { resolveConfig } from './lib/config-resolver.js';
22
19
  import { Logger } from './lib/Logger.js';
23
- import {
24
- fetchPlanRunIssues,
25
- normalizePlanRunLabel,
26
- resolvePlanRunFromIssues,
27
- } from './lib/orchestration/resolve-plan-run.js';
28
20
  import { runPlanRunEpilogue } from './lib/orchestration/run-epilogue.js';
29
21
  import { createProvider } from './lib/provider-factory.js';
30
22
 
31
23
  const CLI_OPTIONS = {
32
- run: { type: 'string' },
33
24
  stories: { type: 'string' },
34
25
  cwd: { type: 'string' },
35
26
  };
@@ -44,13 +35,10 @@ export async function main(argv = process.argv.slice(2)) {
44
35
  options: CLI_OPTIONS,
45
36
  strict: false,
46
37
  });
47
- const runFlag = typeof values.run === 'string' ? values.run.trim() : '';
48
38
  const hasStoriesFlag =
49
39
  typeof values.stories === 'string' && values.stories.trim().length > 0;
50
- if (!runFlag && !hasStoriesFlag) {
51
- throw new Error(
52
- 'Usage: node plan-run-epilogue.js (--run <planRunId> | --stories 1,2,3) [--stories 1,2,3]',
53
- );
40
+ if (!hasStoriesFlag) {
41
+ throw new Error('Usage: node plan-run-epilogue.js --stories 1,2,3');
54
42
  }
55
43
  const cwd =
56
44
  typeof values.cwd === 'string' && values.cwd.trim()
@@ -59,26 +47,16 @@ export async function main(argv = process.argv.slice(2)) {
59
47
  const config = resolveConfig({ cwd });
60
48
  const provider = createProvider(config);
61
49
 
62
- let stories = [];
63
- if (hasStoriesFlag) {
64
- stories = values.stories
65
- .split(',')
66
- .map((s) => Number(s.trim()))
67
- .filter((n) => Number.isInteger(n) && n > 0);
68
- } else {
69
- const planRunLabel = normalizePlanRunLabel(runFlag);
70
- const issues = await fetchPlanRunIssues(provider, {
71
- planRunLabel,
72
- state: 'all',
73
- });
74
- const envelope = resolvePlanRunFromIssues({ run: runFlag, issues });
75
- stories = (envelope.stories ?? [])
76
- .map((s) => Number(s?.id ?? s))
77
- .filter((n) => Number.isInteger(n) && n > 0);
78
- }
50
+ // Story #4540 retired the `--run <planRunId>` label-resolution branch
51
+ // along with the label itself. The epilogue is keyed on the delivered id
52
+ // set, and the synthesized `adhoc-<ids>` id it already used for positional
53
+ // runs is now the only id it needs.
54
+ const stories = values.stories
55
+ .split(',')
56
+ .map((s) => Number(s.trim()))
57
+ .filter((n) => Number.isInteger(n) && n > 0);
79
58
 
80
- const planRunId =
81
- runFlag || `adhoc-${[...stories].sort((a, b) => a - b).join('-')}`;
59
+ const planRunId = `adhoc-${[...stories].sort((a, b) => a - b).join('-')}`;
82
60
 
83
61
  const result = await runPlanRunEpilogue({
84
62
  planRunId,
@@ -87,6 +65,8 @@ export async function main(argv = process.argv.slice(2)) {
87
65
  config,
88
66
  cwd,
89
67
  });
68
+ warnOnUnresolvedBase(result);
69
+ warnOnEmptyRollup(result);
90
70
  Logger.info(JSON.stringify(result, null, 2));
91
71
  if (result.errors?.length) {
92
72
  process.exitCode = 1;
@@ -94,4 +74,69 @@ export async function main(argv = process.argv.slice(2)) {
94
74
  return result;
95
75
  }
96
76
 
77
+ /**
78
+ * Surface an unresolvable combined landed diff as a loud operator warning.
79
+ *
80
+ * The roster's changed-file set is the input the host walks its audit lenses
81
+ * against; a silent absence would read as "nothing changed" and the lens walk
82
+ * would look complete while covering nothing. Not fatal — with no diff the
83
+ * selector degrades to keyword-only lens selection, so the rest of the
84
+ * roster is still useful.
85
+ *
86
+ * @param {object} result - `runPlanRunEpilogue` envelope.
87
+ * @returns {void}
88
+ */
89
+ function warnOnUnresolvedBase(result) {
90
+ const roster = (result?.results ?? []).find(
91
+ (r) => r?.kind === 'audit-roster',
92
+ );
93
+ const base = roster?.baseResolution;
94
+ if (base?.resolved !== false) return;
95
+ Logger.warn(
96
+ `⚠️ Combined landed diff unavailable — the pre-run base sha could not be ` +
97
+ `resolved against \`${base.baseRef}\`: ${base.reason}\n` +
98
+ ` changedFiles is null (NOT an empty set). Determine the run diff by ` +
99
+ `hand before walking the selected lenses.`,
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Surface a zero-signal roll-up over a multi-Story run as a loud operator
105
+ * warning (Story #4578).
106
+ *
107
+ * The failure this exists to prevent is a *reassuring* one. The roll-up read
108
+ * "No friction signals — nothing to follow up" for a 7-Story run that
109
+ * contained a mid-run git outage, a parked worker needing an operator
110
+ * resume, and an acceptance critic that needed four rounds. Nothing was
111
+ * broken in the roll-up — the stream really was empty — but the report was
112
+ * indistinguishable from a clean run, so the retro loop that exists to learn
113
+ * from a run was silently blind to that run's pain.
114
+ *
115
+ * Not fatal: a genuinely friction-free multi-Story run is possible, and this
116
+ * cannot tell the two apart — which is precisely why it asks the operator
117
+ * rather than asserting either reading.
118
+ *
119
+ * @param {object} result - `runPlanRunEpilogue` envelope.
120
+ * @returns {void}
121
+ */
122
+ function warnOnEmptyRollup(result) {
123
+ const rollup = (result?.results ?? []).find(
124
+ (r) => r?.kind === 'follow-up-rollup',
125
+ );
126
+ if (!rollup?.emptyRollupSuspect) return;
127
+ Logger.warn(
128
+ `⚠️ 0 friction signals across ${rollup.storyCount} Stories — telemetry may not ` +
129
+ `have fired.\n` +
130
+ ` An empty roll-up is NOT evidence of a clean run: it is the same output a ` +
131
+ `run with\n` +
132
+ ` heavy friction produces when nothing recorded it. The runtime emits ` +
133
+ `friction from its\n` +
134
+ ` own observables (agent::blocked transitions, failed closes, exhausted ` +
135
+ `merge waits), so\n` +
136
+ ` zero here also means none of those fired. If this run had friction you ` +
137
+ `can name, that\n` +
138
+ ` telemetry gap is itself worth filing.`,
139
+ );
140
+ }
141
+
97
142
  await runAsCli(import.meta.url, main);
@@ -22,10 +22,6 @@ import fs from 'node:fs/promises';
22
22
  import { parseArgs } from 'node:util';
23
23
  import { runAsCli } from './lib/cli-utils.js';
24
24
  import { resolveConfig } from './lib/config-resolver.js';
25
- import {
26
- outboxPathFor,
27
- postCommentOrBuffer,
28
- } from './lib/orchestration/bookkeeping-outbox.js';
29
25
  import {
30
26
  assertValidStructuredCommentType,
31
27
  upsertStructuredComment,
@@ -41,11 +37,6 @@ Flags:
41
37
  retro, epic-run-state, wave-0-start) (required).
42
38
  --body-file Path to a file containing the markdown body (required).
43
39
  --provider Provider name (default: inferred from .agentrc.json github block).
44
- --buffer Headless mode: buffer this upsert to the per-Epic bookkeeping
45
- outbox instead of posting live. Requires --epic. Drained to
46
- GitHub once at finalize by bookkeeping-reconcile.js (Epic
47
- #4476). Omit for attended runs (posts live, unchanged).
48
- --epic <id> Epic id owning the outbox (required with --buffer).
49
40
  --help Show this message.
50
41
  `;
51
42
 
@@ -73,8 +64,6 @@ export function parseArgv(argv) {
73
64
  marker: { type: 'string' },
74
65
  'body-file': { type: 'string' },
75
66
  provider: { type: 'string' },
76
- buffer: { type: 'boolean' },
77
- epic: { type: 'string' },
78
67
  help: { type: 'boolean' },
79
68
  },
80
69
  strict: false,
@@ -126,33 +115,6 @@ export async function main(argv = process.argv.slice(2)) {
126
115
  : config;
127
116
  const provider = createProvider(effectiveConfig);
128
117
 
129
- // Headless buffering (Epic #4476 M5): route the upsert to the per-Epic
130
- // outbox instead of a live GitHub round-trip. Requires --epic to locate the
131
- // outbox; finalize's bookkeeping-reconcile.js drains it once. Attended runs
132
- // (no --buffer) are unchanged.
133
- if (values.buffer) {
134
- const epicId = Number.parseInt(values.epic ?? '', 10);
135
- if (!Number.isInteger(epicId) || epicId <= 0) {
136
- process.stderr.write(
137
- '[post-structured-comment] --buffer requires --epic <id>.\n',
138
- );
139
- process.exit(2);
140
- }
141
- assertValidStructuredCommentType(values.marker);
142
- const { buffered } = await postCommentOrBuffer({
143
- provider,
144
- ticketId,
145
- marker: values.marker,
146
- body,
147
- headless: true,
148
- outboxPath: outboxPathFor(epicId, config),
149
- });
150
- process.stdout.write(
151
- `${JSON.stringify({ success: true, ticketId, type: values.marker, buffered })}\n`,
152
- );
153
- return;
154
- }
155
-
156
118
  const envelope = await runPostStructuredComment({
157
119
  ticketId,
158
120
  type: values.marker,