@garygentry/feature-forge 0.2.6 → 0.2.8

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 (102) hide show
  1. package/adapters/claude/.feature-forge-bundle.json +1 -1
  2. package/adapters/claude/references/portable-root.md +18 -9
  3. package/adapters/claude/references/shared-conventions.md +21 -4
  4. package/adapters/claude/references/stage-exit-protocol.md +1 -1
  5. package/adapters/claude/references/vendor-construct-inventory.md +1 -0
  6. package/adapters/claude/scripts/forge-session.py +259 -10
  7. package/adapters/claude/skills/forge/SKILL.md +9 -9
  8. package/adapters/claude/skills/forge-0-epic/SKILL.md +5 -5
  9. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +2 -2
  10. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  11. package/adapters/claude/skills/forge-1-prd/SKILL.md +1 -1
  12. package/adapters/claude/skills/forge-2-tech/SKILL.md +1 -1
  13. package/adapters/claude/skills/forge-3-specs/SKILL.md +1 -1
  14. package/adapters/claude/skills/forge-4-backlog/SKILL.md +1 -1
  15. package/adapters/claude/skills/forge-5-loop/SKILL.md +2 -2
  16. package/adapters/claude/skills/forge-6-docs/SKILL.md +1 -1
  17. package/adapters/claude/skills/forge-bootstrap/SKILL.md +4 -4
  18. package/adapters/claude/skills/forge-init/SKILL.md +1 -1
  19. package/adapters/claude/skills/forge-verify/SKILL.md +1 -1
  20. package/adapters/claude/skills/forge-verify/references/verification-checklists.md +1 -1
  21. package/adapters/codex/.feature-forge-bundle.json +1 -1
  22. package/adapters/codex/references/portable-root.md +18 -9
  23. package/adapters/codex/references/shared-conventions.md +21 -4
  24. package/adapters/codex/references/stage-exit-protocol.md +1 -1
  25. package/adapters/codex/references/vendor-construct-inventory.md +1 -0
  26. package/adapters/codex/scripts/forge-session.py +259 -10
  27. package/adapters/codex/skills/forge/SKILL.md +9 -9
  28. package/adapters/codex/skills/forge-0-epic/SKILL.md +5 -5
  29. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +2 -2
  30. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  31. package/adapters/codex/skills/forge-1-prd/SKILL.md +1 -1
  32. package/adapters/codex/skills/forge-2-tech/SKILL.md +1 -1
  33. package/adapters/codex/skills/forge-3-specs/SKILL.md +1 -1
  34. package/adapters/codex/skills/forge-4-backlog/SKILL.md +1 -1
  35. package/adapters/codex/skills/forge-5-loop/SKILL.md +2 -2
  36. package/adapters/codex/skills/forge-6-docs/SKILL.md +1 -1
  37. package/adapters/codex/skills/forge-bootstrap/SKILL.md +4 -4
  38. package/adapters/codex/skills/forge-init/SKILL.md +1 -1
  39. package/adapters/codex/skills/forge-verify/SKILL.md +1 -1
  40. package/adapters/codex/skills/forge-verify/references/verification-checklists.md +1 -1
  41. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  42. package/adapters/copilot/references/portable-root.md +18 -9
  43. package/adapters/copilot/references/shared-conventions.md +21 -4
  44. package/adapters/copilot/references/stage-exit-protocol.md +1 -1
  45. package/adapters/copilot/references/vendor-construct-inventory.md +1 -0
  46. package/adapters/copilot/scripts/forge-session.py +259 -10
  47. package/adapters/copilot/skills/forge/forge.md +9 -9
  48. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +5 -5
  49. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +2 -2
  50. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  51. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +1 -1
  52. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +1 -1
  53. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +1 -1
  54. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +1 -1
  55. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +2 -2
  56. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +1 -1
  57. package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +4 -4
  58. package/adapters/copilot/skills/forge-init/forge-init.md +1 -1
  59. package/adapters/copilot/skills/forge-verify/forge-verify.md +1 -1
  60. package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +1 -1
  61. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  62. package/adapters/cursor/references/portable-root.md +18 -9
  63. package/adapters/cursor/references/shared-conventions.md +21 -4
  64. package/adapters/cursor/references/stage-exit-protocol.md +1 -1
  65. package/adapters/cursor/references/vendor-construct-inventory.md +1 -0
  66. package/adapters/cursor/scripts/forge-session.py +259 -10
  67. package/adapters/cursor/skills/forge/forge.mdc +9 -9
  68. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +5 -5
  69. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +2 -2
  70. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  71. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +1 -1
  72. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +1 -1
  73. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +1 -1
  74. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +1 -1
  75. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +2 -2
  76. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +1 -1
  77. package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +4 -4
  78. package/adapters/cursor/skills/forge-init/forge-init.mdc +1 -1
  79. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +1 -1
  80. package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +1 -1
  81. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  82. package/adapters/gemini/gemini-extension.json +1 -1
  83. package/adapters/gemini/references/portable-root.md +18 -9
  84. package/adapters/gemini/references/shared-conventions.md +21 -4
  85. package/adapters/gemini/references/stage-exit-protocol.md +1 -1
  86. package/adapters/gemini/references/vendor-construct-inventory.md +1 -0
  87. package/adapters/gemini/scripts/forge-session.py +259 -10
  88. package/adapters/gemini/skills/forge/forge.md +9 -9
  89. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +5 -5
  90. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +2 -2
  91. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  92. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +1 -1
  93. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +1 -1
  94. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +1 -1
  95. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +1 -1
  96. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +2 -2
  97. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +1 -1
  98. package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +4 -4
  99. package/adapters/gemini/skills/forge-init/forge-init.md +1 -1
  100. package/adapters/gemini/skills/forge-verify/forge-verify.md +1 -1
  101. package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +1 -1
  102. package/package.json +1 -1
