mandrel 2.37.0 → 2.38.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 (154) hide show
  1. package/.agents/README.md +16 -16
  2. package/.agents/agents/plan-critic.md +1 -1
  3. package/.agents/docs/SDLC.md +40 -40
  4. package/.agents/docs/configuration.md +16 -16
  5. package/.agents/docs/execution-reference.md +3 -3
  6. package/.agents/docs/quality-gates.md +2 -2
  7. package/.agents/docs/workflows.md +6 -6
  8. package/.agents/instructions.md +5 -5
  9. package/.agents/rules/changelog-style.md +3 -3
  10. package/.agents/rules/ci-remediation.md +1 -1
  11. package/.agents/rules/git-conventions-reference.md +4 -4
  12. package/.agents/schemas/agentrc.schema.json +9 -9
  13. package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
  14. package/.agents/schemas/validation-evidence.schema.json +1 -1
  15. package/.agents/scripts/acceptance-eval.js +1 -1
  16. package/.agents/scripts/apply-quality-bootstrap.js +1 -1
  17. package/.agents/scripts/audit-to-stories.js +2 -2
  18. package/.agents/scripts/check-doc-links.js +32 -4
  19. package/.agents/scripts/check-test-temp-hygiene.js +1 -1
  20. package/.agents/scripts/check-workflow-cli-lint.js +1 -1
  21. package/.agents/scripts/deliver-light.js +10 -10
  22. package/.agents/scripts/deliver-recover.js +1 -1
  23. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  24. package/.agents/scripts/evidence-gate.js +1 -1
  25. package/.agents/scripts/generate-workflows-doc.js +1 -1
  26. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  27. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +1 -1
  28. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +1 -1
  29. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +5 -5
  30. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +1 -1
  31. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  32. package/.agents/scripts/lib/bdd-scenario-budget.js +1 -1
  33. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  34. package/.agents/scripts/lib/bdd-step-index.js +1 -1
  35. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  36. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  37. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +1 -1
  38. package/.agents/scripts/lib/checks/core-bare-clean.js +1 -1
  39. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +1 -1
  40. package/.agents/scripts/lib/cli-args.js +1 -1
  41. package/.agents/scripts/lib/command-header.js +1 -1
  42. package/.agents/scripts/lib/config/delivery-routing.js +1 -1
  43. package/.agents/scripts/lib/config/explain.js +1 -1
  44. package/.agents/scripts/lib/config/runners.js +2 -2
  45. package/.agents/scripts/lib/config/runtime.js +1 -1
  46. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  47. package/.agents/scripts/lib/config-settings-schema-delivery.js +3 -3
  48. package/.agents/scripts/lib/config-settings-schema-quality.js +6 -6
  49. package/.agents/scripts/lib/config-settings-schema.js +3 -3
  50. package/.agents/scripts/lib/duplicate-search.js +1 -1
  51. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +4 -4
  52. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  53. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  54. package/.agents/scripts/lib/findings/promote-finding.js +12 -12
  55. package/.agents/scripts/lib/findings/route-finding.js +2 -2
  56. package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
  57. package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
  58. package/.agents/scripts/lib/label-constants.js +2 -2
  59. package/.agents/scripts/lib/label-taxonomy.js +1 -1
  60. package/.agents/scripts/lib/onboard/init-tail.js +4 -4
  61. package/.agents/scripts/lib/onboard/scaffold-docs.js +2 -2
  62. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
  63. package/.agents/scripts/lib/orchestration/code-review.js +4 -4
  64. package/.agents/scripts/lib/orchestration/complexity-gate.js +5 -5
  65. package/.agents/scripts/lib/orchestration/deliver-recover.js +3 -3
  66. package/.agents/scripts/lib/orchestration/docs-digest.js +3 -3
  67. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +2 -2
  68. package/.agents/scripts/lib/orchestration/light-backstop.js +1 -1
  69. package/.agents/scripts/lib/orchestration/light-escalation.js +6 -6
  70. package/.agents/scripts/lib/orchestration/light-suitability.js +19 -19
  71. package/.agents/scripts/lib/orchestration/plan-context.js +4 -4
  72. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +2 -2
  73. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +2 -2
  74. package/.agents/scripts/lib/orchestration/plan-metrics.js +1 -1
  75. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +1 -1
  76. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +3 -3
  77. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +6 -6
  78. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +16 -16
  79. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +3 -3
  80. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +6 -6
  81. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +7 -7
  82. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +1 -1
  83. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +3 -3
  84. package/.agents/scripts/lib/orchestration/remote-verifier.js +2 -2
  85. package/.agents/scripts/lib/orchestration/resolve-stories.js +4 -4
  86. package/.agents/scripts/lib/orchestration/run-epilogue.js +2 -2
  87. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +2 -2
  88. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +1 -1
  89. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +5 -1
  90. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -1
  91. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +3 -3
  92. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -2
  93. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  94. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +14 -12
  95. package/.agents/scripts/lib/orchestration/ticket-validator.js +1 -1
  96. package/.agents/scripts/lib/orchestration/ticketing/reads.js +3 -3
  97. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  98. package/.agents/scripts/lib/signals/schema.js +1 -1
  99. package/.agents/scripts/lib/story-adjacency.js +2 -2
  100. package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
  101. package/.agents/scripts/lib/ticket-body-sections.js +1 -1
  102. package/.agents/scripts/lib/util/concurrent-map.js +1 -1
  103. package/.agents/scripts/lib/util/parse-id-list.js +1 -1
  104. package/.agents/scripts/lib/wave-runner/live-probe.js +4 -4
  105. package/.agents/scripts/lib/wave-runner/ready-set.js +1 -1
  106. package/.agents/scripts/lib/workflow-closure.js +1 -1
  107. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +2 -2
  108. package/.agents/scripts/lint-issue-body.js +3 -3
  109. package/.agents/scripts/plan-context.js +4 -4
  110. package/.agents/scripts/plan-critics.js +2 -2
  111. package/.agents/scripts/plan-persist.js +2 -2
  112. package/.agents/scripts/plan-run-epilogue.js +2 -2
  113. package/.agents/scripts/providers/github/board-add.js +1 -1
  114. package/.agents/scripts/providers/github/errors.js +1 -1
  115. package/.agents/scripts/providers/github/tickets.js +6 -6
  116. package/.agents/scripts/resolve-stories.js +3 -3
  117. package/.agents/scripts/resync-status-column.js +1 -1
  118. package/.agents/scripts/run-lint.js +1 -1
  119. package/.agents/scripts/single-story-close.js +2 -2
  120. package/.agents/scripts/single-story-init.js +5 -5
  121. package/.agents/scripts/stories-wave-tick.js +8 -8
  122. package/.agents/skills/core/idea-refinement/SKILL.md +5 -5
  123. package/.agents/skills/core/scope-triage/SKILL.md +3 -3
  124. package/.agents/skills/skills.index.json +1 -1
  125. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -1
  126. package/.agents/workflows/audit-data-model.md +1 -1
  127. package/.agents/workflows/audit-documentation.md +2 -2
  128. package/.agents/workflows/audit-to-stories.md +11 -11
  129. package/.agents/workflows/git-deliver.md +4 -4
  130. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  131. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  132. package/.agents/workflows/helpers/code-review.md +4 -4
  133. package/.agents/workflows/helpers/deliver-light.md +26 -26
  134. package/.agents/workflows/helpers/deliver-reference.md +15 -7
  135. package/.agents/workflows/helpers/deliver-story-reference.md +9 -4
  136. package/.agents/workflows/helpers/deliver-story.md +6 -7
  137. package/.agents/workflows/helpers/diagnose.md +2 -2
  138. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  139. package/.agents/workflows/helpers/plan-reference.md +9 -9
  140. package/.agents/workflows/helpers/qa-core.md +8 -8
  141. package/.agents/workflows/helpers/worktree-lifecycle.md +6 -6
  142. package/.agents/workflows/{deliver.md → mandrel-deliver.md} +15 -19
  143. package/.agents/workflows/{plan.md → mandrel-plan.md} +9 -9
  144. package/.agents/workflows/memory-consolidate.md +4 -4
  145. package/.agents/workflows/prototype.md +3 -3
  146. package/.agents/workflows/qa-assist.md +12 -12
  147. package/.agents/workflows/qa-explore.md +6 -6
  148. package/.agents/workflows/qa-run.md +1 -1
  149. package/README.md +7 -7
  150. package/docs/CHANGELOG.md +11 -0
  151. package/lib/cli/doctor.js +1 -1
  152. package/lib/cli/init.js +1 -1
  153. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +1 -1
  154. package/package.json +1 -1
