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
package/.agents/README.md CHANGED
@@ -96,17 +96,17 @@ The bootstrap pipeline, in order:
96
96
  3. **Project-side mutations.** Seeds `.agentrc.json` from
97
97
  [`starter-agentrc.json`](starter-agentrc.json), merges the framework's
98
98
  runtime dependencies into `package.json`, runs the install, wires the
99
- command-sync hook (the UserPromptSubmit hook that regenerates the flat
100
- `.claude/commands/` tree so every `/<command>` loads), wires the system
101
- prompt (see below), gitignores derived artefacts, and runs the
102
- quality-gates installer.
99
+ system prompt (see below), gitignores derived artefacts, and runs the
100
+ quality-gates installer. The flat `.claude/commands/` tree is generated
101
+ at install time (via `prepare`) and on every `mandrel sync`/`update`
102
+ see [`mandrel sync-commands`](#mandrel-sync-commands) below.
103
103
  4. **GitHub-side mutations.** Creates the label taxonomy, branch protection,
104
104
  and merge-method settings. Skipped with `--skip-github`. Two additional
105
105
  mutations are **opt-in** (prompted y/N, defaulting No, or passed as flags):
106
106
  - `--with-project-board` — provision the Projects V2 Status field and
107
107
  custom fields on an existing board.
108
- - `--with-issue-forms` — generate `.github/ISSUE_TEMPLATE/story.yml` and
109
- `epic.yml` from the ticket-body schema.
108
+ - `--with-issue-forms` — generate `.github/ISSUE_TEMPLATE/story.yml`
109
+ from the ticket-body schema.
110
110
 
111
111
  The bootstrap is idempotent — safe to re-run; an already-configured
112
112
  clone produces zero file mutations.
@@ -154,6 +154,7 @@ Run `mandrel --help` for a subcommand list. Each subcommand supports
154
154
  | `init` | Install + configure mandrel in the current project (cold-start). | `--assume-yes`, `--skip-github`, `--dry-run` |
155
155
  | `sync` | Re-materialize `.agents/` from the installed package payload. | `--dry-run` |
156
156
  | `sync-commands` | Regenerate `.claude/commands/` from `.agents/workflows/`. | — |
157
+ | `sync-agents` | Regenerate `.claude/agents/` from `.agents/agents/`. | — |
157
158
  | `doctor` | Run readiness checks and print per-check remedies. | — |
158
159
  | `update` | Upgrade mandrel to the newest published version. | `--dry-run`, `--install-cmd` |
159
160
  | `migrate` | Apply version-keyed migrations for a version range. | `--from`, `--to`, `--dry-run` |
@@ -175,13 +176,27 @@ mandrel explain --json # same report as JSON
175
176
  ### `mandrel sync-commands`
176
177
 
177
178
  Regenerates the flat `.claude/commands/` projection from `.agents/workflows/`.
178
- The bootstrap wires a `UserPromptSubmit` hook that runs this automatically on
179
- every Claude Code prompt submission, so manual runs are rarely needed.
179
+ Runs automatically at install time (via the `prepare` script) and as part of
180
+ `mandrel sync` / `mandrel update`; doctor's `commands-in-sync` check flags a
181
+ hand-edited or stale tree. Refuses to project when the materialized `.agents/`
182
+ tree doesn't match the running CLI's own version — run `mandrel sync` first.
180
183
 
181
184
  ```bash
182
185
  mandrel sync-commands # rebuild .claude/commands/
183
186
  ```
184
187
 
188
+ ### `mandrel sync-agents`
189
+
190
+ Regenerates the flat `.claude/agents/` projection from `.agents/agents/` —
191
+ the role-scoped boot contexts (`story-worker`, `acceptance-critic`) that
192
+ `delivery.routing.roleScopedAgents` (default `true`) dispatches spawns
193
+ against. Same delegation shape, wiring, and version-match refusal as
194
+ `sync-commands` above.
195
+
196
+ ```bash
197
+ mandrel sync-agents # rebuild .claude/agents/
198
+ ```
199
+
185
200
  ### `mandrel uninstall`
186
201
 
187
202
  Reverses a recorded install using the install ledger
@@ -247,6 +262,13 @@ read-when-relevant pattern skills use).
247
262
  [`rules/test-seams.md`](rules/test-seams.md)) — when the task is in that
248
263
  domain.
249
264
  - Every `SKILL.md` under [`skills/`](skills/) — when the task hits its trigger.
265
+ A `SKILL.md` is itself split the same way: it leads with its **Policy
266
+ Capsule** (the contract, and the whole cost of activating the skill) plus
267
+ pointers into an on-demand `reference.md` sibling carrying the long-form
268
+ material. Activating a skill costs the capsule, not the essay — open a
269
+ `reference.md` section only when the task engages it. Routing does not
270
+ depend on the long-form being inline: skill descriptions live in the
271
+ generated [`skills/skills.index.json`](skills/skills.index.json).
250
272
  - [`docs/execution-reference.md`](docs/execution-reference.md) — log-level and
251
273
  token-budget reference detail lifted out of `instructions.md`.
252
274
 
@@ -280,10 +302,10 @@ For non-interactive (CI) installs, pass `--owner`, `--repo`, and
280
302
  `--assume-yes`; pass `--skip-github` to defer the remote half.
281
303
 
