mandrel 1.59.0 → 1.61.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 (267) hide show
  1. package/.agents/README.md +86 -44
  2. package/.agents/docs/SDLC.md +135 -141
  3. package/.agents/docs/configuration.md +77 -20
  4. package/.agents/docs/quality-gates.md +796 -0
  5. package/.agents/docs/workflows.md +6 -9
  6. package/.agents/instructions.md +12 -11
  7. package/.agents/personas/architect.md +1 -1
  8. package/.agents/personas/product.md +1 -1
  9. package/.agents/personas/project-manager.md +14 -14
  10. package/.agents/personas/technical-writer.md +1 -1
  11. package/.agents/rules/changelog-style.md +5 -5
  12. package/.agents/rules/git-conventions.md +3 -3
  13. package/.agents/runtime-deps.json +2 -2
  14. package/.agents/schemas/agentrc.schema.json +3 -3
  15. package/.agents/schemas/dispatch-manifest.json +4 -4
  16. package/.agents/schemas/epic-spec.schema.json +15 -45
  17. package/.agents/schemas/lifecycle/README.md +1 -1
  18. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
  20. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
  21. package/.agents/schemas/validation-evidence.schema.json +1 -1
  22. package/.agents/scripts/README.md +2 -2
  23. package/.agents/scripts/acceptance-eval.js +1 -1
  24. package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
  25. package/.agents/scripts/agents-bootstrap-github.js +23 -119
  26. package/.agents/scripts/analyze-execution.js +2 -2
  27. package/.agents/scripts/audit-to-stories.js +1 -1
  28. package/.agents/scripts/check-doc-links.js +2 -3
  29. package/.agents/scripts/diagnose-friction.js +1 -1
  30. package/.agents/scripts/dispatcher.js +2 -2
  31. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  32. package/.agents/scripts/epic-audit-prepare.js +3 -3
  33. package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
  34. package/.agents/scripts/epic-deliver-preflight.js +6 -6
  35. package/.agents/scripts/epic-deliver-prepare.js +1 -1
  36. package/.agents/scripts/epic-execute-record-wave.js +4 -4
  37. package/.agents/scripts/epic-plan-healthcheck.js +6 -10
  38. package/.agents/scripts/epic-plan-spec-validate.js +1 -1
  39. package/.agents/scripts/epic-reconcile.js +11 -29
  40. package/.agents/scripts/evidence-gate.js +1 -1
  41. package/.agents/scripts/generate-workflows-doc.js +1 -1
  42. package/.agents/scripts/hierarchy-gate.js +7 -11
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -1
  44. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  45. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
  46. package/.agents/scripts/lib/baseline-snapshot.js +7 -7
  47. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  48. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  49. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
  50. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  51. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +47 -1
  52. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  53. package/.agents/scripts/lib/bootstrap/gh-preflight.js +7 -9
  54. package/.agents/scripts/lib/bootstrap/manifest.js +21 -1
  55. package/.agents/scripts/lib/bootstrap/merge-methods.js +31 -16
  56. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +32 -11
  57. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  58. package/.agents/scripts/lib/config/explain.js +1 -1
  59. package/.agents/scripts/lib/config/runners.js +2 -2
  60. package/.agents/scripts/lib/config/runtime.js +1 -1
  61. package/.agents/scripts/lib/config/sync-agentrc.js +1 -1
  62. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  63. package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
  64. package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
  65. package/.agents/scripts/lib/config-settings-schema.js +3 -3
  66. package/.agents/scripts/lib/detect-package-manager.js +72 -0
  67. package/.agents/scripts/lib/duplicate-search.js +1 -1
  68. package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
  69. package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
  70. package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
  71. package/.agents/scripts/lib/errors/index.js +4 -4
  72. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
  73. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
  74. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  75. package/.agents/scripts/lib/findings/promote-finding.js +10 -10
  76. package/.agents/scripts/lib/label-constants.js +3 -4
  77. package/.agents/scripts/lib/label-taxonomy.js +5 -10
  78. package/.agents/scripts/lib/onboard/detect-stack.js +10 -10
  79. package/.agents/scripts/lib/onboard/init-tail.js +218 -0
  80. package/.agents/scripts/lib/onboard/scaffold-docs.js +18 -3
  81. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
  82. package/.agents/scripts/lib/orchestration/code-review.js +5 -5
  83. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
  84. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
  85. package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
  86. package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
  87. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +9 -25
  88. package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
  89. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +8 -8
  90. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
  91. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
  92. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
  93. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +26 -13
  94. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +1 -1
  95. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
  96. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +2 -2
  97. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
  98. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
  99. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
  100. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
  101. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +6 -21
  102. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
  103. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -1
  104. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -2
  105. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
  106. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
  107. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +8 -8
  108. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -4
  109. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
  110. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
  111. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
  112. package/.agents/scripts/lib/orchestration/file-assumptions.js +2 -2
  113. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
  114. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
  115. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
  116. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -3
  117. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
  118. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +1 -1
  119. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
  120. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
  121. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
  122. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
  123. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
  124. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  125. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
  126. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
  127. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +1 -1
  128. package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
  129. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
  130. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
  131. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
  132. package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
  133. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
  134. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
  135. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
  136. package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
  137. package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
  138. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
  139. package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
  140. package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
  141. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  142. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
  143. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +2 -2
  144. package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
  145. package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
  146. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -2
  147. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
  148. package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
  149. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -12
  150. package/.agents/scripts/lib/orchestration/ticketing/reads.js +8 -8
  151. package/.agents/scripts/lib/orchestration/ticketing/state.js +3 -3
  152. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +2 -2
  153. package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -1
  154. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  155. package/.agents/scripts/lib/preflight-runner.js +1 -1
  156. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
  157. package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
  158. package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
  159. package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
  160. package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
  161. package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
  162. package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
  163. package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
  164. package/.agents/scripts/lib/runtime-deps/preflight.js +6 -6
  165. package/.agents/scripts/lib/signals/schema.js +1 -1
  166. package/.agents/scripts/lib/spec/index.js +1 -1
  167. package/.agents/scripts/lib/spec/loader.js +2 -2
  168. package/.agents/scripts/lib/spec/state.js +7 -16
  169. package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
  170. package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
  171. package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
  172. package/.agents/scripts/lib/story-lifecycle.js +8 -8
  173. package/.agents/scripts/lib/story-plan.js +1 -1
  174. package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
  175. package/.agents/scripts/lib/wave-runner/tick.js +1 -1
  176. package/.agents/scripts/lib/worktree/node-modules-strategy.js +5 -2
  177. package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
  178. package/.agents/scripts/lifecycle-emit.js +1 -1
  179. package/.agents/scripts/providers/github/board-add.js +1 -1
  180. package/.agents/scripts/providers/github/errors.js +1 -1
  181. package/.agents/scripts/providers/github/mappers.js +2 -2
  182. package/.agents/scripts/providers/github/tickets.js +4 -4
  183. package/.agents/scripts/resync-status-column.js +1 -1
  184. package/.agents/scripts/retro-run.js +2 -2
  185. package/.agents/scripts/run-lint.js +1 -1
  186. package/.agents/scripts/single-story-init.js +1 -1
  187. package/.agents/scripts/stories-wave-tick.js +5 -5
  188. package/.agents/scripts/story-close.js +1 -1
  189. package/.agents/scripts/story-init.js +13 -16
  190. package/.agents/scripts/story-phase.js +5 -5
  191. package/.agents/scripts/story-plan.js +3 -3
  192. package/.agents/scripts/sync-branch-from-base.js +1 -1
  193. package/.agents/scripts/validate-docs-freshness.js +1 -1
  194. package/.agents/scripts/wave-tick.js +1 -1
  195. package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
  196. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
  197. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
  198. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
  199. package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
  200. package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
  201. package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
  202. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
  203. package/.agents/skills/core/scope-triage/SKILL.md +9 -10
  204. package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
  205. package/.agents/skills/skills.index.json +7 -7
  206. package/.agents/templates/agent-protocol.md +2 -2
  207. package/.agents/workflows/agents-update.md +16 -31
  208. package/.agents/workflows/audit-architecture.md +2 -2
  209. package/.agents/workflows/audit-clean-code.md +2 -2
  210. package/.agents/workflows/audit-dependencies.md +1 -1
  211. package/.agents/workflows/audit-devops.md +1 -1
  212. package/.agents/workflows/audit-documentation.md +2 -2
  213. package/.agents/workflows/audit-lighthouse.md +1 -1
  214. package/.agents/workflows/audit-performance.md +2 -2
  215. package/.agents/workflows/audit-privacy.md +1 -1
  216. package/.agents/workflows/audit-quality.md +2 -2
  217. package/.agents/workflows/audit-security.md +2 -2
  218. package/.agents/workflows/audit-seo.md +1 -1
  219. package/.agents/workflows/audit-sre.md +1 -1
  220. package/.agents/workflows/audit-to-stories.md +10 -10
  221. package/.agents/workflows/audit-ux-ui.md +1 -1
  222. package/.agents/workflows/deliver.md +85 -0
  223. package/.agents/workflows/explain.md +3 -3
  224. package/.agents/workflows/git-merge-pr.md +1 -1
  225. package/.agents/workflows/git-pr-all.md +13 -10
  226. package/.agents/workflows/git-push.md +6 -3
  227. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  228. package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
  229. package/.agents/workflows/helpers/agents-sync-config.md +3 -2
  230. package/.agents/workflows/helpers/code-review.md +5 -5
  231. package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +43 -43
  232. package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
  233. package/.agents/workflows/helpers/diagnose.md +1 -1
  234. package/.agents/workflows/helpers/epic-audit.md +6 -6
  235. package/.agents/workflows/helpers/epic-deliver-story.md +13 -13
  236. package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
  237. package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
  238. package/.agents/workflows/helpers/epic-testing.md +3 -3
  239. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  240. package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
  241. package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
  242. package/.agents/workflows/helpers/signals.md +1 -1
  243. package/.agents/workflows/helpers/single-story-deliver.md +11 -11
  244. package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
  245. package/.agents/workflows/plan.md +131 -0
  246. package/.agents/workflows/qa-explore.md +1 -1
  247. package/.agents/workflows/qa-run-harness.md +1 -1
  248. package/README.md +19 -39
  249. package/bin/mandrel.js +235 -16
  250. package/docs/CHANGELOG.md +1173 -0
  251. package/lib/cli/doctor.js +45 -3
  252. package/lib/cli/init.js +97 -36
  253. package/lib/cli/registry.js +41 -145
  254. package/lib/cli/sync.js +122 -23
  255. package/lib/cli/uninstall.js +42 -7
  256. package/lib/cli/update.js +524 -210
  257. package/lib/cli/version-helpers.js +59 -0
  258. package/package.json +7 -6
  259. package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
  260. package/.agents/workflows/onboard.md +0 -208
  261. package/lib/cli/__tests__/migrate.test.js +0 -268
  262. package/lib/cli/__tests__/sync-local-zone.test.js +0 -247
  263. package/lib/cli/__tests__/sync.test.js +0 -372
  264. package/lib/cli/__tests__/update-major.test.js +0 -217
  265. package/lib/cli/__tests__/update.test.js +0 -696
  266. package/lib/cli/__tests__/version-check.test.js +0 -398
  267. package/lib/migrations/__tests__/index.test.js +0 -216