@@ -89,7 +89,7 @@ export function branchExistsViaTrackingRef(branch, cwd) {
89
89
  /**
90
90
  * Pure: classify how a `story-<id>` branch should be seeded from the (local,
91
91
  * remote) ref-presence matrix. This is the single source of truth for
92
- * `single-story-init.js#decideStoryBranchSeed` (v2 `/deliver` path).
92
+ * `single-story-init.js#decideStoryBranchSeed` (v2 `/mandrel-deliver` path).
93
93
  *
94
94
  * The init path previously re-implemented the same `local → no-op, remote →
95
95
  * fetch, else create` decision tree; it now delegates here so the branching
@@ -122,7 +122,7 @@ export function classifyBranchSeed({ localHas, remoteHas }) {
122
122
  * The two callers differ in exactly two behavioural axes, both of which are
123
123
  * parameters here — no other conditional branching is introduced:
124
124
  * - **`baseRef`** — the ref to branch from on `create` (`main` for v2
125
- * `/deliver`; pre-v2 Epic close used the Epic branch).
125
+ * `/mandrel-deliver`; pre-v2 Epic close used the Epic branch).
126
126
  * - **`swallowCreateRace`** — when `true`, a `git branch` that exits
127
127
  * non-zero with an "already exists" stderr is treated as reuse rather
128
128
  * than a fatal error (pre-v2 concurrent wave dispatch). When `false`, any create failure
@@ -15,7 +15,7 @@ export const AGENT_LABELS = {
15
15
  // the Story PR is opened against `main`. It flips to
16
16
  // `agent::done` only after the close pipeline confirms the PR merge
17
17
  // landed; if the close is killed mid-flight, the Story remains at
18
- // `agent::closing` so `/deliver` can pick up at the
18
+ // `agent::closing` so `/mandrel-deliver` can pick up at the
19
19
  // post-merge phase rather than re-running preflight. The label is the
20
20
  // distinguishing signal between "hung close" and "finished work".
21
21
  CLOSING: 'agent::closing',
@@ -101,7 +101,7 @@ export const ACCEPTANCE_NA = ACCEPTANCE_LABELS.N_A;
101
101
  * loop). `meta::framework-gap` is applied to issues that surface a defect or
102
102
  * missing capability in the framework itself; `meta::consumer-improvement`
103
103
  * is applied to issues that surface improvements to a consumer project
104
- * (workflow tweaks, ergonomic asks, doc polish). The `/plan` Phase 0
104
+ * (workflow tweaks, ergonomic asks, doc polish). The `/mandrel-plan` Phase 0
105
105
  * fetcher (see `lib/feedback-loop/prior-feedback-fetcher.js`) reads open
106
106
  * issues carrying either label and surfaces them to the planner so retro
107
107
  * signals are routed into durable substrates rather than lost in chat.
@@ -40,7 +40,7 @@ export const LABEL_TAXONOMY = [
40
40
  name: AGENT_LABELS.READY,
41
41
  color: LABEL_COLORS.AGENT,
42
42
  description:
43
- 'Parking state — frozen dispatch manifest exists; awaiting local /deliver',
43
+ 'Parking state — frozen dispatch manifest exists; awaiting local /mandrel-deliver',
44
44
  },
45
45
  {
46
46
  name: AGENT_LABELS.EXECUTING,
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Phase 1 — Offer to scaffold missing docsContextFiles (scaffold-docs.js).
9
9
  * Phase 2 — Run `mandrel doctor` as a readiness gate.
10
- * Phase 3 — Print the /plan handoff next-step text.
10
+ * Phase 3 — Print the /mandrel-plan handoff next-step text.
11
11
  *
12
12
  * The whole tail is idempotent: re-running after an already-onboarded project
13
13
  * re-checks and re-offers scaffolding without duplicating stubs (the scaffolder
@@ -31,13 +31,13 @@ import { STUB_MARKER, scaffoldDocs } from './scaffold-docs.js';
31
31
  // ---------------------------------------------------------------------------
32
32
 
33
33
  /**
34
- * Text printed at the end of the init tail to hand the operator off to /plan.
34
+ * Text printed at the end of the init tail to hand the operator off to /mandrel-plan.
35
35
  *
36
36
  * @type {string}
37
37
  */
38
38
  export const PLAN_HANDOFF_TEXT =
39
39
  '\n✅ Mandrel is ready. Start your first project:\n\n' +
40
- ' /plan --seed "<one-line description of what you want to build>"\n';
40
+ ' /mandrel-plan --seed "<one-line description of what you want to build>"\n';
41
41
 
42
42
  // ---------------------------------------------------------------------------
43
43
  // Internal helpers
@@ -200,7 +200,7 @@ export async function runInitTail({
200
200
  return { scaffoldResult, doctorStatus, ok: false };
201
201
  }
202
202
 
203
- // --- Phase 3: Handoff to /plan -------------------------------------------
203
+ // --- Phase 3: Handoff to /mandrel-plan -------------------------------------------
204
204
  stdout(PLAN_HANDOFF_TEXT);
205
205
  return { scaffoldResult, doctorStatus, ok: true };
206
206
  }
@@ -25,7 +25,7 @@ const AGENT_ROOT = path.resolve(__dirname, '../../..');
25
25
  const DOCS_TEMPLATE_DIR = path.join(AGENT_ROOT, 'templates', 'docs');
26
26
 
27
27
  /**
28
- * Deterministic marker written into every scaffolded stub. The `/plan`
28
+ * Deterministic marker written into every scaffolded stub. The `/mandrel-plan`
29
29
  * first-run preflight (and any tooling that wants to detect unedited stubs)
30
30
  * keys off this exact string — do not change it without a hard cutover.
31
31
  *
@@ -59,7 +59,7 @@ function genericStub(fileName) {
59
59
  /**
60
60
  * Read the dedicated template body for a docsContextFile, or fall back to the
61
61
  * generic stub when no template ships for that name. Either path prepends the
62
- * {@link STUB_MARKER} so the `/plan` first-run preflight can detect un-edited
62
+ * {@link STUB_MARKER} so the `/mandrel-plan` first-run preflight can detect un-edited
63
63
  * stubs regardless of whether a dedicated template was used.
64
64
  *
65
65
  * @param {string} fileName
@@ -170,7 +170,7 @@ export function decideAcceptanceEval({ verdict, maxRounds, round: roundIn }) {
170
170
  /**
171
171
  * Build the per-criterion acceptance-eval signal payload for the retro /
172
172
  * feedback substrate. Carries which acceptance items needed rework and the
173
- * round count so `/plan` Phase 0 feedback fetch and the retro can
173
+ * round count so `/mandrel-plan` Phase 0 feedback fetch and the retro can
174
174
  * surface acceptance churn. PII-free by construction — it carries only
175
175
  * acceptance-item indices, verdicts, and the terminal decision.
176
176
  *
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Story #1155 (Epic #1142, 5.40.0) — extracted the helper-driven
5
5
  * `epic-code-review` invocation into a callable module so the
6
- * `/deliver` runner can run Phase D without spawning a child
6
+ * `/mandrel-deliver` runner can run Phase D without spawning a child
7
7
  * process or routing through an LLM-driven helper.
8
8
  *
9
9
  * Story #2831 (Epic #2815, Pluggable Code Review) — refactored to load
@@ -32,11 +32,11 @@
32
32
  * `code-review` and `audit-results` findings contracts into this one
33
33
  * `verification-results` marker.
34
34
  * - Treats severity.critical > 0 as a halting blocker — the merged
35
- * `/deliver` runner consults `halted` and refuses to advance
35
+ * `/mandrel-deliver` runner consults `halted` and refuses to advance
36
36
  * to Phase E (retro) when set.
37
37
  *
38
38
  * Halting on critical findings is the in-process replacement for the
39
- * helper's "operator must remediate before /deliver" gate.
39
+ * helper's "operator must remediate before /mandrel-deliver" gate.
40
40
  */
41
41
 
42
42
  import { hasSurvivingCritical } from '../audit-suite/findings.js';
@@ -129,7 +129,7 @@ function resolveScopeEnvelope(opts, config) {
129
129
  }
130
130
 
131
131
  /**
132
- * In-process wrapper that the `/deliver` runner and the
132
+ * In-process wrapper that the `/mandrel-deliver` runner and the
133
133
  * `/single-story-deliver` close path consume.
134
134
  *
135
135
  * Story #2252 — emits `code-review.start` immediately on entry and
@@ -132,7 +132,7 @@ export const LITE_ROUTE_LABEL = 'route::lite';
132
132
  * footprint: `trivial` < `moderate` < `substantial`.
133
133
  * - `maxUncertainty` — is the shape determined by the request
134
134
  * (`determined`), or does it still need the design
135
- * decisions `/plan` exists to resolve
135
+ * decisions `/mandrel-plan` exists to resolve
136
136
  * (`needs-design`)?
137
137
  * - `maxDeployables` — named deployable roots (`apps/<x>`, `packages/<x>`, …)
138
138
  * the footprint spans; more than one is epic by
@@ -325,7 +325,7 @@ const EFFORT_RULES = Object.freeze([
325
325
  UNCERTAINTY_SCALE.indexOf(s.uncertainty) >
326
326
  UNCERTAINTY_SCALE.indexOf(c.maxUncertainty),
327
327
  reason: (s) =>
328
- `the shape is not determined by the request (uncertainty "${s.uncertainty}") — the design decisions /plan exists to resolve are still open; full route`,
328
+ `the shape is not determined by the request (uncertainty "${s.uncertainty}") — the design decisions /mandrel-plan exists to resolve are still open; full route`,
329
329
  },
330
330
  {
331
331
  code: SHAPE_CODES.DEPLOYABLE_SPAN,
@@ -657,7 +657,7 @@ function buildEffortShape({
657
657
  /**
658
658
  * Derive the complexity route from an authored Story's **effort and risk**
659
659
  * (Story #4722 AC-3/AC-4; re-anchored off artifact cardinality by Story #4764)
660
- * — the single shape function persist's backstop and `/deliver`'s dispatch
660
+ * — the single shape function persist's backstop and `/mandrel-deliver`'s dispatch
661
661
  * derivation both read, so the two can never disagree about the same body.
662
662
  *
663
663
  * `lite` requires **every** signal to agree, against
@@ -804,7 +804,7 @@ export function deriveStoryShape({
804
804
  }
805
805
 
806
806
  /**
807
- * Decide how `/deliver` executes a Story: **run topology, and nothing else.**
807
+ * Decide how `/mandrel-deliver` executes a Story: **run topology, and nothing else.**
808
808
  *
809
809
  * **`inline` names one indivisible resource: the router's own session.** Two
810
810
  * Stories cannot both own it, so exactly one premise can grant it —
@@ -839,7 +839,7 @@ export function deriveStoryShape({
839
839
  * module header's non-negotiables.
840
840
  *
841
841
  * @param {{ storyCount?: unknown }} [args] `storyCount` is the number of
842
- * Stories the invoking `/deliver` run resolved. Omitted (or not exactly 1)
842
+ * Stories the invoking `/mandrel-deliver` run resolved. Omitted (or not exactly 1)
843
843
  * means the run cannot be shown sibling-free and therefore dispatches as a
844
844
  * sub-agent — never an assumed 1.
845
845
  * @returns {{ mode: 'inline'|'subagent', reasons: string[] }}
@@ -21,7 +21,7 @@
21
21
  * - `closing` with a red PR → enter the fix loop. Waiting is pointless; no
22
22
  * budget turns a failed check green.
23
23
  * - `closing` with a MERGED PR → run confirm. **This is the strand a
24
- * `/deliver` re-run refuses outright**, because `single-story-init.js`
24
+ * `/mandrel-deliver` re-run refuses outright**, because `single-story-init.js`
25
25
  * hard-errors on an already-closed Story — so before this surface, the
26
26
  * merged-but-label-stale Story had no automated way back.
27
27
  * - `done` with a drifted board → run resync. The GitHub Projects bot won
@@ -367,7 +367,7 @@ export function decideRecovery({
367
367
  nextCommand: NEXT_COMMANDS.confirmMerge(storyId),
368
368
  detail:
369
369
  `PR #${pr.number} is MERGED but the Story is at \`${label ?? 'no state label'}\`. ` +
370
- `A /deliver re-run cannot fix this — single-story-init.js hard-errors on an ` +
370
+ `A /mandrel-deliver re-run cannot fix this — single-story-init.js hard-errors on an ` +
371
371
  `already-closed Story. The confirm CLI is idempotent and flips the label from ` +
372
372
  `the already-merged PR, then runs the land tail.`,
373
373
  evidence,
@@ -482,7 +482,7 @@ export function decideRecovery({
482
482
  nextCommand: NEXT_COMMANDS.close(storyId),
483
483
  detail:
484
484
  `Story is at \`${label ?? 'no agent:: state label'}\` — not mid-delivery, so there ` +
485
- `is no strand to recover. Deliver it normally via /deliver ${storyId}.`,
485
+ `is no strand to recover. Deliver it normally via /mandrel-deliver ${storyId}.`,
486
486
  evidence,
487
487
  };
488
488
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * docs-digest.js — per-run docs digest builder (Story #4338).
3
3
  *
4
- * `/deliver` story sub-agents previously re-read every file in
4
+ * `/mandrel-deliver` story sub-agents previously re-read every file in
5
5
  * `project.docsContextFiles` on every Story, re-paying the full docs payload
6
6
  * per child. This module produces a single **digest** — one compact markdown
7
7
  * outline per configured doc — that the parent threads into every child prompt
@@ -17,7 +17,7 @@
17
17
  * generate-and-write export so the planner-context surface
18
18
  * (`plan-context.js` / `authoring-context.js`) can produce a session docs
19
19
  * digest without duplicating the mkdir+writeFile plumbing shared by
20
- * `plan-context.js` / `authoring-context.js` and the `/deliver` workflow.
20
+ * `plan-context.js` / `authoring-context.js` and the `/mandrel-deliver` workflow.
21
21
  */
22
22
 
23
23
  import fs from 'node:fs';
@@ -145,7 +145,7 @@ export async function buildDocsDigest({ docsContextFiles, docsRoot } = {}) {
145
145
  * Build the docs digest and write it to `outputPath`, returning `null` (no
146
146
  * write) when there is nothing to digest. This is the single shared
147
147
  * generate-and-persist export both digest producers call: the per-run
148
- * `/deliver` docs digest (`helpers/deliver-story.md`) and the planner-
148
+ * `/mandrel-deliver` docs digest (`helpers/deliver-story.md`) and the planner-
149
149
  * context digest (`plan-context.js` → `authoring-context.js`, Story
150
150
  * #4433). Callers own path construction (temp-root layout, run id, etc.)
151
151
  * so both surfaces can keep — or deliberately share — their own convention;
@@ -3,7 +3,7 @@
3
3
  * kernel shared by the three per-surface lease guards.
4
4
  *
5
5
  * The per-surface lease guards — today `single-story-lease-guard.js`;
6
- * historically also the retired Epic-tier deliver/plan guards —
6
+ * historically also the retired Epic-tier deliver/mandrel-plan guards —
7
7
  * each carried their own copy of
8
8
  * the operator-handle resolution and the fail-closed acquire wrapper around
9
9
  * `ticket-lease.acquireLease` (refuse any foreign assignee, throwing an
@@ -20,7 +20,7 @@
20
20
  *
21
21
  * - **Operator candidates** — each surface supplies its own ordered
22
22
  * candidate list (e.g. `--as` flag → `github.operatorHandle` →
23
- * `git user.email` for `/deliver`; bare `operatorHandle` for the
23
+ * `git user.email` for `/mandrel-deliver`; bare `operatorHandle` for the
24
24
  * plan/standalone paths).
25
25
  * - **Missing-handle behaviour** — `'null'` (return null; the caller fails
26
26
  * closed at acquire time) vs `'throw'` (refuse immediately with surface
@@ -71,7 +71,7 @@ function runDiffBackstop({
71
71
  *
72
72
  * A refusal also **preserves** the work before it reports (Story #4875): the
73
73
  * implementation is finished and the recycle command hands the receipt to
74
- * `/plan`, so leaving it on an untracked local branch that routine cleanup may
74
+ * `/mandrel-plan`, so leaving it on an untracked local branch that routine cleanup may
75
75
  * reap is not an acceptable end state. Preservation is best-effort and its
76
76
  * outcome is reported either way — a failed push degrades the message, never
77
77
  * the verdict or the exit code.
@@ -7,9 +7,9 @@
7
7
  * {@link module:lib/orchestration/light-suitability}:
8
8
  *
9
9
  * 1. **Recycling the receipt.** A blocked diff backstop used to tell the
10
- * operator to "escalate to `/plan`", which authored a brand-new Story and
10
+ * operator to "escalate to `/mandrel-plan`", which authored a brand-new Story and
11
11
  * left the receipt open with no successor — orphaning its branch, its
12
- * worktree, and a finished implementation. Naming the receipt as `/plan`'s
12
+ * worktree, and a finished implementation. Naming the receipt as `/mandrel-plan`'s
13
13
  * *input* recycles it instead: tickets mode already fetches a ticket,
14
14
  * rewrites it into properly-planned Stories, and closes the source as
15
15
  * superseded.
@@ -45,13 +45,13 @@ import {
45
45
  } from '../observability/runtime-friction.js';
46
46
 
47
47
  /**
48
- * The `/plan` invocation that owns a Story the light path could not land.
48
+ * The `/mandrel-plan` invocation that owns a Story the light path could not land.
49
49
  *
50
50
  * @param {number} storyId
51
51
  * @returns {string}
52
52
  */
53
53
  function buildRecycleCommand(storyId) {
54
- return `/plan ${storyId}`;
54
+ return `/mandrel-plan ${storyId}`;
55
55
  }
56
56
 
57
57
  /**
@@ -106,7 +106,7 @@ export async function recordGateRefusal({
106
106
 
107
107
  /**
108
108
  * Handle a blocked diff backstop: record the refusal as friction and return the
109
- * `/plan` invocation that recycles the receipt.
109
+ * `/mandrel-plan` invocation that recycles the receipt.
110
110
  *
111
111
  * Lives here rather than in the CLI so the shell stays a shell — the backstop
112
112
  * mode's job is to branch and print, not to decide what a refusal means.
@@ -152,7 +152,7 @@ export async function handleBlockedBackstop({
152
152
  * recoverable (Story #4875).
153
153
  *
154
154
  * A blocked backstop refuses the *land*, not the *work*: the implementation is
155
- * complete and the recycle command hands the receipt to `/plan`, which will
155
+ * complete and the recycle command hands the receipt to `/mandrel-plan`, which will
156
156
  * want it. Before this, that work existed only as a local `story-<id>` branch
157
157
  * with no remote ref — an untracked branch is exactly what the routine merged-
158
158
  * branch sweeps and worktree reaping treat as disposable, so the only copy of a
@@ -29,11 +29,11 @@
29
29
  * 3 below does the real enforcement against ground truth.
30
30
  * 2. **Over-scope stops, never silently proceeds ({@link
31
31
  * resolveLightGateOutcome}).** An over-ceiling prompt does **not**
32
- * hard-fail — it STOPS and asks the operator to escalate to `/plan` or
32
+ * hard-fail — it STOPS and asks the operator to escalate to `/mandrel-plan` or
33
33
  * proceed light. Both answers are executable: `proceed-light` is recorded
34
34
  * through {@link resolveOperatorOverride}, which waives a *size
35
35
  * prediction* only, never a risk rule, and only with a human present.
36
- * Under `--yes` (unattended) it fails closed to recommending `/plan`.
36
+ * Under `--yes` (unattended) it fails closed to recommending `/mandrel-plan`.
37
37
  * 3. **Diff-derived backstop ({@link checkLightDiffBackstop}).** After
38
38
  * implementation the **actual** change set is re-checked with
39
39
  * {@link module:lib/orchestration/review-depth.deriveChangeLevel} plus the
@@ -41,7 +41,7 @@
41
41
  * the diff is the real scope signal — and an over-ceiling diff is blocked
42
42
  * rather than landed silently. Story #4856 moved this from a `maxFiles: 4`
43
43
  * cardinality ceiling to changed lines over implementation files, and made
44
- * a block **recycle** its receipt Story through `/plan` tickets mode
44
+ * a block **recycle** its receipt Story through `/mandrel-plan` tickets mode
45
45
  * instead of orphaning it.
46
46
  * 4. **Minimal receipt Story ({@link buildReceiptStoryTicket}).** A
47
47
  * `type::story` ticket is authored inline so `refs #`, history, telemetry,
@@ -131,7 +131,7 @@ function deriveUnwaivableRisk(decision) {
131
131
  `class(es) ${classes.join(', ')} — this is risk, not size, so no ` +
132
132
  `re-slicing, shrinking, or operator override satisfies it and the ` +
133
133
  `diff backstop would refuse the same footprint after the work is ` +
134
- `finished; take this to /plan now`,
134
+ `finished; take this to /mandrel-plan now`,
135
135
  };
136
136
  }
137
137
  if (shape?.migrationSpan === true) {
@@ -142,7 +142,7 @@ function deriveUnwaivableRisk(decision) {
142
142
  reason:
143
143
  `un-waivable: the predicted footprint pairs a migration with its ` +
144
144
  `consumers — this is risk, not size, so no re-slicing or operator ` +
145
- `override satisfies it; take this to /plan now`,
145
+ `override satisfies it; take this to /mandrel-plan now`,
146
146
  };
147
147
  }
148
148
  return { present: false, code: null, classes: [], reason: null };
@@ -237,7 +237,7 @@ export function resolveLedgeredVerdict({ route, reason } = {}) {
237
237
  route: 'full',
238
238
  reason: recordedReason || null,
239
239
  recorded: recordedReason !== '',
240
- note: 'model verdict is not lite — standard /plan route',
240
+ note: 'model verdict is not lite — standard /mandrel-plan route',
241
241
  };
242
242
  }
243
243
  if (recordedReason === '') {
@@ -261,7 +261,7 @@ export function resolveLedgeredVerdict({ route, reason } = {}) {
261
261
  * light path. The deterministic effort/risk derivation and the ledgered model
262
262
  * verdict must **both** agree on `lite`; anything else — clearly-epic work, a
263
263
  * sensitive-path footprint, an unledgered verdict — resolves to `full` (the
264
- * conservative default that routes the operator to `/plan`).
264
+ * conservative default that routes the operator to `/mandrel-plan`).
265
265
  *
266
266
  * The predicted axes are declared by the caller: `predictedKinds` (the distinct
267
267
  * kinds of change; absent, each entry's `assumption` is its kind, so N
@@ -394,7 +394,7 @@ export function resolveOperatorOverride({
394
394
  }
395
395
  if (yes === true) {
396
396
  return refuse(
397
- 'operator override refused — it is attended-only, and --yes means nobody is at the keyboard; over-scope still fails closed to /plan',
397
+ 'operator override refused — it is attended-only, and --yes means nobody is at the keyboard; over-scope still fails closed to /mandrel-plan',
398
398
  );
399
399
  }
400
400
 
@@ -412,7 +412,7 @@ export function resolveOperatorOverride({
412
412
  ? ` (${unwaivable.classes.join(', ')})`
413
413
  : ''
414
414
  }; waiving the size prediction cannot make this land light, and the ` +
415
- `diff backstop would refuse the finished work. Escalate to /plan.`,
415
+ `diff backstop would refuse the finished work. Escalate to /mandrel-plan.`,
416
416
  );
417
417
  }
418
418
  if (!OVERRIDABLE_SHAPE_CODES.includes(code)) {
@@ -441,7 +441,7 @@ export function resolveOperatorOverride({
441
441
  * Resolve what the light gate does with a suitability decision (Story #4740
442
442
  * AC-3). Over-scope never hard-fails: it STOPS and asks the operator to choose,
443
443
  * unless the run is unattended (`--yes`), where it fails closed to recommending
444
- * `/plan` rather than silently proceeding light.
444
+ * `/mandrel-plan` rather than silently proceeding light.
445
445
  *
446
446
  * - suitable → `proceed-light`
447
447
  * - over-scope + attended (`yes:false`) → `ask-operator` (escalate | proceed)
@@ -498,7 +498,7 @@ export function resolveLightGateOutcome({
498
498
  action: 'escalate-plan',
499
499
  reasons: [
500
500
  ...reasons,
501
- '--yes on over-scope fails closed to /plan (never silently proceeds light)',
501
+ '--yes on over-scope fails closed to /mandrel-plan (never silently proceeds light)',
502
502
  ],
503
503
  };
504
504
  }
@@ -519,7 +519,7 @@ export function resolveLightGateOutcome({
519
519
  options: ['escalate-plan', 'proceed-light'],
520
520
  reasons: [
521
521
  ...reasons,
522
- 'predicted scope exceeds the light ceilings — STOP and ask the operator to escalate to /plan or proceed light',
522
+ 'predicted scope exceeds the light ceilings — STOP and ask the operator to escalate to /mandrel-plan or proceed light',
523
523
  ],
524
524
  };
525
525
  }
@@ -587,7 +587,7 @@ export function checkLightDiffBackstop({
587
587
  magnitude: null,
588
588
  ceilings: resolved,
589
589
  reasons: [
590
- 'actual change set is unknown or empty — cannot verify the diff is light; escalate to /plan',
590
+ 'actual change set is unknown or empty — cannot verify the diff is light; escalate to /mandrel-plan',
591
591
  ],
592
592
  };
593
593
  }
@@ -646,12 +646,12 @@ function normalizeMagnitude(magnitude) {
646
646
  function describeSensitivity({ level, classes }) {
647
647
  if (classes.length > 0) {
648
648
  return [
649
- `diff intersects sensitive-path class(es) ${classes.join(', ')} — escalate to /plan (do not land light)`,
649
+ `diff intersects sensitive-path class(es) ${classes.join(', ')} — escalate to /mandrel-plan (do not land light)`,
650
650
  ];
651
651
  }
652
652
  if (level !== 'low') {
653
653
  return [
654
- 'sensitive-path classification unavailable — cannot verify the diff is non-sensitive; escalate to /plan',
654
+ 'sensitive-path classification unavailable — cannot verify the diff is non-sensitive; escalate to /mandrel-plan',
655
655
  ];
656
656
  }
657
657
  return [];
@@ -667,18 +667,18 @@ function describeSensitivity({ level, classes }) {
667
667
  function describeMagnitude(measured, ceilings) {
668
668
  if (measured === null) {
669
669
  return [
670
- 'change magnitude could not be measured (unreadable or unparseable numstat) — cannot verify the diff is light; escalate to /plan',
670
+ 'change magnitude could not be measured (unreadable or unparseable numstat) — cannot verify the diff is light; escalate to /mandrel-plan',
671
671
  ];
672
672
  }
673
673
  const reasons = [];
674
674
  if (measured.implLines > ceilings.maxImplLines) {
675
675
  reasons.push(
676
- `diff changes ${measured.implLines} implementation line(s) (> maxImplLines ${ceilings.maxImplLines}) — escalate to /plan (do not land light)`,
676
+ `diff changes ${measured.implLines} implementation line(s) (> maxImplLines ${ceilings.maxImplLines}) — escalate to /mandrel-plan (do not land light)`,
677
677
  );
678
678
  }
679
679
  if (measured.implFiles > ceilings.maxImplFiles) {
680
680
  reasons.push(
681
- `diff spans ${measured.implFiles} implementation file(s) (> maxImplFiles ${ceilings.maxImplFiles}) — escalate to /plan (do not land light)`,
681
+ `diff spans ${measured.implFiles} implementation file(s) (> maxImplFiles ${ceilings.maxImplFiles}) — escalate to /mandrel-plan (do not land light)`,
682
682
  );
683
683
  }
684
684
  return reasons;
@@ -832,7 +832,7 @@ export function buildReceiptStoryTicket({
832
832
  goal: `${text}${amendNote}`,
833
833
  spec:
834
834
  `Delivered via /deliver-light as a validated single-session change — ` +
835
- `the /plan session is removed for genuinely small work while every ` +
835
+ `the /mandrel-plan session is removed for genuinely small work while every ` +
836
836
  `single-story-close gate runs byte-identical.${amendNote}` +
837
837
  `${overrideNote} ` +
838
838
  `Operator prompt: ${text}`,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * plan-context.js — single planner-context envelope build for `/plan`.
2
+ * plan-context.js — single planner-context envelope build for `/mandrel-plan`.
3
3
  *
4
4
  * Folds the authoring-context builders plus the cross-Story dup search into
5
5
  * ONE JSON envelope, so the authoring middle reads a single file instead of
@@ -481,7 +481,7 @@ export function buildDeliverLightSuggestion(complexitySignals) {
481
481
  reasons: suggested
482
482
  ? [
483
483
  'seed carries no risk signal (no risk-heuristic hits, no ' +
484
- 'sensitive-path classes) — the operator may prefer /deliver for ' +
484
+ 'sensitive-path classes) — the operator may prefer /mandrel-deliver for ' +
485
485
  "this scope; the light path's own gate and diff backstop decide size",
486
486
  ]
487
487
  : reasons,
@@ -597,7 +597,7 @@ function uiSurfaceReason({
597
597
  * derived from the consumer's own checkout, so a frontend-less project — this
598
598
  * repository included — resolves falsey and the offer never fires.
599
599
  *
600
- * The signal carries **no routing authority** (`automatic: false`): `/plan`
600
+ * The signal carries **no routing authority** (`automatic: false`): `/mandrel-plan`
601
601
  * may say that a plan touches UI and that `/prototype` exists, and must never
602
602
  * invoke it. Pure over its inputs and total — a malformed signal bag or an
603
603
  * unreadable manifest degrades, never throws.
@@ -911,7 +911,7 @@ async function gatherEnvelopeInputs({
911
911
  (gather) => gather(),
912
912
  // The per-mode envelope gathers (Story #4952): the duplicate search, the
913
913
  // authoring-context fold and the docs digest have no data dependency on
914
- // one another, so their serialization was incidental and `/plan` paid it
914
+ // one another, so their serialization was incidental and `/mandrel-plan` paid it
915
915
  // with the operator waiting at Gate #1.
916
916
  { concurrency: FANOUT_CONCURRENCY },
917
917
  );
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * plan-critic-conditions.js — size/heuristic-conditional dispatch decisions for
3
- * the /plan author-step critics (Epic #4474 PR6, design §4).
3
+ * the /mandrel-plan author-step critics (Epic #4474 PR6, design §4).
4
4
  *
5
5
  * The collapsed plan flow keeps the consolidation and pre-mortem critics as
6
6
  * fresh-context sub-agent dispatches, but makes each dispatch
@@ -44,7 +44,7 @@
44
44
  * (`appendCriticSkip`) by the caller so under-firing is auditable.
45
45
  *
46
46
  * Pure, synchronous, no I/O. The single caller is `plan-critics-evaluate.js`,
47
- * driven by the `plan-critics.js` CLI that `/plan` runs between Author and
47
+ * driven by the `plan-critics.js` CLI that `/mandrel-plan` runs between Author and
48
48
  * Persist (Story #4592); the CLI owns reading the authored artifacts and the
49
49
  * resolved config.
50
50
  */
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * plan-critics-evaluate.js — shared critic-dispatch evaluation for the
3
- * collapsed /plan flow (#4496 fix 6).
3
+ * collapsed /mandrel-plan flow (#4496 fix 6).
4
4
  *
5
- * One consumer: the `plan-critics.js` CLI, which `/plan` runs between its
5
+ * One consumer: the `plan-critics.js` CLI, which `/mandrel-plan` runs between its
6
6
  * Author and Persist steps. The CLI loads the draft artifacts, calls this
7
7
  * module, prints the verdict as JSON, and records every skip on the
8
8
  * plan-metrics ledger; the workflow dispatches a fresh-context critic
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * plan-metrics.js — append-only plan-invocation ledger (Epic #4474, PR1).
3
3
  *
4
- * The `/plan` collapse (#4474) is measured, not asserted: before any pipeline
4
+ * The `/mandrel-plan` collapse (#4474) is measured, not asserted: before any pipeline
5
5
  * phase is removed, every plan CLI invocation stamps an entry/exit record so
6
6
  * the current 12-phase baseline is captured on disk. Each record is one
7
7
  * newline-terminated JSON line appended to
@@ -1,5 +1,5 @@
1
1
  /**
2
- * persist-helpers.js — pure helper surface for the flat Story `/plan` persist.
2
+ * persist-helpers.js — pure helper surface for the flat Story `/mandrel-plan` persist.
3
3
  *
4
4
  * Exports:
5
5
  * - `resolveBaseBranchRef(config)` — the one place the persist gates learn
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * plan-context-source.js — locate and read the `plan-context.js` envelope so
3
- * persist can derive the `/plan --tickets` source ids from the run that
3
+ * persist can derive the `/mandrel-plan --tickets` source ids from the run that
4
4
  * actually fetched them (Story #4554).
5
5
  *
6
6
  * This lives beside the persist ops rather than inside `plan-persist.js` so
@@ -17,7 +17,7 @@ import path from 'node:path';
17
17
  import { Logger } from '../../Logger.js';
18
18
 
19
19
  /**
20
- * Filename the `/plan` interrogate step writes its envelope to inside
20
+ * Filename the `/mandrel-plan` interrogate step writes its envelope to inside
21
21
  * `--plan-dir` (`plan-context.js --out <plan-dir>/plan-context.json`).
22
22
  */
23
23
  export const PLAN_CONTEXT_FILENAME = 'plan-context.json';
@@ -81,7 +81,7 @@ export async function loadPlanContextEnvelope(planContext) {
81
81
  if (!planContext) {
82
82
  Logger.warn(
83
83
  '[plan-persist] no --plan-dir or --plan-context given, so no ' +
84
- 'plan-context envelope was read. If this was a `/plan --tickets` ' +
84
+ 'plan-context envelope was read. If this was a `/mandrel-plan --tickets` ' +
85
85
  'run, its source tickets can only come from --source-tickets and ' +
86
86
  `will NOT be closed otherwise. ${CAPTURE_HINT}`,
87
87
  );
@@ -1,5 +1,5 @@
1
1
  /**
2
- * run-plan-persist.js — flat Story persist for the v2 `/plan` collapse
2
+ * run-plan-persist.js — flat Story persist for the v2 `/mandrel-plan` collapse
3
3
  * (Stage 3 — `docs/roadmap.md`).
4
4
  *
5
5
  * Ordered, fail-closed pipeline:
@@ -293,7 +293,7 @@ async function renderRunScopedPlanMetricsLine({
293
293
  * from the seed.
294
294
  *
295
295
  * The resolved route decides whether the created Stories carry the
296
- * {@link LITE_ROUTE_LABEL} **hint** (never the control signal — `/deliver`
296
+ * {@link LITE_ROUTE_LABEL} **hint** (never the control signal — `/mandrel-deliver`
297
297
  * re-derives the route from the Story body's shape) and the `route` block
298
298
  * ledgered on their `story-plan-state` checkpoint, including the authored
299
299
  * verdict, its recorded reason, and the per-Story shape evidence. A refused
@@ -531,7 +531,7 @@ async function enforceReachability(reachability, config) {
531
531
  * concurrency, but the `await` on that whole fan-out is what keeps the
532
532
  * Story #4541 invariant intact: *every* checkpoint is on its ticket before the
533
533
  * first `agent::ready` flip is issued, so `ready` still means "fully
534
- * persisted" and a `/deliver` that picks a Story up cannot read a null
534
+ * persisted" and a `/mandrel-deliver` that picks a Story up cannot read a null
535
535
  * checkpoint. Concurrency inside the phase is safe; overlapping the phases is
536
536
  * the race this ordering exists to close.
537
537
  *
@@ -611,7 +611,7 @@ function logEffectiveRoute(route, isLiteRoute) {
611
611
  Logger.info(
612
612
  `[plan-persist] ceremony-lite route upheld by the shape backstop: ` +
613
613
  `created Stories carry the ${LITE_ROUTE_LABEL} hint ` +
614
- `(recorded reason: ${route.authored.reason}). /deliver re-derives ` +
614
+ `(recorded reason: ${route.authored.reason}). /mandrel-deliver re-derives ` +
615
615
  'the route from each Story body — the label is never the control signal.',
616
616
  );
617
617
  return;
@@ -644,10 +644,10 @@ function logPersistEpilogue({ created, primary, planRunLabel }) {
644
644
  `; primary #${primary.id} is agent::ready.`,
645
645
  );
646
646
  Logger.info(
647
- `[plan-persist] Deliver with: /deliver ${created.map((s2) => s2.id).join(' ')}`,
647
+ `[plan-persist] Deliver with: /mandrel-deliver ${created.map((s2) => s2.id).join(' ')}`,
648
648
  );
649
649
  // Metadata only — a GitHub filter for the cohort this run authored, never
650
- // a delivery-resolution input (/deliver stays ids-only, Story #4540).
650
+ // a delivery-resolution input (/mandrel-deliver stays ids-only, Story #4540).
651
651
  Logger.info(
652
652
  `[plan-persist] Cohort grouping label: ${planRunLabel} — filter with ` +
653
653
  `label:${planRunLabel}`,