282
304
  After bootstrap, every Mandrel command is generated into a flat
283
- `.claude/commands/` tree by `npm run sync:commands` (the UserPromptSubmit hook
284
- keeps it current) and loads as a bare `/<command>` slash command — e.g.
285
- `/plan`, `/deliver`, `/audit-security`. The commands load in every Claude Code
286
- environment. The [SDLC guide](docs/SDLC.md) walks end-to-end planning and
305
+ `.claude/commands/` tree by `npm run sync:commands` (kept current at install
306
+ time and on every `mandrel sync`/`update`) and loads as a bare `/<command>`
307
+ slash command — e.g. `/plan`, `/deliver`, `/audit-security`. The commands load
308
+ in every Claude Code environment. The [SDLC guide](docs/SDLC.md) walks end-to-end planning and
287
309
  delivery; Stories pair [`/plan`](workflows/plan.md) (idea → drafted Story Issue)
288
310
  with [`/deliver`](workflows/deliver.md) (Story Issue → merged
289
311
  PR).
@@ -408,9 +430,9 @@ rule:
408
430
  > GitHub I/O, label transitions, JSON validators, NDJSON readers,
409
431
  > diff-vs-baseline gates, template renderers.
410
432
  >
411
- > **Prompt + judgment → make it a Skill.** Examples: composing a Tech
412
- > Spec from an Epic body, classifying friction signals from a failed shell
413
- > command, decomposing a Tech Spec into a ticket hierarchy.
433
+ > **Prompt + judgment → make it a Skill.** Examples: composing a Story's
434
+ > `## Spec` from planning context, classifying friction signals from a
435
+ > failed shell command, decomposing a Spec into Stories.
414
436
 
415
437
  The rule is two-sided on purpose. "Has an LLM step adjacent" is *not*
416
438
  the signal — many deterministic scripts emit a JSON envelope that a host
@@ -424,17 +446,18 @@ The collapsed plan pipeline (`plan-context.js` → author → `plan-persist.js`,
424
446
  Epic #4474) is a **split**: the deterministic halves stay as scripts, the
425
447
  judgment middle moves to a Skill.
426
448
 
427
- - **`--emit-context`** (script half) — fetches the Epic body (which
428
- carries the folded Tech Spec sections), scrapes project docs, emits a
429
- JSON envelope. Parseable in, parseable out. Stays a script.
449
+ - **`--emit-context`** (script half) — fetches the seed/source tickets
450
+ and scrapes project docs, emits a JSON envelope. Parseable in,
451
+ parseable out. Stays a script.
430
452
  - **Authoring middle** (Skill half) — given the envelope, author the
431
- ticket hierarchy JSON. Pure prompt + judgment. Migrates to a Skill
453
+ Story JSON. Pure prompt + judgment. Migrates to a Skill
432
454
  under `.agents/skills/core/` so it ships with declarative
433
455
  `allowed_tools` and a smoke test rather than bespoke prompt-template
434
456
  plumbing inside a Node module.
435
457
  - **Persist half** (script half) — given the author-provided tickets
436
- JSON, validate against the schema, create GitHub issues, flip the Epic
437
- label. Deterministic GitHub I/O + schema validation. Stays a script.
458
+ JSON, validate against the schema, create the `type::story` issue(s)
459
+ and label them `agent::ready`. Deterministic GitHub I/O + schema
460
+ validation. Stays a script.
438
461
 
439
462
  The split codifies the "host LLM authors directly" pattern explicitly:
440
463
  the prompt+judgment step gets a `description`, an
@@ -524,8 +547,8 @@ comment) is the cross-runtime contract.
524
547
  The SDK barrel is `scripts/lib/orchestration/index.js`; its exports are
525
548
  the source of truth for the public in-process surface. Key families
526
549
  include dispatch (`dispatch-engine.js`, `manifest-builder.js`), context
527
- hydration, planning state, label transitions, Epic runner phases,
528
- Story-close internals, retro heuristics, and structured error capture.
550
+ hydration, planning state, label transitions, Story-close internals,
551
+ retro proposals, and structured error capture.
529
552
 
530
553
  ### GitHub authentication
531
554
 
@@ -578,7 +601,7 @@ environment inside the check. A finding includes `id`, `severity`,
578
601
  `autoCorrectable`.
579
602
 
580
603
  `autoCorrect: 'auto'` means the fix is local, bounded, and reversible.
581
- Auto-fixes must not push to remotes, commit to `epic/*` or `main`, amend
604
+ Auto-fixes must not push to remotes, commit to `main`, amend
582
605
  history, recursively delete outside `.worktrees/<id>/`, write GitHub
583
606
  state, or read secret values. Anything requiring those operations must be
584
607
  `refuse-and-print` with a human-run `fixCommand`.
@@ -828,7 +851,7 @@ Two operators can drive the same repository at once — for example, two
828
851
  runs from clobbering one another with **two distinct coordination layers**.
829
852
  They solve different problems and must not be confused:
830
853
 
831
- - **Filesystem locks** (`epic-merge-lock`, `sweep-lock`) serialise work
854
+ - **Filesystem locks** (`sweep-lock`) serialise work
832
855
  **within a single machine/clone**. They are keyed on local process PIDs
833
856
  and live under `.git/` (or a local lockfile path), so they do **not**
834
857
  coordinate across clones. See
