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
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://mandrel.dev/schemas/audit-rules.schema.json",
4
4
  "title": "AuditRulesManifest",
5
- "description": "Schema describing the audit-rules.json manifest read by select-audits.js and lib/audit-suite/runner.js. The manifest enumerates registered audit workflows and the triggers / substitution keys each one accepts.",
5
+ "description": "Schema describing the audit-rules.json manifest read by lib/audit-suite/selector.js and lib/audit-suite/runner.js. The manifest enumerates registered audit workflows and the triggers / substitution keys each one accepts, plus the sensitive-path classes that derive review depth from a change set.",
6
6
  "type": "object",
7
7
  "required": ["version", "audits"],
8
8
  "additionalProperties": false,
@@ -19,9 +19,35 @@
19
19
  "^[a-z][a-z0-9-]*$": { "$ref": "#/definitions/auditEntry" }
20
20
  },
21
21
  "additionalProperties": false
22
+ },
23
+ "sensitivePaths": {
24
+ "type": "object",
25
+ "description": "Map of sensitive-path class name to the globs that identify it. A change set touching any registered pattern derives a `high` change level, which resolves review depth to `deep` and the acceptance critic to `fresh` regardless of how narrow the diff is (deriveChangeLevel in lib/orchestration/review-depth.js). This is configuration, not code: an operator extends the classes or their globs here without editing a module, and the globs run through the same picomatch machinery as the audit-lens `filePatterns` triggers above. An absent or empty block means no path is sensitive and depth falls back to diff width alone.",
26
+ "patternProperties": {
27
+ "^[a-z][a-z0-9-]*$": { "$ref": "#/definitions/sensitivePathClass" }
28
+ },
29
+ "additionalProperties": false
22
30
  }
23
31
  },
