mandrel 1.94.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 (560) hide show
  1. package/.agents/README.md +116 -99
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +45 -51
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +498 -1287
  6. package/.agents/docs/agentrc-reference.json +185 -80
  7. package/.agents/docs/configuration.md +132 -190
  8. package/.agents/docs/execution-reference.md +51 -25
  9. package/.agents/docs/quality-gates.md +25 -33
  10. package/.agents/docs/workflows.md +8 -8
  11. package/.agents/instructions.md +113 -139
  12. package/.agents/rules/ci-remediation.md +11 -15
  13. package/.agents/rules/git-conventions-reference.md +48 -58
  14. package/.agents/rules/git-conventions.md +16 -22
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  16. package/.agents/schemas/agentrc.schema.json +83 -254
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  24. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  25. package/.agents/schemas/signal-event.schema.json +3 -3
  26. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  27. package/.agents/schemas/validation-evidence.schema.json +1 -1
  28. package/.agents/scripts/acceptance-eval.js +22 -66
  29. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  30. package/.agents/scripts/audit-to-stories.js +7 -7
  31. package/.agents/scripts/boot-sweep.js +1 -1
  32. package/.agents/scripts/bootstrap.js +3 -3
  33. package/.agents/scripts/check-dead-exports.js +43 -104
  34. package/.agents/scripts/check-doc-links.js +2 -2
  35. package/.agents/scripts/check-lifecycle-lint.js +7 -10
  36. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  37. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  38. package/.agents/scripts/deliver-recover.js +122 -0
  39. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  40. package/.agents/scripts/evidence-gate.js +20 -50
  41. package/.agents/scripts/generate-skills-index.js +17 -1
  42. package/.agents/scripts/generate-workflows-doc.js +4 -4
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  44. package/.agents/scripts/lib/Logger.js +6 -10
  45. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  46. package/.agents/scripts/lib/audit-suite/selector.js +328 -28
  47. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  48. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  49. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
  50. package/.agents/scripts/lib/baselines/reader.js +1 -6
  51. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  52. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  53. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  54. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  55. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  56. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  57. package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
  58. package/.agents/scripts/lib/checks/index.js +3 -2
  59. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  60. package/.agents/scripts/lib/checks/state.js +17 -248
  61. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
  62. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  63. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  64. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  65. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  66. package/.agents/scripts/lib/cli-args.js +39 -9
  67. package/.agents/scripts/lib/close-validation/gates.js +15 -15
  68. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  69. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  70. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  71. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  72. package/.agents/scripts/lib/config/ci.js +6 -31
  73. package/.agents/scripts/lib/config/delivery-routing.js +52 -35
  74. package/.agents/scripts/lib/config/explain.js +61 -48
  75. package/.agents/scripts/lib/config/github.js +7 -5
  76. package/.agents/scripts/lib/config/limits.js +29 -80
  77. package/.agents/scripts/lib/config/paths.js +0 -2
  78. package/.agents/scripts/lib/config/quality.js +12 -15
  79. package/.agents/scripts/lib/config/runners.js +20 -66
  80. package/.agents/scripts/lib/config/temp-paths.js +30 -63
  81. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  82. package/.agents/scripts/lib/config-resolver.js +2 -7
  83. package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
  84. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
  85. package/.agents/scripts/lib/config-settings-schema.js +100 -60
  86. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  87. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  88. package/.agents/scripts/lib/dependency-parser.js +3 -2
  89. package/.agents/scripts/lib/doc-tiers.js +2 -2
  90. package/.agents/scripts/lib/duplicate-search.js +242 -41
  91. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  93. package/.agents/scripts/lib/format-generated-json.js +97 -0
  94. package/.agents/scripts/lib/framework-version.js +19 -190
  95. package/.agents/scripts/lib/gh-exec.js +8 -0
  96. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  97. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
  98. package/.agents/scripts/lib/git-utils.js +32 -20
  99. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  100. package/.agents/scripts/lib/json-utils.js +1 -2
  101. package/.agents/scripts/lib/label-constants.js +10 -38
  102. package/.agents/scripts/lib/label-taxonomy.js +10 -55
  103. package/.agents/scripts/lib/observability/active-story-env.js +44 -165
  104. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  105. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  106. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  107. package/.agents/scripts/lib/observability/source-classifier.js +5 -5
  108. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  109. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  110. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  111. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  112. package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
  113. package/.agents/scripts/lib/orchestration/code-review.js +78 -436
  114. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  115. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
  116. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  117. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  118. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  119. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  120. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  121. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  122. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  123. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  124. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  125. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
  126. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  127. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  128. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  129. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
  130. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  131. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  132. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  133. package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
  134. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  135. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  136. package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
  137. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  138. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
  139. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  140. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  141. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
  142. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
  143. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  144. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
  145. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
  146. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
  147. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  148. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  149. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  150. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
  151. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  152. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
  153. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  154. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  155. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  156. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  157. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  158. package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
  159. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  160. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  161. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  162. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  163. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  164. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  165. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  166. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  167. package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  170. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  171. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
  172. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  173. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
  174. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  175. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  176. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
  177. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  178. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  179. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
  180. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  181. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  182. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  183. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  184. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  185. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  186. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  187. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
  188. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  189. package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
  190. package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
  191. package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
  192. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  193. package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
  194. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  195. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
  196. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
  197. package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
  198. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
  199. package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
  200. package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
  201. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  202. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  203. package/.agents/scripts/lib/planning-corpus.js +12 -281
  204. package/.agents/scripts/lib/preflight-runner.js +4 -4
  205. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  206. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  207. package/.agents/scripts/lib/signals/index.js +4 -17
  208. package/.agents/scripts/lib/signals/read.js +35 -35
  209. package/.agents/scripts/lib/signals/schema.js +8 -11
  210. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  211. package/.agents/scripts/lib/signals/write.js +0 -1
  212. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  213. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  214. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  215. package/.agents/scripts/lib/story-adjacency.js +17 -19
  216. package/.agents/scripts/lib/story-body/story-body.js +130 -75
  217. package/.agents/scripts/lib/story-plan.js +2 -4
  218. package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
  219. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  220. package/.agents/scripts/lib/test-env.js +14 -1
  221. package/.agents/scripts/lib/test-tiers.js +0 -3
  222. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
  223. package/.agents/scripts/lib/validation-evidence.js +32 -60
  224. package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
  225. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  226. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
  228. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  229. package/.agents/scripts/lint-issue-body.js +71 -40
  230. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  231. package/.agents/scripts/notify.js +4 -3
  232. package/.agents/scripts/plan-context.js +102 -80
  233. package/.agents/scripts/plan-persist.js +230 -279
  234. package/.agents/scripts/plan-run-epilogue.js +142 -0
  235. package/.agents/scripts/post-structured-comment.js +0 -38
  236. package/.agents/scripts/pr-watch-with-update.js +43 -22
  237. package/.agents/scripts/providers/github/compose.js +0 -1
  238. package/.agents/scripts/providers/github/errors.js +0 -19
  239. package/.agents/scripts/providers/github/issues.js +13 -39
  240. package/.agents/scripts/providers/github/mappers.js +5 -12
  241. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  242. package/.agents/scripts/providers/github/tickets.js +33 -156
  243. package/.agents/scripts/providers/github.js +17 -6
  244. package/.agents/scripts/resolve-stories.js +236 -0
  245. package/.agents/scripts/run-coverage.js +4 -1
  246. package/.agents/scripts/run-lint.js +2 -2
  247. package/.agents/scripts/run-verify.js +31 -2
  248. package/.agents/scripts/signals-view.js +25 -21
  249. package/.agents/scripts/single-story-close.js +178 -26
  250. package/.agents/scripts/single-story-confirm-merge.js +313 -24
  251. package/.agents/scripts/single-story-init.js +35 -30
  252. package/.agents/scripts/stories-wave-tick.js +85 -10
  253. package/.agents/scripts/story-plan.js +28 -49
  254. package/.agents/scripts/update-ticket-state.js +14 -65
  255. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  256. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  257. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  258. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  259. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  260. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  261. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  262. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  263. package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
  264. package/.agents/skills/core/scope-triage/SKILL.md +31 -172
  265. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  266. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  267. package/.agents/skills/skills.index.json +3 -53
  268. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  269. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  270. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  271. package/.agents/starter-agentrc.json +0 -5
  272. package/.agents/templates/agent-protocol.md +9 -10
  273. package/.agents/workflows/audit-architecture.md +6 -7
  274. package/.agents/workflows/audit-clean-code.md +7 -7
  275. package/.agents/workflows/audit-dependencies.md +3 -3
  276. package/.agents/workflows/audit-devops.md +3 -3
  277. package/.agents/workflows/audit-documentation.md +9 -10
  278. package/.agents/workflows/audit-lighthouse.md +11 -3
  279. package/.agents/workflows/audit-navigability.md +13 -2
  280. package/.agents/workflows/audit-performance.md +5 -6
  281. package/.agents/workflows/audit-privacy.md +3 -3
  282. package/.agents/workflows/audit-quality.md +11 -12
  283. package/.agents/workflows/audit-security.md +4 -5
  284. package/.agents/workflows/audit-seo.md +13 -3
  285. package/.agents/workflows/audit-sre.md +3 -3
  286. package/.agents/workflows/audit-to-stories.md +20 -20
  287. package/.agents/workflows/audit-ux-ui.md +10 -3
  288. package/.agents/workflows/deliver.md +177 -176
  289. package/.agents/workflows/git-cleanup.md +5 -6
  290. package/.agents/workflows/git-deliver.md +1 -1
  291. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  292. package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
  293. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  294. package/.agents/workflows/helpers/code-review.md +75 -196
  295. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
  296. package/.agents/workflows/helpers/deliver-story.md +606 -0
  297. package/.agents/workflows/helpers/diagnose.md +10 -10
  298. package/.agents/workflows/helpers/parallel-tooling.md +3 -3
  299. package/.agents/workflows/helpers/signals.md +16 -16
  300. package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
  301. package/.agents/workflows/mandrel-update.md +2 -1
  302. package/.agents/workflows/plan.md +277 -145
  303. package/.agents/workflows/qa-assist.md +27 -33
  304. package/.agents/workflows/qa-explore.md +29 -38
  305. package/.agents/workflows/qa-run.md +2 -6
  306. package/README.md +9 -8
  307. package/bin/mandrel.js +12 -1
  308. package/docs/CHANGELOG.md +70 -0
  309. package/lib/cli/registry.js +262 -19
  310. package/lib/cli/sync-agents.js +157 -0
  311. package/lib/cli/sync-commands.js +115 -6
  312. package/lib/cli/sync.js +168 -6
  313. package/lib/cli/update.js +105 -8
  314. package/lib/cli/version-helpers.js +131 -0
  315. package/lib/migrations/README.md +7 -5
  316. package/lib/migrations/index.js +12 -8
  317. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  318. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  319. package/package.json +2 -2
  320. package/.agents/agents/retro.md +0 -42
  321. package/.agents/personas/architect.md +0 -113
  322. package/.agents/personas/devops-engineer.md +0 -38
  323. package/.agents/personas/engineer.md +0 -33
  324. package/.agents/personas/project-manager.md +0 -114
  325. package/.agents/personas/qa-engineer.md +0 -95
  326. package/.agents/personas/security-engineer.md +0 -111
  327. package/.agents/personas/technical-writer.md +0 -101
  328. package/.agents/schemas/dispatch-manifest.json +0 -232
  329. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  330. package/.agents/schemas/epic-spec.schema.json +0 -153
  331. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  332. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  333. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  334. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  335. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  336. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  337. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  338. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  339. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  340. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  341. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  342. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  343. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  344. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  345. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  346. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  347. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  348. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  349. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  350. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  351. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  352. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  353. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  354. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  355. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  356. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  357. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  358. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  359. package/.agents/schemas/risk-verdict.schema.json +0 -66
  360. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  361. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  362. package/.agents/scripts/analyze-execution.js +0 -444
  363. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  364. package/.agents/scripts/check-prepush-recovery.js +0 -90
  365. package/.agents/scripts/dispatcher.js +0 -295
  366. package/.agents/scripts/epic-audit-prepare.js +0 -497
  367. package/.agents/scripts/epic-audit-recheck.js +0 -274
  368. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  369. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  370. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  371. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  372. package/.agents/scripts/epic-plan-clarity.js +0 -211
  373. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  374. package/.agents/scripts/epic-reconcile.js +0 -625
  375. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  376. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  377. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  378. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  379. package/.agents/scripts/lib/config/preflight.js +0 -58
  380. package/.agents/scripts/lib/config/retro.js +0 -77
  381. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  382. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  383. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  384. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  385. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  386. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
  387. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  388. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  389. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  390. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
  391. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  392. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  393. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  394. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  395. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  396. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  397. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  398. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  399. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  400. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  401. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  402. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  403. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  404. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  405. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  406. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  407. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  408. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
  409. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  410. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  411. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  412. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  413. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  414. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  415. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  416. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  417. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  418. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  419. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  420. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  421. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  422. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  423. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  424. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  425. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  426. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
  427. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  428. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  429. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  430. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  431. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  432. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  433. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  434. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  435. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  436. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  437. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  438. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  439. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  440. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  441. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  442. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  443. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  444. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  445. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  446. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  447. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  448. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  449. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  450. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  451. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  452. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  453. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  454. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  455. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  456. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  457. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  458. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  459. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  460. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  461. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
  462. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  463. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  464. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  465. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
  466. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  467. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  468. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  469. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  470. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  471. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  472. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  473. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  474. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  475. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  476. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  477. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  478. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  479. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  480. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  481. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  482. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  483. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  484. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  485. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  486. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  487. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  488. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  489. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  490. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  491. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  492. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  493. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  494. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  495. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  496. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  497. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  498. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  499. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  500. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  501. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  502. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  503. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  504. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  505. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  506. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  507. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  508. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  509. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  510. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  511. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  512. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  513. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  514. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  515. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  516. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  517. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  518. package/.agents/scripts/lib/spec/index.js +0 -36
  519. package/.agents/scripts/lib/spec/loader.js +0 -425
  520. package/.agents/scripts/lib/spec/state.js +0 -208
  521. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  522. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  523. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  524. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  525. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  526. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  527. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  528. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  529. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  530. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  531. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  532. package/.agents/scripts/lifecycle-emit.js +0 -510
  533. package/.agents/scripts/retro-run.js +0 -218
  534. package/.agents/scripts/slice-phase.js +0 -361
  535. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  536. package/.agents/scripts/story-close.js +0 -294
  537. package/.agents/scripts/story-init.js +0 -599
  538. package/.agents/scripts/story-phase.js +0 -369
  539. package/.agents/scripts/wave-tick.js +0 -464
  540. package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
  541. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  542. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  543. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  544. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  545. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  546. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  547. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  548. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  549. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  550. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  551. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  552. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  553. package/.agents/workflows/helpers/epic-audit.md +0 -189
  554. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  555. package/.agents/workflows/helpers/epic-testing.md +0 -125
  556. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  557. package/.agents/workflows/helpers/plan-epic.md +0 -353
  558. package/.agents/workflows/helpers/plan-story.md +0 -251
  559. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  560. package/.agents/workflows/helpers/single-story-deliver.md +0 -557