@@ -844,8 +867,16 @@ The lease primitive lives in
844
867
  [`scripts/lib/orchestration/ticket-lease.js`](scripts/lib/orchestration/ticket-lease.js).
845
868
  Rather than inventing a new state column, the lease rides the ticket's
846
869
  existing **assignees** field: the single assignee *is* the lease owner.
847
- Liveness is decided by the owner's most-recent `story.heartbeat` timestamp
848
- compared against a configurable TTL (`delivery.lease.ttlMs`).
870
+ Liveness is decided by the owner's last-heartbeat timestamp compared against
871
+ a configurable TTL (`delivery.lease.ttlMs`).
872
+
873
+ > **In practice the lease always fails closed.** There is no live heartbeat
874
+ > source — the `story.heartbeat` emitter was structurally inert and has been
875
+ > deleted (A22) — so every guard anchors the owner's heartbeat to *now*,
876
+ > making **any** foreign claim read as live. The **stale-claim reclaim** row
877
+ > below is therefore unreachable in normal operation: a stranded claim is
878
+ > cleared with `--steal`, never by TTL expiry. The TTL and the reclaim branch
879
+ > remain as a seam for a caller that supplies its own `heartbeatAt`.
849
880
 
850
881
  The model has five behaviours, all expressed through `acquireLease` /
851
882
  `releaseLease`:
@@ -855,7 +886,7 @@ The model has five behaviours, all expressed through `acquireLease` /
855
886
  | **Acquire by self-assign** | The ticket is unassigned. | The operator is written to `assignees`; the run proceeds (`reason: 'unclaimed'`). |
856
887
  | **Re-affirm a self-held claim** | The operator already holds the lease. | No write; the run proceeds (`reason: 'already-held'`). |
857
888
  | **Refuse-if-foreign** | A *different* operator holds the lease and their heartbeat is within the TTL (the claim is **live**). | The acquire **fails closed** — the run refuses to start and names the current owner so you know who to coordinate with (`reason: 'held'`). |
858
- | **Stale-claim reclaim** | A foreign claim exists but its heartbeat is older than the TTL (or the owner never heartbeated). | The lease is automatically reassigned to the operator (`reason: 'reclaimed'`). An abandoned claim never wedges the ticket. |
889
+ | **Stale-claim reclaim** *(unreachable — see above)* | A foreign claim exists but the caller supplied a `heartbeatAt` older than the TTL. | The lease is reassigned to the operator (`reason: 'reclaimed'`). No shipped caller supplies one, so this never fires today. |
859
890
  | **`--steal` override** | A foreign claim is *live* and the operator passes `--steal`. | The live claim is forcibly transferred (`reason: 'stolen'`). This is the **only** way past a live foreign claim. |
860
891
 
861
892
  On a clean completion the holder **releases** the lease (clears the
@@ -4,8 +4,9 @@ description: >-
4
4
  Role-scoped boot context for a maker-blind acceptance critic. Booted on its
5
5
  own system prompt (no CLAUDE.md / instructions.md closure). Scores a delivered
6
6
  diff against the Story's acceptance-criteria cluster and emits the verdict
7
- schema — without seeing the maker's self-assessment. INERT under M7-A no
8
- workflow references this agent type yet (that is M7-B).
7
+ schema — without seeing the maker's self-assessment. Live under M7-B
8
+ helpers/deliver-story Step 1a dispatches subagent_type: acceptance-critic
9
+ on the default risk-routed path.
9
10
  ---
10
11
 
11
12
  # acceptance-critic — maker-blind acceptance evaluation
@@ -34,8 +35,11 @@ file they authored. You grade the **work product**, not the homework the maker
34
35
  turned in about it. Your only trusted inputs are:
35
36
 
36
37
  - the working **diff** (`git diff origin/<baseBranch>...HEAD`),
37
- - the Story's inline `acceptance[]` and `verify[]` arrays (from the
38
- `story-init` structured comment: `context.acceptance` / `context.verify`),
38
+ - the Story's inline `acceptance[]` and `verify[]` arrays, read from the
39
+ **Story body itself** (`gh issue view <storyId> --json body`) — its `##
40
+ Acceptance` / `## Verify` sections are the SSOT. The `story-init` structured
41
+ comment does not carry them: it reports init state (`workCwd`,
42
+ `dependenciesInstalled`, `remoteVerified`, …) and nothing else.
39
43
  - the **actual output** of the `verify[]` commands you run yourself.
40
44
 
41
45
  Treat the implementation reasoning as untrusted. Score each criterion afresh
@@ -66,12 +70,10 @@ For each acceptance item in your cluster:
66
70
  a passing run records an evidence entry in the keyspace close consults:
67
71
 