@@ -15,13 +15,7 @@
15
15
  * @see docs/v5-implementation-plan.md Sprint 1C
16
16
  */
17
17
 
18
- import fs from 'node:fs';
19
- import path from 'node:path';
20
18
  import { applyBranchProtection } from './lib/bootstrap/branch-protection.js';
21
- import {
22
- CI_WORKFLOW_RELATIVE_PATH,
23
- renderCiWorkflow,
24
- } from './lib/bootstrap/ci-workflow-template.js';
25
19
  import {
26
20
  compareSemver,
27
21
  MIN_GH_VERSION,
@@ -55,7 +49,7 @@ import {
55
49
  import { createProvider } from './lib/provider-factory.js';
56
50
 
57
51
  const PROJECTS_DOC_POINTER =
58
- 'See docs/project-board.md for the manual Projects V2 setup checklist.';
52
+ 'Configure the board views manually in the GitHub Projects UI.';
59
53
 
60
54
  /**
61
55
  * Detect that an error is a not-found / 404 signal across the surfaces
@@ -266,106 +260,6 @@ async function ensureProjectFields(provider, project, log) {
266
260
  return fields;
267
261
  }
268
262
 
269
- /**
270
- * Create or additively-merge branch protection on `baseBranch` (typically
271
- * `main`) so the `delivery.quality.prGate.checks` suite is required
272
- * before merge. Behaviour rules:
273
- *
274
- * - `enforceBranchProtection: false` → skip, log the opt-out, return a
275
- * `{ status: 'skipped' }` summary.
276
- * - `prGate.checks` empty or absent → skip with a clear log, since there
277
- * is nothing to enforce.
278
- * - Existing protection rule → preserve every existing required-check
279
- * context and append only the missing prGate names.
280
- * - No existing rule → create a fresh one carrying just the prGate
281
- * contexts plus minimal sensible defaults (strict status checks).
282
- *
283
- * Errors (insufficient scopes, repo permission denied, etc.) are logged
284
- * and return a `{ status: 'failed' }` summary so the bootstrap CLI
285
- * surfaces a non-fatal warning rather than aborting the entire run —
286
- * matching how the project-board provisioning steps degrade.
287
- */
288
- async function ensureMainBranchProtection(
289
- provider,
290
- { baseBranch, prGate },
291
- log,
292
- ) {
293
- if (prGate?.enforceBranchProtection === false) {
294
- log(
295
- `[bootstrap] Branch protection on '${baseBranch}': skipped (delivery.quality.prGate.enforceBranchProtection=false).`,
296
- );
297
- return { status: 'skipped', reason: 'opt-out' };
298
- }
299
-
300
- const checkNames = (prGate?.checks ?? [])
301
- .map((c) => c?.name)
302
- .filter((n) => typeof n === 'string' && n.length > 0);
303
- if (checkNames.length === 0) {
304
- log(
305
- `[bootstrap] Branch protection on '${baseBranch}': skipped (no prGate.checks configured).`,
306
- );
307
- return { status: 'skipped', reason: 'no-checks' };
308
- }
309
-
310
- try {
311
- const result = await provider.setBranchProtection(baseBranch, {
312
- contexts: checkNames,
313
- });
314
- const verb = result.created ? 'Created' : 'Updated';
315
- const addedSuffix = result.added.length
316
- ? ` (added: ${result.added.join(', ')})`
317
- : ' (all required checks already present)';
318
- log(
319
- `[bootstrap] Branch protection on '${baseBranch}': ${verb} rule${addedSuffix}.`,
320
- );
321
- return { status: result.created ? 'created' : 'merged', ...result };
322
- } catch (err) {
323
- log(
324
- `[bootstrap] Branch protection on '${baseBranch}': failed — ${err.message}. Proceeding without it.`,
325
- );
326
- return { status: 'failed', reason: err.message };
327
- }
328
- }
329
-
330
- /**
331
- * Render the stabilized-quality-gates CI workflow template into a project
332
- * checkout. Idempotent on the byte level: when `.github/workflows/ci.yml`
333
- * already matches the rendered template, no write occurs and the action is
334
- * `unchanged`. When the file is absent the action is `created`. When the
335
- * file exists with operator-authored differences the helper preserves it
336
- * and returns `custom-workflow-skip` along with the rendered body so the
337
- * bootstrap caller (or `/agents-update`) can offer a side-by-side diff.
338
- *
339
- * Network-free; safe to invoke under tests with a tmp `projectRoot`.
340
- *
341
- * @param {object} args
342
- * @param {string} args.projectRoot - Repo root (must contain or accept
343
- * `.github/workflows/`).
344
- * @param {object} [args.template] - Forwarded to `renderCiWorkflow`.
345
- * @param {boolean} [args.write=true] - When `false`, the helper computes
346
- * the would-be action without touching disk. Used by the
347
- * bootstrap CLI's dry-run mode.
348
- * @returns {{ action: 'created'|'unchanged'|'custom-workflow-skip',
349
- * path: string, rendered: string }}
350
- */
351
- export function ensureCiWorkflow(args) {
352
- const projectRoot = args.projectRoot;
353
- const rendered = renderCiWorkflow(args.template);
354
- const target = path.join(projectRoot, CI_WORKFLOW_RELATIVE_PATH);
355
- if (!fs.existsSync(target)) {
356
- if (args.write !== false) {
357
- fs.mkdirSync(path.dirname(target), { recursive: true });
358
- fs.writeFileSync(target, rendered, 'utf8');
359
- }
360
- return { action: 'created', path: target, rendered };
361
- }
362
- const existing = fs.readFileSync(target, 'utf8');
363
- if (existing === rendered) {
364
- return { action: 'unchanged', path: target, rendered };
365
- }
366
- return { action: 'custom-workflow-skip', path: target, rendered };
367
- }
368
-
369
263
  /**
370
264
  * Run the idempotent bootstrap sequence.
371
265
  *
@@ -397,6 +291,7 @@ export function ensureCiWorkflow(args) {
397
291
  * github?: object,
398
292
  * baseBranch?: string,
399
293
  * githubAdminApproved?: boolean,
294
+ * isTTY?: boolean,
400
295
  * }} [opts] - `githubAdminApproved` MUST be `true` for any GitHub mutation to
401
296
  * occur; any other value (absent / `false`) is treated as "not approved"
402
297
  * and the run is a verified no-op.
@@ -463,12 +358,12 @@ export async function runBootstrap(config, opts = {}) {
463
358
  // Consumer-facing bootstrap promotes the framework's CI-gates-only
464
359
  // stance: branch protection with enforce_admins + 0-approval-count and
465
360
  // the squash-only merge-method allowlist. Behavior-shifting drift on
466
- // either step routes through the HITL confirm gate — non-TTY runs abort
467
- // with a clear stderr message rather than silently apply.
361
+ // branch protection routes through the HITL confirm gate — non-TTY runs
362
+ // abort with a clear stderr message rather than silently apply. The
363
+ // merge-method step differs by design (Story #4045 A4): non-TTY without an
364
+ // assume override default-applies the framework stance with an explicit
365
+ // log line (see mergeMethodsHitlConfirm below).
468
366
  //
469
- // The legacy `ensureMainBranchProtection` helper is preserved (re-
470
- // exported below) so the Epic #1142 Story #1157 contract tests stay
471
- // green; `applyBranchProtection` is its consumer-parity successor.
472
367
  // Post-reshape: bootstrap reads from the new `project` + `github` blocks
473
368
  // exclusively. The legacy "agent settings" opt was removed in Epic #2880.
474
369
  const projectCfg = opts.project ?? config.project ?? {};
@@ -493,10 +388,22 @@ export async function runBootstrap(config, opts = {}) {
493
388
  hitlConfirm,
494
389
  log,
495
390
  });
391
+
392
+ // Merge-methods gate (Story #4045 A4): under non-TTY without an explicit
393
+ // assume override there is no operator to consult, and the default HITL
394
+ // gate declines every non-TTY prompt — which would make applyMergeMethods'
395
+ // documented non-TTY default-apply branch unreachable. Skip the gate in
396
+ // that case so the merge-method stance default-applies with its explicit
397
+ // log line. Interactive runs (and explicit --assume-yes/--assume-no, and
398
+ // injected gates) keep the loud confirm/decline behaviour.
399
+ const stdoutIsTTY = opts.isTTY ?? Boolean(process.stdout.isTTY);
400
+ const mergeMethodsHitlConfirm =
401
+ opts.hitlConfirm ??
402
+ (stdoutIsTTY || opts.assumeYes || opts.assumeNo ? hitlConfirm : undefined);
496
403
  const mergeMethods = await applyMergeMethods({
497
404
  provider,
498
405
  settings,
499
- hitlConfirm,
406
+ hitlConfirm: mergeMethodsHitlConfirm,
500
407
  log,
501
408
  });
502
409
 
@@ -539,8 +446,9 @@ async function main() {
539
446
  }
540
447
 
541
448
  // Preflight runtime deps before the dynamic config-resolver import so
542
- // a green-field consumer who skipped `/agents-bootstrap-project` gets
543
- // a workflow hint instead of a raw `ERR_MODULE_NOT_FOUND`.
449
+ // a consumer who hasn't installed framework runtime deps yet gets a
450
+ // clear hint (`run mandrel init` or `npm install mandrel`) instead of
451
+ // a raw `ERR_MODULE_NOT_FOUND`.
544
452
  try {
545
453
  await preflightRuntimeDeps();
546
454
  } catch (err) {
@@ -569,7 +477,6 @@ async function main() {
569
477
  process.exit(1);
570
478
  }
571
479
 
572
- const installWorkflows = process.argv.includes('--install-workflows');
573
480
  // Epic #1235 Story 5 — flags let CI / non-interactive callers pin the
574
481
  // HITL gate's answer deterministically. The bootstrap is non-interactive
575
482
  // by default in non-TTY contexts (the gate returns false and aborts);
@@ -594,7 +501,6 @@ async function main() {
594
501
 
595
502
  try {
596
503
  const result = await runBootstrap(config, {
597
- installWorkflows,
598
504
  project: config.project,
599
505
  github: config.github,
600
506
  assumeYes,
@@ -617,12 +523,10 @@ async function main() {
617
523
  }
618
524
  }
619
525
 
620
- // Re-export internal helpers for test consumers (no production caller imports them).
621
526
  // Re-export the gh-preflight surface so existing test consumers can keep
622
527
  // importing it from this module after the Story #3349 split.
623
528
  export {
624
529
  compareSemver,
625
- ensureMainBranchProtection,
626
530
  isApiAccessNotFoundError,
627
531
  MIN_GH_VERSION,
628
532
  parseGhVersion,
@@ -18,7 +18,7 @@
18
18
  * fetching each `story-perf-summary` structured comment from the
19
19
  * ticketing provider. Posts the
20
20
  * `<!-- structured:epic-perf-report -->` comment on the Epic ticket.
21
- * Run from the retro composer / `/epic-deliver` Phase 6.0.
21
+ * Run from the retro composer / `/deliver` Phase 6.0.
22
22
  *
23
23
  * Both modes are idempotent: `upsertStructuredComment` deletes the prior
24
24
  * marker before posting the new one.
@@ -27,7 +27,7 @@
27
27
  * NDJSON for a Story, no children for an Epic) so the close pipelines
28
28
  * never block on observability output. Hard failures (bad CLI args,
29
29
  * provider error, schema-violating payload) exit non-zero — the call
30
- * sites in post-merge-pipeline / `/epic-deliver` Phase 5 treat that
30
+ * sites in post-merge-pipeline / `/deliver` Phase 5 treat that
31
31
  * as a non-fatal warning.
32
32
  *
33
33
  * This file is a thin CLI: it wires the I/O readers from
@@ -13,7 +13,7 @@
13
13
  * stdout when --json is set).
14
14
  *
15
15
  * --emit-epic-seed --plan <plan.json> --out <path>
16
- * Read the plan envelope from disk, render the `/epic-plan --idea`
16
+ * Read the plan envelope from disk, render the `/plan --idea`
17
17
  * seed markdown, persist to --out.
18
18
  *
19
19
  * --emit-stories --plan <plan.json>
@@ -5,7 +5,7 @@
5
5
  // Story #2662 — Internal-link and slash-command resolver for active docs.
6
6
  //
7
7
  // Scans every `*.md` under `docs/` and `.agents/` (excluding
8
- // `docs/CHANGELOG.md` and anything under `docs/archive/**`) and validates:
8
+ // `docs/CHANGELOG.md`) and validates:
9
9
  //
10
10
  // 1. Every Markdown relative-path link `[text](relative/path[#anchor])`
11
11
  // resolves to a real file on disk (anchors are not validated, only
@@ -19,7 +19,7 @@
19
19
  //
20
20
  // 3. No active doc mentions any retired slash command. The retired-command
21
21
  // blocklist is seeded with `agents-bootstrap-github`,
22
- // `single-story-plan` (renamed to `/story-plan`), and `mandrel`
22
+ // `single-story-plan` (renamed to `/plan`), and `mandrel`
23
23
  // (retired in favor of the generated `.agents/docs/workflows.md`
24
24
  // catalog) and takes precedence over the workflow-resolution check —
25
25
  // a retired token is always a non-zero exit even if a stale workflow
@@ -125,7 +125,6 @@ export const SLASH_ALLOWLIST = new Set([
125
125
 
126
126
  function isExcludedRelPath(relPath) {
127
127
  if (relPath === 'docs/CHANGELOG.md') return true;
128
- if (relPath.startsWith('docs/archive/')) return true;
129
128
  return false;
130
129
  }
131
130
 
@@ -134,7 +134,7 @@ function buildFrictionSignal({
134
134
  timestamp: new Date().toISOString(),
135
135
  epicId: epicId ?? null,
136
136
  storyId: storyId ?? null,
137
- // 3-tier hierarchy (Epic #3163): no Task tier, so friction signals
137
+ // 2-tier hierarchy (Epic #3163): no Task tier, so friction signals
138
138
  // carry no Task id. The field is retained for schema compatibility
139
139
  // and always null.
140
140
  taskId: null,
@@ -72,12 +72,12 @@ import { loadSpec, loadState } from './lib/spec/index.js';
72
72
  * loaded state mapping. The spec-aware renderer (`buildManifestFromSpec`)
73
73
  * looks up each Story's status via `state.mapping[slug].lastObservedAgentState`;
74
74
  * that field is only refreshed by the structural reconciler, so during
75
- * `/epic-deliver` execution it stays `null` and every Story renders as ⬜
75
+ * `/deliver` execution it stays `null` and every Story renders as ⬜
76
76
  * pending even after the Story merges. The wave-runner replaced the
77
77
  * dispatcher-per-wave refresh loop and the local state.json never sees
78
78
  * the progress signal.
79
79
  *
80
- * Under the 3-tier hierarchy (Epic #3163) the runtime manifest's wave
80
+ * Under the 2-tier hierarchy (Epic #3163) the runtime manifest's wave
81
81
  * records carry `stories[]` (each with the live `storyId` + `status` from
82
82
  * `fetchEpicContext`'s GH query), not the retired `tasks[]` shape. The
83
83
  * overlay walks `manifest.waves[].stories[]` and copies each Story's
@@ -8,7 +8,7 @@
8
8
  * any still-stuck entries by enumerating the processes holding handles
9
9
  * inside the worktree path and terminating them.
10
10
  *
11
- * Invoked by `/epic-deliver`, `/epic-plan-spec` / `/epic-plan-decompose`
11
+ * Invoked by `/deliver`, `/epic-plan-spec` / `/epic-plan-decompose`
12
12
  * (via `drainPendingCleanupAtBoot` → `worktree-sweep.js`), and
13
13
  * `story-close` so the pending-cleanup ledger drains automatically
14
14
  * across the sprint lifecycle. Operators can also run it standalone:
@@ -2,7 +2,7 @@
2
2
  /* node:coverage ignore file */
3
3
 
4
4
  /**
5
- * epic-audit-prepare.js — Phase 4 prepare CLI for `/epic-deliver`.
5
+ * epic-audit-prepare.js — Phase 4 prepare CLI for `/deliver`.
6
6
  *
7
7
  * Thin glue around the audit-suite `selectAudits` SDK. Reads the Epic
8
8
  * ticket, runs the change-set selector against the Epic branch diff
@@ -193,7 +193,7 @@ function resolveTaskSizing(config) {
193
193
  * Best-effort and total, mirroring `resolveRiskRoutedLenses`: a
194
194
  * missing/unparseable checkpoint, an absent `planningRisk` field, or a
195
195
  * provider read failure all degrade to `standard` — the neutral default that
196
- * preserves today's behavior — so an Epic that skipped `/epic-plan` (no
196
+ * preserves today's behavior — so an Epic that skipped `/plan` (no
197
197
  * checkpoint) still gets a passing `standard` pass with no new failure mode.
198
198
  * The changed-file count can only escalate a low-risk Epic to `deep` (a wide
199
199
  * diff) and never downgrades a high-risk one; an unknown/absent count is the
@@ -295,7 +295,7 @@ export async function runEpicAuditPrepare(values, deps = {}) {
295
295
  const runner = deps.selectAudits ?? selectAudits;
296
296
 
297
297
  // Pin the change set to the requested Epic's own branch rather than the
298
- // shared checkout's HEAD (Story #3362). Under two concurrent /epic-deliver
298
+ // shared checkout's HEAD (Story #3362). Under two concurrent /deliver
299
299
  // runs sharing one working copy, a HEAD-relative diff silently reports the
300
300
  // *other* Epic's change set; `refs/heads/epic/<id>` is unambiguous.
301
301
  const epicBranch = `epic/${epicId}`;
@@ -3,9 +3,9 @@
3
3
 
4
4
  /**
5
5
  * epic-deliver-note-intervention.js — record a manual-intervention event
6
- * against the active `/epic-deliver` run-state checkpoint.
6
+ * against the active `/deliver` run-state checkpoint.
7
7
  *
8
- * The host LLM driving `/epic-deliver` invokes this CLI whenever it does
8
+ * The host LLM driving `/deliver` invokes this CLI whenever it does
9
9
  * something out-of-band that disqualifies the Epic from auto-merge:
10
10
  *
11
11
  * - `AskUserQuestion` to the operator mid-run
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  * epic-deliver-preflight.js — Story #2899 (Epic #2880, F13).
6
6
  *
7
- * Estimates the cost of an upcoming `/epic-deliver` run *before* Story
7
+ * Estimates the cost of an upcoming `/deliver` run *before* Story
8
8
  * fan-out and surfaces the result to the operator on two channels:
9
9
  *
10
10
  * 1. A JSON envelope on stdout (always) with the keys
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * The CLI is intentionally side-effect-light when `--dry-run` is set: no
21
21
  * comment write, no lifecycle emit. The slash-command workflow
22
- * (`/epic-deliver` Phase 1) calls the CLI without `--dry-run` so the
22
+ * (`/deliver` Phase 1) calls the CLI without `--dry-run` so the
23
23
  * comment is upserted; if any threshold is breached, the workflow flips
24
24
  * the Epic to `agent::blocked` and surfaces the envelope in chat for
25
25
  * operator review. The CLI itself does NOT flip labels — the workflow
@@ -70,7 +70,7 @@ const HELP = `Usage: node .agents/scripts/epic-deliver-preflight.js \\
70
70
  [--per-story-claude-tokens <n>]
71
71
 
72
72
  Estimates Story count, install cost, wave count, GitHub API request volume,
73
- and Claude Max quota burn for an Epic *before* /epic-deliver fan-out.
73
+ and Claude Max quota burn for an Epic *before* /deliver fan-out.
74
74
 
75
75
  Flags:
76
76
  --dry-run Compute the estimate and print the JSON
@@ -103,7 +103,7 @@ const DEFAULTS = Object.freeze({
103
103
  perStoryApiRequests: 25,
104
104
  perStoryClaudeTokens: 200_000,
105
105
  // Base GH API budget: snapshot getTicket + getSubTickets + plan/manifest
106
- // reads/writes that happen once per /epic-deliver run regardless of
106
+ // reads/writes that happen once per /deliver run regardless of
107
107
  // Story count. Empirical observation from a 5-Story Epic shows ~30
108
108
  // requests for the non-per-Story floor.
109
109
  baseApiRequests: 30,
@@ -240,7 +240,7 @@ export function renderPreflightBody({
240
240
  );
241
241
  } else {
242
242
  lines.push(
243
- '⛔ **Threshold breaches** — `/epic-deliver` will flip the Epic to `agent::blocked` for operator review:',
243
+ '⛔ **Threshold breaches** — `/deliver` will flip the Epic to `agent::blocked` for operator review:',
244
244
  );
245
245
  for (const b of breaches) {
246
246
  lines.push(`- \`${b.key}\` = ${b.observed} (max ${b.max})`);
@@ -284,7 +284,7 @@ export async function runPreflight({
284
284
  const provider = injectedProvider ?? createProvider(config);
285
285
  const thresholds = getPreflight(config);
286
286
 
287
- // Compose the same two phases /epic-deliver Phase 1 runs so the
287
+ // Compose the same two phases /deliver Phase 1 runs so the
288
288
  // preflight numbers match the actual dispatch plan.
289
289
  const ctx = { epicId, provider };
290
290
  let state = {};
@@ -2,7 +2,7 @@
2
2
  /* node:coverage ignore file */
3
3
 
4
4
  /**
5
- * epic-deliver-prepare.js — Step 0/1 of the operator-driven `/epic-deliver`.
5
+ * epic-deliver-prepare.js — Step 0/1 of the operator-driven `/deliver`.
6
6
  *
7
7
  * Composes the existing engine phases that the in-process epic-runner used to
8
8
  * call sequentially, but does NOT dispatch any waves. The CLI is the single
@@ -6,7 +6,7 @@
6
6
  * advance the `epic-run-state` checkpoint, and re-render the unified
7
7
  * `epic-run-progress` rollup on the Epic.
8
8
  *
9
- * The slash-command (`/epic-deliver`) calls this CLI once per wave, after
9
+ * The slash-command (`/deliver`) calls this CLI once per wave, after
10
10
  * its host-level Agent-tool fan-out drains. It is the only writer of the
11
11
  * `epic-run-progress` structured comment for the wave-completion path —
12
12
  * there is no separate `/wave-execute` skill, no `wave-run-progress`
@@ -95,7 +95,7 @@ const HELP = `Usage: node .agents/scripts/epic-execute-record-wave.js \\
95
95
 
96
96
  Records the wave's per-Story outcomes, advances the epic-run-state
97
97
  checkpoint, and upserts the unified epic-run-progress rollup on the Epic.
98
- Prints the next action for the /epic-deliver slash command.
98
+ Prints the next action for the /deliver slash command.
99
99
  `;
100
100
 
101
101
  /**
@@ -237,7 +237,7 @@ export async function runEpicExecuteRecordWave({
237
237
  // Closes the start/end pairing the wave-tick reconciler and the
238
238
  // `--check-idle` watchdog use to derive in-flight Stories. Before this
239
239
  // the only producer was `wave-session.js`, which the host-LLM driven
240
- // /epic-deliver path never imports — so every dispatched Story stayed
240
+ // /deliver path never imports — so every dispatched Story stayed
241
241
  // "in-flight" forever and completed Stories tripped the watchdog.
242
242
  // Best-effort: a failed append must not block the wave loop.
243
243
  emitWaveDispatchEnds({ epicId, verified, config });
@@ -257,7 +257,7 @@ export async function runEpicExecuteRecordWave({
257
257
 
258
258
  // 7. Fire the curated webhook events for this wave boundary. Mirrors the
259
259
  // wave-loop emits in `lib/orchestration/epic-runner/phases/iterate-waves.js`
260
- // for the host-LLM driven /epic-deliver path (which does not pass
260
+ // for the host-LLM driven /deliver path (which does not pass
261
261
  // through `runEpic`). Each helper is fire-and-forget — webhook
262
262
  // misconfig or a transient Slack outage must not block the wave loop.
263
263
  await emitWaveBoundaryNotifications({
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * epic-plan-healthcheck.js — Post-Plan Readiness Check
7
7
  *
8
- * Runs at the end of /epic-plan (Phase 10) to validate the backlog and
8
+ * Runs at the end of /plan (Phase 10) to validate the backlog and
9
9
  * optionally prime the execution environment before handing off to
10
10
  * /epic-deliver.
11
11
  *
@@ -27,7 +27,7 @@
27
27
  * node epic-plan-healthcheck.js --epic <EPIC_ID> \
28
28
  * [--paranoid] [--prime-install] [--dry-run]
29
29
  *
30
- * @see .agents/workflows/epic-plan.md Phase 10
30
+ * @see .agents/workflows/helpers/plan-epic.md Phase 10
31
31
  */
32
32
 
33
33
  import { spawnSync } from 'node:child_process';
@@ -131,7 +131,7 @@ function checkGitRemote(baseBranch, cwd) {
131
131
 
132
132
  /**
133
133
  * Detect whether a Story body carries an inline `## Acceptance` section with
134
- * at least one checklist item. Epic #3078 — under 3-tier hierarchy, Stories
134
+ * at least one checklist item. Epic #3078 — under 2-tier hierarchy, Stories
135
135
  * carry acceptance inline, so the hierarchy check uses this signal as the
136
136
  * mark of a complete, executable Story.
137
137
  *
@@ -152,7 +152,7 @@ function hasInlineAcceptance(body) {
152
152
  }
153
153
 
154
154
  /**
155
- * Validate Epic ticket hierarchy. 3-tier is the only supported hierarchy
155
+ * Validate Epic ticket hierarchy. 2-tier is the only supported hierarchy
156
156
  * after Task #3154 deleted `planning.hierarchy`: every Story must carry an
157
157
  * inline `## Acceptance` checklist; there is no Task layer to graph.
158
158
  *
@@ -181,13 +181,9 @@ async function checkTickets(provider, epicId) {
181
181
  return { ok: false, detail: `Epic #${epicId} has no child tickets.` };
182
182
  }
183
183
 
184
- const features = tickets.filter((t) =>
185
- t.labels.includes(TYPE_LABELS.FEATURE),
186
- );
187
184
  const stories = tickets.filter((t) => t.labels.includes(TYPE_LABELS.STORY));
188
185
 
189
186
  const errors = [];
190
- if (features.length === 0) errors.push('no type::feature tickets');
191
187
  if (stories.length === 0) errors.push('no type::story tickets');
192
188
 
193
189
  const missingAcceptance = stories.filter(
@@ -214,7 +210,7 @@ async function checkTickets(provider, epicId) {
214
210
 
215
211
  return {
216
212
  ok: true,
217
- detail: `${features.length} features, ${stories.length} stories (3-tier, inline acceptance) — hierarchy valid${advisory}.`,
213
+ detail: `${stories.length} stories (2-tier, inline acceptance) — hierarchy valid${advisory}.`,
218
214
  };
219
215
  }
220
216
 
@@ -313,7 +309,7 @@ export async function runPlanHealthcheck(opts = {}) {
313
309
  await timed('git-remote', async () => checkGitRemote(baseBranch, cwd)),
314
310
  );
315
311
 
316
- // Paranoid lane: ticket-hierarchy revalidation (3-tier only).
312
+ // Paranoid lane: ticket-hierarchy revalidation (2-tier only).
317
313
  if (paranoid) {
318
314
  const provider = opts.injectedProvider || createProvider(config);
319
315
  progress('CHECK', 'Validating ticket hierarchy...');
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * epic-plan-spec-validate.js — Phase 7.5 Tech Spec post-authoring gate CLI.
5
5
  *
6
- * `/epic-plan` Phase 7 authors the Tech Spec; Phase 8.3 (Holistic
6
+ * `/plan` Phase 7 authors the Tech Spec; Phase 8.3 (Holistic
7
7
  * Consolidation) reconciles the draft ticket array against the Tech Spec's
8
8
  * `## Delivery Slicing` section, which the decompose-author skill uses as the
9
9
  * capability-boundary anchor. When that section is absent the consolidation
@@ -195,11 +195,11 @@ export async function fetchGhState(provider, epicId) {
195
195
  }
196
196
 
197
197
  /**
198
- * Walk the spec depth-first and yield one `{ slug, entity, title,
199
- * parentSlug, dependsOn }` record per logical entity (epic → feature
200
- * story → task), mirroring the diff engine's `flattenSpec`. Local to the
201
- * CLI so the reseed pass (below) can map spec slugs onto live GH issues
202
- * without importing the diff engine's private walker. Pure.
198
+ * Walk the spec and yield one `{ slug, entity, title, parentSlug,
199
+ * dependsOn }` record per logical entity (epic → story), mirroring the
200
+ * diff engine's `flattenSpec`. Local to the CLI so the reseed pass
201
+ * (below) can map spec slugs onto live GH issues without importing the
202
+ * diff engine's private walker. Pure.
203
203
  *
204
204
  * @param {object} spec
205
205
  * @returns {Array<{slug: string, entity: string, title: string, parentSlug: string|null, dependsOn: string[]}>}
@@ -216,32 +216,14 @@ export function flattenSpecForReseed(spec) {
216
216
  dependsOn: [],
217
217
  });
218
218
  }
219
- for (const feature of spec.features ?? []) {
219
+ for (const story of spec.stories ?? []) {
220
220
  out.push({
221
- slug: feature.slug,
222
- entity: 'feature',
223
- title: String(feature.title ?? ''),
221
+ slug: story.slug,
222
+ entity: 'story',
223
+ title: String(story.title ?? ''),
224
224
  parentSlug: 'epic',
225
- dependsOn: [],
225
+ dependsOn: story.dependsOn ?? [],
226
226
  });
227
- for (const story of feature.stories ?? []) {
228
- out.push({
229
- slug: story.slug,
230
- entity: 'story',
231
- title: String(story.title ?? ''),
232
- parentSlug: feature.slug,
233
- dependsOn: story.dependsOn ?? [],
234
- });
235
- for (const task of story.tasks ?? []) {
236
- out.push({
237
- slug: task.slug,
238
- entity: 'task',
239
- title: String(task.title ?? ''),
240
- parentSlug: story.slug,
241
- dependsOn: [],
242
- });
243
- }
244
- }
245
227
  }
246
228
  return out;
247
229
  }
@@ -255,7 +237,7 @@ export function flattenSpecForReseed(spec) {
255
237
  * file is absent (a fresh checkout, a reaped temp dir, the exact
256
238
  * situation `--resume` exists to recover from), `loadState` returns an
257
239
  * empty mapping, the diff engine sees every spec slug as unmapped, and
258
- * `apply` recreates the entire Feature/Story tree on top of the existing
240
+ * `apply` recreates the entire Story set on top of the existing
259
241
  * one — duplicating every child. This is precisely the failure `--resume`
260
242
  * is meant to prevent.
261
243
  *
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * evidence-gate.js — evidence-aware wrapper around a single shell gate.
5
5
  *
6
- * Tech Spec #819 §"Evidence record (Story 7)" — `/epic-deliver` Phase 3
6
+ * Tech Spec #819 §"Evidence record (Story 7)" — `/deliver` Phase 3
7
7
  * (close-validation) runs `npm run lint` and `npm test` against the Epic
8
8
  * branch before opening the PR.
9
9
  * If the same gate has already passed against the current `git rev-parse
@@ -91,7 +91,7 @@ export function renderWorkflowsDoc(catalog) {
91
91
  'Every command file lives at `.agents/workflows/<name>.md` and is projected',
92
92
  'into a flat `.claude/commands/` tree by `npm run sync:commands` (the',
93
93
  'UserPromptSubmit hook keeps it current) so it shows up as a bare `/<name>`',
94
- 'slash command (e.g. `/epic-deliver`). The projection writes only',
94
+ 'slash command (e.g. `/deliver`). The projection writes only',
95
95
  '`.claude/commands/<name>.md` — there is no plugin manifest and no',
96
96
  'marketplace listing. The commands load in every Claude Code environment.',
97
97
  '',