mandrel 2.37.0 → 2.39.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 (162) hide show
  1. package/.agents/README.md +61 -24
  2. package/.agents/agents/plan-critic.md +1 -1
  3. package/.agents/docs/SDLC.md +40 -40
  4. package/.agents/docs/agentrc-reference.json +1 -4
  5. package/.agents/docs/configuration.md +18 -18
  6. package/.agents/docs/execution-reference.md +3 -3
  7. package/.agents/docs/quality-gates.md +2 -2
  8. package/.agents/docs/workflows.md +6 -6
  9. package/.agents/instructions.md +5 -5
  10. package/.agents/rules/changelog-style.md +3 -3
  11. package/.agents/rules/ci-remediation.md +1 -1
  12. package/.agents/rules/git-conventions-reference.md +4 -4
  13. package/.agents/schemas/agentrc.schema.json +15 -16
  14. package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
  15. package/.agents/schemas/validation-evidence.schema.json +1 -1
  16. package/.agents/scripts/acceptance-eval.js +1 -1
  17. package/.agents/scripts/apply-quality-bootstrap.js +1 -1
  18. package/.agents/scripts/audit-to-stories.js +2 -2
  19. package/.agents/scripts/check-doc-links.js +32 -4
  20. package/.agents/scripts/check-test-temp-hygiene.js +1 -1
  21. package/.agents/scripts/check-workflow-cli-lint.js +1 -1
  22. package/.agents/scripts/deliver-light.js +10 -10
  23. package/.agents/scripts/deliver-recover.js +1 -1
  24. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  25. package/.agents/scripts/evidence-gate.js +1 -1
  26. package/.agents/scripts/generate-skills-index.js +158 -75
  27. package/.agents/scripts/generate-workflows-doc.js +1 -1
  28. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  29. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +1 -1
  30. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +1 -1
  31. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +5 -5
  32. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +1 -1
  33. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  34. package/.agents/scripts/lib/bdd-scenario-budget.js +1 -1
  35. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  36. package/.agents/scripts/lib/bdd-step-index.js +1 -1
  37. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  38. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +1 -1
  40. package/.agents/scripts/lib/changed-files.js +100 -9
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +1 -1
  42. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +1 -1
  43. package/.agents/scripts/lib/cli-args.js +1 -1
  44. package/.agents/scripts/lib/command-header.js +1 -1
  45. package/.agents/scripts/lib/config/delivery-routing.js +1 -1
  46. package/.agents/scripts/lib/config/explain.js +1 -1
  47. package/.agents/scripts/lib/config/runners.js +2 -2
  48. package/.agents/scripts/lib/config/runtime.js +1 -1
  49. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  50. package/.agents/scripts/lib/config-settings-schema-delivery.js +3 -3
  51. package/.agents/scripts/lib/config-settings-schema-quality.js +6 -6
  52. package/.agents/scripts/lib/config-settings-schema.js +28 -10
  53. package/.agents/scripts/lib/duplicate-search.js +1 -1
  54. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +4 -4
  55. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  56. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  57. package/.agents/scripts/lib/findings/promote-finding.js +12 -12
  58. package/.agents/scripts/lib/findings/route-finding.js +2 -2
  59. package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
  60. package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
  61. package/.agents/scripts/lib/label-constants.js +2 -2
  62. package/.agents/scripts/lib/label-taxonomy.js +1 -1
  63. package/.agents/scripts/lib/onboard/init-tail.js +4 -4
  64. package/.agents/scripts/lib/onboard/scaffold-docs.js +2 -2
  65. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
  66. package/.agents/scripts/lib/orchestration/code-review.js +4 -4
  67. package/.agents/scripts/lib/orchestration/complexity-gate.js +5 -5
  68. package/.agents/scripts/lib/orchestration/deliver-recover.js +3 -3
  69. package/.agents/scripts/lib/orchestration/docs-digest.js +3 -3
  70. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +2 -2
  71. package/.agents/scripts/lib/orchestration/light-backstop.js +1 -1
  72. package/.agents/scripts/lib/orchestration/light-escalation.js +6 -6
  73. package/.agents/scripts/lib/orchestration/light-suitability.js +19 -19
  74. package/.agents/scripts/lib/orchestration/plan-context.js +4 -4
  75. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +2 -2
  76. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +2 -2
  77. package/.agents/scripts/lib/orchestration/plan-metrics.js +1 -1
  78. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +1 -1
  79. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +3 -3
  80. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +6 -6
  81. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +16 -16
  82. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +3 -3
  83. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +6 -6
  84. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +7 -7
  85. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +1 -1
  86. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +3 -3
  87. package/.agents/scripts/lib/orchestration/remote-verifier.js +2 -2
  88. package/.agents/scripts/lib/orchestration/resolve-stories.js +4 -4
  89. package/.agents/scripts/lib/orchestration/run-epilogue.js +2 -2
  90. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +2 -2
  91. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +1 -1
  92. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +5 -1
  93. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -1
  94. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +3 -3
  95. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -2
  96. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  97. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +14 -12
  98. package/.agents/scripts/lib/orchestration/ticket-validator.js +1 -1
  99. package/.agents/scripts/lib/orchestration/ticketing/reads.js +3 -3
  100. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  101. package/.agents/scripts/lib/qa/resolve-qa-contract.js +58 -6
  102. package/.agents/scripts/lib/signals/schema.js +1 -1
  103. package/.agents/scripts/lib/skills/skills-index.js +168 -0
  104. package/.agents/scripts/lib/skills/walk-skill-files.js +133 -9
  105. package/.agents/scripts/lib/story-adjacency.js +2 -2
  106. package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
  107. package/.agents/scripts/lib/ticket-body-sections.js +1 -1
  108. package/.agents/scripts/lib/util/concurrent-map.js +1 -1
  109. package/.agents/scripts/lib/util/parse-id-list.js +1 -1
  110. package/.agents/scripts/lib/wave-runner/live-probe.js +4 -4
  111. package/.agents/scripts/lib/wave-runner/ready-set.js +1 -1
  112. package/.agents/scripts/lib/workflow-closure.js +1 -1
  113. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +2 -2
  114. package/.agents/scripts/lint-issue-body.js +3 -3
  115. package/.agents/scripts/plan-context.js +4 -4
  116. package/.agents/scripts/plan-critics.js +2 -2
  117. package/.agents/scripts/plan-persist.js +2 -2
  118. package/.agents/scripts/plan-run-epilogue.js +2 -2
  119. package/.agents/scripts/providers/github/board-add.js +1 -1
  120. package/.agents/scripts/providers/github/errors.js +1 -1
  121. package/.agents/scripts/providers/github/tickets.js +6 -6
  122. package/.agents/scripts/quality-preview.js +50 -9
  123. package/.agents/scripts/resolve-stories.js +3 -3
  124. package/.agents/scripts/resync-status-column.js +1 -1
  125. package/.agents/scripts/run-lint.js +1 -1
  126. package/.agents/scripts/single-story-close.js +2 -2
  127. package/.agents/scripts/single-story-init.js +5 -5
  128. package/.agents/scripts/stories-wave-tick.js +8 -8
  129. package/.agents/scripts/validate-skills.js +53 -66
  130. package/.agents/skills/core/idea-refinement/SKILL.md +5 -5
  131. package/.agents/skills/core/scope-triage/SKILL.md +3 -3
  132. package/.agents/skills/skills.index.json +1 -1
  133. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -1
  134. package/.agents/workflows/audit-data-model.md +1 -1
  135. package/.agents/workflows/audit-documentation.md +2 -2
  136. package/.agents/workflows/audit-to-stories.md +11 -11
  137. package/.agents/workflows/git-deliver.md +4 -4
  138. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  139. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  140. package/.agents/workflows/helpers/code-review.md +4 -4
  141. package/.agents/workflows/helpers/deliver-light.md +26 -26
  142. package/.agents/workflows/helpers/deliver-reference.md +15 -7
  143. package/.agents/workflows/helpers/deliver-story-reference.md +9 -4
  144. package/.agents/workflows/helpers/deliver-story.md +6 -7
  145. package/.agents/workflows/helpers/diagnose.md +2 -2
  146. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  147. package/.agents/workflows/helpers/plan-reference.md +9 -9
  148. package/.agents/workflows/helpers/qa-core.md +8 -8
  149. package/.agents/workflows/helpers/worktree-lifecycle.md +6 -6
  150. package/.agents/workflows/{deliver.md → mandrel-deliver.md} +15 -19
  151. package/.agents/workflows/{plan.md → mandrel-plan.md} +9 -9
  152. package/.agents/workflows/memory-consolidate.md +4 -4
  153. package/.agents/workflows/prototype.md +3 -3
  154. package/.agents/workflows/qa-assist.md +12 -12
  155. package/.agents/workflows/qa-explore.md +6 -6
  156. package/.agents/workflows/qa-run.md +14 -6
  157. package/README.md +7 -7
  158. package/docs/CHANGELOG.md +23 -0
  159. package/lib/cli/doctor.js +1 -1
  160. package/lib/cli/init.js +1 -1
  161. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +1 -1
  162. package/package.json +1 -1