@@ -28,7 +28,7 @@ For pipeline architecture details, read `references/process-overview.md`.
28
28
 
29
29
  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:
30
30
  ```bash
31
- 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')"
31
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
32
32
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
33
33
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
34
34
  ```
@@ -36,14 +36,14 @@ python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specs
36
36
  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**.
37
37
  - **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 your session / start a fresh session):
38
38
  ```bash
39
- 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')"
39
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
40
40
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
41
41
  python3 "$R/scripts/forge-session.py" rank-features --specs-dir "{specsDir}" --json
42
42
  ```
43
- 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).
43
+ 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), `autoFix` (the single source of stage order), and `verifyGate` (`none`/`auto`/`standard` — the single resolved verify-gate, computed once by the ranker; read it rather than re-deriving from `verifyPending`+`autoVerify`). 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).
44
44
  - **Pick the feature:** if exactly one active standalone pipeline exists, show its dashboard. If multiple exist, use the host's question mechanism — **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.
45
45
 
46
- 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>`."
46
+ If no epics and no standalone features exist **on the current branch**, do not conclude the pipeline is empty yet — the state may live on topic branches (a fresh clone / default-branch session sees nothing on disk). Run `discover-feature --all` (via the standard prelude: `python3 "$R/scripts/forge-session.py" discover-feature --all --specs-dir "{specsDir}" --json`). If it surfaces features, list them with their branches and offer to switch (explicit accept + clean tree only, per the Feature Directory Resolution block), then render that feature's dashboard. Only when `--all` also returns nothing, 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>`." Never fabricate a dashboard from memory of earlier sessions.
47
47
 
48
48
  The feature name must be a single kebab-case token. If the user provides multiple words (e.g., "user auth flow"), convert to kebab-case: `user-auth-flow`.
49
49
 
@@ -88,11 +88,11 @@ Use these status indicators:
88
88
 
89
89
  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 your session / start a fresh session chore that makes long, multi-stage runs painful (especially on mobile).
90
90
 
91
- **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").
91
+ **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`, `autoFix`, and `verifyGate` (the resolved gate: `none` → no verify action; `auto` → the §2b catch-up; `standard` → the §3 gate). 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").
92
92
 
93
93
  **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:
94
94
  ```bash
95
- 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')"
95
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
96
96
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
97
97
  python3 "$R/scripts/forge-session.py" context-usage --json
98
98
  ```
@@ -109,7 +109,7 @@ python3 "$R/scripts/forge-session.py" context-usage --json
109
109
  - **`autoFix` is false (default), or preconditions failed** → present a **compact findings digest** as text, then the host's question mechanism: *Apply fixes now (forge-fix)* / *Review findings* / *Skip & advance*.
110
110
  - **`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").
111
111
 
112
- **3. Offer the next step via the host's question mechanism.** (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:
112
+ **3. Offer the next step via the host's question mechanism.** (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`). **Present this gate exactly once and act only on the option the user chooses — never also narrate the not-taken branch.** Concretely: do not print the "start in a clean session" recommendation as prose and *then* auto-invoke the next stage in the same session (or the reverse) — the host's question mechanism answer is the single decision, and only the chosen path's action follows. 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:
113
113
  - **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 your session / start a fresh session, then re-run `/feature-forge:forge {feature}` (or run `{nextCommand}` directly) in the fresh session. Note plainly that you cannot clear your session / start a fresh session 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.
114
114
  - **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.
