@garygentry/feature-forge 0.2.3 → 0.2.5

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 (159) hide show
  1. package/README.md +6 -1
  2. package/adapters/GENERATION-REPORT.md +5 -1
  3. package/adapters/claude/.feature-forge-bundle.json +1 -1
  4. package/adapters/claude/references/forge-config-schema.json +25 -3
  5. package/adapters/claude/references/pipeline-state-schema.json +3 -2
  6. package/adapters/claude/references/portable-root.md +6 -3
  7. package/adapters/claude/references/process-overview.md +10 -0
  8. package/adapters/claude/references/shared-conventions.md +27 -9
  9. package/adapters/claude/references/stage-exit-protocol.md +206 -0
  10. package/adapters/claude/scripts/epic-manifest.py +10 -0
  11. package/adapters/claude/scripts/forge-bootstrap.py +94 -16
  12. package/adapters/claude/scripts/forge-init.sh +7 -1
  13. package/adapters/claude/scripts/forge-root.sh +20 -1
  14. package/adapters/claude/scripts/forge-session.py +866 -31
  15. package/adapters/claude/skills/forge/SKILL.md +29 -15
  16. package/adapters/claude/skills/forge-0-epic/SKILL.md +19 -24
  17. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +6 -4
  18. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  19. package/adapters/claude/skills/forge-1-prd/SKILL.md +13 -4
  20. package/adapters/claude/skills/forge-2-tech/SKILL.md +13 -3
  21. package/adapters/claude/skills/forge-3-specs/SKILL.md +13 -3
  22. package/adapters/claude/skills/forge-4-backlog/SKILL.md +15 -5
  23. package/adapters/claude/skills/forge-5-loop/SKILL.md +19 -21
  24. package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +10 -5
  25. package/adapters/claude/skills/forge-6-docs/SKILL.md +6 -6
  26. package/adapters/claude/skills/forge-bootstrap/SKILL.md +4 -4
  27. package/adapters/claude/skills/forge-fix/SKILL.md +29 -6
  28. package/adapters/claude/skills/forge-guide/SKILL.md +182 -0
  29. package/adapters/claude/skills/forge-init/SKILL.md +29 -1
  30. package/adapters/claude/skills/forge-verify/SKILL.md +46 -15
  31. package/adapters/claude/skills/forge-verify/references/verification-checklists.md +1 -1
  32. package/adapters/codex/.feature-forge-bundle.json +1 -1
  33. package/adapters/codex/references/forge-config-schema.json +25 -3
  34. package/adapters/codex/references/pipeline-state-schema.json +3 -2
  35. package/adapters/codex/references/portable-root.md +6 -3
  36. package/adapters/codex/references/process-overview.md +10 -0
  37. package/adapters/codex/references/shared-conventions.md +27 -9
  38. package/adapters/codex/references/stage-exit-protocol.md +206 -0
  39. package/adapters/codex/scripts/epic-manifest.py +10 -0
  40. package/adapters/codex/scripts/forge-bootstrap.py +94 -16
  41. package/adapters/codex/scripts/forge-init.sh +7 -1
  42. package/adapters/codex/scripts/forge-root.sh +20 -1
  43. package/adapters/codex/scripts/forge-session.py +866 -31
  44. package/adapters/codex/skills/forge/SKILL.md +34 -20
  45. package/adapters/codex/skills/forge-0-epic/SKILL.md +20 -25
  46. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +6 -4
  47. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  48. package/adapters/codex/skills/forge-1-prd/SKILL.md +13 -4
  49. package/adapters/codex/skills/forge-2-tech/SKILL.md +14 -4
  50. package/adapters/codex/skills/forge-3-specs/SKILL.md +13 -3
  51. package/adapters/codex/skills/forge-4-backlog/SKILL.md +15 -5
  52. package/adapters/codex/skills/forge-5-loop/SKILL.md +21 -23
  53. package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +10 -5
  54. package/adapters/codex/skills/forge-6-docs/SKILL.md +6 -6
  55. package/adapters/codex/skills/forge-bootstrap/SKILL.md +4 -4
  56. package/adapters/codex/skills/forge-fix/SKILL.md +29 -6
  57. package/adapters/codex/skills/forge-guide/SKILL.md +191 -0
  58. package/adapters/codex/skills/forge-init/SKILL.md +29 -1
  59. package/adapters/codex/skills/forge-verify/SKILL.md +45 -14
  60. package/adapters/codex/skills/forge-verify/references/verification-checklists.md +1 -1
  61. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  62. package/adapters/copilot/references/forge-config-schema.json +25 -3
  63. package/adapters/copilot/references/pipeline-state-schema.json +3 -2
  64. package/adapters/copilot/references/portable-root.md +6 -3
  65. package/adapters/copilot/references/process-overview.md +10 -0
  66. package/adapters/copilot/references/shared-conventions.md +27 -9
  67. package/adapters/copilot/references/stage-exit-protocol.md +206 -0
  68. package/adapters/copilot/scripts/epic-manifest.py +10 -0
  69. package/adapters/copilot/scripts/forge-bootstrap.py +94 -16
  70. package/adapters/copilot/scripts/forge-init.sh +7 -1
  71. package/adapters/copilot/scripts/forge-root.sh +20 -1
  72. package/adapters/copilot/scripts/forge-session.py +866 -31
  73. package/adapters/copilot/skills/forge/forge.md +34 -20
  74. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +20 -25
  75. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +6 -4
  76. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  77. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +13 -4
  78. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +14 -4
  79. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +13 -3
  80. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +15 -5
  81. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +21 -23
  82. package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +10 -5
  83. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +6 -6
  84. package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +4 -4
  85. package/adapters/copilot/skills/forge-fix/forge-fix.md +29 -6
  86. package/adapters/copilot/skills/forge-guide/forge-guide.md +191 -0
  87. package/adapters/copilot/skills/forge-init/forge-init.md +29 -1
  88. package/adapters/copilot/skills/forge-verify/forge-verify.md +45 -14
  89. package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +1 -1
  90. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  91. package/adapters/cursor/references/forge-config-schema.json +25 -3
  92. package/adapters/cursor/references/pipeline-state-schema.json +3 -2
  93. package/adapters/cursor/references/portable-root.md +6 -3
  94. package/adapters/cursor/references/process-overview.md +10 -0
  95. package/adapters/cursor/references/shared-conventions.md +27 -9
  96. package/adapters/cursor/references/stage-exit-protocol.md +206 -0
  97. package/adapters/cursor/scripts/epic-manifest.py +10 -0
  98. package/adapters/cursor/scripts/forge-bootstrap.py +94 -16
  99. package/adapters/cursor/scripts/forge-init.sh +7 -1
  100. package/adapters/cursor/scripts/forge-root.sh +20 -1
  101. package/adapters/cursor/scripts/forge-session.py +866 -31
  102. package/adapters/cursor/skills/forge/forge.mdc +34 -20
  103. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +20 -25
  104. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +6 -4
  105. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  106. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +13 -4
  107. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +14 -4
  108. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +13 -3
  109. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +15 -5
  110. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +21 -23
  111. package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +10 -5
  112. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +6 -6
  113. package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +4 -4
  114. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +29 -6
  115. package/adapters/cursor/skills/forge-guide/forge-guide.mdc +192 -0
  116. package/adapters/cursor/skills/forge-init/forge-init.mdc +29 -1
  117. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +45 -14
  118. package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +1 -1
  119. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  120. package/adapters/gemini/gemini-extension.json +5 -1
  121. package/adapters/gemini/references/forge-config-schema.json +25 -3
  122. package/adapters/gemini/references/pipeline-state-schema.json +3 -2
  123. package/adapters/gemini/references/portable-root.md +6 -3
  124. package/adapters/gemini/references/process-overview.md +10 -0
  125. package/adapters/gemini/references/shared-conventions.md +27 -9
  126. package/adapters/gemini/references/stage-exit-protocol.md +206 -0
  127. package/adapters/gemini/scripts/epic-manifest.py +10 -0
  128. package/adapters/gemini/scripts/forge-bootstrap.py +94 -16
  129. package/adapters/gemini/scripts/forge-init.sh +7 -1
  130. package/adapters/gemini/scripts/forge-root.sh +20 -1
  131. package/adapters/gemini/scripts/forge-session.py +866 -31
  132. package/adapters/gemini/skills/forge/forge.md +34 -20
  133. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +20 -25
  134. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +6 -4
  135. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  136. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +13 -4
  137. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +14 -4
  138. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +13 -3
  139. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +15 -5
  140. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +21 -23
  141. package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +10 -5
  142. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +6 -6
  143. package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +4 -4
  144. package/adapters/gemini/skills/forge-fix/forge-fix.md +29 -6
  145. package/adapters/gemini/skills/forge-guide/forge-guide.md +191 -0
  146. package/adapters/gemini/skills/forge-init/forge-init.md +29 -1
  147. package/adapters/gemini/skills/forge-verify/forge-verify.md +45 -14
  148. package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +1 -1
  149. package/dist/apply.js +34 -8
  150. package/dist/cli.js +40 -4
  151. package/dist/fsutil.d.ts +0 -12
  152. package/dist/fsutil.js +10 -1
  153. package/dist/manifest.d.ts +1 -1
  154. package/dist/plan.js +22 -2
  155. package/dist/rauf.d.ts +4 -4
  156. package/dist/rauf.js +3 -3
  157. package/dist/report.js +1 -1
  158. package/dist/types.d.ts +1 -1
  159. package/package.json +1 -1