package/.agents/README.md CHANGED
@@ -4,10 +4,10 @@ An opinionated workflow framework for AI coding assistants built on
4
4
  Story-centric GitHub orchestration. Planning, execution, and state all live natively in GitHub Issues, Labels, and Projects V2.
5
5
 
6
6
  This is the consumer README inside the distributed `.agents/` bundle. It explains what each part of the bundle is for and captures the cross-directory authoring conventions. The process narrative for
7
- `/plan` and `/deliver` stays in [`docs/SDLC.md`](docs/SDLC.md).
7
+ `/mandrel-plan` and `/mandrel-deliver` stays in [`docs/SDLC.md`](docs/SDLC.md).
8
8
 
9
9
  The framework payload (`.agents/`) is consumed by host repos. It ships inside the [`mandrel`](https://www.npmjs.com/package/mandrel)
10
- npm package and is materialized into a consumer's `./.agents/` directory by `mandrel sync`. It carries a system prompt, a baseline rule pack, a two-tier skill library, a slash-command workflow set, and the orchestration engine that runs Story-centric plans on GitHub (`/plan` → Stories, `/deliver` → `story-*` → `main`).
10
+ npm package and is materialized into a consumer's `./.agents/` directory by `mandrel sync`. It carries a system prompt, a baseline rule pack, a two-tier skill library, a slash-command workflow set, and the orchestration engine that runs Story-centric plans on GitHub (`/mandrel-plan` → Stories, `/mandrel-deliver` → `story-*` → `main`).
11
11
 
12
12
  The framework version is the version of the installed [`mandrel`](https://www.npmjs.com/package/mandrel) npm package — run `npm ls mandrel` (or read `package.json`), not a
13
13
  count here.
@@ -44,7 +44,7 @@ unattended.
44
44
 
45
45
  After it completes, `mandrel init` runs the onboarding tail automatically —
46
46
  stack detection, docs scaffolding offer, a `mandrel doctor` readiness gate,
47
- and a printed `/plan` handoff — so you land at planning in one command.
47
+ and a printed `/mandrel-plan` handoff — so you land at planning in one command.
48
48
 
49
49
  ### Manual Install
50
50
 
@@ -273,10 +273,10 @@ For non-interactive (CI) installs, pass `--owner`, `--repo`, and
273
273
  After bootstrap, every Mandrel command is generated into a flat
274
274
  `.claude/commands/` tree by `npm run sync:commands` (kept current at install
275
275
  time and on every `mandrel sync`/`update`) and loads as a bare `/<command>`
276
- slash command — e.g. `/plan`, `/deliver`, `/audit-security`. The commands load
276
+ slash command — e.g. `/mandrel-plan`, `/mandrel-deliver`, `/audit-security`. The commands load
277
277
  in every Claude Code environment. The [SDLC guide](docs/SDLC.md) walks end-to-end planning and
278
- delivery; Stories pair [`/plan`](workflows/plan.md) (idea → drafted Story Issue)
279
- with [`/deliver`](workflows/deliver.md) (Story Issue → merged
278
+ delivery; Stories pair [`/mandrel-plan`](workflows/mandrel-plan.md) (idea → drafted Story Issue)
279
+ with [`/mandrel-deliver`](workflows/mandrel-deliver.md) (Story Issue → merged
280
280
  PR).
281
281
 
282
282
  ---
@@ -319,12 +319,12 @@ in `runtime-deps.json`.
319
319
 
320
320
  ## Ticket Hierarchy
321
321
 
322
- Orchestration and planning are **Story-only** (`type::story`) — `/plan`
322
+ Orchestration and planning are **Story-only** (`type::story`) — `/mandrel-plan`
323
323
  persists Stories with inline `acceptance[]` / `verify[]` and a folded
324
- `## Spec`; `/deliver` runs `helpers/deliver-story` on `story-<id>` → PR →
324
+ `## Spec`; `/mandrel-deliver` runs `helpers/deliver-story` on `story-<id>` → PR →
325
325
  `main`. There is no `type::epic` / `type::task` label, Epic issue form, or
326
326
  `epic/<id>` integration branch; a ticket carrying an `Epic: #N` footer is
327
- refused by `/deliver`. The execution-model contract is owned by
327
+ refused by `/mandrel-deliver`. The execution-model contract is owned by
328
328
  [`instructions.md` § 5.B](instructions.md) and [`docs/SDLC.md`](docs/SDLC.md).
329
329
 
330
330
  ---
@@ -334,7 +334,7 @@ refused by `/deliver`. The execution-model contract is owned by
334
334
  | Path | Purpose |
335
335
  | ---- | ------- |
336
336
  | [`instructions.md`](instructions.md) | Primary system prompt loaded by the host AI tool. |
337
- | [`docs/SDLC.md`](docs/SDLC.md) | Operator process for `/plan` and `/deliver`. |
337
+ | [`docs/SDLC.md`](docs/SDLC.md) | Operator process for `/mandrel-plan` and `/mandrel-deliver`. |
338
338
  | [`starter-agentrc.json`](starter-agentrc.json) | Bootstrap delta-seed copied to the consumer repo root as `.agentrc.json`. |
339
339
  | [`agentrc-reference.json`](docs/agentrc-reference.json) | Exhaustive editor reference enumerating every schema key with its framework default. |
340
340
  | [`agents/`](agents/) | Optional role-scoped spawn boot contexts (`delivery.routing.roleScopedAgents`). |
@@ -535,7 +535,7 @@ sessions, `gh auth login` is sufficient.
535
535
  ## Self-Healing Checks
536
536
 
537
537
  `scripts/lib/checks/` is the discovery-based registry of named checks
538
- consumed by preflight guards (`/deliver`, `single-story-close`, `npm test`),
538
+ consumed by preflight guards (`/mandrel-deliver`, `single-story-close`, `npm test`),
539
539
  the `diagnose.js` ad-hoc viewer, and the retro surface. Use one check per
540
540
  file. The runner (`index.js`) loads checks at process start and filters by
541
541
  scope at each call site.
@@ -636,7 +636,7 @@ Schema conventions:
636
636
 
637
637
  ## Code review providers (pluggable chain)
638
638
 
639
- `runCodeReview()` (invoked from `helpers/deliver-story` and `/deliver`'s
639
+ `runCodeReview()` (invoked from `helpers/deliver-story` and `/mandrel-deliver`'s
640
640
  risk-routed ceremony) loads its review backend through a pluggable registry
641
641
  configured via `delivery.codeReview.providers` — an array of entries iterated
642
642
  in declaration order. The chain-entry field semantics (`name`, `scopes`,
@@ -666,7 +666,7 @@ documented once in
666
666
  ## Multi-developer coordination
667
667
 
668
668
  Two operators can drive the same repository at once — for example, two
669
- `/deliver <storyId>` runs from separate clones. The framework keeps those
669
+ `/mandrel-deliver <storyId>` runs from separate clones. The framework keeps those
670
670
  runs from clobbering one another with **two distinct coordination layers**.
671
671
  They solve different problems and must not be confused:
672
672
 
@@ -712,14 +712,14 @@ yanks the claim back from whoever legitimately took over.
712
712
 
713
713
  **Where it's wired:**
714
714
 
715
- - **`/deliver`** runs each Story through `helpers/deliver-story`, which
715
+ - **`/mandrel-deliver`** runs each Story through `helpers/deliver-story`, which
716
716
  acquires the lease on the **Story** ticket at init and releases it at close
717
717
  ([`single-story-lease-guard.js`](scripts/lib/orchestration/single-story-lease-guard.js)).
718
718
  A live foreign claim refuses the run; pass `--steal` to override. The Story
719
719
  path requires `github.operatorHandle` to be set — without an operator identity
720
720
  the lease has no owner to record.
721
- - **`/plan`** does not take a planning lease on an Epic ticket. Planning is a
722
- short authoring ceremony over Stories; concurrent `/plan` runs coordinate
721
+ - **`/mandrel-plan`** does not take a planning lease on an Epic ticket. Planning is a
722
+ short authoring ceremony over Stories; concurrent `/mandrel-plan` runs coordinate
723
723
  via ordinary GitHub issue creation, not an Epic lease guard.
724
724
 
725
725
  ---
@@ -775,7 +775,16 @@ time by `resolveQaContract`. Copy the reference shape from
775
775
  "qa": {
776
776
  "featureRoot": "tests/features", // root the selector resolves .feature files against
777
777
  "fixturesManifest": "tests/fixtures/personas.json", // persona → seed-data manifest
778
- "signInSeam": { "urlTemplate": "/dev/sign-in-as/{persona}" }, // dev seam (see step 3)
778
+ "environments": { // one entry per deployment target
779
+ "local": {
780
+ "baseUrl": "http://localhost:3000",
781
+ "signInSeam": { "urlTemplate": "/dev/sign-in-as/{persona}" } // dev seam (see step 3)
782
+ },
783
+ "staging": {
784
+ "baseUrl": "https://staging.example.test",
785
+ "allowWrites": false // no signInSeam — an honestly seamless target
786
+ }
787
+ },
779
788
  "personas": ["admin", "member"], // name-only array — the honest shape for a url-template seam
780
789
  "consoleAllowlist": ["[HMR]"], // optional benign-noise filter (default [])
781
790
  "designTokens": "src/styles/tokens.css" // optional visual-check pointer (default null)
@@ -783,8 +792,9 @@ time by `resolveQaContract`. Copy the reference shape from
783
792
  }
784
793
  ```
785
794
 
786
- `featureRoot`, `fixturesManifest`, `signInSeam`, and `personas` are mandatory;
787
- omitting any one makes the resolver throw a field-named error.
795
+ `featureRoot`, `fixturesManifest`, `environments`, and `personas` are mandatory;
796
+ omitting any one makes the resolver throw a field-named error. Within an
797
+ environment only `baseUrl` is required — `signInSeam` is optional (see step 3).
788
798
  `consoleAllowlist` and `designTokens` default to `[]` and `null`.
789
799
 
790
800
  `personas` accepts **two shapes** (the resolver normalizes both to one
@@ -800,13 +810,16 @@ canonical internal map keyed by persona name):
800
810
  (or credential) seam where that material is genuinely consulted:
801
811
 
802
812
  ```jsonc
803
- "signInSeam": { "skill": "stack/qa/sign-in" },
813
+ "signInSeam": { "skill": "stack/qa/acme-sso" }, // a skill YOU author (see step 3)
804
814
  "personas": {
805
815
  "admin": { "credentialRef": "QA_ADMIN_CREDENTIAL" }, // stored-credential reference, never an inline secret
806
- "member": { "signInSkill": "stack/qa/sign-in-member" } // or a per-persona sign-in skill
816
+ "member": { "signInSkill": "stack/qa/acme-sso-member" } // or a per-persona sign-in skill
807
817
  }
808
818
  ```
809
819
 
820
+ Both skill ids above are **illustrative names for skills you write** — the
821
+ framework ships no sign-in skill. Step 3 says where they go.
822
+
810
823
  ### 2. Author the fixtures manifest
811
824
 
812
825
  Create the file referenced by `fixturesManifest`. It binds each persona to the
@@ -824,9 +837,33 @@ credentials are never entered. Expose one of two shapes:
824
837
  - **`{ urlTemplate }`** — a dev sign-in route where `{persona}` is substituted
825
838
  (e.g. `/dev/sign-in-as/{persona}` → `/dev/sign-in-as/admin`); gate it to
826
839
  non-production builds. Pair with the name-only `personas` array.
827
- - **`{ skill }`** — when sign-in is multi-step or non-URL, point at a consumer
828
- skill whose `SKILL.md` the harness reads. Pair with the object-map
829
- `personas` form (per step 1).
840
+ - **`{ skill }`** — when sign-in is multi-step or non-URL, name a skill by its
841
+ tier-relative id (e.g. `stack/qa/acme-sso`) whose `SKILL.md` the harness
842
+ reads. Pair with the object-map `personas` form (per step 1).
843
+ - **Omit it entirely** — the honest shape for a target with no sign-in seam at
844
+ all, such as a deployed build whose dev bypass is tree-shaken out. The
845
+ workflows then drive the unauthenticated surface and record the gap rather
846
+ than fabricating a session.
847
+
848
+ **Where a `{ skill }` seam resolves.** The id is looked up under
849
+ `.agents/skills/` (the package payload) and then `.agents/local/skills/` —
850
+ the consumer-writable zone. Author your own sign-in skill in the local zone:
851
+
852
+ ```text
853
+ .agents/local/skills/stack/qa/acme-sso/SKILL.md → id: stack/qa/acme-sso
854
+ ```
855
+
856
+ `.agents/local/` is never copied into by `mandrel sync`, never pruned, and
857
+ never reported as payload drift by `mandrel doctor`, so a skill you write
858
+ there survives every upgrade. It is held to the same bar as a shipped skill —
859
+ `validate-skills.js` checks its frontmatter and Policy Capsule, and
860
+ `generate-skills-index.js` writes it into its own
861
+ `.agents/local/skills/skills.index.json` (never into the shipped manifest,
862
+ which must stay byte-identical to the package payload).
863
+
864
+ A seam naming an id that resolves under neither root is rejected by
865
+ `resolveQaEnvironment` when the contract is resolved — not silently carried
866
+ until a sweep reaches its sign-in step.
830
867
 
831
868
  Once these three `qa.*` keys are in place, `/qa-explore <surface>`, `/qa-assist`,
832
869
  and `/qa-run <selector>` all resolve the contract and operate against the bound
@@ -5,7 +5,7 @@ description: >-
5
5
  system prompt (no CLAUDE.md / instructions.md closure). Reviews an authored
6
6
  plan draft (stories.json, optional techspec.md) against a single critic
7
7
  charter — consolidation or pre-mortem — and returns findings, without seeing
8
- the planner's authoring transcript. Dispatched by workflows/plan.md §2.5 when
8
+ the planner's authoring transcript. Dispatched by workflows/mandrel-plan.md §2.5 when
9
9
  delivery.routing.roleScopedAgents is enabled (the default).
10
10
  ---
11
11
 
@@ -11,7 +11,7 @@ An Epic may still exist as an **optional untyped human umbrella issue**
11
11
  `.github/ISSUE_TEMPLATE/story.yml`), but **delivery and planning
12
12
  orchestration are Story-only**: there is no Epic wave loop, no
13
13
  `epic/<id>` integration branch, no `epic.yaml` reconciler, and any ticket
14
- that still carries an `Epic: #N` footer is **refused** by `/deliver`
14
+ that still carries an `Epic: #N` footer is **refused** by `/mandrel-deliver`
15
15
  (close it or re-plan it as a v2 Story).
16
16
 
17
17
  The framework is **Claude Code-first**: `.claude/`, hooks, skills, and
@@ -26,25 +26,25 @@ ADR 20260512-coupling-stance in [`../docs/decisions.md`](../../docs/decisions.md
26
26
 
27
27
  From zero to shipped:
28
28
 
29
- 1. **Plan the work.** Run [`/plan`](../workflows/plan.md) in your agentic IDE.
29
+ 1. **Plan the work.** Run [`/mandrel-plan`](../workflows/mandrel-plan.md) in your agentic IDE.
30
30
  The framework authors **one Story by default** (folded Tech Spec in
31
31
  `## Spec`), splitting into N>1 only under the default-single split policy.
32
- Three operator modes are the **only** accepted entries — `/plan --seed
33
- "<text>"` (ideate from chat text), `/plan --seed-file <path>` (author from
32
+ Three operator modes are the **only** accepted entries — `/mandrel-plan --seed
33
+ "<text>"` (ideate from chat text), `/mandrel-plan --seed-file <path>` (author from
34
34
  on-disk notes / a plan seed — the [`/audit-to-stories`](../workflows/audit-to-stories.md)
35
- handoff via `--emit-plan-seed`), and `/plan --tickets 123[,456…]` (analyze
36
- existing issue(s), preferring an N=1 rewrite). `/plan` is a **single path**
35
+ handoff via `--emit-plan-seed`), and `/mandrel-plan --tickets 123[,456…]` (analyze
36
+ existing issue(s), preferring an N=1 rewrite). `/mandrel-plan` is a **single path**
37
37
  — interrogate → author → persist, bracketed by two HITL gates and a single
38
38
  critic gate — with no Epic/Story router, scope-triage verdict, or
39
39
  `deliveryShape`. Duplicate search targets open **Stories**, never Epics. The
40
- step-by-step lives in [`plan.md`](../workflows/plan.md).
40
+ step-by-step lives in [`mandrel-plan.md`](../workflows/mandrel-plan.md).
41
41
 
42
- 2. **Deliver the Story.** Run [`/deliver <storyId>`](../workflows/deliver.md)
43
- (or `/deliver <a> <b> …` for several). `/deliver` takes only Story ids and
42
+ 2. **Deliver the Story.** Run [`/mandrel-deliver <storyId>`](../workflows/mandrel-deliver.md)
43
+ (or `/mandrel-deliver <a> <b> …` for several). `/mandrel-deliver` takes only Story ids and
44
44
  resolves their dependency graph from live state — body edges union native
45
45
  GitHub `blocked_by` edges, every blocker checked against its real issue
46
46
  state, so a Story whose blocker landed in an earlier plan run is simply
47
- ready. `/deliver` owns input resolution and dispatch order — the declared
47
+ ready. `/mandrel-deliver` owns input resolution and dispatch order — the declared
48
48
  `depends_on` edges plus a delivery-time file-overlap guard that withholds
49
49
  two Stories whose footprints would race the same path (see
50
50
  [`architecture.md` § Scheduler safety mechanics](../../docs/architecture.md));
@@ -52,14 +52,14 @@ From zero to shipped:
52
52
  [`helpers/deliver-story`](../workflows/helpers/deliver-story.md) —
53
53
  init → implement → acceptance self-eval → ceremony → close → CI watch →
54
54
  confirm-merge — which owns its own per-step detail. For a multi-Story run,
55
- `/deliver` sequences ready Stories by `depends_on` — plus that footprint
55
+ `/mandrel-deliver` sequences ready Stories by `depends_on` — plus that footprint
56
56
  guard — and runs the per-run epilogue (audit roster · follow-up roll-up ·
57
57
  sibling coherence) once after the last Story lands.
58
58
 
59
59
  That is the whole happy path. Everything below is **detail** — branching
60
60
  conventions, HITL escalation, audit lenses — that you only need when the
61
61
  default flow requires adjustment. It intentionally **links** to
62
- [`plan.md`](../workflows/plan.md) and [`deliver.md`](../workflows/deliver.md)
62
+ [`mandrel-plan.md`](../workflows/mandrel-plan.md) and [`mandrel-deliver.md`](../workflows/mandrel-deliver.md)
63
63
  rather than re-documenting the ceremony they own.
64
64
 
65
65
  ## Core Principles
@@ -79,7 +79,7 @@ rather than re-documenting the ceremony they own.
79
79
  `story-<id>` branch. Each Story reaches `main` through its own PR
80
80
  (squash + required checks); there is **no** `epic/<id>` integration
81
81
  branch and **no** `--no-ff` wave merge.
82
- - **One delivery engine.** `/deliver` resolves and sequences a Story set;
82
+ - **One delivery engine.** `/mandrel-deliver` resolves and sequences a Story set;
83
83
  `helpers/deliver-story` executes each Story identically (trivial or
84
84
  large). Story sub-agents run inside the operator's Claude session via
85
85
  the Agent tool — worktree filesystem isolation is preserved; only the
@@ -133,12 +133,12 @@ graph LR
133
133
 
134
134
  subgraph Phase0 ["Phase 0: Bootstrap"]
135
135
  direction TB
136
- Z["👤 npx mandrel init<br/>(install → sync → bootstrap.js → onboarding tail → /plan handoff)"]:::manual
136
+ Z["👤 npx mandrel init<br/>(install → sync → bootstrap.js → onboarding tail → /mandrel-plan handoff)"]:::manual
137
137
  end
138
138
 
139
139
  subgraph Phase1 ["Phase 1: Plan"]
140
140
  direction TB
141
- A["👤 /plan --seed | --seed-file | --tickets"]:::manual
141
+ A["👤 /mandrel-plan --seed | --seed-file | --tickets"]:::manual
142
142
  B["🤖 interrogate → author → persist"]:::agentic
143
143
  A --> B
144
144
  B -.-> B_Art["📄 type::story issue(s)<br/>(+ depends_on edges)"]:::artifact
@@ -146,7 +146,7 @@ graph LR
146
146
 
147
147
  subgraph Phase2 ["Phase 2: Deliver"]
148
148
  direction TB
149
- E["👤 /deliver &lt;storyId&gt; [&lt;storyId&gt;…]"]:::manual
149
+ E["👤 /mandrel-deliver &lt;storyId&gt; [&lt;storyId&gt;…]"]:::manual
150
150
  F["🤖 deliver-story: story-&lt;id&gt; from main<br/>implement → self-eval → ceremony → close"]:::agentic
151
151
  G["🤖 close-validation → code-review → open PR"]:::agentic
152
152
  E --> F --> G
@@ -192,14 +192,14 @@ branch-protection entries are preserved; missing ones are added.
192
192
 
193
193
  ## Phase 1: Planning
194
194
 
195
- Planning is owned end-to-end by [`/plan`](../workflows/plan.md). Rather than
195
+ Planning is owned end-to-end by [`/mandrel-plan`](../workflows/mandrel-plan.md). Rather than
196
196
  re-document the ceremony here, this section states the contract the rest of
197
197
  the SDLC depends on:
198
198
 
199
199
  - **Entry is text or tickets, never Epic.** The only accepted invocations
200
200
  are `--seed`, `--seed-file`, and `--tickets`. There is no `--idea`, no
201
- `--one-pager`, no `--from-notes`, and no positional `/plan <epicId>`.
202
- - **One Story by default.** `/plan` authors a single `type::story` issue
201
+ `--one-pager`, no `--from-notes`, and no positional `/mandrel-plan <epicId>`.
202
+ - **One Story by default.** `/mandrel-plan` authors a single `type::story` issue
203
203
  whose body carries a folded `## Spec` (inline only — never spilled to
204
204
  `docs/`) plus top-level `acceptance[]` / `verify[]`. It splits into N>1
205
205
  siblings (ordered by `depends_on` edges) **only**
@@ -213,7 +213,7 @@ the SDLC depends on:
213
213
  `assertAcceptancePartition` so every acceptance criterion belongs to
214
214
  exactly one Story.
215
215
  - **Handoff.** Persist creates the Story issue(s) at `agent::ready` and
216
- names the delivery command: `/deliver <storyId> [<storyId> ...]`.
216
+ names the delivery command: `/mandrel-deliver <storyId> [<storyId> ...]`.
217
217
 
218
218
  Optional split advisory notes come from
219
219
  [`core/scope-triage`](../skills/core/scope-triage/SKILL.md); there is no
@@ -223,13 +223,13 @@ behind them.
223
223
  Audit findings enter planning through
224
224
  [`/audit-to-stories`](../workflows/audit-to-stories.md), which groups and
225
225
  deduplicates findings and hands off via `--emit-plan-seed` →
226
- `/plan --seed-file <path>`.
226
+ `/mandrel-plan --seed-file <path>`.
227
227
 
228
228
  ---
229
229
 
230
230
  ## Phase 2: Delivery
231
231
 
232
- Delivery is owned end-to-end by [`/deliver`](../workflows/deliver.md), which
232
+ Delivery is owned end-to-end by [`/mandrel-deliver`](../workflows/mandrel-deliver.md), which
233
233
  delegates every Story to
234
234
  [`helpers/deliver-story`](../workflows/helpers/deliver-story.md). This
235
235
  section states the contract; the per-Story step detail (init, implement,
@@ -241,11 +241,11 @@ self-eval, ceremony, close, CI watch, confirm-merge, cleanup) lives in the
241
241
 
242
242
  | Mode | Entry point | When to use |
243
243
  | --- | --- | --- |
244
- | **Single Story** | `/deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
245
- | **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**), resolved from live state so edges may point at Stories from earlier plan runs; a delivery-time file-overlap guard additionally withholds two Stories whose footprints would race the same path (`delivery.deliverRunner.footprintGuard`). Each lands through its own PR, and the per-run epilogue runs after the set lands. |
246
- | **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/deliver`; not an operator slash command. |
244
+ | **Single Story** | `/mandrel-deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
245
+ | **Story set** | `/mandrel-deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**), resolved from live state so edges may point at Stories from earlier plan runs; a delivery-time file-overlap guard additionally withholds two Stories whose footprints would race the same path (`delivery.deliverRunner.footprintGuard`). Each lands through its own PR, and the per-run epilogue runs after the set lands. |
246
+ | **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/mandrel-deliver`; not an operator slash command. |
247
247
 
248
- The single operator-facing entry point is `/deliver`. It performs no
248
+ The single operator-facing entry point is `/mandrel-deliver`. It performs no
249
249
  git/label mutations itself — `deliver-story` owns every script invocation
250
250
  per Story. Any ticket that is not `type::story`, or that still carries an
251
251
  `Epic: #N` reference, is a hard error naming the ID and the fix (close or
@@ -269,7 +269,7 @@ own planning risk. Hard gates (lint / test / format / coverage / CRAP /
269
269
  maintainability) always run at close — risk never disables them; it only
270
270
  tunes acceptance-critic mode, review depth, and audit-lens selection. The
271
271
  full profile × scope matrix lives in
272
- [`deliver.md` § Ceremony](../workflows/deliver.md).
272
+ [`mandrel-deliver.md` § Ceremony](../workflows/mandrel-deliver.md).
273
273
 
274
274
  ### State sync
275
275
 
@@ -321,7 +321,7 @@ resolution.
321
321
  ## HITL (Human-in-the-Loop) model
322
322
 
323
323
  On the happy path there is exactly **one** mandatory operator touchpoint
324
- after `/deliver` fires (blocker resolution). PR merge is autonomous via
324
+ after `/mandrel-deliver` fires (blocker resolution). PR merge is autonomous via
325
325
  armed auto-merge; the operator becomes a second touchpoint only by
326
326
  exception.
327
327
 
@@ -411,7 +411,7 @@ pass — the tiers below *are* the audit machinery.
411
411
  | --- | --- | --- | --- |
412
412
  | Tier 1 — write-time | During Story implementation | Footprint-matched **local**-lens authoring checklists threaded into the Story prompt (`checklistPath`) | advisory |
413
413
  | Tier 2 — Story-scope | `single-story-close.js` (maker-blind subprocess) | Local-tier lens roster over the Story diff (`selectLocalLenses`) + review pillars, posted as `verification-results` | blocking on 🔴 |
414
- | Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global lenses (`selectAudits`) over the combined landed tip | blocking |
414
+ | Tier 3 — run closeout | `/mandrel-deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global lenses (`selectAudits`) over the combined landed tip | blocking |
415
415
 
416
416
  - **`local`** lenses (decidable from a single Story's diff) are verified at
417
417
  Tiers 1–2 and are **not** re-run at run closeout.
@@ -452,7 +452,7 @@ baseline edits. The runbooks (bootstrap, refresh, floor policy) are owned by
452
452
  The standalone `/audit-<dimension>` workflows write
453
453
  `audit-<dimension>-results.md` under `temp/audits/`;
454
454
  [`/audit-to-stories`](../workflows/audit-to-stories.md) groups and deduplicates
455
- those findings and hands off to `/plan --seed-file` (or opens standalone
455
+ those findings and hands off to `/mandrel-plan --seed-file` (or opens standalone
456
456
  Stories), closing the loop back into planning.
457
457
 
458
458
  ---
@@ -560,9 +560,9 @@ Editing the main checkout's `.agentrc.json` only affects **the next**
560
560
 
561
561
  ### `Epic: #N` refusal
562
562
 
563
- `/deliver` refuses any ticket that still carries an `Epic: #N` footer or is
563
+ `/mandrel-deliver` refuses any ticket that still carries an `Epic: #N` footer or is
564
564
  not `type::story`. This is expected — v2 has no Epic delivery path. Close
565
- the ticket or re-plan the work as a v2 Story via `/plan --tickets <id>`.
565
+ the ticket or re-plan the work as a v2 Story via `/mandrel-plan --tickets <id>`.
566
566
 
567
567
  ---
568
568
 
@@ -570,13 +570,13 @@ the ticket or re-plan the work as a v2 Story via `/plan --tickets <id>`.
570
570
 
571
571
  | Command | Purpose |
572
572
  | --- | --- |
573
- | `npx mandrel init` | Cold-start — install `mandrel` (if absent), `mandrel sync`, `bootstrap.js` (provisions repo + Projects V2 board, labels, branch protection), then the onboarding tail (stack detection, docs scaffolding, doctor gate, `/plan` handoff). |
574
- | `/plan --seed "<text>"` | Plan from chat text — interrogate → author **one Story by default** → persist `type::story`. |
575
- | `/plan --seed-file <path>` | Plan from on-disk notes / a plan seed (the `/audit-to-stories` handoff). |
576
- | `/plan --tickets <ids>` | Analyze existing issue(s) into proper Stories (prefer an N=1 rewrite). |
577
- | `/deliver <storyId>` | Deliver one Story via `helpers/deliver-story` — `story-<id>` → PR → `main`. |
578
- | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (resolved from live state), then run the per-run epilogue. |
579
- | *helper* `helpers/deliver-story` | Per-Story engine invoked by `/deliver`; not an operator slash command. See [`deliver-story.md`](../workflows/helpers/deliver-story.md). |
580
- | `/audit-to-stories` | Convert audit findings into a plan seed / Stories → `/plan --seed-file`. |
573
+ | `npx mandrel init` | Cold-start — install `mandrel` (if absent), `mandrel sync`, `bootstrap.js` (provisions repo + Projects V2 board, labels, branch protection), then the onboarding tail (stack detection, docs scaffolding, doctor gate, `/mandrel-plan` handoff). |
574
+ | `/mandrel-plan --seed "<text>"` | Plan from chat text — interrogate → author **one Story by default** → persist `type::story`. |
575
+ | `/mandrel-plan --seed-file <path>` | Plan from on-disk notes / a plan seed (the `/audit-to-stories` handoff). |
576
+ | `/mandrel-plan --tickets <ids>` | Analyze existing issue(s) into proper Stories (prefer an N=1 rewrite). |
577
+ | `/mandrel-deliver <storyId>` | Deliver one Story via `helpers/deliver-story` — `story-<id>` → PR → `main`. |
578
+ | `/mandrel-deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (resolved from live state), then run the per-run epilogue. |
579
+ | *helper* `helpers/deliver-story` | Per-Story engine invoked by `/mandrel-deliver`; not an operator slash command. See [`deliver-story.md`](../workflows/helpers/deliver-story.md). |
580
+ | `/audit-to-stories` | Convert audit findings into a plan seed / Stories → `/mandrel-plan --seed-file`. |
581
581
  | `/qa-explore` · `/qa-assist` · `/qa-run` | Agent-led / human-led exploratory QA and the automated Gherkin harness. |
582
582
  | `/git-deliver` | Ad-hoc delivery of working-tree changes — detects the git setup and escalates to commit, commit + push, or commit + push + PR (auto-merge armed). |
@@ -363,9 +363,6 @@
363
363
  },
364
364
  "staging": {
365
365
  "baseUrl": "https://staging.example.test",
366
- "signInSeam": {
367
- "skill": "stack/qa/sign-in"
368
- },
369
366
  "allowWrites": false
370
367
  }
371
368
  },
@@ -374,7 +371,7 @@
374
371
  "credentialRef": "QA_ADMIN_CREDENTIAL"
375
372
  },
376
373
  "member": {
377
- "signInSkill": "stack/qa/sign-in-member"
374
+ "credentialRef": "QA_MEMBER_CREDENTIAL"
378
375
  }
379
376
  },
380
377
  "gherkinLint": {
@@ -55,8 +55,8 @@ top-level keys are validation errors.
55
55
  | ------------- | -------- | ---------------------------------------------------------------------------------- |
56
56
  | `project` | **Yes** | Project-local paths, base branch, validation commands, and context-hydration files. |
57
57
  | `github` | No | Ticketing provider config: owner/repo, branch protection, merge methods, notifications. |
58
- | `planning` | No | `/plan` tuning: conflict advisories, complexity routing, navigability gate. (Story sizing ceilings and the planner-context cap are code-absolute — not agentrc.) |
59
- | `delivery` | No | `/deliver` tuning: quality gates, worktree isolation, runners, CI watch, code-review providers. |
58
+ | `planning` | No | `/mandrel-plan` tuning: conflict advisories, complexity routing, navigability gate. (Story sizing ceilings and the planner-context cap are code-absolute — not agentrc.) |
59
+ | `delivery` | No | `/mandrel-deliver` tuning: quality gates, worktree isolation, runners, CI watch, code-review providers. |
60
60
  | `qa` | No | Agent-driven QA harness contract: feature root, fixtures, environments, personas. |
61
61
  | `$schema` | No | JSON Schema pointer for editor tooling. |
62
62
 
@@ -118,7 +118,7 @@ GitHub provider identity plus the remote stance the bootstrap enforces. `owner`,
118
118
 
119
119
  ### `planning` (optional)
120
120
 
121
- Inputs to `/plan`: risk escalation heuristics, ceremony-lite routing, and the cross-Story conflict-finding severity gates.
121
+ Inputs to `/mandrel-plan`: risk escalation heuristics, ceremony-lite routing, and the cross-Story conflict-finding severity gates.
122
122
 
123
123
  | Key | Required | Type | Default | Description |
124
124
  | --- | --- | --- | --- | --- |
@@ -138,7 +138,7 @@ Inputs to `/plan`: risk escalation heuristics, ceremony-lite routing, and the cr
138
138
 
139
139
  ### `delivery` (optional)
140
140
 
141
- Everything `/deliver` and `single-story-close` consume: execution timeouts, worktree isolation, runner concurrency, docs freshness, signals, quality gates, merge/CI watch, review ceremony, and the feedback loop.
141
+ Everything `/mandrel-deliver` and `single-story-close` consume: execution timeouts, worktree isolation, runner concurrency, docs freshness, signals, quality gates, merge/CI watch, review ceremony, and the feedback loop.
142
142
 
143
143
  | Key | Required | Type | Default | Description |
144
144
  | --- | --- | --- | --- | --- |
@@ -154,8 +154,8 @@ Everything `/deliver` and `single-story-close` consume: execution timeouts, work
154
154
  | `tempRetention.classes.validationEvidence` | No | `boolean` | `true` | Per-Story validation-evidence.json, lifecycle.ndjson, and manifest.md under the standalone and per-run story trees. |
155
155
  | `tempRetention.classes.auditResults` | No | `boolean` | `true` | <tempRoot>/audits/ — audit lens reports. |
156
156
  | `tempRetention.classes.planDirs` | No | `boolean` | `true` | <tempRoot>/plan-<slug>/ — abandoned plan authoring dirs. Age-floored only; the current run is always excluded. |
157
- | `deliverRunner` | No | `object` | — | Bounded-concurrency knob for the /deliver fan-out. |
158
- | `deliverRunner.concurrencyCap` | No | `integer` | `3` | Maximum ready Stories dispatched by /deliver at once. Default 3. Moderate by design — keeps host-quota consumption predictable while allowing a small ready-set fan-out. Set 1 for strictly sequential delivery; raise further on hosts with adequate parallel-agent quota. See deliver.md for the sequencing model and throughput tradeoff. |
157
+ | `deliverRunner` | No | `object` | — | Bounded-concurrency knob for the /mandrel-deliver fan-out. |
158
+ | `deliverRunner.concurrencyCap` | No | `integer` | `3` | Maximum ready Stories dispatched by /mandrel-deliver at once. Default 3. Moderate by design — keeps host-quota consumption predictable while allowing a small ready-set fan-out. Set 1 for strictly sequential delivery; raise further on hosts with adequate parallel-agent quota. See deliver.md for the sequencing model and throughput tradeoff. |
159
159
  | `deliverRunner.footprintGuard` | No | `"enforce"` \| `"advisory"` | `"enforce"` | How a file-footprint collision affects dispatch. 'enforce' (default, and the behaviour to keep unless you have a reason) withholds a Story whose footprint races a peer admitted this beat or one still in flight — the guard encodes delivery-time-only knowledge (open implementation windows, foreign leases, ground that moved since planning) that no depends_on edge can carry. 'advisory' still DETECTS every collision and reports each would-be withhold in the tick envelope, but lets dispatch follow the declared depends_on edges alone — a deliberate throughput trade for a run whose ordering is fully declared. See stories-wave-tick.js and helpers/deliver-reference.md. |
160
160
  | `worktreeIsolation` | No | `object` | — | Per-Story git worktree provisioning. Each Story is implemented in its own checkout so concurrent siblings never share a working tree. |
161
161
  | `worktreeIsolation.enabled` | No | `boolean` | `true` | When true, `single-story-init.js` materializes a worktree per Story. False implements every Story in the main checkout, which is only safe for strictly serial delivery. |
@@ -284,22 +284,22 @@ Everything `/deliver` and `single-story-close` consume: execution timeouts, work
284
284
  | `quality.baselineEpsilon.bundle-size` | No | `number` | `1024` | — |
285
285
  | `quality.baselineEpsilon.duplication` | No | `number` | `0.5` | — |
286
286
  | `quality.requireBaselines` | No | `boolean` | `false` | Story #4495. Fail-closed baseline-enforcement policy for the unified check-baselines close-validation gate. When false (default), a consumer that enables baseline gates (crap/maintainability/…) but has not committed the corresponding baseline artifacts under baselines/ gets a clean skip-with-reason instead of a deterministic first-try close failure. Set true to keep the gate registered so an absent baseline artifact fails close-validation with a preflight hint naming the fix (the fail-closed posture). |
287
- | `quality.navigability` | No | `object` | — | Navigability lens + journey-suite config (Epic #4131, F2/F3/F1/F4). Read by audit-suite/selector.js (route globs) and /deliver's per-Story ceremony (journey suite). Opt-in: absent or empty routeGlobs degrades to a silent no-op. |
287
+ | `quality.navigability` | No | `object` | — | Navigability lens + journey-suite config (Epic #4131, F2/F3/F1/F4). Read by audit-suite/selector.js (route globs) and /mandrel-deliver's per-Story ceremony (journey suite). Opt-in: absent or empty routeGlobs degrades to a silent no-op. |
288
288
  | `quality.navigability.routeGlobs` | No | `array<string>` | `[]` | Glob patterns (pages/**, app/**/route.ts) marking paths that add a user-facing route — the route-tree SSOT the navigability lens enumerates and the route-added routing predicate matches against. |
289
289
  | `quality.navigability.navRegistry` | No | `array<string>` | `[]` | Tokens identifying the nav-registry SSOT the navigability lens checks every route resolves a nav door against. |
290
- | `quality.navigability.journeySuite` | No | `string` | — | Path or command for the per-persona journey suite /deliver's per-Story ceremony runs. |
290
+ | `quality.navigability.journeySuite` | No | `string` | — | Path or command for the per-persona journey suite /mandrel-deliver's per-Story ceremony runs. |
291
291
  | `mergeWatch` | No | `object` | — | Knobs consumed by the close-and-land merge wait (Story #4543; defaults in `lib/orchestration/merge-poll.js`). `mode` (Story #4698) selects the close-time merge posture. `intervalSeconds` is the poll cadence between `gh pr view` probes after the arm. `maxWaitSeconds` bounds ONE invocation of the merge wait and its expiry returns a resumable `pending` terminal with no label mutation; `maxBudgetSeconds` bounds the CUMULATIVE wait across resumes (anchored at the PR's createdAt, so a resume does not restart the clock) and exhausting it is the genuine give-up that classifies and blocks. `updateAttempts` caps the bounded update of a behind-the-base PR. |
292
292
  | `mergeWatch.mode` | No | `"sync"` \| `"async"` | — | Close-time merge-wait posture (Story #4698). `sync` (default) keeps the in-close foreground merge wait unchanged. `async` caps the per-invocation wait to a short ~60s probe window — long enough to catch an instant merge and, via the head-anchored required-check predicate, an instantly-red required check — then returns the resumable `pending` terminal (exit 3) with a `nextCommand`. Opt in when slow CI makes the foreground wait routinely expire: the worker launches `nextCommand` in the background instead of burning the host tool slot polling. `maxBudgetSeconds` (the cumulative give-up) is unchanged. |
293
293
  | `mergeWatch.intervalSeconds` | No | `integer` | `30` | Seconds between merge-wait polls. Default 30. |
294
294
  | `mergeWatch.maxWaitSeconds` | No | `integer` | — | Per-invocation merge-wait bound (seconds). Default 300 (5 minutes) — chosen to fit inside a single host tool invocation (~10 min ceiling) alongside the close gates that precede the wait. Expiry yields `pending` (exit 3), never a block. Headless callers with no host ceiling raise this to land in one block. |
295
295
  | `mergeWatch.maxBudgetSeconds` | No | `integer` | `3600` | Cumulative wall-clock budget (seconds) across merge-wait resumes, anchored at the PR's createdAt. Default 3600 (60 minutes). Exhausting this classifies the block and transitions the Story to agent::blocked. |
296
296
  | `mergeWatch.updateAttempts` | No | `integer` | — | Maximum times the merge wait will bring a behind-the-base PR up to date before giving up on the branch. Default 3. Set 0 to disable the update. |
297
- | `codeReview` | No | `object` | — | Review-provider chain plus bounded-retry knobs for the /deliver code-review ceremony. |
297
+ | `codeReview` | No | `object` | — | Review-provider chain plus bounded-retry knobs for the /mandrel-deliver code-review ceremony. |
298
298
  | `codeReview.providers[]` | No | `array<object>` | `[{"name":"native"},{"name":"security-review","scopes":["story"],"optional":true},{"name":"ultrareview","scopes":["story"],"manualPrompt":true,"when":{"label":"risk::high"}}]` | Review-provider chain (Story #2871). When unset or empty, defaults to [{ name: "native" }]. The orchestrator iterates inline entries in declaration order and merges their Finding[] before posting one structured comment; manual-prompt entries (e.g. ultrareview) contribute a trailing 'Manual review suggestions' section. Selecting an adapter whose probe fails hard-fails at factory construction unless declared `optional: true` in the chain. Each item has: name, scopes, optional, manualPrompt, when. |
299
299
  | `codeReview.providerConfig` | No | `object` | — | Optional escape hatch for adapter-specific configuration. No documented keys in Epic #2815; reserved so future adapters can be configured without another schema migration. |
300
- | `codeReview.maxFixAttempts` | No | `integer` | `3` | Maximum auto-fix retry attempts per finding in /deliver Phase 5 (code-review). 0 disables auto-fix. Default 3. |
300
+ | `codeReview.maxFixAttempts` | No | `integer` | `3` | Maximum auto-fix retry attempts per finding in /mandrel-deliver Phase 5 (code-review). 0 disables auto-fix. Default 3. |
301
301
  | `codeReview.maxFixScopeFiles` | No | `integer` | `5` | Maximum file count a single auto-fix may modify before escalating to agent::blocked. Default 5. |
302
- | `codeReview.autoFixSeverity` | No | `"high"` \| `"medium"` | `"medium"` | Severity threshold for on-branch remediation in /deliver Phase 5 (code-review). `medium` (default) routes 🔴/🟠/🟡 findings into the host-LLM focused-fix routing (Mediums batched per lens: one commit per lens, a single validation + rescan at the end) while 🟢 suggestions still graduate to follow-up issues; `high` reproduces the pre-4399 Critical/High-only routing. Hard cutover — no back-compat flag. |
302
+ | `codeReview.autoFixSeverity` | No | `"high"` \| `"medium"` | `"medium"` | Severity threshold for on-branch remediation in /mandrel-deliver Phase 5 (code-review). `medium` (default) routes 🔴/🟠/🟡 findings into the host-LLM focused-fix routing (Mediums batched per lens: one commit per lens, a single validation + rescan at the end) while 🟢 suggestions still graduate to follow-up issues; `high` reproduces the pre-4399 Critical/High-only routing. Hard cutover — no back-compat flag. |
303
303
  | `review` | No | `object` | — | Close-scope review tuning (Story #4699). Governs the Story-scope local-lens pass that runs inside the close subprocess; the maker-blind code-review pass and all hard gates are unaffected. |
304
304
  | `review.lensDiffFloor` | No | `integer` | — | Changed-line floor for the close-scope lens walk (Story #4699). A diff strictly below this many changed lines (additions + deletions) with zero sensitive-path hits skips lens materialization and records the skip in the findings-yield ledger. Default 40; 0 disables the skip. Hard gates and the maker-blind code-review pass are unaffected. |
305
305
  | `refactorStage` | No | `object` | — | Opt-in, config-gated post-green refactor checkpoint wired into story-deliver (Story #3430, Epic #3418). Strictly additive and default-OFF: when disabled, story-deliver behaves exactly as before. Advisory only — never changes existing close-validation gate semantics. |
@@ -336,8 +336,8 @@ Agent-driven QA harness contract (Epic #3214; environment-keyed by Epic #4326).
336
336
  | --- | --- | --- | --- | --- |
337
337
  | `featureRoot` | No | `string` | `"tests/features"` | Directory holding the Gherkin feature files the QA sweep drives. |
338
338
  | `fixturesManifest` | No | `string` | `"tests/fixtures/personas.json"` | Path to the persona/fixture manifest the harness seeds from. |
339
- | `environments` | No | `object<map>` | `{"local":{"baseUrl":"http://localhost:3000","signInSeam":{"urlTemplate":"/dev/sign-in-as/{persona}"}},"staging":{"baseUrl":"https://staging.example.test","signInSeam":{"skill":"stack/qa/sign-in"},"allowWrites":false}}` | Deployment targets the QA harness can run against (Epic #4326). A map keyed by environment name (e.g. `local`, `staging`), each carrying its own `baseUrl`, its own per-environment sign-in seam (the same url-template/skill union as the top-level seam), and an optional `allowWrites` gate. resolveQaEnvironment selects one environment per invocation by name or by raw-URL origin match against `baseUrl`; `allowWrites` defaults to true only for the `local` environment. Replaces the retired top-level single `signInSeam`. |
340
- | `personas` | No | one of: `array`, `object` | `{"admin":{"credentialRef":"QA_ADMIN_CREDENTIAL"},"member":{"signInSkill":"stack/qa/sign-in-member"}}` | Personas the QA-harness sign-in seam accepts. Two accepted shapes: (1) a plain array of persona names — the honest shape for a `urlTemplate` dev-impersonation seam, where the persona name is the sole input the workflow consumes; (2) the object-map form keyed by persona name, where each entry carries per-persona auth material (`credentialRef` or `signInSkill`) consulted only under a skill-based or credential-based seam. |
339
+ | `environments` | No | `object<map>` | `{"local":{"baseUrl":"http://localhost:3000","signInSeam":{"urlTemplate":"/dev/sign-in-as/{persona}"}},"staging":{"baseUrl":"https://staging.example.test","allowWrites":false}}` | Deployment targets the QA harness can run against (Epic #4326). A map keyed by environment name (e.g. `local`, `staging`), each carrying its own `baseUrl`, an optional per-environment sign-in seam, and an optional `allowWrites` gate. `signInSeam` is the union `{ urlTemplate }` (a dev impersonation route) or `{ skill }` (a skill id such as `stack/qa/acme-sso`, resolved against `.agents/skills/` then the consumer-writable `.agents/local/skills/` zone, and rejected loudly by resolveQaEnvironment when it resolves under neither); omit it entirely for a target with no sign-in seam. resolveQaEnvironment selects one environment per invocation by name or by raw-URL origin match against `baseUrl`; `allowWrites` defaults to true only for the `local` environment. Replaces the retired top-level single `signInSeam`. |
340
+ | `personas` | No | one of: `array`, `object` | `{"admin":{"credentialRef":"QA_ADMIN_CREDENTIAL"},"member":{"credentialRef":"QA_MEMBER_CREDENTIAL"}}` | Personas the QA-harness sign-in seam accepts. Two accepted shapes: (1) a plain array of persona names — the honest shape for a `urlTemplate` dev-impersonation seam, where the persona name is the sole input the workflow consumes; (2) the object-map form keyed by persona name, where each entry carries per-persona auth material (`credentialRef` or `signInSkill`) consulted only under a skill-based or credential-based seam. |
341
341
  | `gherkinLint` | No | `object` | `{"scopes":{"web":{"featureRoots":["apps/web/tests/features"],"stepRoots":["apps/web/tests/steps"]}},"exemptionTags":["@skip"],"stepWaivers":[]}` | Static Gherkin corpus gate (Story #5013). Optional; the gate runs only when this block is present, so an upgrade never reddens the lint of a consumer that never asked the framework to police its `.feature` files. Inside the opt-in it fails closed: an unresolvable `@cucumber/gherkin` parser, or a scope resolving zero step definitions, exits 1 rather than reporting a clean run. |
342
342
  | `gherkinLint.scopes` | Yes | `object<map>` | — | Binding scopes, keyed by name. Each scope resolves its own features against its own step definitions only — pooling every step root into one matcher list is what makes a cross-app false bind possible, where a step defined solely in app B silently vouches for app A. The scope name appears verbatim in every unbound finding. |
343
343
  | `gherkinLint.exemptionTags` | No | `array<string>` | `["@skip"]` | Tags marking a scenario as intentionally non-binding, so must-bind skips it. Never an escape from must-compile: a parse error in the file still fails the run. Default: ["@skip"]. |
@@ -414,7 +414,7 @@ A config still carrying the retired key is a hard validation failure; the
414
414
  proxy in both directions (a detailed prompt can describe trivial work, a
415
415
  terse one complex work), so `maxSeedWords` was **removed** in the hard
416
416
  cutover (a config still setting it is rejected as an additional property).
417
- Routing is now staged on the objective shape of the work: `/plan`'s context
417
+ Routing is now staged on the objective shape of the work: `/mandrel-plan`'s context
418
418
  envelope emits advisory `complexitySignals` (enumerated-artifact count,
419
419
  risk-heuristic hits, repo state of predicted paths, sensitive-path classes)
420
420
  with **no routing authority**; the planner authors the trivial-vs-standard
@@ -423,7 +423,7 @@ A config still carrying the retired key is a hard validation failure; the
423
423
  lite claim against each authored Story's own shape (`changes[]` count,
424
424
  acceptance count, creates-vs-refactors mix, sensitive-path classes — the
425
425
  framework constants `STORY_SHAPE_CEILINGS`) and **fails closed to `full`**
426
- when the shape exceeds the ceilings; and `/deliver` re-derives the route
426
+ when the shape exceeds the ceilings; and `/mandrel-deliver` re-derives the route
427
427
  from the fetched Story body via the same shape function at dispatch. The
428
428
  `route::lite` label is a human-visible hint only — a lost label cannot
429
429
  misroute delivery. A lite-shaped Story executes inline (no story-worker or
@@ -515,7 +515,7 @@ number of keys.
515
515
 
516
516
  | File | Audience | Role |
517
517
  | --------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
518
- | `.agentrc.json` (repo root) | The framework dogfooding itself | Live config used when running `/plan` and `/deliver` against this repo. Exercises the framework end-to-end on its own source tree. |
518
+ | `.agentrc.json` (repo root) | The framework dogfooding itself | Live config used when running `/mandrel-plan` and `/mandrel-deliver` against this repo. Exercises the framework end-to-end on its own source tree. |
519
519
  | `.agents/starter-agentrc.json` | Downstream consumer repos | Bootstrap delta-seed a consumer copies via `cp .agents/starter-agentrc.json .agentrc.json`. Minimum schema-required keys only. |
520
520
  | `.agents/docs/agentrc-reference.json` | Operators and reviewers | Exhaustive editor reference enumerating every schema key with its framework default. Not a copy target. |
521
521
 
@@ -637,8 +637,8 @@ under one identity. So each contributor sets their own in `.agentrc.local.json`:
637
637
  carries only the non-personal placeholder `@[USERNAME]` (so CI and fresh clones
638
638
  validate without naming a real person). The placeholder is **not** a usable
639
639
  identity: [`normalizeOperatorHandle`](../scripts/lib/orchestration/ticket-lease.js)
640
- resolves `@[USERNAME]` to `null`, and the lease guards (`/plan`,
641
- `/deliver`, `/deliver`) **fail closed** — they throw with a
640
+ resolves `@[USERNAME]` to `null`, and the lease guards (`/mandrel-plan`,
641
+ `/mandrel-deliver`, `/mandrel-deliver`) **fail closed** — they throw with a
642
642
  "set your own handle in `.agentrc.local.json`" message rather than running an
643
643
  ownerless, unguarded workflow. Your local overlay replaces the placeholder with
644
644
  your real handle, and the guards proceed. By contrast, `github.owner` / `repo`
@@ -73,9 +73,9 @@ and schema mechanics are in [§ Friction telemetry](#friction-telemetry) above.
73
73
 
74
74
  Mandrel does **not** enforce live LLM spend from response metadata. It bounds
75
75
  two things, both **fixed framework constants** rather than operator knobs, and
76
- both **fail closed**: the assembled `/plan` context envelope, and plan-time
76
+ both **fail closed**: the assembled `/mandrel-plan` context envelope, and plan-time
77
77
  Story sizing. Your host runtime (editor / CLI) owns session quota and hard
78
- stops. Consult this section when reasoning about why `/plan` refused an
78
+ stops. Consult this section when reasoning about why `/mandrel-plan` refused an
79
79
  over-ceiling envelope or an over-budget Story count.
80
80
 
81
81
  > **There is no configurable context budget.** `planning.context.maxBytes` /
@@ -90,7 +90,7 @@ over-ceiling envelope or an over-budget Story count.
90
90
  > and was deleted in Story #5005; only its `estimateTokens` helper survived,
91
91
  > re-homed in `lib/orchestration/spec-spill.js`.
92
92
 
93
- ### Planner-context envelope (`/plan`)
93
+ ### Planner-context envelope (`/mandrel-plan`)
94
94
 
95
95
  - **`PLAN_CONTEXT_ENVELOPE_BYTE_CEILING`** (`lib/orchestration/plan-context.js`):
96
96
  256 KB (≈64K tokens at the ≈4-chars/token estimate) on the serialized
@@ -35,7 +35,7 @@ it once and reuse the context as you read through any individual gate.
35
35
 
36
36
  ## Concurrent close safety
37
37
 
38
- `/deliver` may close multiple Stories from separate branches in quick
38
+ `/mandrel-deliver` may close multiple Stories from separate branches in quick
39
39
  succession; each rebases onto the latest `main` in its own base-sync phase
40
40
  (`phases/base-sync.js`) before the push, so concurrent closes serialize
41
41
  through their own worktrees rather than racing one shared branch. The push
@@ -517,7 +517,7 @@ should land in a commit whose:
517
517
 
518
518
  There is no CI guardrail rejecting unlabeled baseline edits; the convention is
519
519
  preserved so the operator can grep refresh commits in a PR diff, but
520
- self-policing is the operator's job during `/deliver`'s watch loop.
520
+ self-policing is the operator's job during `/mandrel-deliver`'s watch loop.
521
521
 
522
522
  ### The per-method coverage join (Story #4775)
523
523