24
32
  "definitions": {
33
+ "sensitivePathClass": {
34
+ "type": "object",
35
+ "required": ["filePatterns"],
36
+ "additionalProperties": false,
37
+ "properties": {
38
+ "description": {
39
+ "type": "string",
40
+ "description": "What this class covers — why a change here warrants a deeper pass."
41
+ },
42
+ "filePatterns": {
43
+ "type": "array",
44
+ "description": "Glob patterns matched against the changed files of the diff under review.",
45
+ "items": { "type": "string", "minLength": 1 },
46
+ "uniqueItems": true,
47
+ "minItems": 1
48
+ }
49
+ }
50
+ },
25
51
  "auditEntry": {
26
52
  "type": "object",
27
53
  "required": ["triggers", "scope"],
@@ -33,6 +59,12 @@
33
59
  "enum": ["local", "cumulative", "global"],
34
60
  "description": "Concern-ownership tier declaring the widest scope at which this lens's concern becomes decidable. `local` — decidable from a single Story's diff (verified at write-time + Story-scope review). `cumulative` — only decidable across the Epic's combined diff (verified at Epic close). `global` — evaluates a whole-product property regardless of the diff (verified at Epic close; exempt from change-set narrowing). All tier routing derives from this one field via resolveLensTier()."
35
61
  },
62
+ "target": {
63
+ "type": "string",
64
+ "enum": ["web", "any"],
65
+ "description": "Target-applicability gate: the kind of project this lens can say anything about. `web` — the lens reads a rendered web surface (pages, routes, HTML/CSS, design tokens) and is skipped entirely on a project that has none, however well its keyword or file-pattern triggers match. `any` — always applicable. ABSENT MEANS `any`: omitting the key never changes a lens's behaviour. Applicability is decided by the hasWebSurface() probe in lib/audit-suite/selector.js from observables in the consumer's own checkout — configured navigability routeGlobs, a declared web-framework dependency, or a tracked .html/.css/.jsx/.tsx source file — and NOT from an .agentrc key, so a consumer with a real web surface keeps these lenses with no configuration. The probe fails OPEN: an indeterminate answer treats the project as web-capable, because a wasted lens run is recoverable and silently dropped coverage is not.",
66
+ "default": "any"
67
+ },
36
68
  "substitutionKeys": {
37
69
  "type": "array",
38
70
  "description": "Substitution keys this audit accepts via run-audit-suite --substitution. Empty array means no caller-supplied keys are allowed.",
@@ -10,8 +10,7 @@ throw.
10
10
  Each event in the Tech Spec taxonomy has a `<event>.schema.json`
11
11
  file. The ledger record (`emitted | completed | failed` union)
12
12
  lives in `ledger-record.schema.json` and is consumed by
13
- `ledger-writer.js` and the `lib/orchestration/lifecycle/ledger-diff.js`
14
- assertion helpers.
13
+ `ledger-writer.js`.
15
14
 
16
15
  Schemas are intentionally permissive (`additionalProperties: true`)
17
16
  on inner objects whose shape is dictated by upstream tooling (e.g.
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/ledger-record.schema.json",
4
4
  "title": "Lifecycle ledger record (emitted | completed | failed)",
5
- "description": "Append-only NDJSON record shape for temp/run-<id>/lifecycle.ndjson. Three discriminated kinds; consumers (LedgerWriter, the ledger-diff assertion helpers, TraceLogger) discriminate on `kind`.",
5
+ "description": "Append-only NDJSON record shape for temp/run-<id>/lifecycle.ndjson. Three discriminated kinds; consumers (LedgerWriter, TraceLogger) discriminate on `kind`.",
6
6
  "oneOf": [
7
7
  { "$ref": "#/$defs/emitted" },
8
8
  { "$ref": "#/$defs/completed" },
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/merge.flip-failed.schema.json",
4
+ "title": "merge.flip-failed",
5
+ "description": "Emitted when a delivery run observed a CONFIRMED merge but the agent::closing → agent::done label write itself failed. Deliberately distinct from merge.unlanded (Story #4539): the merge landed, so attributing this to an unlanded merge sends the operator to branch protection and required checks when the real fault is an API failure on the label write, remedied by re-running single-story-confirm-merge.js. scope distinguishes the epic-path (ticketId = epicId) from the standalone story-path (ticketId = storyId).",
6
+ "type": "object",
7
+ "required": [
8
+ "event",
9
+ "scope",
10
+ "ticketId",
11
+ "prNumber",
12
+ "blockClass",
13
+ "reason",
14
+ "elapsedSeconds"
15
+ ],
16
+ "properties": {
17
+ "event": { "type": "string", "const": "merge.flip-failed" },
18
+ "scope": {
19
+ "type": "string",
20
+ "enum": ["epic", "story"]
21
+ },
22
+ "ticketId": { "type": "integer", "minimum": 1 },
23
+ "prNumber": { "type": "integer", "minimum": 1 },
24
+ "blockClass": {
25
+ "type": "string",
26
+ "enum": ["merged-flip-failed"]
27
+ },
28
+ "reason": { "type": "string", "minLength": 1 },
29
+ "elapsedSeconds": { "type": "number", "minimum": 0 },
30
+ "timestamp": { "type": "string", "format": "date-time" }
31
+ },
32
+ "additionalProperties": false
33
+ }
@@ -25,6 +25,7 @@
25
25
  "type": "string",
26
26
  "enum": [
27
27
  "checks-pending-timeout",
28
+ "checks-failed",
28
29
  "branch-protection-human-required",
29
30
  "arm-failure",
30
31
  "api-race-other",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/story.merged.schema.json",
4
4
  "title": "story.merged",
5
- "description": "Emitted from the story-close path after a Story branch successfully merges into epic/<id>.",
5
+ "description": "Emitted from the story-close path after a Story branch successfully merges into main (single-story/confirm-merge.js).",
6
6
  "type": "object",
7
7
  "required": ["storyId", "sha"],
8
8
  "properties": {
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/signal-event.schema.json",
4
4
  "title": "SignalEvent",
5
- "description": "One NDJSON line emitted by the signals writer (Epic #1030; canonical envelope cutover Epic #4406 / Story #4413). Runtime events live in append-only NDJSON on local disk under temp/epic-<eid>/stories/story-<sid>/signals.ndjson (per-Story) and temp/epic-<eid>/signals.ndjson (Epic-level wave lifecycle); tickets carry only summaries (story-perf-summary, epic-perf-report). `kind: trace` is the raw tool-call trace; the named kinds are derived signals. This is the ONLY shape — the legacy `timestamp` / `epic` aliases and the `source: { tool }` provenance object were deleted in the same PR that moved every writer (no read-side compatibility branch).",
5
+ "description": "One NDJSON line emitted by the signals writer (Epic #1030; canonical envelope cutover Epic #4406 / Story #4413). Runtime events live in append-only NDJSON on local disk under temp/run-<id>/stories/story-<sid>/signals.ndjson (per-Story) and temp/run-<id>/signals.ndjson (Epic-level wave lifecycle); The stream stays local: Story #4545 deleted the perf-summary / perf-report comment surface that used to roll it up onto tickets, leaving the retro as the consumer. `kind: trace` is the raw tool-call trace; the named kinds are derived signals. This is the ONLY shape — the legacy `timestamp` / `epic` aliases and the `source: { tool }` provenance object were deleted in the same PR that moved every writer (no read-side compatibility branch).",
6
6
  "type": "object",
7
7
  "additionalProperties": true,
8
8
  "required": ["kind", "ts"],
@@ -33,7 +33,7 @@
33
33
  "source": {
34
34
  "type": "string",
35
35
  "enum": ["framework", "consumer"],
36
- "description": "Framework/consumer classification injected by `tagSignalSource` (signals-writer.js) for records appended via appendSignal/appendEpicSignal. Reserved exclusively for this classifier tag — the originating tool/surface lives in `emitter`."
36
+ "description": "Framework/consumer classification injected by `tagSignalSource` (signals-writer.js) for records appended via appendSignal. Reserved exclusively for this classifier tag — the originating tool/surface lives in `emitter`."
37
37
  },
38
38
  "emitter": {
39
39
  "type": "object",
@@ -57,7 +57,7 @@
57
57
  "category": {
58
58
  "type": "string",
59
59
  "minLength": 1,
60
- "description": "Top-level friction category (e.g. Execution Error, baseline-refresh-regression). Read directly by perf-aggregator frictionByCategory and the retro routed-proposal extraction — never nested under details."
60
+ "description": "Top-level friction category (e.g. Execution Error, baseline-refresh-regression). Read directly by the retro routed-proposal extraction — never nested under details."
61
61
  },
62
62
  "phase": {
63
63
  "type": ["string", "null"],
@@ -0,0 +1,152 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/story-deliver-terminal.schema.json",
4
+ "title": "story-deliver-terminal",
5
+ "description": "The single terminal envelope every Story close-and-land invocation emits (Story #4543). Before this schema, the delivery tail had two divergent prose return contracts — one in .agents/workflows/helpers/deliver-story.md, a different one in .agents/agents/story-worker.md — and neither was validated by anything, so a caller could not tell a landed Story from a parked one without re-probing GitHub. This is the SSOT both now reference rather than restate. status is exactly one of landed | pending | blocked | failed; phase names where the run ended; tail carries per-step booleans so a partial-tail degradation is visible without failing an otherwise-landed merge; nextCommand names the single command that resumes or remediates the run, drawn from the same vocabulary deliver-recover.js prints.",
6
+ "type": "object",
7
+ "required": [
8
+ "kind",
9
+ "storyId",
10
+ "status",
11
+ "phase",
12
+ "elapsedSeconds",
13
+ "nextCommand"
14
+ ],
15
+ "properties": {
16
+ "kind": { "type": "string", "const": "story-deliver-terminal" },
17
+ "storyId": { "type": "integer", "minimum": 1 },
18
+ "status": {
19
+ "type": "string",
20
+ "description": "landed — the PR merged, the Story is agent::done, and the post-land tail was attempted. pending — a bounded wait expired with the PR still in flight; NO label was mutated and no merge.unlanded event was emitted, so the run is resumable via nextCommand. blocked — a classified hard block; the Story carries agent::blocked and blocked.blockClass names the class. failed — a phase crashed; phase names which one.",
21
+ "enum": ["landed", "pending", "blocked", "failed"]
22
+ },
23
+ "phase": {
24
+ "type": "string",
25
+ "description": "The pipeline phase the run ended in. Mirrors the close pipeline's phase names so a terminal envelope is attributable to one step.",
26
+ "enum": [
27
+ "init",
28
+ "wrong-tree-guard",
29
+ "close-validation",
30
+ "base-sync",
31
+ "push",
32
+ "pull-request",
33
+ "code-review",
34
+ "auto-merge",
35
+ "confirm-merge",
36
+ "post-land",
37
+ "done"
38
+ ]
39
+ },
40
+ "storyBranch": { "type": ["string", "null"] },
41
+ "baseBranch": { "type": ["string", "null"] },
42
+ "pr": {
43
+ "type": ["object", "null"],
44
+ "description": "Live PR facts as observed at terminal time. null before a PR exists (an early-phase failure). `number` is nullable for the real case where `gh pr create` returned a URL the /pull/<n> parser could not read: the PR exists and its url is known, but nothing can address it by number — including auto-merge, which is why that path reports autoMergeReason: pr-number-unparseable.",
45
+ "required": ["number"],
46
+ "properties": {
47
+ "number": { "type": ["integer", "null"], "minimum": 1 },
48
+ "url": { "type": ["string", "null"] },
49
+ "state": {
50
+ "type": ["string", "null"],
51
+ "description": "GitHub PR state as last probed (OPEN | MERGED | CLOSED)."
52
+ },
53
+ "checksStatus": {
54
+ "type": ["string", "null"],
55
+ "description": "Aggregate required-check rollup at terminal time.",
56
+ "enum": [
57
+ "success",
58
+ "pending",
59
+ "still-running",
60
+ "failure",
61
+ "unknown",
62
+ null
63
+ ]
64
+ },
65
+ "autoMergeEnabled": { "type": ["boolean", "null"] }
66
+ },
67
+ "additionalProperties": false
68
+ },
69
+ "gates": {
70
+ "type": "object",
71
+ "description": "Outcome of each close gate this invocation was responsible for. A gate the run skipped (--skip-validation, or a phase it never reached) reports \"skipped\" rather than being omitted, so a missing gate is never mistaken for a passing one.",
72
+ "additionalProperties": {
73
+ "type": "string",
74
+ "enum": ["passed", "failed", "skipped"]
75
+ }
76
+ },
77
+ "tail": {
78
+ "type": ["object", "null"],
79
+ "description": "Per-step outcomes of the post-land tail. Deliberately per-step booleans rather than one aggregate success bit: the worktree-reap defect this repo fixed existed precisely because a phase reported an outcome it never checked, and an aggregate invites that class of bug back. A false here degrades the report, never the land.",
80
+ "required": [
81
+ "followUps",
82
+ "statusResync",
83
+ "refCleanup",
84
+ "baseFastForward"
85
+ ],
86
+ "properties": {
87
+ "followUps": { "type": "boolean" },
88
+ "statusResync": { "type": "boolean" },
89
+ "refCleanup": { "type": "boolean" },
90
+ "baseFastForward": { "type": "boolean" },
91
+ "details": {
92
+ "type": "object",
93
+ "description": "Per-step diagnostic detail — the reason a false step reported false.",
94
+ "additionalProperties": { "type": ["string", "null"] }
95
+ }
96
+ },
97
+ "additionalProperties": false
98
+ },
99
+ "blocked": {
100
+ "type": ["object", "null"],
101
+ "description": "Present iff status === \"blocked\". blockClass comes from the shared classifier (merge-block-class.js) or the merged-flip-failed terminal, never an ad hoc string.",
102
+ "required": ["blockClass", "reason"],
103
+ "properties": {
104
+ "blockClass": {
105
+ "type": "string",
106
+ "enum": [
107
+ "checks-pending-timeout",
108
+ "checks-failed",
109
+ "branch-protection-human-required",
110
+ "arm-failure",
111
+ "api-race-other",
112
+ "predicate-refused",
113
+ "merged-flip-failed"
114
+ ]
115
+ },
116
+ "reason": { "type": "string", "minLength": 1 },
117
+ "frictionCommentId": {
118
+ "type": ["string", "null"],
119
+ "description": "Pointer to the friction comment carrying the operator-facing remediation."
120
+ }
121
+ },
122
+ "additionalProperties": false
123
+ },
124
+ "failure": {
125
+ "type": ["object", "null"],
126
+ "description": "Present iff status === \"failed\".",
127
+ "required": ["reason"],
128
+ "properties": {
129
+ "reason": { "type": "string", "minLength": 1 }
130
+ },
131
+ "additionalProperties": false
132
+ },
133
+ "nextCommand": {
134
+ "type": ["string", "null"],
135
+ "description": "The single command that advances this Story from where it stopped, or null when status === \"landed\" and nothing remains. Shares its vocabulary with deliver-recover.js so recovery and normal resumption speak one language."
136
+ },
137
+ "elapsedSeconds": { "type": "number", "minimum": 0 },
138
+ "waitBudget": {
139
+ "type": ["object", "null"],
140
+ "description": "Merge-wait accounting. maxWaitSeconds bounds THIS invocation (defaulting under the host's single-tool-invocation ceiling); cumulativeSeconds is anchored at the PR's createdAt so a resume does not restart the clock, and maxBudgetSeconds bounds that cumulative total.",
141
+ "properties": {
142
+ "maxWaitSeconds": { "type": "integer", "minimum": 1 },
143
+ "waitedSeconds": { "type": "number", "minimum": 0 },
144
+ "cumulativeSeconds": { "type": "number", "minimum": 0 },
145
+ "maxBudgetSeconds": { "type": "integer", "minimum": 1 }
146
+ },
147
+ "additionalProperties": false
148
+ },
149
+ "timestamp": { "type": "string", "format": "date-time" }
150
+ },
151
+ "additionalProperties": false
152
+ }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "validation-evidence",
4
4
  "title": "Validation Evidence",
5
- "description": "Per-scope record of which validation gates have passed against which commit SHA. Written by lib/validation-evidence.js under the per-Epic temp tree at temp/epic-<epicId>/validation-evidence.json (Epic-scoped) or temp/epic-<epicId>/stories/story-<storyId>/validation-evidence.json (Story-scoped). Standalone Stories (no parent Epic) use a storyId-anchored keyspace at temp/standalone/stories/story-<storyId>/validation-evidence.json. All paths are gitignored via temp/. Consumed by close-validation, epic-code-review, the acceptance self-eval critic, and /deliver Phase 3 (close-validation) to skip identical re-runs against an already-validated tree. The `storyId` field carries the scope id and equals the epic id for Epic-scoped records.",
5
+ "description": "Per-scope record of which validation gates have passed against which commit SHA. Written by lib/validation-evidence.js under the per-Epic temp tree at temp/run-<id>/validation-evidence.json (Epic-scoped) or temp/run-<id>/stories/story-<storyId>/validation-evidence.json (Story-scoped). Standalone Stories (no parent Epic) use a storyId-anchored keyspace at temp/standalone/stories/story-<storyId>/validation-evidence.json. All paths are gitignored via temp/. Consumed by close-validation, epic-code-review, the acceptance self-eval critic, and /deliver Phase 3 (close-validation) to skip identical re-runs against an already-validated tree. The `storyId` field carries the scope id and equals the epic id for Epic-scoped records.",
6
6
  "type": "object",
7
7
  "required": ["storyId", "schemaVersion", "records"],
8
8
  "properties": {
@@ -32,26 +32,20 @@
32
32
  * — this CLI is the decision + signal boundary, mirroring how the existing
33
33
  * gates separate decision from ticket mutation.
34
34
  *
35
- * Two invocation shapes (Epic #4475, M4-B):
36
- * - Per-Story (fan-out): the diff is one Story's; round scoping is per
37
- * Story off the Story's `signals.ndjson`.
38
- * - Per-AC-cluster (single delivery): `--epic <id> --cluster <clusterId>`
39
- * with NO `--story`. The verdict scores one AC cluster of the Epic's
40
- * `## Acceptance Table` against the cumulative `main..epic/<id>` diff;
41
- * round scoping is per cluster off the Epic's `signals.ndjson`. This is
42
- * the acceptance-dilution guard — `ceil(totalACs / clusterCeiling)`
43
- * independent maker-blind critic passes, one per cluster.
35
+ * One invocation shape: per-Story. The diff is one Story's; round scoping
36
+ * is per Story off the Story's `signals.ndjson`. (v2.0.0 removed the Epic
37
+ * tier along with the per-AC-cluster `--epic <id> --cluster <id>` mode that
38
+ * scored an Epic `## Acceptance Table` against a `main..epic/<id>` diff.)
44
39
  *
45
40
  * CLI:
46
- * --story <id> Story ID (required unless --cluster is given).
47
- * --epic <id> Parent Epic ID (required with --cluster).
48
- * --cluster <id> AC-cluster id for the single-delivery critic.
41
+ * --story <id> Story ID (required).
49
42
  * --verdict <path> Path to the round's verdict JSON (required).
50
43
  * --no-signal Suppress the signal emit (tests).
51
44
  *
52
45
  * Stdout: a single JSON envelope
53
46
  * { storyId, epicId, decision, round, cap, capReached, totalCriteria,
54
47
  * metCount, unmetCriteria[], signalEmitted }
48
+ * (`epicId` is retained as a always-null field for envelope stability.)
55
49
  *
56
50
  * @see .agents/scripts/lib/orchestration/acceptance-eval-decision.js
57
51
  * @see .agents/schemas/acceptance-eval-verdict.schema.json
@@ -68,10 +62,7 @@ import addFormats from 'ajv-formats';
68
62
  import { runAsCli } from './lib/cli-utils.js';
69
63
  import { getAcceptanceEval, resolveConfig } from './lib/config-resolver.js';
70
64
  import { Logger } from './lib/Logger.js';
71
- import {
72
- appendEpicSignal,
73
- appendSignal,
74
- } from './lib/observability/signals-writer.js';
65
+ import { appendSignal } from './lib/observability/signals-writer.js';
75
66
  import {
76
67
  buildAcceptanceEvalSignal,
77
68
  decideAcceptanceEval,
@@ -139,22 +130,14 @@ function parseCliArgs(argv) {
139
130
  args: argv,
140
131
  options: {
141
132
  story: { type: 'string' },
142
- epic: { type: 'string' },
143
- cluster: { type: 'string' },
144
133
  verdict: { type: 'string' },
145
134
  'no-signal': { type: 'boolean', default: false },
146
135
  },
147
136
  strict: false,
148
137
  });
149
138
  const storyId = Number.parseInt(values.story ?? '', 10);
150
- const epicRaw = Number.parseInt(values.epic ?? '', 10);
151
139
  return {
152
140
  storyId: Number.isInteger(storyId) && storyId > 0 ? storyId : null,
153
- epicId: Number.isInteger(epicRaw) && epicRaw > 0 ? epicRaw : null,
154
- clusterId:
155
- typeof values.cluster === 'string' && values.cluster.length > 0
156
- ? values.cluster
157
- : null,
158
141
  verdictPath: values.verdict ?? null,
159
142
  emitSignal: values['no-signal'] !== true,
160
143
  };
@@ -168,7 +151,6 @@ function parseCliArgs(argv) {
168
151
  *
169
152
  * @param {object} args
170
153
  * @param {number} args.storyId
171
- * @param {number | null} args.epicId
172
154
  * @param {object} args.verdict — validated verdict object.
173
155
  * @param {object} args.config — resolved `.agentrc.json`.
174
156
  * @param {boolean} args.emitSignal
@@ -182,23 +164,18 @@ function parseCliArgs(argv) {
182
164
  * @returns {Promise<{ envelope: object, exitCode: number }>}
183
165
  */
184
166
  export async function runAcceptanceEval(
185
- { storyId, epicId, clusterId = null, verdict, config, emitSignal, round },
167
+ { storyId, verdict, config, emitSignal, round },
186
168
  deps = {},
187
169
  ) {
188
170
  const {
189
171
  appendSignalFn = appendSignal,
190
- appendEpicSignalFn = appendEpicSignal,
191
172
  deriveRoundFn = deriveAcceptanceEvalRound,
192
173
  } = deps;
193
- const clusterMode =
194
- typeof clusterId === 'string' &&
195
- clusterId.length > 0 &&
196
- Number.isInteger(epicId);
197
174
  const { maxRounds } = getAcceptanceEval(config);
198
175
  const resolvedRound =
199
176
  Number.isInteger(round) && round >= 1
200
177
  ? round
201
- : deriveRoundFn({ epicId: epicId ?? null, storyId, clusterId, config });
178
+ : deriveRoundFn({ epicId: null, storyId, config });
202
179
  const outcome = decideAcceptanceEval({
203
180
  verdict,
204
181
  maxRounds,
@@ -208,21 +185,16 @@ export async function runAcceptanceEval(
208
185
  let signalEmitted = false;
209
186
  if (emitSignal) {
210
187
  const signal = {
211
- ...buildAcceptanceEvalSignal({ storyId, epicId, outcome, clusterId }),
188
+ ...buildAcceptanceEvalSignal({ storyId, epicId: null, outcome }),
212
189
  ts: new Date().toISOString(),
213
190
  };
214
191
  try {
215
- // Cluster mode (single delivery) writes to the epic-level signals
216
- // stream so per-cluster round counts survive resume; the per-Story
217
- // path writes to the Story stream (unchanged).
218
- signalEmitted = clusterMode
219
- ? await appendEpicSignalFn({ epicId, signal, config })
220
- : await appendSignalFn({
221
- epicId,
222
- storyId,
223
- signal,
224
- config,
225
- });
192
+ signalEmitted = await appendSignalFn({
193
+ epicId: null,
194
+ storyId,
195
+ signal,
196
+ config,
197
+ });
226
198
  } catch (err) {
227
199
  // Observability is best-effort — a failed signal write must never
228
200
  // take down the gate. The decision still stands.
@@ -236,8 +208,7 @@ export async function runAcceptanceEval(
236
208
 
237
209
  const envelope = {
238
210
  storyId: storyId ?? null,
239
- epicId: epicId ?? null,
240
- ...(clusterMode ? { clusterId } : {}),
211
+ epicId: null,
241
212
  decision: outcome.decision,
242
213
  round: outcome.round,
243
214
  cap: outcome.cap,
@@ -261,19 +232,11 @@ export async function runAcceptanceEval(
261
232
  }
262
233
 
263
234
  export async function main(argv = process.argv.slice(2)) {
264
- const { storyId, epicId, clusterId, verdictPath, emitSignal } =
265
- parseCliArgs(argv);
235
+ const { storyId, verdictPath, emitSignal } = parseCliArgs(argv);
266
236
 
267
- // Epic #4475 (M4-B): two invocation shapes.
268
- // - Per-Story (fan-out): --story <id> [--epic <id>].
269
- // - Per-AC-cluster (single delivery): --epic <id> --cluster <id> (no
270
- // --story); the verdict scores one AC cluster of the Epic's Acceptance
271
- // Table against the cumulative main..epic/<id> diff.
272
- const clusterMode = Boolean(clusterId) && Number.isInteger(epicId);
273
- if (!storyId && !clusterMode) {
237
+ if (!storyId) {
274
238
  throw new Error(
275
- 'Usage: node acceptance-eval.js --story <id> [--epic <id>] --verdict <path> [--no-signal]\n' +
276
- ' or: node acceptance-eval.js --epic <id> --cluster <clusterId> --verdict <path> [--no-signal]',
239
+ 'Usage: node acceptance-eval.js --story <id> --verdict <path> [--no-signal]',
277
240
  );
278
241
  }
279
242
  if (!verdictPath) {
@@ -305,13 +268,8 @@ export async function main(argv = process.argv.slice(2)) {
305
268
  const verdict = validateVerdict(parsed);
306
269
 
307
270
  // A verdict whose embedded storyId disagrees with the CLI flag is a
308
- // wiring error worth failing on, not a silent mismatch. Skipped in cluster
309
- // mode (no --story; the verdict scores an AC cluster, not a Story).
310
- if (
311
- !clusterMode &&
312
- Number.isInteger(verdict.storyId) &&
313
- verdict.storyId !== storyId
314
- ) {
271
+ // wiring error worth failing on, not a silent mismatch.
272
+ if (Number.isInteger(verdict.storyId) && verdict.storyId !== storyId) {
315
273
  throw new Error(
316
274
  `acceptance-eval: verdict storyId (${verdict.storyId}) does not match --story ${storyId}.`,
317
275
  );
@@ -320,8 +278,6 @@ export async function main(argv = process.argv.slice(2)) {
320
278
  const config = resolveConfig();
321
279
  const { envelope, exitCode } = await runAcceptanceEval({
322
280
  storyId,
323
- epicId,
324
- clusterId,
325
281
  verdict,
326
282
  config,
327
283
  emitSignal,
@@ -3,7 +3,7 @@
3
3
  * agents-bootstrap-github — Idempotent Label & Field Setup
4
4
  *
5
5
  * Creates the required label taxonomy and project board custom fields
6
- * for the v5 Epic-centric flow on a target GitHub repo. Idempotent —
6
+ * for the v5 Story-centric flow on a target GitHub repo. Idempotent —
7
7
  * skips resources that already exist.
8
8
  *
9
9
  * Usage:
@@ -45,8 +45,8 @@
45
45
  * and custom fields. Off by default — the project
46
46
  * board object is still created when a project
47
47
  * name is supplied, but decoration is skipped.
48
- * --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
49
- * and epic.yml. Off by default.
48
+ * --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml.
49
+ * Off by default.
50
50
  * --reap-conflicting-workflows Delete Projects V2 built-in workflows that
51
51
  * race against the orchestrator (destructive)
52
52
  * --help Print this help
@@ -112,7 +112,7 @@ Flags:
112
112
  --with-project-board Opt-in: provision the Projects V2 Status field
113
113
  and custom fields (default: off — prompted y/N).
114
114
  --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
115
- and epic.yml (default: off — prompted y/N).
115
+ (default: off — prompted y/N).
116
116
  --reap-conflicting-workflows Delete Projects V2 built-in workflows that
117
117
  race against the orchestrator (destructive)
118
118
  --help Print this help