@@ -22,14 +22,14 @@ For pipeline architecture details, read `references/process-overview.md`.
22
22
  **If a feature name is provided** (e.g., `/feature-forge:forge auth`):
23
23
  - **First test whether the name is an epic:** if `{specsDir}/{name}/epic-manifest.json` exists, render the **Epic Dashboard** (see format below) and stop — do not treat it as a feature.
24
24
  - Otherwise, resolve the name via the **Feature Directory Resolution** block in `references/shared-conventions.md` (so a nested epic-member name finds its dashboard too). On a resolution failure (`not-found` / `ambiguous` at exit 1; `unsafe-name` or a path-containment escape at exit 2), surface it verbatim.
25
- - On `not-found` for a never-started feature, ask: "No pipeline exists for '{feature}'. Want to start one? Run `/feature-forge:forge-1-prd {feature}` to begin."
25
+ - On `not-found`, first run the cross-branch discovery step from that same Feature Directory Resolution block (`forge-session.py discover-feature` — the state may live on a topic branch or an unfetched remote branch). Candidates → offer switch / fetch+switch per that block (explicit accept + clean tree only), then re-resolve and render the dashboard. Only when discovery also returns nothing, ask: "No pipeline exists for '{feature}' on any branch. Want to start one? Run `/feature-forge:forge-1-prd {feature}` to begin." Never render a dashboard from memory of earlier sessions (anti-fabrication guard).
26
26
  - If resolution succeeds, display the per-feature pipeline status dashboard (see format below) from `{resolvedFeatureDir}/`.
27
27
 
28
28
  **If no feature name is provided:** list in two tiers.
29
29
 
30
30
  1. **Epics first.** Identify epic directories as any `{specsDir}/*/` that directly contains an `epic-manifest.json` **and no `.pipeline-state.json` of its own** (an epic root is never itself a feature). For each epic, run:
31
31
  ```bash
32
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
32
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
33
33
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
34
34
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
35
35
  ```
@@ -37,11 +37,11 @@ python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specs
37
37
  2. **Standalone features below.** Scan the remaining `{specsDir}/*/` that directly contain a `.pipeline-state.json` **without** an `epic` back-pointer. A nested member's `.pipeline-state.json` is **attributed to its epic (Tier 1), never listed as a standalone feature**.
38
38
  - **Rank by recency.** Run the recency ranker so the most-recently-touched active feature is the default — the user rarely has to type a name (especially on mobile after a `/clear`):
39
39
  ```bash
40
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
40
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
41
41
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
42
42
  python3 "$R/scripts/forge-session.py" rank-features --specs-dir "{specsDir}" --json
43
43
  ```
44
- This returns `{active: [...], counts: {...}}` with active features sorted by `updatedAt` **descending** (row 0 is the most recent). Each row carries `currentStage`, `nextStage`, `nextCommand`, `verifyPending`, and `verifyCommand` (the single source of stage order). The `active` list excludes nested epic members surfaced in Tier 1 — but the ranker scans them too, so ignore rows whose `epic` is non-null here (they belong to the epic rollup).
44
+ This returns `{active: [...], counts: {...}}` with active features sorted by `updatedAt` **descending** (row 0 is the most recent). Each row carries `currentStage`, `nextStage`, `nextCommand`, `verifyPending`, `verifyCommand`, `verifyStage`, `verifyState` (`fresh`/`stale`/`failing`/`never`/`none`), `autoVerify` (the effective per-stage setting), and `autoFix` (the single source of stage order). A top-level `invalidAutoVerifyKeys` array appears when `forge.config.json` has `autoVerifyStages` keys outside the five verify-capable stages — surface it as a one-line warning. The `active` list excludes nested epic members surfaced in Tier 1 — but the ranker scans them too, so ignore rows whose `epic` is non-null here (they belong to the epic rollup).
45
45
  - **Pick the feature:** if exactly one active standalone pipeline exists, show its dashboard. If multiple exist, use `AskUserQuestion` — **list the most-recently-updated first, labeled `(recommended)`**, each option's description showing its `currentStage` and a relative age ("updated 2h ago"). Always include a free-form escape ("A different feature / something else") so the user is never boxed in. Then render the chosen feature's dashboard.
46
46
 
47
47
  If no epics and no standalone features exist, say: "No active feature pipelines found. Start one with `/feature-forge:forge-1-prd <feature-name>` or group several with `/feature-forge:forge-0-epic <epic-name>`."
@@ -89,29 +89,43 @@ Use these status indicators:
89
89
 
90
90
  After rendering a **per-feature** dashboard for an **active** pipeline (skip this for paused/abandoned pipelines and for the Epic Dashboard), don't stop at a text suggestion — actively offer to start the next stage. This removes the copy-paste-after-`/clear` chore that makes long, multi-stage runs painful (especially on mobile).
91
91
 