115
115
  - **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.
@@ -132,7 +132,7 @@ This applies whether the feature was named explicitly (`/feature-forge:forge {fe
132
132
  When the named argument is an epic (`{specsDir}/{name}/epic-manifest.json` exists), render the epic dashboard instead of a per-feature one. Run:
133
133
 
134
134
  ```bash
135
- 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')"
135
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
136
136
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
137
137
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
138
138
  ```
@@ -203,7 +203,7 @@ Support these sub-commands for pipeline lifecycle management:
203
203
 
204
204
  - Set the manifest's top-level `status` (`paused` / `active` / `abandoned`) via the helper's `set-status` mutator — an atomic write that also bumps `updatedAt`:
205
205
  ```bash
206
- 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')"
206
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
207
207
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
208
208
  python3 "$R/scripts/epic-manifest.py" set-status "{epic}" --status paused --specs-dir "{specsDir}"
209
209
  ```
@@ -38,7 +38,7 @@ checks but still load any on-disk artifacts.
38
38
  plugin path and the configured specs dir:
39
39
 
40
40
  ```bash
41
- 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
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
42
42
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
43
43
  python3 "$R/scripts/epic-manifest.py" <subcommand> ... --specs-dir "{specsDir}"
44
44
  ```
@@ -72,7 +72,7 @@ Resolve the epic subtree path `{specsDir}/{epic}/` and decide which branch to ru
72
72
  epic, confirm the epic name itself does not collide with any existing feature or epic:
73
73
 
74
74
  ```bash
75
- 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')"
75
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
76
76
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
77
77
  python3 "$R/scripts/epic-manifest.py" check-name "{epic}" --specs-dir "{specsDir}"
78
78
  ```
@@ -116,7 +116,7 @@ For **each** proposed feature name, before accepting it into the set, enforce gl
116
116
  and name safety via the helper:
117
117
 
118
118
  ```bash
119
- 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')"
119
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
120
120
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
121
121
  python3 "$R/scripts/epic-manifest.py" check-name "{feature}" --specs-dir "{specsDir}"
122
122
  ```
@@ -176,7 +176,7 @@ For the *initial* creation write the skill writes the file directly — atomic g
176
176
  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:
177
177
 
178
178
  ```bash
179
- 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')"
179
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
180
180
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
181
181
  python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
182
182
  ```
@@ -248,7 +248,7 @@ now self-contained: manifest + EPIC.md + one subdirectory per member.
248
248
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
249
249
 
250
250
  ```bash
251
- 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')"
251
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
252
252
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
253
253
  python3 "$R/scripts/forge-session.py" stage-exit --feature "{epic}" --stage forge-0-epic --next-feature "{first-actionable-feature}" --specs-dir "{specsDir}" --host generic
254
254
  ```
@@ -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="$(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')"
19
+ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$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="$(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')"
80
+ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$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
  ```
@@ -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="$(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')"
15
+ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$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}" \
@@ -116,7 +116,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
116
116
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
117
117
 
118
118
  ```bash
119
- 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')"
119
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
120
120
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
121
121
  python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-1-prd --specs-dir "{specsDir}" --host generic
122
122
  ```
@@ -193,7 +193,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
193
193
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
194
194
 
195
195
  ```bash
196
- 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')"
196
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
197
197
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
198
198
  python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-2-tech --specs-dir "{specsDir}" --host generic
199
199
  ```
@@ -147,7 +147,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
147
147
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
148
148
 
149
149
  ```bash
150
- 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')"
150
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
151
151
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
152
152
  python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-3-specs --specs-dir "{specsDir}" --host generic
153
153
  ```
@@ -141,7 +141,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`. Foll
141
141
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
142
142
 
143
143
  ```bash
144
- 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')"
144
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
145
145
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
146
146
  python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-4-backlog --specs-dir "{specsDir}" --host generic
147
147
  ```
@@ -60,7 +60,7 @@ Read the resolved feature's `.pipeline-state.json`. **If it has no `epic` key, s
60
60
  1. Run `render-status "{epic}" --specs-dir "{specsDir}" --json` via the helper:
61
61
 
62
62
  ```bash
63
- 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')"
63
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
64
64
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
65
65
  python3 "$R/scripts/epic-manifest.py" \
66
66
  render-status "{epic}" --specs-dir "{specsDir}" --json
@@ -113,7 +113,7 @@ Verify the file exists on disk. If not, STOP and tell the user: "No backlog.json
113
113
 
114
114
  ### 1f. Branch Pre-flight (if using git)
115
115
 
