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
@@ -1,63 +0,0 @@
1
- /**
2
- * plan-review-routing.js — resolve Phase 7 review-stop vs auto-proceed.
3
- *
4
- * Pure ESM, no I/O. Consumes the shared planningRisk envelope (derived
5
- * from the planner-authored risk verdict via `deriveRiskEnvelope`) and
6
- * optional operator overrides to decide whether the plan wrapper should
7
- * STOP for human review before Phase 8.
8
- */
9
-
10
- /**
11
- * @typedef {import('./planning-risk.js').PlanningRiskEnvelope} PlanningRiskEnvelope
12
- * @typedef {'review-required' | 'auto-proceed' | 'operator-override-review'} ReviewRoutingDecision
13
- */
14
-
15
- /**
16
- * @typedef {Object} ReviewRoutingEnvelope
17
- * @property {ReviewRoutingDecision} decision
18
- * @property {boolean} requiresStop
19
- * @property {boolean} forceReviewApplied
20
- * @property {string} operatorMessage
21
- */
22
-
23
- const AUTO_PROCEED_MESSAGE =
24
- 'Planning risk is low — auto-proceeding to Phase 8 decomposition after spec validation. Context tickets remain open until Epic delivery finalizes.';
25
-
26
- const REVIEW_REQUIRED_MESSAGE =
27
- 'Planning risk requires operator review — STOP before Phase 8. Review the Tech Spec sections and the Acceptance Table — both managed sections of the Epic body — on GitHub and confirm in this session before decomposition.';
28
-
29
- const FORCE_REVIEW_MESSAGE =
30
- 'Operator override — forcing review stop before Phase 8 despite low planning risk.';
31
-
32
- /**
33
- * Resolve whether Phase 7 should STOP for operator review before Phase 8.
34
- *
35
- * @param {{ planningRisk: PlanningRiskEnvelope, forceReview?: boolean }} input
36
- * @returns {ReviewRoutingEnvelope}
37
- */
38
- export function resolveReviewRouting({ planningRisk, forceReview = false }) {
39
- if (forceReview) {
40
- return {
41
- decision: 'operator-override-review',
42
- requiresStop: true,
43
- forceReviewApplied: true,
44
- operatorMessage: FORCE_REVIEW_MESSAGE,
45
- };
46
- }
47
-
48
- if (planningRisk.requiresReview) {
49
- return {
50
- decision: 'review-required',
51
- requiresStop: true,
52
- forceReviewApplied: false,
53
- operatorMessage: REVIEW_REQUIRED_MESSAGE,
54
- };
55
- }
56
-
57
- return {
58
- decision: 'auto-proceed',
59
- requiresStop: false,
60
- forceReviewApplied: false,
61
- operatorMessage: AUTO_PROCEED_MESSAGE,
62
- };
63
- }
@@ -1,104 +0,0 @@
1
- /**
2
- * phases/risk-verdict.js — read + schema-validate the planner-authored
3
- * risk verdict (Epic #3865).
4
- *
5
- * The `epic-plan-spec-author` Skill writes `risk-verdict.json` as the
6
- * fourth planning artifact; the persist half of `epic-plan-spec.js` loads
7
- * it through this module before deriving the planningRisk envelope. A
8
- * missing, unparseable, or schema-invalid verdict throws — the spec phase
9
- * fails closed rather than mis-routing the review gate.
10
- */
11
-
12
- import { readFileSync } from 'node:fs';
13
- import path from 'node:path';
14
- import { fileURLToPath } from 'node:url';
15
-
16
- import Ajv2020 from 'ajv/dist/2020.js';
17
- import addFormats from 'ajv-formats';
18
-
19
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
-
21
- export const RISK_VERDICT_SCHEMA_PATH = path.resolve(
22
- __dirname,
23
- '..',
24
- '..',
25
- '..',
26
- '..',
27
- 'schemas',
28
- 'risk-verdict.schema.json',
29
- );
30
-
31
- /** @type {Map<string, import('ajv').ValidateFunction>} */
32
- const validatorCache = new Map();
33
-
34
- /**
35
- * Compile (and cache) the Ajv2020 validator for the risk-verdict schema.
36
- *
37
- * @param {string} schemaPath
38
- * @param {{ readFileSync: typeof readFileSync }} io
39
- * @returns {import('ajv').ValidateFunction}
40
- */
41
- function getRiskVerdictValidator(schemaPath, io) {
42
- const cached = validatorCache.get(schemaPath);
43
- if (cached) return cached;
44
- const ajv = new Ajv2020({ allErrors: true, strict: false });
45
- addFormats(ajv);
46
- const schema = JSON.parse(io.readFileSync(schemaPath, 'utf8'));
47
- const validate = ajv.compile(schema);
48
- validatorCache.set(schemaPath, validate);
49
- return validate;
50
- }
51
-
52
- /**
53
- * Validate a parsed risk verdict against the schema. Throws with the full
54
- * Ajv error detail on any violation so the spec phase never routes the
55
- * review gate off a malformed verdict.
56
- *
57
- * @param {unknown} verdict
58
- * @param {{ schemaPath?: string, io?: { readFileSync: typeof readFileSync } }} [opts]
59
- * @returns {import('../planning-risk.js').RiskVerdict} The validated verdict (same reference).
60
- */
61
- export function validateRiskVerdict(verdict, opts = {}) {
62
- const validate = getRiskVerdictValidator(
63
- opts.schemaPath ?? RISK_VERDICT_SCHEMA_PATH,
64
- opts.io ?? { readFileSync },
65
- );
66
- if (!validate(verdict)) {
67
- const detail = (validate.errors ?? [])
68
- .map((e) => `${e.instancePath || '/'} ${e.message}`)
69
- .join('; ');
70
- throw new Error(
71
- `[epic-plan-spec] risk verdict failed schema validation: ${detail}`,
72
- );
73
- }
74
- return /** @type {import('../planning-risk.js').RiskVerdict} */ (verdict);
75
- }
76
-
77
- /**
78
- * Read, parse, and schema-validate the risk-verdict file the
79
- * `epic-plan-spec-author` Skill wrote.
80
- *
81
- * @param {string} verdictPath
82
- * @param {{ schemaPath?: string, io?: { readFileSync: typeof readFileSync } }} [opts]
83
- * @returns {import('../planning-risk.js').RiskVerdict}
84
- */
85
- export function loadRiskVerdict(verdictPath, opts = {}) {
86
- const io = opts.io ?? { readFileSync };
87
- let raw;
88
- try {
89
- raw = io.readFileSync(verdictPath, 'utf8');
90
- } catch (err) {
91
- throw new Error(
92
- `[epic-plan-spec] cannot read risk verdict at ${verdictPath}: ${err.message}`,
93
- );
94
- }
95
- let parsed;
96
- try {
97
- parsed = JSON.parse(raw);
98
- } catch (err) {
99
- throw new Error(
100
- `[epic-plan-spec] risk verdict at ${verdictPath} is not valid JSON: ${err.message}`,
101
- );
102
- }
103
- return validateRiskVerdict(parsed, opts);
104
- }
@@ -1,213 +0,0 @@
1
- /**
2
- * planning-context-budget.js
3
- *
4
- * Bounded planning-context budget for the `--emit-context` planning scripts
5
- * (Epic #817 Story 9). Provides a summary representation of large markdown
6
- * payloads (project docs, Epic body, Tech Spec body) so the host LLM is not
7
- * handed multi-100KB envelopes when the underlying material exceeds the
8
- * configured `maxBytes` budget.
9
- *
10
- * Two pure helpers:
11
- * - `summarizeDoc(filePath, content, maxBytes)` extracts headings + bounded
12
- * excerpts for one document.
13
- * - `applyBudget(items, limits, opts)` decides full vs summary for a
14
- * collection of `{ path, content }` items based on `summaryMode` and the
15
- * total payload size.
16
- *
17
- * Both functions are deterministic and have no I/O.
18
- */
19
-
20
- const HEADING_RE = /^(#{2,3})\s+(.+?)\s*$/;
21
-
22
- /**
23
- * Default per-excerpt cap so a single section heading does not consume the
24
- * entire per-doc byte budget. The bounded sum across excerpts is enforced
25
- * separately by {@link summarizeDoc}.
26
- */
27
- const DEFAULT_PER_EXCERPT_BYTES = 800;
28
-
29
- /**
30
- * Default planning-context limits when callers do not pass through
31
- * `getLimits(config).planningContext`. Mirrors `LIMITS_DEFAULTS` in
32
- * `lib/config/limits.js` so this module is usable in standalone tests.
33
- */
34
- export const PLANNING_CONTEXT_DEFAULTS = Object.freeze({
35
- maxBytes: 50000,
36
- summaryMode: 'auto',
37
- });
38
-
39
- function byteLen(s) {
40
- if (s == null) return 0;
41
- return Buffer.byteLength(String(s), 'utf-8');
42
- }
43
-
44
- function extractHeadings(content) {
45
- if (!content) return [];
46
- const lines = String(content).split(/\r?\n/);
47
- const out = [];
48
- for (const line of lines) {
49
- const m = HEADING_RE.exec(line);
50
- if (m) out.push({ level: m[1].length, text: m[2] });
51
- }
52
- return out;
53
- }
54
-
55
- /**
56
- * Split a markdown body into preamble + per-heading sections so excerpts can
57
- * be emitted with the heading they belong to. Lines preceding the first
58
- * `## ` / `### ` heading become the `preamble` section (heading: null).
59
- */
60
- function splitSections(content) {
61
- if (!content) return [];
62
- const lines = String(content).split(/\r?\n/);
63
- const sections = [{ heading: null, body: [] }];
64
- for (const line of lines) {
65
- const m = HEADING_RE.exec(line);
66
- if (m) {
67
- sections.push({ heading: m[2], body: [] });
68
- } else {
69
- sections[sections.length - 1].body.push(line);
70
- }
71
- }
72
- return sections;
73
- }
74
-
75
- /**
76
- * Trim a multi-line section to the first non-empty paragraph, capped at
77
- * `maxBytes` of utf-8. Preserves whitespace inside the kept paragraph but
78
- * collapses leading/trailing blank lines so excerpts stay compact.
79
- */
80
- function firstParagraph(lines, maxBytes) {
81
- const text = lines.join('\n').replace(/^\s+|\s+$/g, '');
82
- if (!text) return '';
83
- // Take up to the first blank-line break (paragraph boundary).
84
- const para = text.split(/\n\s*\n/)[0] ?? '';
85
- const trimmed = para.trim();
86
- if (byteLen(trimmed) <= maxBytes) return trimmed;
87
- // Hard truncate at maxBytes utf-8 with an ellipsis marker so callers can
88
- // tell the excerpt is bounded rather than corrupt.
89
- const buf = Buffer.from(trimmed, 'utf-8').subarray(0, maxBytes);
90
- // Avoid splitting a multi-byte codepoint at the boundary.
91
- let safe = buf.toString('utf-8');
92
- if (safe.length > 1 && safe.charCodeAt(safe.length - 1) === 0xfffd) {
93
- safe = safe.slice(0, -1);
94
- }
95
- return `${safe.replace(/\s+$/, '')}…`;
96
- }
97
-
98
- /**
99
- * Summarise a single markdown doc. Emits headings + per-section excerpts
100
- * (preamble first), each bounded so a runaway section never blows the budget.
101
- *
102
- * @param {string} filePath repo-relative path used as the `path` field
103
- * @param {string} content full markdown body
104
- * @param {number} [maxBytes=50000] total per-doc byte budget for excerpts
105
- * @returns {{ path: string, headings: string[], excerpts: Array<{heading: string|null, snippet: string}>, byteSize: number }}
106
- */
107
- export function summarizeDoc(filePath, content, maxBytes = 50000) {
108
- const safeContent = typeof content === 'string' ? content : '';
109
- const byteSize = byteLen(safeContent);
110
- const headingObjs = extractHeadings(safeContent);
111
- const headings = headingObjs.map((h) => h.text);
112
-
113
- const sections = splitSections(safeContent);
114
- const perExcerptCap = Math.min(
115
- DEFAULT_PER_EXCERPT_BYTES,
116
- Math.max(120, Math.floor(maxBytes / Math.max(1, sections.length))),
117
- );
118
-
119
- const excerpts = [];
120
- let used = 0;
121
- for (const sec of sections) {
122
- if (used >= maxBytes) break;
123
- const remaining = Math.max(0, maxBytes - used);
124
- const cap = Math.min(perExcerptCap, remaining);
125
- const snippet = firstParagraph(sec.body, cap);
126
- if (!snippet) continue;
127
- excerpts.push({ heading: sec.heading, snippet });
128
- used += byteLen(snippet);
129
- }
130
-
131
- return {
132
- path: filePath,
133
- headings,
134
- excerpts,
135
- byteSize,
136
- };
137
- }
138
-
139
- function normalizeItems(items) {
140
- if (!Array.isArray(items)) return [];
141
- return items
142
- .filter((it) => it && typeof it === 'object')
143
- .map((it) => ({
144
- path: it.path ?? it.name ?? '',
145
- content: typeof it.content === 'string' ? it.content : '',
146
- }));
147
- }
148
-
149
- function totalBytes(items) {
150
- let n = 0;
151
- for (const it of items) n += byteLen(it.content);
152
- return n;
153
- }
154
-
155
- function buildFullItems(items) {
156
- return items.map((it) => ({
157
- path: it.path,
158
- content: it.content,
159
- byteSize: byteLen(it.content),
160
- }));
161
- }
162
-
163
- function buildSummaryItems(items, maxBytes) {
164
- // Distribute the byte budget across docs proportional to their size, with
165
- // a per-doc floor so even tiny docs get a heading + tiny excerpt.
166
- const total = totalBytes(items) || 1;
167
- const floor = Math.max(512, Math.floor(maxBytes / Math.max(1, items.length)));
168
- return items.map((it) => {
169
- const share = Math.max(
170
- floor,
171
- Math.floor((byteLen(it.content) / total) * maxBytes),
172
- );
173
- return summarizeDoc(it.path, it.content, share);
174
- });
175
- }
176
-
177
- /**
178
- * Apply the planning-context budget to a collection of doc-shaped items.
179
- *
180
- * @param {Array<{path?: string, name?: string, content: string}>} items
181
- * @param {{ maxBytes?: number, summaryMode?: 'auto'|'always'|'never' }} [limits]
182
- * @param {{ fullContext?: boolean }} [opts] — `fullContext: true` forces full
183
- * mode regardless of `summaryMode` (mirrors the `--full-context` CLI flag).
184
- * @returns {{ mode: 'full'|'summary', items: Array<object>, totalBytes: number }}
185
- */
186
- export function applyBudget(items, limits = {}, opts = {}) {
187
- const merged = { ...PLANNING_CONTEXT_DEFAULTS, ...(limits || {}) };
188
- const { maxBytes, summaryMode } = merged;
189
- const { fullContext = false } = opts;
190
-
191
- const norm = normalizeItems(items);
192
- const total = totalBytes(norm);
193
-
194
- if (fullContext || summaryMode === 'never') {
195
- return { mode: 'full', items: buildFullItems(norm), totalBytes: total };
196
- }
197
- if (summaryMode === 'always') {
198
- return {
199
- mode: 'summary',
200
- items: buildSummaryItems(norm, maxBytes),
201
- totalBytes: total,
202
- };
203
- }
204
- // auto — summarise iff payload exceeds the budget.
205
- if (total > maxBytes) {
206
- return {
207
- mode: 'summary',
208
- items: buildSummaryItems(norm, maxBytes),
209
- totalBytes: total,
210
- };
211
- }
212
- return { mode: 'full', items: buildFullItems(norm), totalBytes: total };
213
- }
@@ -1,194 +0,0 @@
1
- /**
2
- * planning-risk.js — derive the Epic planning-risk envelope from a
3
- * planner-authored risk verdict.
4
- *
5
- * Pure ESM, no I/O. The planner (the `epic-plan-spec-author` Skill) judges
6
- * the Epic it just specced and supplies a verdict of shape
7
- * `{ axes: [{ axis, level, rationale }], summary }`, validated against
8
- * `.agents/schemas/risk-verdict.schema.json` before it reaches this module.
9
- * This module owns the deterministic control-flow outputs — overall level,
10
- * review requirement, acceptance disposition, and gate decision — so the
11
- * model supplies the *judgment input* while the harness owns the *gate
12
- * decision* (Epic #3865 hard cutover from the retired keyword-regex
13
- * classifier; see `docs/roadmap.md` Part 1).
14
- */
15
-
16
- /** @typedef {'low' | 'medium' | 'high'} RiskLevel */
17
- /** @typedef {'required' | 'recommended' | 'not-applicable'} AcceptanceDisposition */
18
- /** @typedef {'review-required' | 'auto-proceed'} GateDecision */
19
-
20
- /**
21
- * @typedef {Object} PlanningRiskAxis
22
- * @property {string} axis
23
- * @property {RiskLevel} level
24
- * @property {string} rationale
25
- */
26
-
27
- /**
28
- * @typedef {Object} RiskVerdict
29
- * @property {PlanningRiskAxis[]} axes
30
- * @property {string} summary
31
- */
32
-
33
- /**
34
- * @typedef {Object} PlanningRiskEnvelope
35
- * @property {PlanningRiskAxis[]} axes
36
- * @property {RiskLevel} overallLevel
37
- * @property {boolean} requiresReview
38
- * @property {AcceptanceDisposition} acceptanceDisposition
39
- * @property {GateDecision} gateDecision
40
- * @property {string} [acceptanceWaivedReason] Present only when the
41
- * acceptance disposition was forced to `not-applicable` by a non-axis
42
- * signal (currently: no BDD runner detected). An operator-visible
43
- * rationale so the override is never silent (Story #4145).
44
- */
45
-
46
- /**
47
- * @typedef {Object} BddRunnerProbe
48
- * @property {string|null} runner
49
- * @property {boolean} fallback `true` when no supported BDD runner was
50
- * detected in the project (`verifyBddRunnerPendingTag`).
51
- * @property {string} [reason]
52
- */
53
-
54
- const LEVEL_RANK = Object.freeze({ low: 0, medium: 1, high: 2 });
55
-
56
- /**
57
- * Axes whose presence forces a `required` acceptance disposition. Mirrored
58
- * by the `axis` enum in `.agents/schemas/risk-verdict.schema.json` — keep
59
- * the two lists in sync.
60
- */
61
- export const REQUIRED_AXES = new Set([
62
- 'visible-behavior',
63
- 'public-api',
64
- 'security',
65
- 'data-migration',
66
- 'billing',
67
- 'destructive-mutation',
68
- 'critical-workflow',
69
- ]);
70
-
71
- /**
72
- * Axes that, when they are the only signals present, waive the acceptance
73
- * spec (`not-applicable`). Mirrored by the `axis` enum in
74
- * `.agents/schemas/risk-verdict.schema.json` — keep the two lists in sync.
75
- */
76
- export const NOT_APPLICABLE_AXES = new Set([
77
- 'docs-only',
78
- 'test-harness',
79
- 'internal-refactor',
80
- ]);
81
-
82
- /**
83
- * @param {PlanningRiskAxis[]} axes
84
- * @returns {RiskLevel}
85
- */
86
- function resolveOverallLevel(axes) {
87
- if (axes.length === 0) return 'low';
88
- return axes.reduce(
89
- (highest, entry) =>
90
- LEVEL_RANK[entry.level] > LEVEL_RANK[highest] ? entry.level : highest,
91
- 'low',
92
- );
93
- }
94
-
95
- /**
96
- * @param {PlanningRiskAxis[]} axes
97
- * @param {RiskLevel} overallLevel
98
- * @returns {AcceptanceDisposition}
99
- */
100
- function resolveAcceptanceDisposition(axes, overallLevel) {
101
- const requiredAxes = axes.filter((entry) => REQUIRED_AXES.has(entry.axis));
102
- if (requiredAxes.length > 0) {
103
- return 'required';
104
- }
105
- if (
106
- overallLevel === 'medium' ||
107
- axes.some((entry) => entry.level === 'medium')
108
- ) {
109
- return 'recommended';
110
- }
111
- if (
112
- axes.length > 0 &&
113
- axes.every((entry) => NOT_APPLICABLE_AXES.has(entry.axis))
114
- ) {
115
- return 'not-applicable';
116
- }
117
- if (overallLevel === 'low') return 'not-applicable';
118
- return 'recommended';
119
- }
120
-
121
- /**
122
- * @param {RiskLevel} overallLevel
123
- * @param {PlanningRiskAxis[]} axes
124
- * @returns {boolean}
125
- */
126
- function resolveRequiresReview(overallLevel, axes) {
127
- if (overallLevel === 'high') return true;
128
- if (overallLevel === 'medium') {
129
- return axes.some(
130
- (entry) =>
131
- entry.level === 'medium' &&
132
- (REQUIRED_AXES.has(entry.axis) || entry.axis === 'visible-behavior'),
133
- );
134
- }
135
- return false;
136
- }
137
-
138
- /**
139
- * Derive the stable planningRisk envelope from a schema-validated planner
140
- * verdict. Pure derivation — schema validation happens at the read boundary
141
- * (`plan-persist.js` via `loadRiskVerdict`), never here, so a malformed verdict fails closed
142
- * before this function runs.
143
- *
144
- * **No-BDD-runner waiver (Story #4145).** The acceptance disposition the risk
145
- * axes derive presumes a BDD runner exists to satisfy an authored AC table.
146
- * When `opts.bddRunner.fallback === true` (no supported runner detected — e.g.
147
- * a `node:test` repo with no `tests/features/**`), an authored AC table can
148
- * never be reconciled by `@epic-<id>-ac-*` feature tags, so `/deliver`
149
- * finalize would abort. In that case the disposition is **forced** to
150
- * `not-applicable` regardless of the risk axes, and `acceptanceWaivedReason`
151
- * records the override so it is operator-visible, not silent. The
152
- * `requiresReview` / `gateDecision` outputs are unaffected — a high-risk
153
- * Epic still routes to review; only the acceptance-spec requirement is
154
- * waived. Repos that ship a BDD runner (`fallback !== true`) are unaffected.
155
- *
156
- * @param {RiskVerdict} [verdict]
157
- * @param {{ bddRunner?: BddRunnerProbe|null }} [opts]
158
- * @returns {PlanningRiskEnvelope}
159
- */
160
- export function deriveRiskEnvelope(verdict = {}, { bddRunner = null } = {}) {
161
- const axes = (Array.isArray(verdict.axes) ? verdict.axes : []).map(
162
- ({ axis, level, rationale }) => ({ axis, level, rationale }),
163
- );
164
-
165
- const overallLevel = resolveOverallLevel(axes);
166
- const axisDisposition = resolveAcceptanceDisposition(axes, overallLevel);
167
- const requiresReview = resolveRequiresReview(overallLevel, axes);
168
- const gateDecision = requiresReview ? 'review-required' : 'auto-proceed';
169
-
170
- const noBddRunner = bddRunner?.fallback === true;
171
- // Force the waiver only when the axes would otherwise have required (or
172
- // recommended) an AC table; if the disposition is already not-applicable
173
- // there is nothing to override and no waiver rationale to surface.
174
- const forceWaiver = noBddRunner && axisDisposition !== 'not-applicable';
175
- const acceptanceDisposition = forceWaiver
176
- ? 'not-applicable'
177
- : axisDisposition;
178
-
179
- /** @type {PlanningRiskEnvelope} */
180
- const envelope = {
181
- axes,
182
- overallLevel,
183
- requiresReview,
184
- acceptanceDisposition,
185
- gateDecision,
186
- };
187
- if (forceWaiver) {
188
- envelope.acceptanceWaivedReason =
189
- `no BDD runner detected (${bddRunner?.reason ?? 'no-bdd-runner-detected'}) — ` +
190
- `an authored acceptance-spec AC table cannot be reconciled by feature tags, ` +
191
- `so the acceptance disposition is waived to not-applicable (was ${axisDisposition}).`;
192
- }
193
- return envelope;
194
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * phases/branch-cleanup.js — post-merge Story branch deletion phase.
3
- *
4
- * Delegates the "delete this branch from local + remote, treat not-found
5
- * as success" idempotency contract to `lib/git-branch-cleanup.js` so the
6
- * deletion rules live in one place. A local delete failure is logged
7
- * loudly (operators usually need to investigate a stale worktree),
8
- * while a remote not-found is treated as a no-op.
9
- */
10
-
11
- import { deleteBranchEverywhere } from '../../../git-branch-cleanup.js';
12
-
13
- function reapPhaseLogger(progress) {
14
- return progress ?? (() => {});
15
- }
16
-
17
- export async function branchCleanupPhase(ctx, state = {}) {
18
- const {
19
- storyBranch,
20
- repoRoot,
21
- progress,
22
- logger,
23
- branchCleanup = deleteBranchEverywhere,
24
- } = ctx;
25
- const log = reapPhaseLogger(progress);
26
- log('CLEANUP', `Deleting story branch: ${storyBranch}`);
27
-
28
- const result = branchCleanup(storyBranch, {
29
- cwd: repoRoot,
30
- noVerify: true,
31
- });
32
-
33
- if (!result.local.deleted) {
34
- const stderr = (result.local.stderr || '').trim();
35
- const reapStatus = state.worktreeReap?.status;
36
- logger.error(
37
- ` Local branch ${storyBranch} delete failed: ${stderr || 'unknown'}. ` +
38
- `Check for stale worktrees (git worktree list).` +
39
- (reapStatus ? ` worktreeReap=${reapStatus}.` : ''),
40
- );
41
- }
42
- if (result.remote.deleted) {
43
- if (result.remote.reason === 'not-found') {
44
- log('CLEANUP', `Remote branch ${storyBranch} not found — skipped`);
45
- } else {
46
- log('CLEANUP', `✅ Remote branch ${storyBranch} deleted`);
47
- }
48
- }
49
-
50
- return {
51
- localDeleted: result.local.deleted,
52
- remoteDeleted: result.remote.deleted,
53
- localReason: result.local.reason,
54
- remoteReason: result.remote.reason,
55
- };
56
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * phases/dashboard-refresh.js — retired dispatch-manifest refresh seam.
3
- *
4
- * The Stage 5 hard cutover deletes the dispatcher/manifest surface; keep this
5
- * phase as a no-op so any still-wired post-merge pipeline can drain safely.
6
- */
7
-
8
- function reapPhaseLogger(progress) {
9
- return progress ?? (() => {});
10
- }
11
-
12
- export async function dashboardRefreshPhase(ctx) {
13
- const { skipDashboard, progress } = ctx;
14
- const log = reapPhaseLogger(progress);
15
- if (skipDashboard) {
16
- log('DASHBOARD', 'Skipping dashboard refresh (--skip-dashboard flag set)');
17
- return false;
18
- }
19
- log('DASHBOARD', 'Dispatch manifest refresh retired; no dashboard updated.');
20
- return false;
21
- }