92
- **1. Read the next step.** From the `rank-features --json` output (above), find this feature's row and read its `nextStage`, `nextCommand`, `verifyPending`, and `verifyCommand`. If the feature is not in the `active` list (paused/abandoned), or `nextStage` is `null` (every production stage complete), skip the drive prompt — instead congratulate the user and, if `forge-6-docs` has not run, offer it; otherwise note the pipeline is complete.
92
+ **1. Read the next step.** From the `rank-features --json` output (above), find this feature's row and read its `nextStage`, `nextCommand`, `verifyPending`, `verifyCommand`, `verifyStage`, `verifyState`, `autoVerify`, and `autoFix`. If the feature is not in the `active` list (paused/abandoned), or `nextStage` is `null` (every production stage complete), skip the drive prompt — instead congratulate the user and, if `forge-6-docs` has not run, offer it; otherwise note the pipeline is complete. If the payload has a non-empty `invalidAutoVerifyKeys`, print a one-line warning first (e.g. "⚠️ forge.config.json `autoVerifyStages` has unknown keys: … — they are ignored; fix the typo").
93
93
 
94
94
  **2. Check the context window.** Run the context-usage helper so you can advise whether to continue here or start the next stage in a fresh session:
95
95
  ```bash
96
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
96
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
97
97
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
98
98
  python3 "$R/scripts/forge-session.py" context-usage --json
99
99
  ```