68
72
  ```bash
69
- # Epic-attached Story:
70
73
  node <main-repo>/.agents/scripts/evidence-gate.js \
71
- --epic-id <epicId> --scope-id <storyId> --gate lint \
74
+ --standalone --scope-id <storyId> --gate lint \
72
75
  --worktree <worktree> -- npm run lint
73
76
 
74
- # Standalone Story (no parent Epic): use --standalone, omit --epic-id.
75
77
  node <main-repo>/.agents/scripts/evidence-gate.js \
76
78
  --standalone --scope-id <storyId> --gate typecheck \
77
79
  --worktree <worktree> -- <resolved typecheck command>
@@ -3,8 +3,8 @@ name: story-worker
3
3
  description: >-
4
4
  Role-scoped boot context for a single Story delivery child, booted on its own
5
5
  system prompt (no CLAUDE.md / instructions.md closure). Carries the
6
- load-bearing delivery MUSTs standalone. INERT under M7-A — no workflow
7
- references this agent type yet (that is M7-B).
6
+ load-bearing delivery MUSTs standalone. Dispatched by helpers/deliver-story
7
+ when delivery.routing.roleScopedAgents is enabled (the default).
8
8
  ---
9
9
 
10
10
  # story-worker — Story delivery boot context
@@ -44,10 +44,10 @@ You run as a sub-agent with **no input channel** mid-run.
44
44
  the **main checkout** (the worktree does not exist yet). Invoke it
45
45
  **synchronously** with the Bash maximum timeout — a per-worktree install can
46
46
  take several minutes; do not background it.
47
- 2. Capture `workCwd`, `dependenciesInstalled`, and `context.parentId` from the
48
- init envelope. When worktree isolation is on, `cd` into the printed
49
- **absolute** `workCwd` before doing any implementation work. The main
50
- checkout's HEAD is never moved by you.
47
+ 2. Capture `workCwd` and `dependenciesInstalled` from the init envelope (it
48
+ is flat — there is no `context` block). When worktree isolation is on, `cd`
49
+ into the printed **absolute** `workCwd` before doing any implementation
50
+ work. The main checkout's HEAD is never moved by you.
51
51
  3. Every subsequent command runs against that worktree path. Because cwd may
52
52
  reset between calls, prefer absolute paths anchored at `workCwd`.
53
53
 
@@ -60,8 +60,7 @@ git -C "<workCwd>" branch --show-current # MUST print story-<storyId>
60
60
  ```
61
61
 
62
62
  If it does **not** report `story-<storyId>`, **STOP** — do not commit. Never
63
- commit Story work to `main`, to an Epic branch directly, or outside the
64
- worktree/branch. Re-run `single-story-init.js` (it is idempotent on partial state) to
63
+ commit Story work to `main` or outside the worktree/branch. Re-run `single-story-init.js` (it is idempotent on partial state) to
65
64
  restore the branch before proceeding.
66
65
 
67
66
  ## Commit discipline
@@ -79,7 +78,7 @@ Author commits directly on `story-<storyId>` following the always-on git core
79
78
  ## Docs context — digest first
80
79
 
81
80
  Do **not** re-read every file in `project.docsContextFiles`. Your caller passes