@@ -37,16 +37,14 @@ and dedup/route decisions. The agent never invents those decisions in prose.
37
37
  > a structured agent-driven bug-hunt the operator wants captured into a
38
38
  > triageable ledger.
39
39
  >
40
- > **Persona**: `qa-engineer` · **Skills**: `core/qa-coverage-mapping`,
41
- > `stack/qa/qa-explore-driving`
40
+ > **Skills**: `core/qa-coverage-mapping`, `stack/qa/qa-explore-driving`
42
41
 
43
- ## Persona
42
+ ## Role framing
44
43
 
45
- Adopt the **`qa-engineer`** persona
46
- ([`.agents/personas/qa-engineer.md`](../personas/qa-engineer.md)) for the whole
47
- run. You are the quality gatekeeper: you value coverage, hermetic
48
- environments, and deterministic results. Re-read that persona file as your
49
- first action so the Plan/Capture/Triage loop is governed by it.
44
+ You are the quality gatekeeper for this run: value coverage, hermetic
45
+ environments, and deterministic results. Do **not** invent signal — capture
46
+ what the surface shows. Apply the QA skills below; there is no separate
47
+ persona pack.
50
48
 
51
49
  ## Driving conventions skill
52
50
 
@@ -89,10 +87,10 @@ ledger**; do not switch methods mid-surface without a new Plan note.
89
87
  | --------- | -------- | ---------------------------------- | -------------------------------------------------------------------------------------- |