100
100
  - `{"available": true, ...}` → note `pct` (e.g. "context ~68% full") and `overThreshold`. Window/threshold come from `contextWindowTokens` / `contextWarnThreshold` in `forge.config.json` (the helper defaults to a 200k window and 0.7 threshold, and auto-bumps the assumed window to 1M once observed usage exceeds 200k; **on a 1M-context model set `contextWindowTokens: 1000000` so the percentage is accurate below 200k too** — 1M can't be detected from the transcript until usage crosses 200k).
101
101
  - `{"available": false, ...}` → omit context advice silently (non-Claude host, or a fresh session with no transcript). Never treat this as an error.
102
102
 
103
- **3. Offer the next step via `AskUserQuestion`.** Output the dashboard + a one-line context note as text, then ask (per the Decision Support protocol in `references/shared-conventions.md`). Options, in this order:
104
- - **Start `{nextStage}` now** — recommended **when context is healthy** (`overThreshold` false or context unavailable).
105
- - **Start in a clean session** — recommended-**first** instead **when `overThreshold` is true**. The work survives a clear because all state is on disk: instruct the user to `/clear`, then re-run `/feature-forge:forge {feature}` (or run `{nextCommand}` directly) in the fresh session. Note plainly that you cannot `/clear` for them.
106
- - **Verify `{stage}` first** — include **only when `verifyPending` is true**; selecting it runs `{verifyCommand}`.
103
+ **2b. Auto-verify catch-up (when `verifyPending` is true).** Under this behavior the just-completed authoring stage runs auto-verify **in-stage** (`references/stage-exit-protocol.md`, in-stage verify block), which clears `verifyPending` — so on the normal path this branch does **nothing**. It fires only as a **catch-up**: `verifyPending` is still true because the producing stage could not dispatch a clean-room subagent (non-Claude host), or ran before this behavior landed. When it does fire, decide whether verify runs automatically (identical logic to the in-stage run, so a stage that already verified is never double-verified):
104
+
105
+ - **`autoVerify` is true for the just-completed `verifyStage`** → **skip the verify question entirely** and run verify now, *provided it can run clean-room*. Auto-verify is safe to run unattended only because verify executes in a fresh `forge-verifier` subagent that inherits none of this session's context (so no `/clear` is needed and only a compact digest returns). Guard the clean-room assumption: proceed unattended **only when the `Agent` tool + `forge-verifier` subagent are available**. Invoke `feature-forge:forge-verify` via the `Skill` tool in **require-clean (`auto`) mode** — in that mode forge-verify refuses to run inline and returns a sentinel if the subagent is not dispatchable (see `skills/forge-verify/SKILL.md`). Then:
106
+ - **Sentinel returned (clean-room unavailable)** → do **not** run verify inline. Degrade to the manual gate: fall through to step 3 with the **"Verify `{stage}` first (manual)"** option included, and if `overThreshold`, recommend "/clear, then verify in a clean session." Verify state stays outstanding; the stage is never advanced on false assurance.
107
+ - **Verify passed / no findings** → proceed to the normal advance gate (step 3), no verify option.
108
+ - **Verify found findings** →
109
+ - **`autoFix` is true AND preconditions hold** — the findings document has **zero unresolved decision points** and the **working tree is clean** → invoke `feature-forge:forge-fix` via the `Skill` tool, then run a **mandatory re-verify** (require-clean mode). Advance only if the re-verify passes. On **any** precondition miss (decisions required, dirty tree), a forge-fix early stop, or a red re-verify → fall back to the digest + prompt below (never a silent partial mutation).
110
+ - **`autoFix` is false (default), or preconditions failed** → present a **compact findings digest** as text, then `AskUserQuestion`: *Apply fixes now (forge-fix)* / *Review findings* / *Skip & advance*.
111
+ - **`autoVerify` is false/unconfigured** → do not auto-run; use the advance gate in step 3, which gains the folded opt-in verify options ("Verify `{stage}` now" and "Verify `{stage}` now + enable auto-verify going forward").
112
+
113
+ **3. Offer the next step via `AskUserQuestion`.** (Reached when auto-verify did not fully resolve the step, or `verifyPending` is false.) Output the dashboard + a one-line context note as text, then ask (per the Decision Support protocol in `references/shared-conventions.md`). This is the same **Stage Exit Protocol** the stage skills stamp (`references/stage-exit-protocol.md`) — a clean session at the boundary is recommended on its own merits, and `overThreshold` only modulates *how emphatically*, never *whether*. Options, in this order:
114
+ - **Start `{nextStage}` in a clean session** — **recommended, unconditionally**, at every boundary. A clean session is the right default for the next stage on its own merits, independent of window size. The work survives a clear because all state is on disk: instruct the user to `/clear`, then re-run `/feature-forge:forge {feature}` (or run `{nextCommand}` directly) in the fresh session. Note plainly that you cannot `/clear` for them. **When `overThreshold` is true**, strengthen this wording (the window is also genuinely full) and add mid-stage compaction advice; **when the window is healthy**, still recommend the clean session — `overThreshold` is a *secondary, additive* modifier here, not the clear on/off switch.
115
+ - **Continue in this session** — the always-available alternative, reasonable when the window is nearly empty and the user would rather not clear. Not the default.
116
+ - **Verify `{stage}` now** — include **only when `verifyPending` is true and `autoVerify` is false**, and the clean-room path is available. **Recommended**, since verify is clean-room and rarely worth skipping. Runs verify now (require-clean mode); **does not** change config.
117
+ - **Verify `{stage}` now + enable auto-verify going forward** — same trigger as the option above; runs verify now **and** patches `autoVerify: true` into `forge.config.json` in place (preserve formatting and other keys) so every future stage verifies automatically without prompting. This is the **folded** config-enable — it replaces the old post-hoc "make auto-verify the default?" follow-up. No silent config writes: the config changes **only** when the user picks this option.
118
+ - **Verify `{stage}` first (manual)** — include **only when `verifyPending` is true** and the clean-room path is unavailable (the Tier-2 degradation above), or the host lacks the `Skill`/`Agent` tools; selecting it runs `{verifyCommand}` (inline / manual). Offer the "enable auto-verify" choice as text only if a config write is possible.
107
119
  - **Pick a different stage** — free-form escape to any stage or other action.
108
120
 
109
121
  **4. Act on the choice.**
110
- - **Start now** → if `autoInvokeNextStage` is true (default) **and** the `Skill` tool is available, invoke the chosen stage **via the `Skill` tool** in this same session (e.g. `skill: "feature-forge:forge-3-specs"`, `args: "{feature}"`) — no retyping, no paste. If `autoInvokeNextStage` is false, or the `Skill` tool is unavailable (a non-Claude host), fall back to printing `{nextCommand}` prominently for the user to run.
111
- - **Clean session** → give the exact next command and the `/clear`-then-re-run instruction; do not invoke anything.
112
- - **Verify** → invoke `feature-forge:forge-verify` via the `Skill` tool (or print `{verifyCommand}` on a non-Claude host).
122
+ - **Clean session** (the default) → give the exact next command and the `/clear`-then-re-run instruction; do not invoke anything (you cannot `/clear` for the user).
123
+ - **Continue in this session** → if `autoInvokeNextStage` is true (default) **and** the `Skill` tool is available, invoke the chosen stage **via the `Skill` tool** in this same session (e.g. `skill: "feature-forge:forge-3-specs"`, `args: "{feature}"`) — no retyping, no paste. If `autoInvokeNextStage` is false, or the `Skill` tool is unavailable (a non-Claude host), fall back to printing `{nextCommand}` prominently for the user to run.
124
+ - **Verify now / Verify now + enable auto-verify** → invoke `feature-forge:forge-verify` via the `Skill` tool (require-clean mode). For the **enable-auto-verify** variant, additionally patch `autoVerify: true` into `forge.config.json` in place (preserve formatting and other keys) — never a silent write. On a non-Claude host or when degrading to the manual/inline gate, print `{verifyCommand}` instead.
113
125
  - **Different stage** → honor the free-form request.
114
126
 
127
+ **Host fallback.** On a non-Claude host or when the `Skill`/`Agent` tools are unavailable, auto-verify never runs unattended — fall back to printing `{verifyCommand}` exactly as today, mirroring `autoInvokeNextStage`.
128
+
115
129
  This applies whether the feature was named explicitly (`/feature-forge:forge {feature}`) or resolved from the recency default.
116
130
 
117
131
  ### Epic Dashboard
@@ -119,7 +133,7 @@ This applies whether the feature was named explicitly (`/feature-forge:forge {fe
119
133
  When the named argument is an epic (`{specsDir}/{name}/epic-manifest.json` exists), render the epic dashboard instead of a per-feature one. Run:
120
134
 
121
135
  ```bash
122
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
136
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
123
137
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
124
138
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
125
139
  ```
@@ -190,7 +204,7 @@ Support these sub-commands for pipeline lifecycle management:
190
204
 
191
205
  - Set the manifest's top-level `status` (`paused` / `active` / `abandoned`) via the helper's `set-status` mutator — an atomic write that also bumps `updatedAt`:
192
206
  ```bash
193
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
207
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
194
208
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
195
209
  python3 "$R/scripts/epic-manifest.py" set-status "{epic}" --status paused --specs-dir "{specsDir}"
196
210
  ```
@@ -39,7 +39,7 @@ checks but still load any on-disk artifacts.
39
39
  plugin path and the configured specs dir:
40
40
 
41
41
  ```bash
42
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
42
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
43
43
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
44
44
  python3 "$R/scripts/epic-manifest.py" <subcommand> ... --specs-dir "{specsDir}"
45
45
  ```
@@ -73,14 +73,14 @@ Resolve the epic subtree path `{specsDir}/{epic}/` and decide which branch to ru
73
73
  epic, confirm the epic name itself does not collide with any existing feature or epic:
74
74
 
75
75
  ```bash
76
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
76
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
77
77
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
78
78
  python3 "$R/scripts/epic-manifest.py" check-name "{epic}" --specs-dir "{specsDir}"
79
79
  ```
80
80
 
81
81
  - Exit `0` → the name is free; proceed to C1.
82
82
  - Exit `1` (`duplicate-name`) → STOP and surface the helper's finding **verbatim**; ask
83
- (via `AskUserQuestion`) for a different epic name, then re-run check-name.
83
+ for a different epic name, then re-run check-name.
84
84
  - Exit `2` (unsafe name) → STOP and surface the finding; ask for a corrected name.
85
85
 
86
86
  ---
@@ -117,14 +117,14 @@ For **each** proposed feature name, before accepting it into the set, enforce gl
117
117
  and name safety via the helper:
118
118
 
119
119
  ```bash
120
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
120
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
121
121
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
122
122
  python3 "$R/scripts/epic-manifest.py" check-name "{feature}" --specs-dir "{specsDir}"
123
123
  ```
124
124
 
125
125
  - Exit `0` → accept the name.
126
126
  - Exit `1` (`duplicate-name`) → reject that name; surface the finding verbatim and re-prompt
127
- (via `AskUserQuestion`) for a different name.
127
+ for a different name.
128
128
  - Exit `2` (`unsafe-name`) → reject; surface the finding and re-prompt.
129
129
 
130
130
  Never accept a feature name that has not passed `check-name` exit 0.
@@ -177,7 +177,7 @@ For the *initial* creation write the skill writes the file directly — atomic g
177
177
  required for in-place mutation, which is the helper mutators' job. Creating the epic dir first creates `{specsDir}/`, so after writing the manifest invoke the **Specs Directory Hygiene** block in `references/shared-conventions.md` (idempotent; stage anything it writes with this stage's commit). Then validate:
178
178
 
179
179
  ```bash
180
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
180
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
181
181
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
182
182
  python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
183
183
  ```
@@ -237,29 +237,24 @@ now self-contained: manifest + EPIC.md + one subdirectory per member.
237
237
 
238
238
  ### Step C8 — Review, Pipeline State & Commit
239
239
 
240
- 1. **Review.** Present a summary (epic name, N features, dependency edges, contracts) as text,
241
- then use `AskUserQuestion`: "Does this epic decomposition look right? Any feature, dependency,
242
- or contract to change before I commit?" If the user wants changes, loop back to the relevant
243
- creation step, re-compose, and re-validate.
240
+ 1. **Review.** Present a summary (epic name, N features, dependency edges, contracts) as text, then use `AskUserQuestion`: "Does this epic decomposition look right? Any feature, dependency, or contract to change before I commit?" If the user wants changes, loop back to the relevant creation step, re-compose, and re-validate.
244
241
 
245
- 2. **Commit (Git Commit Protocol).** If `gitCommitAfterStage` is true, follow the Git Commit
246
- Protocol in shared-conventions:
247
- - Stage the whole epic subtree only: `git add {specsDir}/{epic}/` — never `git add -A`. This
248
- captures `epic-manifest.json`, `EPIC.md`, and all member `.pipeline-state.json` files
249
- atomically.
242
+ 2. **Commit (Git Commit Protocol).** If `gitCommitAfterStage` is true, follow the Git Commit Protocol in shared-conventions:
243
+ - Stage the whole epic subtree only: `git add {specsDir}/{epic}/` — never `git add -A`. This captures `epic-manifest.json`, `EPIC.md`, and all member `.pipeline-state.json` files atomically.
250
244
  - Commit with message `"{commitPrefix}({epic}): create epic with {N} features"`.
251
- - On success, capture the commit hash. On failure (pre-commit hook, conflict), report and do
252
- not mark complete; never use `--no-verify`/`--force`.
245
+ - On success, capture the commit hash for the closing message only — the epic manifest has no `commitHash` field, so nothing is written back into a committed file and the two-commit step of the Git Commit Protocol does not apply here. On failure (pre-commit hook, conflict), report and do not mark complete; never use `--amend`/`--no-verify`/`--force`.
253
246
 
254
- 3. **Closing message.** After a successful creation, tell the user the next steps:
247
+ 3. **Closing message — the Stage Exit Protocol.** Congratulate the user ("Epic `{epic}` created with {N} features."), then close with the Stage Exit Protocol below (single-sourced in `references/stage-exit-protocol.md`; the epic → first-PRD boundary is a full stage boundary — do not improvise a "Next steps" list). `{first-actionable-feature}` = any feature with empty `dependsOn` (or the first entry of `render-status`'s `actionable` set):
255
248
 
256
- > Epic `{epic}` created with {N} features. Next steps:
257
- > - `/feature-forge:forge {epic}` to see the epic dashboard
258
- > - `/feature-forge:forge-verify {epic}` to verify the epic
259
- > - `/feature-forge:forge-1-prd {first-actionable-feature}` to start the first feature
249
+ **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
260
250
 
261
- The first-actionable feature is any feature with empty `dependsOn` (or the first entry of
262
- `render-status`'s `actionable` set).
251
+ ```bash
252
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
253
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
254
+ python3 "$R/scripts/forge-session.py" stage-exit --feature "{epic}" --stage forge-0-epic --next-feature "{first-actionable-feature}" --specs-dir "{specsDir}" --host claude
255
+ ```
256
+
257
+ Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
263
258
 
264
259
  ---
265
260
 
@@ -16,7 +16,7 @@ question goes through `AskUserQuestion`.
16
16
  Before offering any edit, validate the existing manifest:
17
17
 
18
18
  ```bash
19
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
19
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
20
20
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
21
21
  python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
22
22
  ```
@@ -77,7 +77,7 @@ status is **not** `not-started`, warn the user. Read the **live** status (never
77
77
  completion in prose):
78
78
 
79
79
  ```bash
80
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
80
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
81
81
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
82
82
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
83
83
  ```
@@ -160,8 +160,10 @@ follow the Git Commit Protocol in shared-conventions:
160
160
  `"forge({epic}): create epic with 4 features"`, `"forge({epic}): add feature api-gateway"`,
161
161
  `"forge({epic}): remove feature legacy-session"`, `"forge({epic}): reorder features"`,
162
162
  `"forge({epic}): set dependency on token-service"`, or `"forge({epic}): set status paused"`.
163
- 3. On success, capture the commit hash. On failure (pre-commit hook, conflict), report and do
164
- **not** mark complete; never use `--no-verify`/`--force`.
163
+ 3. On success, capture the commit hash for reporting only — the epic manifest has no `commitHash`
164
+ field, so nothing is written back into a committed file and the two-commit step of the Git Commit
165
+ Protocol does not apply here. On failure (pre-commit hook, conflict), report and do **not** mark
166
+ complete; never use `--amend`/`--no-verify`/`--force`.
165
167
 
166
168
  Because every mutation is committed, the git history of `epic-manifest.json` is the audit trail; no
167
169
  separate in-manifest audit log is kept.
@@ -12,7 +12,7 @@ the write if it would introduce a cycle, dangling ref, duplicate, or schema viol
12
12
  flag surface (owned by 02 §7):
13
13
 
14
14
  ```bash
15
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
15
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
16
16
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
17
17
  # Add a feature — seeds EMPTY exposes/consumes; contracts are populated below.
18
18
  python3 "$R/scripts/epic-manifest.py" add-feature "{epic}" "{feature}" \
@@ -110,10 +110,19 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
110
110
  - Record `artifacts`, `completedAt`
111
111
  - Set `stages.forge-1-prd.basedOnVersions` to `{}` (no upstream dependencies)
112
112
  - Check downstream stages (`forge-2-tech`, `forge-3-specs`, `forge-4-backlog`, `forge-5-loop`, `forge-6-docs`). If any have `basedOnVersions` referencing an older version of `forge-1-prd`, set their status to `stale`.
113
- 2. Use `AskUserQuestion` to ask: "Anything you want to note before we wrap? (preserved across sessions)"
114
- - If yes, store in the `notes` field
115
- 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (including `{specsDir}/AGENTS.md` / `{specsDir}/CLAUDE.md` if the Specs Directory Hygiene step just wrote them), attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"`, then set `stages.forge-1-prd.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
116
- 5. Tell the user: "PRD complete. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the PRD\n - `/feature-forge:forge-2-tech {feature}` to start the tech spec\n - `/feature-forge:forge {feature}` to see full pipeline status"
113
+ 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
114
+ 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (including `{specsDir}/AGENTS.md` / `{specsDir}/CLAUDE.md` if the Specs Directory Hygiene step just wrote them), attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"` (marking `stages.forge-1-prd.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
115
+ 4. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list):
116
+
117
+ **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
118
+
119
+ ```bash
120
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
121
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
122
+ python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-1-prd --specs-dir "{specsDir}" --host claude
123
+ ```
124
+
125
+ Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
117
126
 
118
127
  ## Gotchas
119
128
 
@@ -187,9 +187,19 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
187
187
  - Record `artifacts`, `completedAt`, `version`
188
188
  - Set `stages.forge-2-tech.basedOnVersions` to `{"forge-1-prd": <current forge-1-prd version>}`
189
189
  - Check downstream stages (forge-3-specs, forge-4-backlog, forge-5-loop, forge-6-docs). If any have `basedOnVersions` referencing an older version of forge-2-tech, set their status to `stale`
190
- 2. Use `AskUserQuestion` to ask about notes to persist
191
- 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete tech-spec v{n}"`, then set `stages.forge-2-tech.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
192
- 5. Tell the user: "Tech spec complete. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the tech spec\n - `/feature-forge:forge-3-specs {feature}` to create implementation specs\n - `/feature-forge:forge {feature}` to see full pipeline status"
190
+ 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
191
+ 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete tech-spec v{n}"` (marking `stages.forge-2-tech.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
192
+ 4. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list):
193
+
194
+ **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
195
+
196
+ ```bash
197
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
198
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
199
+ python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-2-tech --specs-dir "{specsDir}" --host claude
200
+ ```
201
+
202
+ Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
193
203
 