82
- a `docsDigestPath` (the per-Epic docs digest — a compact per-file outline:
81
+ a `docsDigestPath` (the per-run docs digest — a compact per-file outline:
83
82
  path, size, heading outline with line numbers, first paragraph under each
84
83
  `##`). Read that digest, decide which docs bear on this Story, then **pull the
85
84
  full file on demand** (jump to the section at the line number the digest names)
@@ -89,9 +88,9 @@ mandate — read a full doc only if the Story's own context points you at one.
89
88
 
90
89
  ## Close gates — do not pre-run
91
90
 
92
- `story-close.js` runs the canonical close-validation chain (**typecheck, lint,
93
- test, format, maintainability, coverage, crap**) before it merges. Do **not**
94
- pre-run those gates as a matter of course — running `npm run typecheck &&
91
+ `single-story-close.js` runs the canonical close-validation chain (**typecheck,
92
+ lint, test, format, maintainability, coverage, crap**) before it merges. Do
93
+ **not** pre-run those gates as a matter of course — running `npm run typecheck &&
95
94
  npm run lint && npm test` as advisory pre-flight while iterating on a fix is
96
95
  fine, but the close pipeline is the authoritative gate. The bounded acceptance
97
96
  self-eval loop (below) may share `lint` / `typecheck` evidence with close via
@@ -110,21 +109,16 @@ scores the working diff against **each** `acceptance[]` item and consumes the
110
109
  - **`block`** (round cap reached, criteria still unmet) → take the blocked path.
111
110
  Never silently proceed to close.
112
111
 
113
- ## Lifecycle: heartbeat & blocked (MUST)
114
-
115
- - **Heartbeat.** Emit a `story.heartbeat` lifecycle event on every phase
116
- transition (or when you stall on a long-running step) so the parent
117
- `/deliver` idle watchdog can tell a live child from a dead one. In practice
118
- this is the `story-run-progress` structured comment (via
119
- `post-structured-comment.js` / the close pipeline) at each transition;
120
- write it at every transition, and relay one terse line per transition
121
- (e.g. `Story #<id>: implementing closing`), not the full body.
122
- - **Blocked.** If you genuinely cannot proceed, flip the snapshot to `blocked`,
123
- transition the Story to `agent::blocked`, post a `friction` comment naming
124
- the decision needed (or the unmet criteria and their evidence), and **exit
125
- non-zero**. **Never fall silent** — a child with no heartbeat, no commit, and
126
- no `agent::blocked` label is exactly the dead-child failure the watchdog is
127
- built to catch.
112
+ ## Lifecycle: progress & blocked (MUST)
113
+
114
+ - **Progress.** Relay one terse line per phase transition (e.g.
115
+ `Story #<id>: implementing closing`), not a full body. Your commits on
116
+ `story-<id>` and these lines are the progress surface.
117
+ - **Blocked.** If you genuinely cannot proceed, transition the Story to
118
+ `agent::blocked`, post a `friction` comment naming the decision needed (or
119
+ the unmet criteria and their evidence), and **exit non-zero**.
120
+ **Never fall silent** a child that stalls without an `agent::blocked`
121
+ label and no commit is indistinguishable from a dead one.
128
122
  - **Anti-thrashing.** If you hit the same error class twice with the same fix,
129
123
  or drift through reads without narrowing the problem, STOP: summarize what
130
124
  recurred and either re-plan or take the blocked path. Do not paper over a
@@ -136,26 +130,27 @@ The Story's init envelope carries `remoteVerified` + `remoteProbe`. When
136
130
  `remoteVerified` is `false`, transition the Story to `agent::blocked` quoting
137
131
  `remoteProbe.detail` and stop. Implementing the Story inline outside the
138
132
  worktree / branch / PR path — or committing it to local `main` — is expressly
139
- **forbidden**. The close pipeline's push (`story-close.js`) is the only
133
+ **forbidden**. The close pipeline's push (`single-story-close.js`) is the only
140
134
  sanctioned way the work lands.
141
135
 
142
136
  ## Return schema
143
137
 
144
- Your authoritative status is the `story-run-progress` snapshot comment that
145
- the deliver/close pipeline upserts at each transition — the parent
146
- `/deliver` aggregator reads that, not your chat. On completion, return a
147
- compact JSON object naming the terminal state and evidence:
148
-
149
- ```json
150
- {
151
- "storyId": "<storyId>",
152
- "state": "done | blocked",
153
- "branch": "story-<storyId>",
154
- "prUrl": "<url or null>",
155
- "gates": { "acceptanceEval": "proceed | block", "close": "passed | n/a" },
156
- "blockedReason": "<null, or the friction summary when state=blocked>"
157
- }
158
- ```
159
-
160
- Exit zero only when the Story reached `agent::done` (merged/landed via the
161
- close pipeline). Exit non-zero on any blocked terminus.
138
+ Your return contract is
139
+ [`story-deliver-terminal.schema.json`](../schemas/story-deliver-terminal.schema.json)
140
+ the SSOT for every field (Story #4543). Fields are deliberately not
141
+ restated here; that duplication is what drifted.
142
+
143
+ `single-story-close.js` emits a validated envelope between its
144
+ `--- STORY DELIVER TERMINAL ---` markers. **Relay it**; never hand-compose
145
+ one. Its `status` is one of four; your exit code mirrors it:
146
+
147
+ - `landed` → 0. Merged, `agent::done`, tail attempted (a `false` in `tail.*`
148
+ degrades the report, not the land).
149
+ - `pending` 3. **Resumable, not a failure** the bounded merge wait
150
+ expired with the PR healthy, or a human owns the merge. Nothing was
151
+ mutated; `nextCommand` resumes it. The only sanctioned no-merge ending.
152
+ - `blocked` / `failed` → exit non-zero. Take the blocked path above.
153
+
154
+ Stranded? Probe, don't guess:
155
+ `node .agents/scripts/deliver-recover.js --story <id>` (read-only, prints
156
+ one next command).
@@ -6,7 +6,7 @@
6
6
 
7
7
  # Performance & Bottleneck Audit — authoring checklist
8
8
 
9
- > Audit hot paths, algorithmic complexity, and I/O bottlenecks in the tooling surface (`epic-close`, dispatcher, gates); propose remediations.
9
+ > Audit hot paths, algorithmic complexity, and I/O bottlenecks in the tooling surface (`single-story-close`, dispatcher, gates); propose remediations.
10
10
 
11
11
  Self-check your change against this lens's concerns before you ship:
12
12
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Mandrel uses **Story-centric GitHub orchestration** — GitHub Issues,
4
4
  Labels, and Projects V2 are the Single Source of Truth. Plans persist as
5
- `type::story` tickets (optionally grouped by a `plan-run::<id>` label);
5
+ `type::story` tickets ordered by `depends_on` edges;
6
6
  each Story is delivered on its own `story-<id>` branch and reaches `main`
7
7
  through its own PR.
8
8
 
@@ -49,19 +49,23 @@ From zero to shipped:
49
49
  probe, risk heuristics, `systemPrompts.story`). Duplicate review
50
50
  folds into **gate #1**.
51
51
  2. **Author** — write `stories.json` (**one Story by default**) with a
52
- folded Tech Spec in `## Spec` / `## Slicing`, plus
53
- `risk-verdict.json` (axes + summary only — no `deliveryShape`).
52
+ folded Tech Spec in `## Spec` / `## Slicing`. There is no risk artifact
53
+ to author (Story #4542).
54
54
  Binding criteria live in top-level `acceptance[]` / `verify[]`;
55
55
  changes/references are `{ path, assumption }` objects. Split into
56
56
  N>1 only under the default-single split policy.
57
- 3. **Persist** — **gate #2** (risk-routed; typically skipped for N=1
58
- low-risk) then `plan-persist.js` runs every deterministic gate and
59
- creates Story issue(s) with `type::story` + `agent::ready` (plus a
60
- shared `plan-run::<id>` label when N>1).
57
+ 3. **Persist** — **gate #2** (raised only by an explicit `--force-review`)
58
+ then `plan-persist.js` runs every deterministic gate and
59
+ creates Story issue(s) with `type::story` + `agent::ready`, writing
60
+ each authored `depends_on` edge into the sibling body as a
61
+ `blocked by #<id>` footer when N>1.
61
62
 
62
63
  2. **Deliver the Story.** Run [`/deliver <storyId>`](../workflows/deliver.md)
63
- (or `/deliver <a> <b> …`, or `/deliver --run <planRunId>` for a
64
- multi-Story plan-run) in your IDE. `/deliver` owns input resolution and
64
+ (or `/deliver <a> <b> …` for several) in your IDE. `/deliver` takes
65
+ only Story ids and resolves their dependency graph from live state —
66
+ body edges union native GitHub `blocked_by` edges, with every blocker
67
+ checked against its real issue state, so a Story whose blocker landed in
68
+ an earlier plan run is simply ready. `/deliver` owns input resolution and
65
69
  `depends_on` sequencing only — every Story runs through
66
70
  [`helpers/deliver-story`](../workflows/helpers/deliver-story.md), the
67
71
  single v2 delivery engine. Per-Story it:
@@ -72,11 +76,12 @@ From zero to shipped:
72
76
  2. **Implement** — the agent delivers the Story in one guarded session
73
77
  against its inline `acceptance[]` / `verify[]` contract (optional
74
78
  `## Slicing` intra-session checkpoints).
75
- 3. **Acceptance self-eval** — a bounded, risk-routed critic loop scores
76
- the working diff against each acceptance item before close (see
79
+ 3. **Acceptance self-eval** — a bounded critic loop scores the working
80
+ diff against each acceptance item before close (see
77
81
  [`helpers/acceptance-self-eval`](../workflows/helpers/acceptance-self-eval.md)).
78
- 4. **Ceremony** — risk-routed acceptance critics, review depth, and
79
- audit lenses (`ceremony-routing.js`).
82
+ 4. **Ceremony** — acceptance critic mode and review depth, both routed off
83
+ the change level derived from the Story's own diff
84
+ (`review-depth.js#deriveChangeLevel` → `ceremony-routing.js`).
80
85
  5. **Close** (`single-story-close.js`) — runs close-validation gates,
81
86
  the maker-blind Story-scope code review, pushes `story-<id>`, opens
82
87
  a PR to `main`, and (under the default `delivery.ci.autoMerge:
@@ -88,7 +93,7 @@ From zero to shipped:
88
93
  `MERGED` PR the Story flips to `agent::done`; local branch cleanup
89
94
  and Projects-v2 Status re-assert run out-of-band.
90
95
 
91
- For a multi-Story plan-run, `/deliver` sequences ready Stories by
96
+ For a multi-Story run, `/deliver` sequences ready Stories by
92
97
  `depends_on` and runs the per-run epilogue (audit roster · follow-up
93
98
  roll-up · sibling coherence) once after the last Story lands.
94
99
 
@@ -105,8 +110,8 @@ rather than re-documenting the ceremony they own.
105
110
  - **Layered state stores with explicit precedence.** Ticket status lives
106
111
  in GitHub Issues and Labels; the lifecycle bus
107
112
  (`temp/run-<id>/lifecycle.ndjson`) is the canonical resume target for
108
- in-flight runs; structured comments (`story-run-progress`,
109
- `verification-results`, retro) are the operator-visible rollup. The
113
+ in-flight runs; structured comments (`verification-results`, retro) are
114
+ the operator-visible rollup. The
110
115
  stores, their owners, and their conflict-resolution rules are listed in
111
116
  [§ State stores](#state-stores) — that matrix is the single source of
112
117
  truth for "who owns which write."
@@ -149,9 +154,8 @@ on-disk layout resolved by
149
154
  | State Store | Owner (canonical writer) | Mutation API | Idempotency key | Conflict resolution |
150
155
  | --- | --- | --- | --- | --- |
151
156
  | GitHub labels | `transitionTicketState` via `ticketing.js` | `gh issue edit --add-label / --remove-label`, wrapped in `update-ticket-state.js` | `(ticketId, label-set)` — set-equality before write | Authoritative for current ticket lifecycle state; if a label disagrees with the lifecycle ledger, the **ledger wins on resume** and the label is re-derived. |
152
- | `story-run-progress` comment | `story-phase.js` (per Story, per phase transition) | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='story-run-progress')` | Authoritative for Story-level phase progress. |
153
157
  | `verification-results` comment | `lib/orchestration/code-review.js` | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='verification-results')` | Authoritative for the Story-scope review + lens findings; critical findings block close. |
154
- | Lifecycle ledger NDJSON | `lifecycle-emit.js` (single append-only writer per run) | Append-only line write to `temp/run-<id>/lifecycle.ndjson` | `(runId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived. |
158
+ | Lifecycle ledger NDJSON | `LedgerWriter` (`lib/orchestration/lifecycle/ledger-writer.js`, registered as the first listener on every bus event — single append-only writer per run) | Append-only line write to `temp/run-<id>/lifecycle.ndjson` | `(runId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived. |
155
159
  | Validation evidence cache | `evidence-gate.js` | JSON cache file under the run temp tree, keyed by HEAD SHA | `(gate, git rev-parse HEAD)` | Pure cache: a missing entry triggers a re-run; presence is a fast-path skip. Cache eviction is safe. |
156
160
  | PR / auto-merge state | `single-story-close.js` (sole authorized caller of `gh pr merge`) | `gh pr merge --auto --squash --delete-branch`; PR open via the close pipeline's `gh pr create` | `(prNumber, head-branch SHA)` — `gh pr list --head` probes before create | GitHub is authoritative for PR + auto-merge arming state; the ledger records the *intent* to arm, GitHub records the outcome. |
157
161
  | Worktree cleanup state | `WorktreeManager.reap` (via `single-story-close.js` / `git-cleanup.js`) | `git worktree remove` + on-disk pending-cleanup JSON under the run temp tree | `(storyId, worktree-path)` | Filesystem is authoritative for "is the worktree gone?"; the pending-cleanup JSON only tracks stale-registry entries needing a follow-up sweep. |
@@ -180,12 +184,12 @@ graph LR
180
184
  A["👤 /plan --seed | --seed-file | --tickets"]:::manual
181
185
  B["🤖 interrogate → author → persist"]:::agentic
182
186
  A --> B
183
- B -.-> B_Art["📄 type::story issue(s)<br/>(+ optional plan-run::&lt;id&gt;)"]:::artifact
187
+ B -.-> B_Art["📄 type::story issue(s)<br/>(+ depends_on edges)"]:::artifact
184
188
  end
185
189
 
186
190
  subgraph Phase2 ["Phase 2: Deliver"]
187
191
  direction TB
188
- E["👤 /deliver &lt;storyId&gt;<br/>(or --run &lt;planRunId&gt;)"]:::manual
192
+ E["👤 /deliver &lt;storyId&gt; [&lt;storyId&gt;…]"]:::manual
189
193
  F["🤖 deliver-story: story-&lt;id&gt; from main<br/>implement → self-eval → ceremony → close"]:::agentic
190
194
  G["🤖 close-validation → code-review → open PR"]:::agentic
191
195
  E --> F --> G
@@ -267,7 +271,7 @@ the SDLC depends on:
267
271
  - **One Story by default.** `/plan` authors a single `type::story` issue
268
272
  whose body carries a folded `## Spec` (inline only — never spilled to
269
273
  `docs/`) plus top-level `acceptance[]` / `verify[]`. It splits into N>1
270
- siblings (sharing a `plan-run::<id>` label + `depends_on` edges) **only**
274
+ siblings (ordered by `depends_on` edges) **only**
271
275
  under the default-single split policy: near-zero overlap or a genuine
272
276
  architectural seam. Coupled work stays one Story and is decomposed inside
273
277
  `## Slicing` as intra-session checkpoints, not sibling tickets.
@@ -278,8 +282,7 @@ the SDLC depends on:
278
282
  `assertAcceptancePartition` so every acceptance criterion belongs to
279
283
  exactly one Story.
280
284
  - **Handoff.** Persist creates the Story issue(s) at `agent::ready` and
281
- names the delivery command: `/deliver <storyId>` (or `/deliver --run
282
- <planRunId>`).
285
+ names the delivery command: `/deliver <storyId> [<storyId> ...]`.
283
286
 
284
287
  Optional split advisory notes come from
285
288
  [`core/scope-triage`](../skills/core/scope-triage/SKILL.md); there is no
@@ -308,8 +311,7 @@ self-eval, ceremony, close, CI watch, confirm-merge, cleanup) lives in the
308
311
  | Mode | Entry point | When to use |
309
312
  | --- | --- | --- |
310
313
  | **Single Story** | `/deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
311
- | **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**); each lands through its own PR. |
312
- | **Plan-run** | `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue after the set lands. |
314
+ | **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**), resolved from live state so edges may point at Stories from earlier plan runs; each lands through its own PR, and the per-run epilogue runs after the set lands. |
313
315
  | **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/deliver`; not an operator slash command. |
314
316
 
315
317
  The single operator-facing entry point is `/deliver`. It performs no
@@ -374,14 +376,14 @@ Concurrent runs are serialised by **two distinct layers**:
374
376
  assignee; `--steal` is the only override. See
375
377
  [`README.md` § Multi-developer coordination](../README.md#multi-developer-coordination).
376
378
 
377
- ### Concurrent close — push retry
379
+ ### Concurrent close
378
380
 
379
381
  `single-story-close.js` syncs the Story branch from `origin/main` before
380
- pushing and opening/locating the PR. Bounded retry constants live in
381
- `.agents/scripts/lib/config/runners.js` (`DEFAULT_STORY_MERGE_RETRY`:
382
- 3 attempts, `[250, 500, 1000]` ms backoff). A real content conflict aborts
383
- the loop with a clear error, leaves the tree clean, and exits non-zero for
384
- manual resolution.
382
+ pushing and opening/locating the PR, so concurrent closes serialize through
383
+ their own worktrees rather than racing one shared branch. The push does not
384
+ retry: a rejected push, or a real content conflict at base-sync, aborts with
385
+ a clear error, leaves the tree clean, and exits non-zero for manual
386
+ resolution.
385
387
 
386
388
  ---
387
389
 
@@ -486,14 +488,18 @@ pass — the tiers below *are* the audit machinery.
486
488
  | --- | --- | --- | --- |
487
489
  | Tier 1 — write-time | During Story implementation | Footprint-matched **local**-lens authoring checklists threaded into the Story prompt (`checklistPath`) | advisory |
488
490
  | Tier 2 — Story-scope | `single-story-close.js` (maker-blind subprocess) | Local-tier lens roster over the Story diff (`selectLocalLenses`) + review pillars, posted as `verification-results` | blocking on 🔴 |
489
- | Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global + risk-routed lenses (`selectAudits` / `resolveAuditLenses`) over the combined landed tip | blocking |
491
+ | Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global lenses (`selectAudits`) over the combined landed tip | blocking |
490
492
 
491
493
  - **`local`** lenses (decidable from a single Story's diff) are verified at
492
494
  Tiers 1–2 and are **not** re-run at run closeout.
493
- - **`cumulative`** lenses (only decidable across a plan-run's combined diff)
495
+ - **`cumulative`** lenses (only decidable across a run's combined diff)
494
496
  and **`global`** lenses (whole-product properties) are verified at Tier 3.
495
- - **Risk-routed** lenses run regardless of tier when a high-risk axis (or a
496
- route-adding change set) demands them.
497
+
498
+ There is no risk-routed lens tier. Story #4542 deleted the risk→lens router:
499
+ it had zero callers while this document claimed it ran inside close. Lens
500
+ selection is change-set-matched (`selectAudits` / `selectLocalLenses`); the
501
+ `sensitivePaths` classes in `audit-rules.json` route review **depth**, not
502
+ lenses.
497
503
 
498
504
  The run-closeout roster is deliberately **slim**: it excludes every
499
505
  local-tier change-set lens so the outermost tier — where a fix is most
@@ -504,8 +510,8 @@ expensive — does not re-verify a concern already covered shift-left.
504
510
  The Story-scope code review runs **outside the maker's context**, inside
505
511
  the `single-story-close.js` close subprocess, over `main...story-<id>`
506
512
  (see [`helpers/code-review.md`](../workflows/helpers/code-review.md)). It
507
- walks the Story diff once, executing the risk-routed lens roster as review
508
- dimensions alongside the review pillars, and posts the unified
513
+ walks the Story diff once, executing the change-set-matched local lens roster
514
+ as review dimensions alongside the review pillars, and posts the unified
509
515
  `verification-results` comment. Remediation is tier-aware and split by
510
516
  finding class off `delivery.codeReview.autoFixSeverity` (default `medium`);
511
517
  surviving 🔴 Critical findings halt the run. The legacy `scope: epic`
@@ -513,12 +519,14 @@ Epic-branch review path was removed with the v2 cutover.
513
519
 
514
520
  ### Quality ratchets
515
521
 
516
- - **Maintainability ratchet** (`check-maintainability.js`) — fails if the
522
+ - **Maintainability ratchet** (`check-baselines.js` via
523
+ `lib/baselines/kinds/maintainability.js`) — fails if the
517
524
  composite score drops below the established baseline.
518
- - **CRAP gate** (`check-crap.js`) — per-method complexity × coverage risk
525
+ - **CRAP gate** (`check-baselines.js` via `lib/baselines/kinds/crap.js`) —
526
+ per-method complexity × coverage risk
519
527
  against `baselines/crap.json`, wired into close-validation, `ci.yml`, and
520
- `.husky/pre-push`. The `baseline-refresh:`-tagged commit convention is the
521
- project standard for baseline edits (see
528
+ `.husky/pre-push`. The `baseline-refresh: true` commit-trailer convention
529
+ is the project standard for baseline edits (see
522
530
  [`core/gates-and-baselines`](../skills/core/gates-and-baselines/SKILL.md)).
523
531
 
524
532
  ### Audits → Stories
@@ -552,7 +560,7 @@ Severity vocabulary (`eventSeverity()` derives it for state transitions):
552
560
 
553
561
  | Severity | Used for | Webhook prefix |
554
562
  | --- | --- | --- |
555
- | `low` | `story-run-progress` upserts, intermediate transitions, audit reports. | `[low]` |
563
+ | `low` | Intermediate transitions, audit reports. | `[low]` |
556
564
  | `medium` | Operator-visible milestones: Story state transitions, story merged, run complete. | `[medium]` |
557
565
  | `high` | Operator must act (HITL gates, Story blockers, autonomous-chain failures); body leads with `🚨 Action Required:`. | `[Action Required]` |
558
566
 
@@ -650,8 +658,7 @@ the ticket or re-plan the work as a v2 Story via `/plan --tickets <id>`.
650
658
  | `/plan --seed-file <path>` | Plan from on-disk notes / a plan seed (the `/audit-to-stories` handoff). |
651
659
  | `/plan --tickets <ids>` | Analyze existing issue(s) into proper Stories (prefer an N=1 rewrite). |
652
660
  | `/deliver <storyId>` | Deliver one Story via `helpers/deliver-story` — `story-<id>` → PR → `main`. |
653
- | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order; each lands through its own PR. |
654
- | `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue. |
661
+ | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (resolved from live state), then run the per-run epilogue. |
655
662
  | *helper* `helpers/deliver-story` | Per-Story engine invoked by `/deliver`; not an operator slash command. See [`deliver-story.md`](../workflows/helpers/deliver-story.md). |
656
663
  | `/audit-to-stories` | Convert audit findings into a plan seed / Stories → `/plan --seed-file`. |
657
664
  | `/qa-explore` · `/qa-assist` · `/qa-run` | Agent-led / human-led exploratory QA and the automated Gherkin harness. |