90
88
  | `surface` | yes | `feature:login`, `area:onboarding` | A human label for the single surface to explore. Recorded as each ledger item's `coverage`. |
91
89
 
92
- If no `surface` is supplied, **stop and ask** the operator to name one — the
93
- `qa-engineer` Golden Rule forbids inventing scope. `/qa-explore` is **bounded
94
- to one surface per session**: explore exactly the named surface, do not wander
95
- into adjacent surfaces, and start a fresh session for a different surface.
90
+ If no `surface` is supplied, **stop and ask** the operator to name one — do
91
+ not invent scope. `/qa-explore` is **bounded to one surface per session**:
92
+ explore exactly the named surface, do not wander into adjacent surfaces, and
93
+ start a fresh session for a different surface.
96
94
 
97
95
  ## Project contract
98
96
 
@@ -161,7 +159,7 @@ advances phases autonomously. If the operator does not confirm, stop and hold.
161
159
  Goal: agree on **what** will be explored and **how the agent will drive it**
162
160
  before touching the surface.
163
161
 
164
- 1. Re-read the `qa-engineer` persona and the
162
+ 1. Re-read the
165
163
  [`stack/qa/qa-explore-driving`](../skills/stack/qa/qa-explore-driving/SKILL.md)
166
164
  skill, and resolve the `qa` contract and session (above).
167
165
  2. **Resolve the target environment** via
@@ -339,33 +337,26 @@ For each untriaged ledger item:
339
337
  import { promoteFindings } from '../scripts/lib/findings/promote-finding.js';
340
338
  const { promotions } = await promoteFindings(ledgerItems, {
341
339
  searchIssues, // GitHub provider, open + closed
342
- createStory, // tight cluster (≤2 surfaces): render seed → /plan --from-notes
343
- createEpic, // broad cluster (>2 surfaces): render seed /plan --idea
340
+ createStory, // tight cluster (≤2 surfaces): seed → /plan --seed-file
341
+ createPlanSeed, // broad cluster (>2 surfaces): same /plan --seed-file path (may N>1)
344
342
  });