194
204
  ## Gotchas
195
205
 
@@ -141,9 +141,19 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
141
141
  - Record all created files in `artifacts`, including `TRACEABILITY.md`
142
142
  - Set `stages.forge-3-specs.basedOnVersions` to `{"forge-1-prd": <current version>, "forge-2-tech": <current version>}`
143
143
  - Check downstream stages (forge-4-backlog, forge-5-loop, forge-6-docs). If any have `basedOnVersions` referencing older versions, set their status to `stale`
144
- 2. Use `AskUserQuestion` to ask about notes to persist
145
- 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete implementation specs v{n}"`, then set `stages.forge-3-specs.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
146
- 5. Tell the user: "Implementation specs complete. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the specs (strongly recommended)\n - `/feature-forge:forge-4-backlog {feature}` to generate the backlog\n - `/feature-forge:forge {feature}` to see full pipeline status"
144
+ 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
145
+ 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete implementation specs v{n}"` (marking `stages.forge-3-specs.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
146
+ 4. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Specs feed every downstream stage, so the verify gate matters here:
147
+
148
+ **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
149
+
150
+ ```bash
151
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
152
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
153
+ python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-3-specs --specs-dir "{specsDir}" --host claude
154
+ ```
155
+
156
+ Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
147
157
 
148
158
  ## Gotchas