116
- The runner commits each completed item straight onto the current branch, so guard against committing onto the default branch. Skip if not a git repo or `branchPerFeature` is false. Read the current branch (`git rev-parse --abbrev-ref HEAD`) and default branch (`git symbolic-ref --quiet refs/remotes/origin/HEAD`, else `main`/`master`). If `.pipeline-state.json` records a `branch` that differs from the current one, warn via the host's question mechanism (offer **switch back** or **proceed here**). Otherwise, if the current branch **is** the default, strongly recommend via the host's question mechanism creating/switching to `{branchPrefix}{feature}` (`git switch -c`, then record it to the state `branch` field) before the loop commits — still allowing **proceed on `{defaultBranch}`**. Never hard-stop.
116
+ The runner commits each item onto the current branch. Skip if not a git repo or `branchPerFeature` is false. Otherwise run the **Branch Reconciliation** block in `references/shared-conventions.md` (it runs `reconcile-branch` and, on `warn-drift` — you are on the default branch — strongly recommends creating `{branchPrefix}{feature}` via the host's question mechanism before the loop commits; on `adopt-current` it updates the recorded branch to the current one, never pushing you back to a stale/imposed branch). Never hard-stop.
117
117
 
118
118
  ## Step 2: Construct the Loop Command
119
119
 
@@ -43,7 +43,7 @@ Check `.pipeline-state.json` for `stages.forge-verify-impl`. If it is **absent**
43
43
  If the resolved feature has an `epic` back-pointer in its `.pipeline-state.json`, run:
44
44
 
45
45
  ```bash
46
- 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')"
46
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
47
47
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
48
48
  python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
49
49
  ```
@@ -58,7 +58,7 @@ Every bash invocation begins with the byte-identical portable-root prelude, then
58
58
  helper. Pass `--specs-dir ./specs` (the default) so the gate allow-lists the specs directory.
59
59
 
60
60
  ```bash
61
- 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')"
61
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
62
62
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
63
63
  python3 "$R/scripts/forge-bootstrap.py" check "<target-dir>" --json --specs-dir ./specs
64
64
  ```
@@ -135,7 +135,7 @@ when running under a Claude host (e.g. the host's question mechanism is availabl
135
135
  `CLAUDE.md` only when `host == "claude"`.
136
136
 
137
137
  ```bash
138
- 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')"
138
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
139
139
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
140
140
  python3 "$R/scripts/forge-bootstrap.py" scaffold "<target-dir>" --json --answers '<Answers JSON>'
141
141
  ```
@@ -143,7 +143,7 @@ python3 "$R/scripts/forge-bootstrap.py" scaffold "<target-dir>" --json --answers
143
143
  ### Step 5 — verify
144
144
 
145
145
  ```bash
146
- 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
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
147
147
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
148
148
  python3 "$R/scripts/forge-bootstrap.py" verify "<target-dir>" --json --answers '<Answers JSON>'
149
149
  ```
@@ -169,7 +169,7 @@ and removes the sentinel before staging so it never enters history. Read
169
169
  leave the sentinel in-progress (resumable) — do **not** declare success.
170
170
 
171
171
  ```bash
172
- 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')"
172
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
173
173
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
174
174
  python3 "$R/scripts/forge-bootstrap.py" commit "<target-dir>" --json --answers '<Answers JSON>' [--stage-only]
175
175
  ```
@@ -9,7 +9,7 @@ description: Initialize feature-forge configuration in the current project. Use
9
9
  Run the initialization script to create `forge.config.json` with default settings:
10
10
 
11
11
  ```bash
12
- 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')"
12
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
13
13
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
14
14
  bash "$R/scripts/forge-init.sh"
15
15
  ```
@@ -255,7 +255,7 @@ Do NOT mark as `findings-applied` — that happens after the fix pass.
255
255
  - For specs verification, also run the deterministic traceability validator to supplement agent-driven traceability checks. Include any uncovered requirements or orphaned references as findings:
256
256
 
257
257
  ```bash
258
- 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')"
258
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$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')"
259
259
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
260
260
  python3 "$R/scripts/validate-traceability.py" {resolvedFeatureDir}/PRD.md {resolvedFeatureDir}/ --json
261
261
  ```
@@ -192,7 +192,7 @@ findings to E01/E02/E03/E08. Then perform the judgment checks E04–E07 by readi
192
192
  manifest, EPIC.md, and completed members' specs.
193
193
 
194
194
  ```bash
195
- 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')"
195
+ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$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')"
196
196
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
197
197
  python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
198
198
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garygentry/feature-forge",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Cross-agent installer for the feature-forge skill suite — installs the canonical forge pipeline into Claude, Codex, Copilot, Cursor, or Gemini.",
5
5
  "license": "MIT",
6
6
  "type": "module",