345
343
  ```
346
344
 
347
345
  - **Sizing is delegated, not decided in prose.** `promoteFindings` runs
348
346
  `clusterLedgerItems` + `targetForCluster`: a cluster spanning **≤2**
349
347
  distinct coverage surfaces routes to `createStory`; **>2** routes to
350
- `createEpic`. The workflow introduces no new sizing, clustering, or dedup
351
- logic — `route-finding.js` / `promote-finding.js` remain the single
352
- implementation.
353
- - **`createStory` (`/plan --from-notes`)** — render a **redacted**
354
- `--from-notes` seed from the cluster (reuse the `/audit-to-stories`
355
- Phase 5b notes shape; redaction already ran in Capture), **stamp the
348
+ `createPlanSeed`. Neither port opens an Epic ticket both chain
349
+ `/plan --seed-file`. The workflow introduces no new sizing, clustering,
350
+ or dedup logic — `route-finding.js` / `promote-finding.js` remain the
351
+ single implementation.
352
+ - **`createStory` / `createPlanSeed` (`/plan --seed-file`)** render a
353
+ **redacted** plan seed from the cluster (reuse the `/audit-to-stories`
354
+ Phase 5a seed shape; redaction already ran in Capture), **stamp the
356
355
  cluster's `fingerprintFooter(sha)` verbatim into the seed body**, then
357
- chain `/plan --from-notes <seed>`. The footer must survive into the issue
358
- body the Story create path writes it round-trips through
359
- `story-plan.js --body <file> --dry-run` unchanged (asserted by the
360
- deterministic round-trip test under `tests/`) so a later `routeFinding`
361
- dedups the same finding instead of re-filing it.
362
- - **`createEpic` (`/plan --idea`)** — carry the cluster's
363
- `fingerprintFooter(sha)` into the `/plan --idea` seed, then chain
364
- `/plan --idea <seed>`. **Known limitation (not solved here):**
365
- per-child-Story fingerprint propagation through full Epic decomposition is
366
- *not* guaranteed — the fingerprint is carried in the Epic seed only; the
367
- child Stories `/plan` spawns from that seed are not individually
368
- footer-stamped.
356
+ chain `/plan --seed-file <seed>`. Prefer one Story; split only under
357
+ the default-single policy. The footer must survive into the issue body
358
+ so a later `routeFinding` dedups the same finding instead of re-filing
359
+ it.
369
360
  - **A `file` disposition never opens a raw GitHub Issue.** Every `file`
370
361
  finding flows through `promoteFindings` → `/plan`; only `defer` and
371
362
  `dismiss` skip the `/plan` handoff.
@@ -379,8 +370,8 @@ For each untriaged ledger item:
379
370
  After triage, write the updated dispositions back to the ledger (still under
380
371
  `temp/qa/`), and summarize: items captured, the driving method used, classes,
381
372
  routes (`new`/`update-existing`/`duplicate`/`regression-of-closed`), the
382
- Stories (`/plan --from-notes`) and Epics (`/plan --idea`) promoted, and the
383
- deferred rolling backlog that a resumed session will pick up.
373
+ Stories (`/plan --seed-file`) promoted, and the deferred rolling backlog
374
+ that a resumed session will pick up.
384
375
 
385
376
  ---
386
377
 
@@ -423,7 +414,7 @@ deferred rolling backlog that a resumed session will pick up.
423
414
  deterministic — never re-derive them in prose.
424
415
  - **Promote through `/plan`, never a raw Issue.** A `file`-dispositioned
425
416
  finding is promoted via `promoteFindings`, which chains into
426
- [`/plan`](plan.md) (`--from-notes` for a tight cluster, `--idea` for a broad
417
+ [`/plan`](plan.md) (`--seed-file` for a tight cluster, `--seed` for a broad
427
418
  one) — mirroring [`/audit-to-stories`](audit-to-stories.md). `/qa-explore`
428
419
  never opens a bare GitHub Issue for a `file` finding. The cluster's
429
420
  `fingerprintFooter(sha)` is stamped verbatim into the seed so a future
@@ -435,8 +426,8 @@ deferred rolling backlog that a resumed session will pick up.
435
426
  ## See also
436
427
 
437
428
  - [`/plan`](plan.md) — the planning pipeline `/qa-explore` Triage chains into
438
- for a `file`-dispositioned finding (`--from-notes` for a Story, `--idea` for
439
- an Epic). The plan→deliver hard stop is preserved across the handoff.
429
+ for a `file`-dispositioned finding (`--seed-file` / `--seed`). The
430
+ plan→deliver hard stop is preserved across the handoff.
440
431
  - [`/qa-assist`](qa-assist.md) — the human-led sibling that enriches a single
441
432
  operator observation and triages through the same `/plan` handoff.
442
433
  - [`/audit-to-stories`](audit-to-stories.md) — the precedent for the
@@ -381,17 +381,13 @@ For each untriaged ledger item:
381
381
  [`promote-finding.js`](../scripts/lib/findings/promote-finding.js) — the
382
382
  same cluster/size/route/file path `/qa-explore` and `/audit-to-stories`
383
383
  consume (`clusterLedgerItems` + `targetForCluster`: a cluster spanning ≤2
384
- coverage surfaces routes to `createStory` via `/plan --from-notes`, >2 to
385
- `createEpic` via `/plan --idea`, with the cluster's `fingerprintFooter(sha)`
384
+ coverage surfaces routes to `createStory` via `/plan --seed-file`, >2 to
385
+ `createPlanSeed` via `/plan --seed`, with the cluster's `fingerprintFooter(sha)`
386
386
  stamped verbatim into the seed). A `file` disposition never opens a raw
387
387
  GitHub Issue; only `defer` and `dismiss` skip the `/plan` handoff.
388
388
  5. **Gate:** any ticket-filing, seed write, `/plan` invocation, or label
389
389
  mutation is a write — confirm each with the operator before it happens.
390
390
 
391
- If the run was triggered from an Epic-testing context, hand the approved,
392
- promoted findings to the Epic-testing helper for attachment to the Epic's QA
393
- evidence ticket.
394
-
395
391
  ## Step 6 — Report
396
392
 
397
393
  Summarize the sweep in chat with:
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![CI / CD](https://github.com/dsj1984/mandrel/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/dsj1984/mandrel/actions/workflows/ci.yml)
4
4
 
5
5
  An opinionated workflow framework for AI coding assistants built on
6
- Epic-centric GitHub orchestration. Planning, execution, and state all live
6
+ Story-centric GitHub orchestration. Planning, execution, and state all live
7
7
  natively in GitHub Issues, Labels, and Projects V2.
8
8
 
9
9
  ## Prerequisites
@@ -35,7 +35,8 @@ npx mandrel init # install mandrel → sync → prompt → bootstrap →
35
35
 
36
36
  ```text
37
37
  # then, inside Claude Code (commands load from .claude/commands/):