149
159
 
@@ -39,7 +39,7 @@ Resolve the **loop runner** from the `loopRunner` block in `forge.config.json`,
39
39
 
40
40
  **Prerequisite check:** Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode, stages `forge-1-prd`, `forge-2-tech`, and `forge-3-specs` must all be `complete`. If not, STOP and tell the user which prerequisites are missing.
41
41
 
42
- **Strongly recommended:** Check if specs have been verified. If not, use `AskUserQuestion` to warn with the cost of skipping: "Specs haven't been verified yet. Recommended: run `/feature-forge:forge-verify {feature}` first — unverified specs can carry gaps or contradictions that get baked into backlog items and only surface mid-loop, where they're far more expensive to fix. Continue anyway?" Offer **Verify first (recommended)** · **Continue without verifying**.
42
+ **Verification check.** Check whether the specs have been verified. If not, use `AskUserQuestion` to warn with the cost of skipping: "Specs haven't been verified yet. Recommended: run `/feature-forge:forge-verify {feature}` first — unverified specs can carry gaps or contradictions that get baked into backlog items and only surface mid-loop, where they're far more expensive to fix. Continue anyway?" Offer **Verify first (recommended)** · **Continue without verifying**.
43
43
 
44
44
  ## Step 2: Load All Specs
45
45
 
@@ -123,7 +123,7 @@ Interpret the result:
123
123
 
124
124
  Present a summary: total items N, dependency-chain depth, estimated loop iterations (`ceil(pendingItems * loopIterationMultiplier)`). Note whether validation passed or was skipped (runner not yet available).
125
125
 
126
- Use `AskUserQuestion` to ask: "Ready to proceed, or any adjustments needed?"
126
+ State that the backlog is ready and invite adjustments before committing — a statement, not a forced gate: "Backlog is ready. Tell me if you want any items split, merged, or reordered; otherwise I'll record state and commit." Proceed to Step 7 unless the user asks for changes.
127
127
 
128
128
  ## Step 7: Update Pipeline State and Commit
129
129
 
@@ -134,10 +134,20 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`. Foll
134
134
  - Set `stages.forge-4-backlog.basedOnVersions` to `{"forge-1-prd": <current version>, "forge-2-tech": <current version>, "forge-3-specs": <current version>}`
135
135
  - Set `currentStage` to `forge-5-loop`
136
136
  - Check downstream stages (`forge-5-loop`, `forge-6-docs`). If any have `basedOnVersions` referencing an older version of `forge-4-backlog`, set their status to `stale`.
137
- 2. Use `AskUserQuestion` to ask about notes to persist
138
- 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol: stage files, attempt commit, then set status to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
137
+ 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
138
+ 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol: stage files, attempt commit (marking `stages.forge-4-backlog.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
139
139
  4. If verification was available but the user chose to skip it, record `stages.forge-verify-backlog.status` as `"skipped"` in pipeline state.
140
- 5. Tell user: "Backlog complete with {N} items. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the backlog\n - `/feature-forge:forge-5-loop {feature}` to run the loop\n - `/feature-forge:forge {feature}` to see full pipeline status"
140
+ 5. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Lead with the item count ("Backlog complete with {N} items."), then:
141
+
142
+ **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
143
+
144
+ ```bash
145
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
146
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
147
+ python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-4-backlog --specs-dir "{specsDir}" --host claude
148
+ ```
149
+
150
+ Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
141
151
 
142
152
  ## Gotchas
143
153
 
@@ -50,7 +50,7 @@ Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode, `stages.
50
50
 
51
51
  ### 1b. Verification Check
52
52
 
53
- Check if `stages.forge-verify-backlog` exists and has status `passed` or `findings-applied`. If not, use `AskUserQuestion` to warn:
53
+ Check if `stages.forge-verify-backlog` exists and has status `passed` or `findings-applied`. If not, use `AskUserQuestion` to warn with the cost of skipping:
54
54
 
55
55
  "Backlog hasn't been verified yet. Recommended: run `/feature-forge:forge-verify {feature}` first — the loop implements items autonomously and commits as it goes, so a bad item (wrong scope, missing dependency, untestable acceptance criteria) is far cheaper to catch now than after several commits build on it. Continue anyway?" Offer **Verify first (recommended)** · **Continue without verifying**.
56
56
 
@@ -61,7 +61,7 @@ Read the resolved feature's `.pipeline-state.json`. **If it has no `epic` key, s
61
61
  1. Run `render-status "{epic}" --specs-dir "{specsDir}" --json` via the helper:
62
62
 
63
63
  ```bash
64
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
64
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
65
65
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
66
66
  python3 "$R/scripts/epic-manifest.py" \
67
67
  render-status "{epic}" --specs-dir "{specsDir}" --json
@@ -259,11 +259,7 @@ output templates — **all-done**, **needs-human**, **blocked**, **deferred**, a
259
259
 
260
260
  Update `{resolvedFeatureDir}/.pipeline-state.json`:
261
261
 
262
- 1. Set `stages.forge-5-loop`:
263
- - `status`: `"complete"` if all backlog items are `done`, otherwise `"in-progress"`
264
- - `completedAt`: current ISO timestamp (only if complete)
265
- - `basedOnVersions`: `{"forge-4-backlog": <current version from pipeline state>}`
266
- - `artifacts`: `["{backlogDir}/{loopRunner.stateDir}/state.json"]`
262
+ 1. Set `stages.forge-5-loop`: `status` = `"complete"` if all backlog items are `done`, else `"in-progress"`; `completedAt` = current ISO timestamp (only if complete); `basedOnVersions` = `{"forge-4-backlog": <current version from pipeline state>}`; `artifacts` = `["{backlogDir}/{loopRunner.stateDir}/state.json"]`.
267
263
  2. If all items complete: set `currentStage` to `"forge-6-docs"`
268
264
  3. Update `updatedAt`
269
265
 
@@ -277,25 +273,27 @@ Update `{resolvedFeatureDir}/.pipeline-state.json`:
277
273
 
278
274
  **Gate:** only run this step if (a) the resolved feature's `.pipeline-state.json` has an `epic` key **and** (b) Step 5 set `stages.forge-5-loop.status` to `complete` (all backlog items done). If either is false, **skip** — standalone completed features are handled by Step 5b, and partial runs end as today (REQ-COMPAT-01).
279
275
 
280
- 1. **Offer impl-verify first (recommended, skippable).** Per the completion rule (`00-core-definitions.md §7`), a feature whose `forge-verify-impl.status == findings-reported` does **not** unblock dependents. Use `AskUserQuestion` (NOT inline prose) to offer:
281
-
282
- > "{feature}'s loop is done. Recommended: run `/feature-forge:forge-verify {feature} impl` before unblocking dependents. Run it now, or skip and continue the handoff?"
283
-
284
- The user may skip (then completion is judged on the §7 rule with impl-verify absent).
276
+ 1. **Offer impl-verify first (recommended, skippable).** Per the completion rule (`00-core-definitions.md §7`), a feature whose `forge-verify-impl.status == findings-reported` does **not** unblock dependents. Use `AskUserQuestion` (NOT inline prose) to offer: *"{feature}'s loop is done. Recommended: run `/feature-forge:forge-verify {feature} impl` before unblocking dependents. Run it now, or skip and continue the handoff?"* The user may skip (then completion is judged on the §7 rule with impl-verify absent).
285
277
  2. **Recompute and announce.** Run `render-status "{epic}" --specs-dir "{specsDir}" --json`. Announce the feature's completion and the epic rollup (e.g. "2/4 features complete") — derived live from disk, never re-computed in prose.
286
- 3. **Identify the next actionable feature(s).** Read `render-status`'s `actionable` set (features whose every dependency is now complete and that are not themselves complete) and `nextCommand`.
287
- - **None actionable** (everything done, or remaining features still blocked): say so.
288
- - If `rollup.total > 0` **AND** `rollup.complete == rollup.total`, suggest `/feature-forge:forge-6-docs {feature}` and note the epic-level documentation offer (§10). The `rollup.total > 0` guard prevents an **empty epic** (`0 == 0`) from being reported complete.
289
- - Otherwise, list what is still blocked and on which dependencies. End — do not prompt to start a feature that cannot start.
290
- - **One or more actionable:** use `AskUserQuestion` presenting **each actionable feature** as an option (plus "stop here"). Execution is **serial** — the user picks exactly one (REQ-ORCH-03). Do **not** autonomously chain into the next pipeline.
291
- 4. **Begin the chosen feature.** For the picked feature:
292
- - **PRD absent** (no `PRD.md`, or `stages.forge-1-prd` not complete): offer to author it now — "Start `/feature-forge:forge-1-prd {chosen}`?" (REQ-ORCH-02). On yes, hand off to forge-1-prd (which injects epic context per §5.1).
293
- - **PRD present:** point the user at the chosen feature's `nextCommand` from render-status.
278
+ 3. **Identify the next actionable feature(s).** Read `render-status`'s `actionable` set (every dependency now complete, not itself complete) and `nextCommand`. **None actionable:** say so — if `rollup.total > 0` **AND** `rollup.complete == rollup.total`, suggest `/feature-forge:forge-6-docs {feature}` and note the epic-level documentation offer (§10) (the `rollup.total > 0` guard prevents an **empty epic** `0 == 0` from reading as complete); otherwise list what is still blocked and on which dependencies, then end (do not prompt to start a feature that cannot start). **One or more actionable:** use `AskUserQuestion` presenting **each actionable feature** as an option (plus "stop here"). Execution is **serial** — the user picks exactly one (REQ-ORCH-03); do **not** autonomously chain into the next pipeline.
279
+ 4. **Begin the chosen feature.** **PRD absent** (no `PRD.md`, or `stages.forge-1-prd` not complete): offer to author it now — "Start `/feature-forge:forge-1-prd {chosen}`?" (REQ-ORCH-02); on yes, hand off to forge-1-prd (which injects epic context per §5.1). **PRD present:** point the user at the chosen feature's `nextCommand` from render-status.
294
280
  5. **Commit (REQ-OBS-01).** When `gitCommitAfterStage` is true, commit the Step 5 completion write (and any manifest `updatedAt` bump) via the shared-conventions **Git Commit Protocol**, staging the epic subtree so the member state change commits atomically: `git add {specsDir}/{epic}/` then `{commitPrefix}({feature}): complete loop`. If `gitCommitAfterStage` is false, skip the commit.
281
+ 6. **Close the handoff with the Stage Exit Protocol.** Finishing feature `{feature}` → starting the picked feature `{chosen}`'s PRD is a **cold** stage boundary (single-sourced in `references/stage-exit-protocol.md`). Feature `{feature}`'s impl-verify was already offered in Step 6.1, so step 1's gate self-suppresses when it ran or was skipped — the block collapses to `/clear` → next-command. Present it only when the chosen feature's PRD is absent (a PRD-present pick just runs its `nextCommand`):
282
+
283
+ **This stage is done — walk the user through the Stage Exit Protocol** before moving on. The order is fixed, and step 2 is something only the user can do:
284
+
285
+ 1. **Verify feature {feature}'s loop first — if it isn't already verified.** If verify already ran in this session — via the in-stage auto-verify on the authoring stages, or the interactive impl-verify offered above on the loop — or is already fresh on record, or the stage was explicitly skipped, say so and go straight to step 2. Only when `autoVerify` is off for this stage **and** verify is **missing or stale** do you present the **Standard Verify Gate**: verify **now, before clearing**, using `AskUserQuestion` with exactly these three options — but only when the host has a question mechanism **and** the clean-room path is available (the `Agent` tool plus a dispatchable `forge-verifier` subagent):
286
+ - **Verify feature {feature}'s loop now** *(recommended)* — dispatch the clean-room `forge-verifier` subagent from this session in require-clean mode; the digest returns here so any fix decision keeps its context. One-time — it does **not** change config.
287
+ - **Verify now + enable auto-verify going forward** — verify now **and** patch `"autoVerify": true` into `forge.config.json` in place (preserve formatting and every other key) so future stages verify automatically, no prompt. This complements the `forge-init` opt-in. **Do not auto-commit this config change** — treat it like `notes`: a user-facing edit the user commits on their own cadence, never folded into a stage's artifact commit.
288
+ - **Skip for now** — go straight to `/clear` and the next command without verifying. Record this stage's verify status as `"skipped"` in pipeline state (mirroring the existing skip handling) **only** on an explicit skip — a skip does not go stale.
289
+
290
+ **Host / clean-room fallback (not a user-selectable option):** if the question mechanism, the `Agent` tool, or the `forge-verifier` subagent is unavailable, do **not** run clean-room — degrade to printing `/feature-forge:forge-verify {feature} impl` for the user to run inline/manually (mirroring `autoInvokeNextStage`), and offer the auto-verify enable as plain text only if a config write is possible.
291
+ 2. **Then `/clear`.** Recommended **unconditionally** at this boundary for a clean start — independent of how full the context window is. Every artifact is on disk, so the work survives the clear. **I can't `/clear` for you — you have to run it yourself.**
292
+ 3. **Then run `/feature-forge:forge-1-prd {chosen}`** in the fresh session — or re-run `/feature-forge:forge` to let the navigator resume from disk.
295
293
 
296
294
  ## Gotchas
297
295
 