38
- /plan # ideation -> PRD/Tech Spec -> Epic with child Stories
38
+ /plan --seed "…" # interrogate author one Story (default) persist
39
+ /deliver <id> # story-<id> → PR → main
39
40
  ```
40
41
 
41
42
  `npx mandrel init` installs `mandrel` (when `./.agents/` is absent),
@@ -47,9 +48,9 @@ any time to configure). Pass `--assume-yes` for a non-interactive run that
47
48
  proceeds straight to configure (and forwards the flag to bootstrap). When
48
49
  `./.agents/` is already present (you ran `npm install mandrel` first), `init`
49
50
  skips the install/sync and goes straight to the prompt. Once `mandrel init`
50
- completes, you land at the `/plan` handoff — run `/plan --idea "<seed>"` to
51
- start planning your first Epic, then deliver it with `/deliver <id>` (wave
52
- loopvalidationreview → retro → open PR).
51
+ completes, you land at the `/plan` handoff — run `/plan --seed "<idea>"` to
52
+ author your first Story, then deliver it with `/deliver <storyId>`
53
+ (`story-<id>`PR`main`).
53
54
 
54
55
  ### Manual equivalent
55
56
 
@@ -217,9 +218,9 @@ against malicious lifecycle scripts in compromised transitive packages
217
218
  install scripts for a specific install, run
218
219
  `npm install --ignore-scripts=false` for that invocation only.
219
220
 
220
- CRAP and Maintainability gates fire at every checkpoint (keystroke,
221
- pre-commit, pre-push, story-close, CI, Epic merge) against the same
222
- thresholds from `delivery.quality.*` in `.agentrc.json`.
221
+ CRAP and Maintainability gates fire at three sites — close-validation
222
+ (story close), `.husky/pre-push`, and CI (`ci.yml`, push + PR) against
223
+ the same thresholds from `delivery.quality.*` in `.agentrc.json`.
223
224
 
224
225
  ## License
225
226
 
package/bin/mandrel.js CHANGED
@@ -57,7 +57,18 @@ const SUBCOMMANDS = new Map([
57
57
  'sync-commands',
58
58
  {
59
59
  description: 'regenerate .claude/commands/ from .agents/workflows/',
60
- knownFlags: new Set(['--dry-run']),
60
+ // No --dry-run: the projection scripts have no preview mode, and
61
+ // accepting the flag while syncing for real overwrote .claude/ on an
62
+ // operator who asked for a preview. Reject it at the dispatcher.
63
+ knownFlags: new Set([]),
64
+ },
65
+ ],
66
+ [
67
+ 'sync-agents',
68
+ {
69
+ description: 'regenerate .claude/agents/ from .agents/agents/',
70
+ // Same contract as sync-commands: no preview mode, so no --dry-run.
71
+ knownFlags: new Set([]),
61
72
  },
62
73
  ],
63
74
  [
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,76 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.1.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.0.0...mandrel-v2.1.0) (2026-07-17)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * **plan:** plan-persist.js no longer accepts --risk-verdict and no plan-time step authors a risk verdict; review depth and the acceptance critic mode are derived from the diff at close time.
11
+ * /deliver no longer accepts --run <planRunId> or --dep, and /plan no longer applies a plan-run::<id> label. Deliver Story ids; the graph resolves itself from live state.
12
+
13
+ ### Added
14
+
15
+ * /deliver takes only Story ids and resolves dependencies dynamically (retire plan-run) ([#4540](https://github.com/dsj1984/mandrel/issues/4540)) ([#4560](https://github.com/dsj1984/mandrel/issues/4560)) ([e9935cc](https://github.com/dsj1984/mandrel/commit/e9935cc332b43862d79dca9979691077327e1882))
16
+ * **dead-exports:** add a production-mode pass that discounts test-only importers (refs [#4575](https://github.com/dsj1984/mandrel/issues/4575)) ([#4582](https://github.com/dsj1984/mandrel/issues/4582)) ([0a77ca9](https://github.com/dsj1984/mandrel/commit/0a77ca91bdd67a294b66cc076e45c43bc4d691c8))
17
+ * **deliver:** script-owned land tail, resumable pending status, terminal envelope, and deliver-recover ([#4543](https://github.com/dsj1984/mandrel/issues/4543)) ([#4566](https://github.com/dsj1984/mandrel/issues/4566)) ([f234306](https://github.com/dsj1984/mandrel/commit/f234306d1465fe96d19d361f1501ad8edf055cc3))
18
+ * **plan:** close --tickets source issues as superseded by default ([#4535](https://github.com/dsj1984/mandrel/issues/4535)) ([#4553](https://github.com/dsj1984/mandrel/issues/4553)) ([c35e298](https://github.com/dsj1984/mandrel/commit/c35e29880edba4fec0c45687071fbea242236370))
19
+ * **plan:** mirror sibling depends_on into native blocked_by edges (refs [#4544](https://github.com/dsj1984/mandrel/issues/4544)) ([#4570](https://github.com/dsj1984/mandrel/issues/4570)) ([6b94968](https://github.com/dsj1984/mandrel/commit/6b949688e4fd487c979044f2473e3837a4637e1a))
20
+
21
+
22
+ ### Fixed
23
+
24
+ * **bootstrap:** honor command:false in the workflow/command parity check ([#4588](https://github.com/dsj1984/mandrel/issues/4588)) ([493b3eb](https://github.com/dsj1984/mandrel/commit/493b3eb039eefabbd2e33af6a08933d43876c052))
25
+ * **cli:** resolve versions from the consumer, not the running CLI — and make the sync surface fail loudly on skew ([#4530](https://github.com/dsj1984/mandrel/issues/4530)) ([#4536](https://github.com/dsj1984/mandrel/issues/4536)) ([5f20563](https://github.com/dsj1984/mandrel/commit/5f20563eca79203096b49e8fa3dfaa64e2487e12))
26
+ * **cli:** stop sync pruning generated .agents/ files — declare a never-pruned registry so the install ledger survives ([#4534](https://github.com/dsj1984/mandrel/issues/4534)) ([#4552](https://github.com/dsj1984/mandrel/issues/4552)) ([ceccd57](https://github.com/dsj1984/mandrel/commit/ceccd572614a7d8c5226bdd9f1a3b793381be4dd))
27
+ * **column-sync:** stop two more test suites leaking into the shared meta cache ([#4561](https://github.com/dsj1984/mandrel/issues/4561)) ([757e509](https://github.com/dsj1984/mandrel/commit/757e509ff4aa95a091fe9a5de053396a78a26793)), closes [#4555](https://github.com/dsj1984/mandrel/issues/4555)
28
+ * **deliver:** diff the plan-run epilogue against the pre-run base, not origin/main...HEAD (refs [#4550](https://github.com/dsj1984/mandrel/issues/4550)) ([#4558](https://github.com/dsj1984/mandrel/issues/4558)) ([79ddbf6](https://github.com/dsj1984/mandrel/commit/79ddbf61d19bdf256a06aabb860651be6bdce94b))
29
+ * **deliver:** ground the audit roster's lens selection in the landed diff (refs [#4571](https://github.com/dsj1984/mandrel/issues/4571)) ([#4573](https://github.com/dsj1984/mandrel/issues/4573)) ([fa06aca](https://github.com/dsj1984/mandrel/commit/fa06acaedc0c3070516ec32d447f0755a06ea0eb))
30
+ * **deliver:** repair the close-and-land default path (config, operator-merge, follow-ups, reap, reporting) ([#4539](https://github.com/dsj1984/mandrel/issues/4539)) ([#4551](https://github.com/dsj1984/mandrel/issues/4551)) ([9b5c3ee](https://github.com/dsj1984/mandrel/commit/9b5c3ee61b2030e96ff88091761b258eb43fdf43))
31
+ * make `npm run verify` a true CI mirror: include dead-exports + arch-cycles (or catalogue them as CI-only) ([#4549](https://github.com/dsj1984/mandrel/issues/4549)) ([#4557](https://github.com/dsj1984/mandrel/issues/4557)) ([70d088a](https://github.com/dsj1984/mandrel/commit/70d088a646fd1867f3d536c541f89c1c49b0b866))
32
+ * **plan:** make persist resumable and align its gates with the authoring contract ([#4541](https://github.com/dsj1984/mandrel/issues/4541)) ([#4565](https://github.com/dsj1984/mandrel/issues/4565)) ([1cbe974](https://github.com/dsj1984/mandrel/commit/1cbe974154403edab14e006e83f42a5c414150d1))
33
+ * **plan:** make the fan-out deletion gate count importers, not basename word matches ([#4547](https://github.com/dsj1984/mandrel/issues/4547)) ([#4567](https://github.com/dsj1984/mandrel/issues/4567)) ([4c5c724](https://github.com/dsj1984/mandrel/commit/4c5c7248e88136bac83cd91db38658390139c588))
34
+ * **plan:** thread sourceTickets through the envelope so --tickets superseding cannot silently no-op ([#4554](https://github.com/dsj1984/mandrel/issues/4554)) ([#4559](https://github.com/dsj1984/mandrel/issues/4559)) ([4546c40](https://github.com/dsj1984/mandrel/commit/4546c405b2131f6c5afd3ccf40bccb357f4223a0))
35
+ * **quality:** retire the unconsumed miDropMustRefactor/miDropCap knobs and make maintainability.tolerance the single MI-drop control ([#4531](https://github.com/dsj1984/mandrel/issues/4531)) ([#4548](https://github.com/dsj1984/mandrel/issues/4548)) ([fe0c7ce](https://github.com/dsj1984/mandrel/commit/fe0c7ce3ad40e21b957cd6d0a916efbc5e75f634))
36
+ * **skills-index:** emit biome-formatted JSON so regeneration leaves no drift (refs [#4546](https://github.com/dsj1984/mandrel/issues/4546)) ([#4568](https://github.com/dsj1984/mandrel/issues/4568)) ([bdb223e](https://github.com/dsj1984/mandrel/commit/bdb223e2979c0d386ca260b6743cdf2062dbff09))
37
+
38
+
39
+ ### Changed
40
+
41
+ * **checks:** drop the dead epic merge-lock and epic-branch probes ([#4581](https://github.com/dsj1984/mandrel/issues/4581)) ([28cb4ab](https://github.com/dsj1984/mandrel/commit/28cb4abf4aa9c0c0120598c26dd5b7220b195678))
42
+ * **docs:** move weight out of always-loaded prompts and skill essays into on-demand references ([#4546](https://github.com/dsj1984/mandrel/issues/4546)) ([#4564](https://github.com/dsj1984/mandrel/issues/4564)) ([14381b3](https://github.com/dsj1984/mandrel/commit/14381b3efd7ce774e39dd47f535bb55991387617))
43
+ * **plan:** derive review depth from the diff and retire the authored risk verdict (refs [#4542](https://github.com/dsj1984/mandrel/issues/4542)) ([#4569](https://github.com/dsj1984/mandrel/issues/4569)) ([7a7fb50](https://github.com/dsj1984/mandrel/commit/7a7fb50f7ec0e33d616fa54618fc0b93c2e310a6))
44
+
45
+ ## [2.0.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.94.0...mandrel-v2.0.0) (2026-07-14)
46
+
47
+
48
+ ### ⚠ BREAKING CHANGES
49
+
50
+ * **v2 Story collapse:** one ticket type (`type::story`), one delivery
51
+ path (`/deliver` → `helpers/deliver-story`), one branch model
52
+ (`story-<id>` → PR → `main`). `type::epic`, the epic integration
53
+ branch, wave/dispatch fan-out, and `delivery.routing.singleDelivery`
54
+ are removed. Per-Story file/AC ceilings are replaced by
55
+ `planning.modelCapacity` session-mass thresholds. In-flight v1 Epics
56
+ must land before upgrading.
57
+
58
+
59
+ ### Features
60
+
61
+ * collapse `/plan` to a single flat-Story path and retire epic/story routers
62
+ * collapse delivery onto `helpers/deliver-story` with plan-run sequencing
63
+ * deletion sweep for wave/dispatch, epic-runner, and epic lifecycle strata
64
+ * re-key run temp to `temp/run-<id>/`; slim personas and drop `type::epic`
65
+ * drop `delivery.routing.singleDelivery`; land Story-only docs freshness
66
+
67
+
68
+ ### Documentation
69
+
70
+ * refresh always-loaded hierarchy prose (`AGENTS.md`, `CLAUDE.md`,
71
+ `instructions.md` §5, `SDLC.md`, `architecture.md`, consumer README)
72
+ * regenerate `.agents/docs/configuration.md` without the inert
73
+ `singleDelivery` cell
74
+
5
75
  ## [1.94.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.93.0...mandrel-v1.94.0) (2026-07-13)
6
76
 
7
77
 
@@ -31,12 +31,17 @@ import {
31
31
  satisfiesNodeEngine,
32
32
  } from '../../.agents/scripts/lib/bootstrap/project-bootstrap.js';
33
33
  import { isCommandExcluded } from '../../.agents/scripts/lib/command-header.js';
34
+ import { getDeliveryRouting } from '../../.agents/scripts/lib/config/delivery-routing.js';
34
35
  import {
35
36
  defaultResolvePackageRoot,
36
37
  listFiles as listPayloadFiles,
37
38
  } from './sync.js';
38
39
  import { readCache } from './version-check.js';
39
- import { compareVersions as compareSemver } from './version-helpers.js';
40
+ import {
41
+ compareVersions as compareSemver,
42
+ resolveConsumerPinSpec,
43
+ satisfiesPinSpec,
44
+ } from './version-helpers.js';
40
45
 
41
46
  // ---------------------------------------------------------------------------
42
47
  // Internal helpers
@@ -309,6 +314,60 @@ function runCommandsInSync({ projectRoot, cwd, readDir, readFile } = {}) {
309
314
  // check: agents-in-sync
310
315
  // ---------------------------------------------------------------------------
311
316
 
317
+ /**
318
+ * Best-effort raw JSON read — no AJV, no merge validation. Absent, unreadable,
319
+ * or malformed files degrade to `null` so a config problem never crashes a
320
+ * doctor check; the caller applies framework defaults on `null`.
321
+ *
322
+ * @param {string} absPath
323
+ * @param {typeof fs} fsImpl
324
+ * @returns {object | null}
325
+ */
326
+ function readJsonSafe(absPath, fsImpl) {
327
+ try {
328
+ return JSON.parse(fsImpl.readFileSync(absPath, 'utf8'));
329
+ } catch {
330
+ return null;
331
+ }
332
+ }
333
+
334
+ /**
335
+ * Resolve `delivery.routing.roleScopedAgents` (default `true`) for
336
+ * `agents-in-sync`'s fatal/advisory branch below, WITHOUT importing the full
337
+ * `resolveConfig()` chain — that chain pulls in AJV (`config-schema.js`),
338
+ * which would violate this module's own "Node built-ins only" contract (see
339
+ * the module doc: registry.js must load inside the preflight guard, before
340
+ * any third-party package is guaranteed present).
341
+ *
342
+ * Reads `.agentrc.json` and `.agentrc.local.json` directly and shallow-merges
343
+ * only the `delivery.routing` block (local wins per-key) — narrower than the
344
+ * resolver's full deep-merge, but sufficient for this one boolean, and it
345
+ * still honours a local override rather than silently ignoring it. Delegates
346
+ * the actual default/coercion to `getDeliveryRouting` (`config/delivery-
347
+ * routing.js`), which has zero imports of its own and is already the single
348
+ * source of truth for this default elsewhere in the framework.
349
+ *
350
+ * @param {string} projectRoot
351
+ * @param {typeof fs} fsImpl
352
+ * @returns {boolean}
353
+ */
354
+ function resolveRoleScopedAgentsFlag(projectRoot, fsImpl) {
355
+ const base = readJsonSafe(path.join(projectRoot, '.agentrc.json'), fsImpl);
356
+ const local = readJsonSafe(
357
+ path.join(projectRoot, '.agentrc.local.json'),
358
+ fsImpl,
359
+ );
360
+ const merged = {
361
+ delivery: {
362
+ routing: {
363
+ ...(base?.delivery?.routing ?? {}),
364
+ ...(local?.delivery?.routing ?? {}),
365
+ },
366
+ },
367
+ };
368
+ return getDeliveryRouting(merged).roleScopedAgents;
369
+ }
370
+
312
371
  /**
313
372
  * Dry-run the sync-claude-agents logic: compare `.agents/agents/*.md` sources
314
373
  * to the generated `.claude/agents/*.md` role-agent tree and report parity.
@@ -326,30 +385,52 @@ function runCommandsInSync({ projectRoot, cwd, readDir, readFile } = {}) {
326
385
  * A repo with no `.agents/agents/` sources and no `.claude/agents/` tree is a
327
386
  * clean no-op (0 sources, 0 dests → "up to date").
328
387
  *
329
- * **Inert-scaffolding divergence from `commands-in-sync` (#4478 PR-2).** The
330
- * role agents are inert no workflow spawns them yet — so a **never
331
- * materialized** agent tree (sources present, but the `.claude/agents/` tree
332
- * empty) is NOT a readiness failure: it is reported as advisory, not fatal.
333
- * Once the tree HAS been materialized, drift (a source missing from the dest,
334
- * or a stale dest file) fails the check exactly like `commands-in-sync`. M7-B
335
- * (the spawn flip) is where the sync is wired into the delivery flows and this
336
- * tolerance is tightened.
388
+ * **Tightened from advisory to fatal (Story #4530, M7-B).** Prior to this
389
+ * Story, a **never materialized** agent tree (sources present, `.claude/
390
+ * agents/` empty) was reported as advisory — "inert", because no workflow
391
+ * spawned the role agents yet. M7-B has landed: `helpers/deliver-story` Step
392
+ * 1a dispatches `subagent_type: acceptance-critic` on the **default** path
393
+ * (`roleScopedAgents` defaults `true`). An unmaterialized tree under that
394
+ * default is no longer a benign scaffolding gap it is the acceptance
395
+ * ceremony's fresh-context critic silently failing to spawn and falling back
396
+ * to a weaker inline critic, with doctor reporting green throughout. This
397
+ * check now fails in exactly that case. When `roleScopedAgents` is `false`
398
+ * (the operator kill-switch), an unmaterialized tree is expected — the check
399
+ * stays advisory. Once the tree HAS been materialized, drift (a source
400
+ * missing from the dest, or a stale dest file) fails the check exactly like
401
+ * `commands-in-sync`, unconditionally, exactly as before this Story.
337
402
  *
338
403
  * Injectable seams (used by tests so no real filesystem is touched):
339
404
  * - `cwd()` replaces `process.cwd` so tests can pin the consumer root.
340
405
  * - `readDir` replaces `fs.readdirSync`.
406
+ * - `fsImpl` replaces the `node:fs` surface used for the `.agentrc.json` /
407
+ * `.agentrc.local.json` reads.
408
+ * - `roleScopedAgents` overrides the resolved flag directly, bypassing the
409
+ * config reads entirely.
341
410
  *
342
- * @param {{ projectRoot?: string, cwd?: () => string, readDir?: (dir: string) => string[] }} [opts]
411
+ * @param {{
412
+ * projectRoot?: string,
413
+ * cwd?: () => string,
414
+ * readDir?: (dir: string) => string[],
415
+ * fsImpl?: typeof fs,
416
+ * roleScopedAgents?: boolean,
417
+ * }} [opts]
343
418
  * @returns {{ ok: boolean, detail: string, remedy?: string }}
344
419
  */