298
- - **Plugin-root discovery (1b-epic helper) covers installed paths, not workspace-dev checkouts.** The `forge-root.sh` search in 1b-epic probes `~/.claude/skills/feature-forge`, `~/.claude/plugins/*/feature-forge`, and `./.agents/skills/feature-forge` — the locations of an **installed** plugin. A feature-forge **source checkout** (e.g. `~/workspace/feature-forge`) is not on that list, so the helper exits "cannot locate plugin root." That is expected in a dev environment, not a bug; run the epic-manifest script from the checkout directly (`python3 <checkout>/scripts/epic-manifest.py …`). Note the `~/.claude/plugins/*/feature-forge` glob can also print a zsh "no matches found" line when that dir is empty — harmless.
296
+ - **Plugin-root discovery (1b-epic helper) covers installed paths, not workspace-dev checkouts.** The `forge-root.sh` search in 1b-epic probes `~/.claude/skills/feature-forge`, `~/.claude/plugins/cache/*/feature-forge/*` (marketplace-cache installs), `~/.claude/plugins/*/feature-forge`, and `./.agents/skills/feature-forge` — the locations of an **installed** plugin. A feature-forge **source checkout** (e.g. `~/workspace/feature-forge`) is not on that list, so the helper exits "cannot locate plugin root." That is expected in a dev environment, not a bug; run the epic-manifest script from the checkout directly (`python3 <checkout>/scripts/epic-manifest.py …`). The bootstrap prelude wraps its candidate loop in `bash -c` so the `~/.claude/plugins/*/feature-forge` glob is zsh-safe: an empty expansion no longer aborts the loop under zsh's `nomatch`.
299
297
  - `{backlogDir}` is a **directory path**, not a file path. Pass `specs/auth`, not `specs/auth/backlog.json`.
300
298
  - rauf resolves `RAUF.md` with fallback: checks `{backlogDir}/.rauf/RAUF.md` first, then the project's `.rauf/RAUF.md`. As long as the runner is installed in the project, the prompt template will be found.
301
299
  - State files (state.json, {loopRunner.logFile}, etc.) are created at `{backlogDir}/{loopRunner.stateDir}/` — this is within the feature's spec directory and is expected. State is isolated per backlog dir, so concurrent features don't collide.
@@ -4,15 +4,20 @@ These are the five verbatim result-report output templates for **Step 4b** of
4
4
  `forge-5-loop/SKILL.md`. Pick **every** branch that applies (a run can be both
5
5
  blocked and needs-human) and render its report.
6
6
 
7
- **All items done:**
7
+ **All items done.** Print the completion summary, then close with the **warm-acceptable
8
+ variant** of the Stage Exit Protocol (single-sourced in
9
+ `references/stage-exit-protocol.md`) — the `forge-5-loop → forge-6-docs` boundary is the
10
+ one place where clearing before the next stage is optional:
8
11
  ```
9
12
  Loop completed for {feature}. All {N} items implemented successfully.
10
-
11
- Next steps:
12
- - /feature-forge:forge-verify {feature} impl Verify the implementation
13
- - /feature-forge:forge-6-docs {feature} Generate architecture docs
14
13
  ```
15
14
 
15
+ **The loop is complete — this is the one boundary where clearing before the next stage is optional.**
16
+
17
+ 1. **Verify is already offered above.** Impl-verify is offered interactively right after this report (Step 5b for a standalone feature, Step 6.1 for an epic member) — run it there rather than as a second gate. It runs clean-room, so it needs no fresh session.
18
+ 2. **Clearing is optional here — warm is fine.** `forge-6-docs` benefits from the still-warm context of what the loop actually did, so continuing in this same session is the easy default. A cold start also works — every artifact is on disk — but there is no need to force it.
19
+ 3. **Then run `/feature-forge:forge-6-docs {feature}`** — in this warm session, or a fresh one if you prefer.
20
+
16
21
  **Runner review pass.** A review flag (e.g. rauf's `--review`) makes the runner run
17
22
  a post-loop review that **auto-creates and implements fix items** rather than handing
18
23
  findings to the user — distinct from `forge-verify impl` (a clean-context audit that
@@ -44,18 +44,18 @@ Check `.pipeline-state.json` for `stages.forge-verify-impl`. If it is **absent**
44
44
  If the resolved feature has an `epic` back-pointer in its `.pipeline-state.json`, run:
45
45
 
46
46
  ```bash
47
- R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
47
+ R="$(bash -c 'for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
48
48
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
49
49
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
50
50
  ```
51
51
 
52
52
  If `render-status` fails, skip the epic-level offer and proceed with the per-feature docs only; surface the error per the exit-1/exit-2 split in the **Feature Directory Resolution** block of `references/shared-conventions.md` (exit 1 → parse `{findings[]}` from stdout; exit 2 → surface the plain `Error:` stderr line verbatim).
53
53
 
54
- **Only if `rollup.total > 0 AND rollup.complete == rollup.total`** (every member is complete-for-orchestration; the `total > 0` guard excludes an empty epic), use `AskUserQuestion` to offer:
54
+ **Only if `rollup.total > 0 AND rollup.complete == rollup.total`** (every member is complete-for-orchestration; the `total > 0` guard excludes an empty epic), offer the extra doc as a statement the user can take or leave — not a forced question:
55
55
 
56
- "All {total} features in the '{epic}' epic are complete. Generate an **epic-level architecture document** spanning the features, in addition to {feature}'s per-feature docs?"
56
+ "All {total} features in the '{epic}' epic are complete. I can also generate an **epic-level architecture document** spanning the features, alongside {feature}'s per-feature docs — say the word and I'll add it."
57
57
 
58
- On yes, synthesize a doc at **`{docsDir}/{epic}/`** sourced from: the `EPIC.md` narrative, each member's per-feature docs, and the manifest contracts (each feature's `exposes`/`consumes`). When the epic-level doc is written, the Step 5 commit also stages `{docsDir}/{epic}/`.
58
+ If the user asks for it, synthesize a doc at **`{docsDir}/{epic}/`** sourced from: the `EPIC.md` narrative, each member's per-feature docs, and the manifest contracts (each feature's `exposes`/`consumes`). When the epic-level doc is written, the Step 5 commit also stages `{docsDir}/{epic}/`.
59
59
 
60
60
  If not all members are complete (or the feature has no `epic` back-pointer), **do not offer** — the per-feature doc flow proceeds unchanged.
61
61
 
@@ -97,7 +97,7 @@ Based on feature complexity and existing doc conventions, propose a doc plan:
97
97
  └── adr-001-*.md — Architecture decision records (if significant decisions were made)
98
98
  ```
99
99
 
100
- Present the plan and use `AskUserQuestion` to get the user's confirmation.
100
+ Present the plan as a statement and invite edits before writing — not a forced confirmation gate: "Here's the doc plan I'll generate. Tell me if you want to add, remove, or restructure any documents; otherwise I'll proceed." Write the docs unless the user asks for changes.
101
101
 
102
102
  ## Step 3: Write Documentation
103
103
 
@@ -176,7 +176,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
176
176
  - Set `currentStage` to `complete`
177
177
  - Record `artifacts`
178
178
  - Set `stages.forge-6-docs.basedOnVersions` to include versions for all completed upstream stages. Always include forge-1-prd, forge-2-tech, forge-3-specs. Include forge-4-backlog and forge-5-loop ONLY if they have status `complete`.
179
- 2. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (`git add {docsDir}/{feature}/ {resolvedFeatureDir}/` — and **also** `{docsDir}/{epic}/` when an epic-level doc was written in Step 1), attempt commit with message `"{commitPrefix}({feature}): complete architecture docs"`, then set `stages.forge-6-docs.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
179
+ 2. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (`git add {docsDir}/{feature}/ {resolvedFeatureDir}/` — and **also** `{docsDir}/{epic}/` when an epic-level doc was written in Step 1), attempt commit with message `"{commitPrefix}({feature}): complete architecture docs"` (marking `stages.forge-6-docs.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
180
180
  4. Tell user: "Documentation complete. Feature pipeline for '{feature}' is finished!\n `/feature-forge:forge {feature}` to see the final pipeline status."
181
181
 
182
182
  ## Gotchas