345
- function runAgentsInSync({ projectRoot, cwd, readDir } = {}) {
420
+ function runAgentsInSync({
421
+ projectRoot,
422
+ cwd,
423
+ readDir,
424
+ fsImpl = fs,
425
+ roleScopedAgents,
426
+ } = {}) {
346
427
  const getCwd = cwd ?? (() => process.cwd());
347
428
  const root = projectRoot ?? getCwd();
348
429
  const listDir =
349
430
  readDir ??
350
431
  ((dir) => {
351
432
  try {
352
- return fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
433
+ return fsImpl.readdirSync(dir).filter((f) => f.endsWith('.md'));
353
434
  } catch {
354
435
  return [];
355
436
  }
@@ -365,14 +446,26 @@ function runAgentsInSync({ projectRoot, cwd, readDir } = {}) {
365
446
  .filter((f) => !f.startsWith('.'))
366
447
  .sort();
367
448
 
368
- // Never-materialized agent tree: inert, so advisory (ok:true), not fatal.
369
449
  if (dests.length === 0) {
450
+ if (sources.length === 0) {
451
+ return { ok: true, detail: '0 agents up to date' };
452
+ }
453
+ const resolvedFlag =
454
+ typeof roleScopedAgents === 'boolean'
455
+ ? roleScopedAgents
456
+ : resolveRoleScopedAgentsFlag(root, fsImpl);
457
+ if (!resolvedFlag) {
458
+ // Kill-switch off: an unmaterialized tree is expected, not a defect.
459
+ return {
460
+ ok: true,
461
+ detail: `${sources.length} agent def(s) not materialized (roleScopedAgents is disabled)`,
462
+ };
463
+ }
370
464
  return {
371
- ok: true,
372
- detail:
373
- sources.length === 0
374
- ? '0 agents up to date'
375
- : `${sources.length} agent def(s) not yet materialized (inert)`,
465
+ ok: false,
466
+ detail: `${sources.length} agent def(s) not yet materialized in .claude/agents/`,
467
+ remedy:
468
+ 'Run `mandrel sync-agents` to regenerate the `.claude/agents/` tree.',
376
469
  };
377
470
  }
378
471
 
@@ -392,7 +485,7 @@ function runAgentsInSync({ projectRoot, cwd, readDir } = {}) {
392
485
  ok: false,
393
486
  detail: parts.join(', '),
394
487
  remedy:
395
- 'Run `npm run sync:agents` to regenerate the `.claude/agents/` tree.',
488
+ 'Run `mandrel sync-agents` to regenerate the `.claude/agents/` tree.',
396
489
  };
397
490
  }
398
491
 
@@ -705,6 +798,149 @@ export function runAgentsDrift({ cwd, fsImpl = fs, resolvePackageRoot } = {}) {
705
798
  };
706
799
  }
707
800
 
801
+ // ---------------------------------------------------------------------------
802
+ // check: pin-current
803
+ // ---------------------------------------------------------------------------
804
+
805
+ /**
806
+ * Fatal doctor check (Story #4525 / #4530): is the version actually
807
+ * resolvable in `node_modules` **consistent with** the consumer's declared
808
+ * `mandrel` dependency range (`package.json`)?
809
+ *
810
+ * This is a **different** signal from `agents-drift` (are the materialized
811
+ * `.agents/` file *contents* byte-identical to the installed payload) and
812
+ * from `version-current` below (is a *newer* version *published*). Neither
813
+ * of those catches the shape of bug #4525 reported: a `package.json` pin
814
+ * that has fallen out of agreement with what `node_modules` actually
815
+ * resolves to — e.g. an out-of-band symlink, or `npm install mandrel@latest
816
+ * --no-save` — which `mandrel doctor` graded as fully green before this
817
+ * check existed, because the only version `defaultCurrentVersion` ever read
818
+ * WAS the inflated `node_modules` one.
819
+ *
820
+ * **Range-aware.** The declared pin is a *range*, not an equality, so the
821
+ * question this check asks is satisfaction, not identity. A consumer who
822
+ * declares `^2.1.0` and runs a routine `npm update` gets 2.4.0 in
823
+ * `node_modules` with `package.json` untouched — that is npm behaving
824
+ * exactly as documented, and under this project's `always-bump-minor`
825
+ * release cadence it is the *normal* steady state, not a defect. Grading it
826
+ * fatal (as this check originally did, comparing only the pin's base
827
+ * version) made `mandrel doctor` cry wolf on healthy installs.
828
+ *
829
+ * The graded contract:
830
+ * - installed **satisfies** the declared range and equals its base version
831
+ * → pass, quietly.
832
+ * - installed **satisfies** the declared range but is newer than its base
833
+ * (`^2.1.0` + 2.4.0) → pass with an **advisory** `detail`. Re-pinning via
834
+ * `mandrel update` is tidier, but nothing is broken. This mirrors how
835
+ * `version-current` stays non-fatal: `ok: true` with the advisory carried
836
+ * in `detail` (the registry's `advisory: true` flag documents an entry
837
+ * whose `run()` *never* fails, which is not true of this check).
838
+ * - installed does **not** satisfy the declared range (`^2.1.0` + 3.0.0, or
839
+ * an exact `2.1.0` pin + 2.4.0) → **fail**. The declared dependency does
840
+ * not describe the code that is running.
841
+ * - installed is **behind** the pin's base version (`^2.4.0` + 2.1.0) →
842
+ * **fail**, and note that `<` the base never satisfies any of the ranges
843
+ * `resolveConsumerPinSpec` yields, so this is a sub-case of the above
844
+ * given a distinct, more actionable message.
845
+ *
846
+ * Skips cleanly (not a failure) when there is no resolvable pin at all — no
847
+ * `package.json`, no `mandrel` entry in `dependencies`/`devDependencies`, or
848
+ * a non-semver specifier (`workspace:`, `git+`, `latest`, a comparator
849
+ * range) — via {@link resolveConsumerPinSpec}'s own `null` contract. This
850
+ * is also how mandrel's own repo (no self-dependency) and workspace/npx
851
+ * consumers degrade to a clean pass rather than a false failure.
852
+ *
853
+ * Injectable seams (used by tests so no real filesystem or package is
854
+ * needed):
855
+ * - `cwd()` — replaces `process.cwd`, anchoring both the pin read and the
856
+ * `node_modules` resolution at the same consumer root (mirrors
857
+ * `agents-drift` / `agents-in-sync`).
858
+ * - `fsImpl` — replaces the `node:fs` surface.
859
+ * - `resolvePackageRoot(fromDir)` — replaces `mandrel` resolution; throws
860
+ * when the package is not installed.
861
+ *
862
+ * @param {{
863
+ * cwd?: () => string,
864
+ * fsImpl?: typeof fs,
865
+ * resolvePackageRoot?: (fromDir: string) => string,
866
+ * }} [opts]
867
+ * @returns {{ ok: boolean, detail: string, remedy?: string }}
868
+ */
869
+ export function runPinCurrent({ cwd, fsImpl = fs, resolvePackageRoot } = {}) {
870
+ const getCwd = cwd ?? (() => process.cwd());
871
+ const resolveRoot = resolvePackageRoot ?? defaultResolvePackageRoot;
872
+ const projectRoot = getCwd();
873
+
874
+ const spec = resolveConsumerPinSpec(projectRoot, fsImpl);
875
+ if (!spec) {
876
+ return {
877
+ ok: true,
878
+ detail: 'no resolvable mandrel dependency pin — skipped',
879
+ };
880
+ }
881
+
882
+ let installedRoot;
883
+ try {
884
+ installedRoot = resolveRoot(projectRoot);
885
+ } catch {
886
+ // No baseline to compare the pin against; agents-materialized /
887
+ // runtime-deps own the "not installed" remedy.
888
+ return {
889
+ ok: true,
890
+ detail: 'mandrel not installed — pin check skipped',
891
+ };
892
+ }
893
+
894
+ let installed;
895
+ try {
896
+ const parsed = JSON.parse(
897
+ fsImpl.readFileSync(path.join(installedRoot, 'package.json'), 'utf8'),
898
+ );
899
+ installed = String(parsed.version);
900
+ } catch {
901
+ return {
902
+ ok: true,
903
+ detail: 'installed version unreadable — pin check skipped',
904
+ };
905
+ }
906
+
907
+ const declared = `${spec.operator}${spec.version}`;
908
+
909
+ if (compareSemver(installed, spec.version) < 0) {
910
+ return {
911
+ ok: false,
912
+ detail: `package.json pins ${declared} but an older v${installed} is installed`,
913
+ remedy:
914
+ 'Run `npm install` to install a version satisfying the package.json pin.',
915
+ };
916
+ }
917
+
918
+ if (!satisfiesPinSpec(installed, spec)) {
919
+ return {
920
+ ok: false,
921
+ detail: `package.json pins ${declared} but v${installed} is installed — outside the declared range`,
922
+ remedy:
923
+ 'Run `mandrel update` to reconcile the package.json pin with the installed version.',
924
+ };
925
+ }
926
+
927
+ if (compareSemver(installed, spec.version) > 0) {
928
+ // In range, just newer than the declared base — the ordinary result of an
929
+ // `npm update` under a caret/tilde pin. Healthy, so `ok: true`; the
930
+ // advisory rides in `detail` (the doctor runner only prints `remedy` for
931
+ // failures).
932
+ return {
933
+ ok: true,
934
+ detail: `v${installed} satisfies the ${declared} pin but is newer than it — run \`mandrel update\` to re-pin (advisory)`,
935
+ };
936
+ }
937
+
938
+ return {
939
+ ok: true,
940
+ detail: `pin ${declared} matches the installed version`,
941
+ };
942
+ }
943
+
708
944
  // ---------------------------------------------------------------------------
709
945
  // check: version-current
710
946
  // ---------------------------------------------------------------------------
@@ -870,6 +1106,13 @@ export const registry = [
870
1106
  name: 'agents-drift',
871
1107
  run: (opts) => runAgentsDrift(opts),
872
1108
  },
1109
+ {
1110
+ name: 'pin-current',
1111
+ // Fatal, unlike version-current below (Story #4525/#4530): a pin/install
1112
+ // disagreement means the declared dependency does not describe the code
1113
+ // that is running.
1114
+ run: (opts) => runPinCurrent(opts),
1115
+ },
873
1116
  {
874
1117
  name: 'version-current',
875
1118
  // Non-fatal: surfaces a cache-only stale-version advisory. `run()` always