@garygentry/feature-forge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/LICENSE +21 -0
  2. package/adapters/GENERATION-REPORT.md +128 -0
  3. package/adapters/claude/agents/forge-researcher.md +137 -0
  4. package/adapters/claude/agents/forge-spec-writer.md +115 -0
  5. package/adapters/claude/agents/forge-verifier.md +121 -0
  6. package/adapters/claude/references/epic-manifest-schema.json +120 -0
  7. package/adapters/claude/references/forge-config-schema.json +166 -0
  8. package/adapters/claude/references/pipeline-state-schema.json +110 -0
  9. package/adapters/claude/references/portable-root.md +56 -0
  10. package/adapters/claude/references/process-overview.md +123 -0
  11. package/adapters/claude/references/ralph-loop-contract.md +221 -0
  12. package/adapters/claude/references/shared-conventions.md +144 -0
  13. package/adapters/claude/references/skill-frontmatter.schema.json +17 -0
  14. package/adapters/claude/references/stack-resolution.md +51 -0
  15. package/adapters/claude/references/stacks/_generic.md +90 -0
  16. package/adapters/claude/references/stacks/go.md +138 -0
  17. package/adapters/claude/references/stacks/python.md +163 -0
  18. package/adapters/claude/references/stacks/rust.md +151 -0
  19. package/adapters/claude/references/stacks/typescript.md +111 -0
  20. package/adapters/claude/references/vendor-construct-inventory.md +49 -0
  21. package/adapters/claude/scripts/forge-root.sh +50 -0
  22. package/adapters/claude/skills/forge/SKILL.md +165 -0
  23. package/adapters/claude/skills/forge-0-epic/SKILL.md +303 -0
  24. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +222 -0
  25. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +64 -0
  26. package/adapters/claude/skills/forge-1-prd/SKILL.md +121 -0
  27. package/adapters/claude/skills/forge-1-prd/references/prd-template.md +106 -0
  28. package/adapters/claude/skills/forge-2-tech/SKILL.md +198 -0
  29. package/adapters/claude/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  30. package/adapters/claude/skills/forge-3-specs/SKILL.md +154 -0
  31. package/adapters/claude/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  32. package/adapters/claude/skills/forge-3-specs/references/spec-examples.md +71 -0
  33. package/adapters/claude/skills/forge-4-backlog/SKILL.md +146 -0
  34. package/adapters/claude/skills/forge-5-loop/SKILL.md +303 -0
  35. package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +63 -0
  36. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +214 -0
  37. package/adapters/claude/skills/forge-6-docs/SKILL.md +179 -0
  38. package/adapters/claude/skills/forge-6-docs/references/doc-conventions.md +126 -0
  39. package/adapters/claude/skills/forge-fix/SKILL.md +65 -0
  40. package/adapters/claude/skills/forge-init/SKILL.md +29 -0
  41. package/adapters/claude/skills/forge-verify/SKILL.md +219 -0
  42. package/adapters/claude/skills/forge-verify/references/verification-checklists.md +379 -0
  43. package/adapters/codex/agents/forge-researcher.md +133 -0
  44. package/adapters/codex/agents/forge-spec-writer.md +112 -0
  45. package/adapters/codex/agents/forge-verifier.md +115 -0
  46. package/adapters/codex/agents/openai.yaml +10 -0
  47. package/adapters/codex/references/epic-manifest-schema.json +120 -0
  48. package/adapters/codex/references/forge-config-schema.json +166 -0
  49. package/adapters/codex/references/pipeline-state-schema.json +110 -0
  50. package/adapters/codex/references/portable-root.md +56 -0
  51. package/adapters/codex/references/process-overview.md +123 -0
  52. package/adapters/codex/references/ralph-loop-contract.md +221 -0
  53. package/adapters/codex/references/shared-conventions.md +144 -0
  54. package/adapters/codex/references/skill-frontmatter.schema.json +17 -0
  55. package/adapters/codex/references/stack-resolution.md +51 -0
  56. package/adapters/codex/references/stacks/_generic.md +90 -0
  57. package/adapters/codex/references/stacks/go.md +138 -0
  58. package/adapters/codex/references/stacks/python.md +163 -0
  59. package/adapters/codex/references/stacks/rust.md +151 -0
  60. package/adapters/codex/references/stacks/typescript.md +111 -0
  61. package/adapters/codex/references/vendor-construct-inventory.md +49 -0
  62. package/adapters/codex/scripts/forge-root.sh +50 -0
  63. package/adapters/codex/skills/forge/forge.md +164 -0
  64. package/adapters/codex/skills/forge-0-epic/forge-0-epic.md +302 -0
  65. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +222 -0
  66. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +64 -0
  67. package/adapters/codex/skills/forge-1-prd/forge-1-prd.md +120 -0
  68. package/adapters/codex/skills/forge-1-prd/references/prd-template.md +106 -0
  69. package/adapters/codex/skills/forge-2-tech/forge-2-tech.md +197 -0
  70. package/adapters/codex/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  71. package/adapters/codex/skills/forge-3-specs/forge-3-specs.md +153 -0
  72. package/adapters/codex/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  73. package/adapters/codex/skills/forge-3-specs/references/spec-examples.md +71 -0
  74. package/adapters/codex/skills/forge-4-backlog/forge-4-backlog.md +145 -0
  75. package/adapters/codex/skills/forge-5-loop/forge-5-loop.md +302 -0
  76. package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +63 -0
  77. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +214 -0
  78. package/adapters/codex/skills/forge-6-docs/forge-6-docs.md +178 -0
  79. package/adapters/codex/skills/forge-6-docs/references/doc-conventions.md +126 -0
  80. package/adapters/codex/skills/forge-fix/forge-fix.md +64 -0
  81. package/adapters/codex/skills/forge-init/forge-init.md +29 -0
  82. package/adapters/codex/skills/forge-verify/forge-verify.md +218 -0
  83. package/adapters/codex/skills/forge-verify/references/verification-checklists.md +379 -0
  84. package/adapters/copilot/agents/forge-researcher.md +133 -0
  85. package/adapters/copilot/agents/forge-spec-writer.md +112 -0
  86. package/adapters/copilot/agents/forge-verifier.md +115 -0
  87. package/adapters/copilot/references/epic-manifest-schema.json +120 -0
  88. package/adapters/copilot/references/forge-config-schema.json +166 -0
  89. package/adapters/copilot/references/pipeline-state-schema.json +110 -0
  90. package/adapters/copilot/references/portable-root.md +56 -0
  91. package/adapters/copilot/references/process-overview.md +123 -0
  92. package/adapters/copilot/references/ralph-loop-contract.md +221 -0
  93. package/adapters/copilot/references/shared-conventions.md +144 -0
  94. package/adapters/copilot/references/skill-frontmatter.schema.json +17 -0
  95. package/adapters/copilot/references/stack-resolution.md +51 -0
  96. package/adapters/copilot/references/stacks/_generic.md +90 -0
  97. package/adapters/copilot/references/stacks/go.md +138 -0
  98. package/adapters/copilot/references/stacks/python.md +163 -0
  99. package/adapters/copilot/references/stacks/rust.md +151 -0
  100. package/adapters/copilot/references/stacks/typescript.md +111 -0
  101. package/adapters/copilot/references/vendor-construct-inventory.md +49 -0
  102. package/adapters/copilot/scripts/forge-root.sh +50 -0
  103. package/adapters/copilot/skills/forge/forge.md +164 -0
  104. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +302 -0
  105. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +222 -0
  106. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +64 -0
  107. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +120 -0
  108. package/adapters/copilot/skills/forge-1-prd/references/prd-template.md +106 -0
  109. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +197 -0
  110. package/adapters/copilot/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  111. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +153 -0
  112. package/adapters/copilot/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  113. package/adapters/copilot/skills/forge-3-specs/references/spec-examples.md +71 -0
  114. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +145 -0
  115. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +302 -0
  116. package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +63 -0
  117. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +214 -0
  118. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +178 -0
  119. package/adapters/copilot/skills/forge-6-docs/references/doc-conventions.md +126 -0
  120. package/adapters/copilot/skills/forge-fix/forge-fix.md +64 -0
  121. package/adapters/copilot/skills/forge-init/forge-init.md +29 -0
  122. package/adapters/copilot/skills/forge-verify/forge-verify.md +218 -0
  123. package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +379 -0
  124. package/adapters/cursor/agents/forge-researcher.mdc +134 -0
  125. package/adapters/cursor/agents/forge-spec-writer.mdc +113 -0
  126. package/adapters/cursor/agents/forge-verifier.mdc +116 -0
  127. package/adapters/cursor/references/epic-manifest-schema.json +120 -0
  128. package/adapters/cursor/references/forge-config-schema.json +166 -0
  129. package/adapters/cursor/references/pipeline-state-schema.json +110 -0
  130. package/adapters/cursor/references/portable-root.md +56 -0
  131. package/adapters/cursor/references/process-overview.md +123 -0
  132. package/adapters/cursor/references/ralph-loop-contract.md +221 -0
  133. package/adapters/cursor/references/shared-conventions.md +144 -0
  134. package/adapters/cursor/references/skill-frontmatter.schema.json +17 -0
  135. package/adapters/cursor/references/stack-resolution.md +51 -0
  136. package/adapters/cursor/references/stacks/_generic.md +90 -0
  137. package/adapters/cursor/references/stacks/go.md +138 -0
  138. package/adapters/cursor/references/stacks/python.md +163 -0
  139. package/adapters/cursor/references/stacks/rust.md +151 -0
  140. package/adapters/cursor/references/stacks/typescript.md +111 -0
  141. package/adapters/cursor/references/vendor-construct-inventory.md +49 -0
  142. package/adapters/cursor/scripts/forge-root.sh +50 -0
  143. package/adapters/cursor/skills/forge/forge.mdc +165 -0
  144. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +303 -0
  145. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +222 -0
  146. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +64 -0
  147. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +121 -0
  148. package/adapters/cursor/skills/forge-1-prd/references/prd-template.md +106 -0
  149. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +198 -0
  150. package/adapters/cursor/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  151. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +154 -0
  152. package/adapters/cursor/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  153. package/adapters/cursor/skills/forge-3-specs/references/spec-examples.md +71 -0
  154. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +146 -0
  155. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +303 -0
  156. package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +63 -0
  157. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +214 -0
  158. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +179 -0
  159. package/adapters/cursor/skills/forge-6-docs/references/doc-conventions.md +126 -0
  160. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +65 -0
  161. package/adapters/cursor/skills/forge-init/forge-init.mdc +30 -0
  162. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +219 -0
  163. package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +379 -0
  164. package/adapters/gemini/agents/forge-researcher.md +133 -0
  165. package/adapters/gemini/agents/forge-spec-writer.md +112 -0
  166. package/adapters/gemini/agents/forge-verifier.md +115 -0
  167. package/adapters/gemini/gemini-extension.json +54 -0
  168. package/adapters/gemini/references/epic-manifest-schema.json +120 -0
  169. package/adapters/gemini/references/forge-config-schema.json +166 -0
  170. package/adapters/gemini/references/pipeline-state-schema.json +110 -0
  171. package/adapters/gemini/references/portable-root.md +56 -0
  172. package/adapters/gemini/references/process-overview.md +123 -0
  173. package/adapters/gemini/references/ralph-loop-contract.md +221 -0
  174. package/adapters/gemini/references/shared-conventions.md +144 -0
  175. package/adapters/gemini/references/skill-frontmatter.schema.json +17 -0
  176. package/adapters/gemini/references/stack-resolution.md +51 -0
  177. package/adapters/gemini/references/stacks/_generic.md +90 -0
  178. package/adapters/gemini/references/stacks/go.md +138 -0
  179. package/adapters/gemini/references/stacks/python.md +163 -0
  180. package/adapters/gemini/references/stacks/rust.md +151 -0
  181. package/adapters/gemini/references/stacks/typescript.md +111 -0
  182. package/adapters/gemini/references/vendor-construct-inventory.md +49 -0
  183. package/adapters/gemini/scripts/forge-root.sh +50 -0
  184. package/adapters/gemini/skills/forge/forge.md +164 -0
  185. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +302 -0
  186. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +222 -0
  187. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +64 -0
  188. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +120 -0
  189. package/adapters/gemini/skills/forge-1-prd/references/prd-template.md +106 -0
  190. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +197 -0
  191. package/adapters/gemini/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  192. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +153 -0
  193. package/adapters/gemini/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  194. package/adapters/gemini/skills/forge-3-specs/references/spec-examples.md +71 -0
  195. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +145 -0
  196. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +302 -0
  197. package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +63 -0
  198. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +214 -0
  199. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +178 -0
  200. package/adapters/gemini/skills/forge-6-docs/references/doc-conventions.md +126 -0
  201. package/adapters/gemini/skills/forge-fix/forge-fix.md +64 -0
  202. package/adapters/gemini/skills/forge-init/forge-init.md +29 -0
  203. package/adapters/gemini/skills/forge-verify/forge-verify.md +218 -0
  204. package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +379 -0
  205. package/dist/agent-targets.d.ts +70 -0
  206. package/dist/agent-targets.js +111 -0
  207. package/dist/apply.d.ts +49 -0
  208. package/dist/apply.js +246 -0
  209. package/dist/cli.d.ts +94 -0
  210. package/dist/cli.js +508 -0
  211. package/dist/detect.d.ts +45 -0
  212. package/dist/detect.js +72 -0
  213. package/dist/fsutil.d.ts +56 -0
  214. package/dist/fsutil.js +175 -0
  215. package/dist/hash.d.ts +50 -0
  216. package/dist/hash.js +107 -0
  217. package/dist/index.d.ts +8 -0
  218. package/dist/index.js +9 -0
  219. package/dist/manifest.d.ts +72 -0
  220. package/dist/manifest.js +222 -0
  221. package/dist/plan.d.ts +66 -0
  222. package/dist/plan.js +166 -0
  223. package/dist/rauf.d.ts +83 -0
  224. package/dist/rauf.js +118 -0
  225. package/dist/report.d.ts +35 -0
  226. package/dist/report.js +110 -0
  227. package/dist/source.d.ts +69 -0
  228. package/dist/source.js +164 -0
  229. package/dist/types.d.ts +264 -0
  230. package/dist/types.js +57 -0
  231. package/package.json +42 -0
@@ -0,0 +1,115 @@
1
+ ---
2
+ # GENERATED — DO NOT EDIT. Source: agents/forge-verifier.md. Regenerate: python3 scripts/build-adapters.py
3
+ name: forge-verifier
4
+ description: Verifies feature forge pipeline artifacts for completeness, consistency, and quality. Delegates to this agent when running /feature-forge:forge-verify or when the user asks to check specs, backlog, or implementation for gaps. This agent has read-only tools and persistent memory — it cannot modify files, only analyze and report findings.
5
+ ---
6
+
7
+ You are a meticulous verification agent for the feature-forge development pipeline. Your job is to find gaps, inconsistencies, and quality issues in feature specs, backlogs, and implementations.
8
+
9
+ ## Your Role
10
+
11
+ You are the "second set of eyes." You receive artifacts (PRDs, tech specs, implementation specs, backlogs, source code) and analyze them against structured checklists. You produce actionable findings that a separate agent can apply in a clean session.
12
+
13
+ You have READ-ONLY access. You cannot and should not modify any files. Your output is returned as your response — the parent agent handles writing the findings document to disk.
14
+
15
+ ## How You Work
16
+
17
+ 1. Read the pipeline state file to understand what stage the feature is at
18
+ 2. Load all relevant artifacts for the current verification mode
19
+ 3. Execute every check in the verification checklists (loaded via the forge-verify skill)
20
+ 4. Return structured findings as your response in the Output Format specified below
21
+ 5. Generate a fix plan suitable for a fresh agent to execute
22
+
23
+ ## Scoped / Parallel Operation
24
+
25
+ You may be dispatched in one of three ways. The parent's prompt tells you which:
26
+
27
+ 1. **Full verifier (single instance):** verify every check for the mode and return all findings. This is the default for small modes (prd, tech).
28
+ 2. **Dimensioned instance (one of several in parallel):** the prompt gives you a **dimension label** (e.g. "cross-reference & traceability") and an **exact set of CHECK-IDs you own**. Verify ONLY those checks; ignore the rest (another instance owns them). Return findings for your slice. Your `Checks Executed: N of M` line counts only your assigned slice. **Treat `MEMORY.md` as read-only in this mode** — apply what you've learned but do NOT write it; concurrent instances would race. Memory consolidation happens only on full-verifier runs.
29
+ 3. **Skeptic (adversarial confirmation):** the prompt hands you one or more *claimed* findings and asks you to **refute** them. Try hard to prove each wrong from the artifacts. Return a verdict per finding (CONFIRMED / REFUTED + why). **Default to REFUTED when you cannot positively confirm the finding from the artifacts** — the goal is to strip false positives, so the burden of proof is on the finding.
30
+
31
+ ## Context Pressure Management
32
+
33
+ For large spec suites (>8 documents), process verification in phases: load shared types and architecture specs first for cross-reference and type consistency checks, then load subsystem specs in batches for domain-specific checks. (In dimensioned mode your slice is already narrow — load only the artifacts your assigned checks need.)
34
+
35
+ ## Using Your Memory
36
+
37
+ You have persistent memory in your `MEMORY.md` file. Use it to track:
38
+
39
+ - **Recurring patterns**: If you keep finding the same type of gap across features, note it. Over time you'll learn this project's blind spots.
40
+ - **Project conventions**: As you review more specs, capture conventions that should be consistent (naming patterns, error handling approaches, test strategies).
41
+ - **False positives to avoid**: If you've flagged something before and the user said it was intentional, note it so you don't flag it again.
42
+
43
+ At the end of each verification pass, update your memory with any new patterns you've observed. Keep `MEMORY.md` curated — summarize and consolidate rather than appending endlessly.
44
+
45
+ ## Verification Quality Standards
46
+
47
+ - Every finding must be specific enough that a fresh agent can act on it without conversational context
48
+ - Severity must be accurate: `gap` (missing coverage), `inconsistency` (contradictory), `improvement` (not wrong but better exists), `error` (factually incorrect)
49
+ - Include exact file paths and section references
50
+ - Include a concrete suggested fix, not just a description of the problem
51
+ - If you find zero issues, say so honestly — but also note in your memory that this feature had a clean verification, which is unusual for complex features
52
+
53
+ ## Output Format
54
+
55
+ Return your findings as your final response using exactly this markdown structure. The parent agent will write it to `.verification/VERIFY-{mode}-{date}.md`:
56
+
57
+ ```markdown
58
+ # Verification Report: {feature} ({mode})
59
+ Date: {YYYY-MM-DD}
60
+ Pipeline Stage: {currentStage}
61
+ Artifacts Reviewed: {list of files}
62
+ Checks Executed: {N} of {M} ({X} pass, {Y} fail, {Z} not-applicable)
63
+
64
+ ## Summary
65
+ - Total findings: {N}
66
+ - Gaps: {N}
67
+ - Inconsistencies: {N}
68
+ - Improvements: {N}
69
+ - Errors: {N}
70
+
71
+ ## Findings
72
+
73
+ ### V-001: {Short title}
74
+ - **Severity:** gap | inconsistency | improvement | error
75
+ - **Location:** {filename}, section {N.N}
76
+ - **Issue:** {Detailed description}
77
+ - **Suggested fix:** {Specific, actionable fix}
78
+ - **References:** {Other files/sections involved}
79
+ - **Checklist:** {CHECK-XXX IDs}
80
+
81
+ ## Fix Execution Plan
82
+
83
+ ### User Decisions Required
84
+ {List or "None — all fixes can be applied directly."}
85
+
86
+ ### Execution Steps
87
+ #### Step {N}: {Short title}
88
+ - **Files:** {paths}
89
+ - **Addresses:** {V-NNN IDs}
90
+ - **Action:** {Exact change description}
91
+ - **Depends on:** {Step N or "none"}
92
+ ```
93
+
94
+ ## Bash Tool Usage
95
+
96
+ You have Bash access for read-only operations ONLY. The following is an exhaustive allowlist.
97
+
98
+ ### Allowed Commands
99
+ - `python`, `python3` — for running validation scripts under the plugin root resolved by the portable resolver (`scripts/forge-root.sh`; see `references/portable-root.md`)
100
+ - `wc` — counting lines, words, characters
101
+ - `find` — locating files (read-only)
102
+ - `ls`, `tree` — listing directory contents
103
+ - `head`, `tail` — viewing file excerpts
104
+ - `cat` — reading file contents
105
+ - Type-check commands from forge.config.json (e.g., `bun run typecheck`, `mypy`, `go vet`)
106
+ - Test commands from forge.config.json (e.g., `bun test`, `pytest`, `cargo test`)
107
+
108
+ ### Forbidden Commands
109
+ ALL commands not listed above are forbidden. Specifically:
110
+ - `git` (any subcommand)
111
+ - `rm`, `mv`, `cp`, `mkdir`, `touch`, `chmod`
112
+ - `tee`, `sed -i`, `awk` (with file modification)
113
+ - Write/append redirects (`>`, `>>`)
114
+ - Package managers (`pip install`, `npm install`, `bun install`, `cargo install`)
115
+ - Any command that creates, modifies, or deletes files
@@ -0,0 +1,120 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://feature-forge/references/epic-manifest-schema.json",
4
+ "title": "Feature Forge Epic Manifest",
5
+ "description": "Canonical record of an epic's membership, dependency edges, charters, and contracts. Lives at {specsDir}/{epic}/epic-manifest.json. Carries NO per-feature status field (REQ-STATE-02); status is derived live from each member's .pipeline-state.json.",
6
+ "type": "object",
7
+ "required": ["schemaVersion", "epic", "description", "status", "narrativeDoc", "createdAt", "updatedAt", "features"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schemaVersion": {
11
+ "const": 1,
12
+ "description": "Schema evolution guard."
13
+ },
14
+ "epic": {
15
+ "type": "string",
16
+ "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
17
+ "description": "Matches the epic subtree directory name. Globally unique, kebab-case."
18
+ },
19
+ "description": {
20
+ "type": "string",
21
+ "description": "One-paragraph epic summary."
22
+ },
23
+ "status": {
24
+ "type": "string",
25
+ "enum": ["active", "paused", "abandoned", "complete"],
26
+ "description": "Epic lifecycle state (REQ-ORCH-05)."
27
+ },
28
+ "narrativeDoc": {
29
+ "const": "EPIC.md",
30
+ "description": "Relative pointer to the narrative document (REQ-EPIC-03)."
31
+ },
32
+ "createdAt": {
33
+ "type": "string",
34
+ "format": "date-time",
35
+ "description": "Set once at creation."
36
+ },
37
+ "updatedAt": {
38
+ "type": "string",
39
+ "format": "date-time",
40
+ "description": "Bumped by every mutator on each atomic write (REQ-OBS-01)."
41
+ },
42
+ "features": {
43
+ "type": "array",
44
+ "items": { "$ref": "#/definitions/feature" },
45
+ "description": "Ordered. Order is the user-declared sequence; it is NOT a dependency ordering."
46
+ }
47
+ },
48
+ "definitions": {
49
+ "feature": {
50
+ "type": "object",
51
+ "required": ["name", "charter", "dependsOn", "exposes", "consumes"],
52
+ "additionalProperties": false,
53
+ "properties": {
54
+ "name": {
55
+ "type": "string",
56
+ "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
57
+ "description": "Globally unique across the whole specs tree, kebab-case (REQ-DIR-04)."
58
+ },
59
+ "charter": {
60
+ "type": "string",
61
+ "description": "One-paragraph scope statement + contract obligations (REQ-EPIC-04). No full PRD at creation."
62
+ },
63
+ "dependsOn": {
64
+ "type": "array",
65
+ "items": { "type": "string" },
66
+ "description": "Names of sibling features in this epic (REQ-EPIC-02). Every entry must be a name in features[]. May be empty."
67
+ },
68
+ "exposes": {
69
+ "type": "array",
70
+ "items": { "$ref": "#/definitions/contract" },
71
+ "description": "What this feature provides to dependents (REQ-EPIC-03). May be empty."
72
+ },
73
+ "consumes": {
74
+ "type": "array",
75
+ "items": { "$ref": "#/definitions/consumedContract" },
76
+ "description": "What this feature relies on from its dependencies (REQ-EPIC-03). May be empty."
77
+ }
78
+ }
79
+ },
80
+ "contract": {
81
+ "type": "object",
82
+ "required": ["name", "kind", "summary"],
83
+ "additionalProperties": false,
84
+ "properties": {
85
+ "name": {
86
+ "type": "string",
87
+ "description": "Identifier of the exposed artifact (e.g. verifyJwt, JWT_SECRET)."
88
+ },
89
+ "kind": {
90
+ "type": "string",
91
+ "enum": ["function", "type", "endpoint", "module", "event"],
92
+ "description": "Kind of exposed artifact."
93
+ },
94
+ "summary": {
95
+ "type": "string",
96
+ "description": "One-line human description."
97
+ }
98
+ }
99
+ },
100
+ "consumedContract": {
101
+ "type": "object",
102
+ "required": ["from", "name", "summary"],
103
+ "additionalProperties": false,
104
+ "properties": {
105
+ "from": {
106
+ "type": "string",
107
+ "description": "Name of the sibling feature providing this. Must be present in features[]."
108
+ },
109
+ "name": {
110
+ "type": "string",
111
+ "description": "Identifier being consumed; should match an exposes[].name of the from feature."
112
+ },
113
+ "summary": {
114
+ "type": "string",
115
+ "description": "One-line human description."
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,166 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Feature Forge Configuration",
4
+ "description": "Project-level configuration for the feature-forge plugin. Place as forge.config.json in your project root.",
5
+ "type": "object",
6
+ "properties": {
7
+ "specsDir": {
8
+ "type": "string",
9
+ "default": "./specs",
10
+ "description": "Root directory for feature spec documents. Each feature gets a subdirectory."
11
+ },
12
+ "docsDir": {
13
+ "type": "string",
14
+ "default": "./docs/architecture",
15
+ "description": "Root directory for generated architecture documentation."
16
+ },
17
+ "backlogDir": {
18
+ "type": "string",
19
+ "description": "Optional override for backlog location. If set, backlog.json is written here instead of with the feature specs. Default behavior: backlog.json is written to {specsDir}/{feature}/backlog.json."
20
+ },
21
+ "gitCommitAfterStage": {
22
+ "type": "boolean",
23
+ "default": true,
24
+ "description": "Automatically commit after each pipeline stage completes."
25
+ },
26
+ "commitPrefix": {
27
+ "type": "string",
28
+ "default": "forge",
29
+ "description": "Prefix for conventional commit messages, e.g., forge(auth): complete PRD"
30
+ },
31
+ "stack": {
32
+ "type": "string",
33
+ "description": "Detected or configured project stack identifier. Selects guidance from references/stacks/{stack}.md. Set during forge-2-tech or manually. Examples: 'typescript', 'python', 'go', 'rust'."
34
+ },
35
+ "typeCheckCommand": {
36
+ "type": "string",
37
+ "description": "Command to verify type correctness or lint. Examples: 'bun run typecheck', 'mypy .', 'go vet ./...'. Used in acceptance criteria and verification."
38
+ },
39
+ "testCommand": {
40
+ "type": "string",
41
+ "description": "Command to run tests. Examples: 'bun test', 'pytest', 'go test ./...'. Used in acceptance criteria and verification."
42
+ },
43
+ "loopIterationMultiplier": {
44
+ "type": "number",
45
+ "default": 1.5,
46
+ "minimum": 1,
47
+ "description": "Multiplier applied to pending backlog item count to calculate loop iterations. Higher values allow more retries. Default: 1.5 (e.g., 10 items = 15 iterations)."
48
+ },
49
+ "loopRunner": {
50
+ "type": "object",
51
+ "description": "The autonomous loop runner feature-forge drives. Defaults to rauf when absent (forge-5 states 'defaulting to rauf loop runner'). Every command is a template — {bin}, {backlogDir}, {specsDir}, {iterations} are substituted at call time — so an alternative ralph-style runner conforming to rauf's SPEC-BACKLOG-TOOL-CONTRACT.md can be swapped in without editing any skill. See references/ralph-loop-contract.md.",
52
+ "properties": {
53
+ "name": {
54
+ "type": "string",
55
+ "default": "rauf",
56
+ "description": "Display name of the loop runner."
57
+ },
58
+ "bin": {
59
+ "type": "string",
60
+ "default": "rauf",
61
+ "description": "The runner executable. Assumed on PATH; may be an absolute path. Substituted as {bin} in every command."
62
+ },
63
+ "runCommand": {
64
+ "type": "string",
65
+ "default": "{bin} loop run . --backlog {backlogDir} --iterations {iterations}",
66
+ "description": "Run the loop. Launched in the background by forge-5. Human-formatted output; used as the fallback launch command when eventStreamCommand is absent."
67
+ },
68
+ "eventStreamCommand": {
69
+ "type": "string",
70
+ "default": "{bin} loop run . --backlog {backlogDir} --iterations {iterations} --ndjson",
71
+ "description": "PREFERRED launch command for forge-5. Same as runCommand but emits one machine-readable JSON event per stdout line (NDJSON): item_completed / item_blocked / needs_human / signal_parsed / loop_completed / loop_error / loop_cancelled / llm_stuck_warning, each with {type, timestamp, projectPath} plus payload (a circuit-breaker halt surfaces as loop_error). forge-5 redirects this stdout to {backlogDir}/{stateDir}/events.ndjson and arms a Monitor on it for live, structured supervision. If a runner cannot emit NDJSON, omit this field — forge-5 falls back to runCommand + tailing the human log."
72
+ },
73
+ "validateCommand": {
74
+ "type": "string",
75
+ "default": "{bin} backlog validate . --backlog {backlogDir} --specs-dir {specsDir} --json",
76
+ "description": "Validate a backlog. MUST exit 0=valid, 1=findings, 2=usage/IO, and emit { valid, findings[] } with --json. `specReferences` are project-root-relative (resolved against the project root); `--specs-dir` only gates the existence check, so passing the specs root ({specsDir}) is sufficient."
77
+ },
78
+ "statusCommand": {
79
+ "type": "string",
80
+ "default": "{bin} status . --backlog {backlogDir}",
81
+ "description": "One-shot loop status, human-formatted. Shown to the user as a monitoring hint."
82
+ },
83
+ "statusJsonCommand": {
84
+ "type": "string",
85
+ "default": "{bin} status . --backlog {backlogDir} --json",
86
+ "description": "Machine-readable derived status used by forge-5 for milestone tallies and the final summary. Emits { loopState, iteration, maxIterations, currentItem, lastSignal, backlogSummary{pending,inProgress,blocked,needsHuman,deferred,done,total}, lock{...} }. Distinguishes the three non-done outcomes (genuine blocked vs needsHuman vs runner-deferred 'false blocks')."
87
+ },
88
+ "listCommand": {
89
+ "type": "string",
90
+ "default": "{bin} backlog list . --backlog {backlogDir} --json",
91
+ "description": "List backlog items as JSON."
92
+ },
93
+ "followCommand": {
94
+ "type": "string",
95
+ "default": "{bin} follow . --backlog {backlogDir}",
96
+ "description": "Stream live loop events, HUMAN-formatted (pretty-printed / log tail) — for a person watching in another terminal, NOT a machine-readable surface. forge-5 supervises via eventStreamCommand (NDJSON) instead."
97
+ },
98
+ "logCommand": {
99
+ "type": "string",
100
+ "default": "{bin} log . --backlog {backlogDir} --follow",
101
+ "description": "Tail the runner log, human-formatted. Monitoring hint for the user."
102
+ },
103
+ "watchCommand": {
104
+ "type": "string",
105
+ "default": "{bin} status . --backlog {backlogDir} --json",
106
+ "description": "Machine-readable status used by forge-5 for stall detection. rauf's `loop watch` verb was removed in v0.5.0, so this now points at `status --json`; forge-5 keys off the iteration-status `stuckWarning` flag (read from `status --json` / `iteration-status.json`) rather than guessing liveness from state.json timestamps."
107
+ },
108
+ "versionCommand": {
109
+ "type": "string",
110
+ "default": "{bin} version --json",
111
+ "description": "Report runner version as { version: <semver> }. Used to enforce minRunnerVersion before running."
112
+ },
113
+ "agentArgument": {
114
+ "type": "string",
115
+ "default": "--agent {agent}",
116
+ "description": "Tokenized argument appended to the launch command (eventStreamCommand/runCommand) when forge resolves a non-default coding agent for the run. {agent} is substituted ONLY with a validated, advertised agent id (a member of the set agentsProbeCommand reports). PRESENCE of this field advertises the runner's agent surface: when present and non-empty, forge-5 offers the per-run agent selector, honors defaultAgent, and may run agentsProbeCommand; OMIT it for a runner with no agent dimension and forge skips agent selection entirely — no selector, no probe, no {agent} substitution, no agent argument sent (byte-identical to today). Distinct from the version gate (minRunnerVersion)."
117
+ },
118
+ "agentsProbeCommand": {
119
+ "type": "string",
120
+ "default": "{bin} agents --json",
121
+ "description": "Coding-agent availability probe. MUST emit { agents: [{ id, displayName, available, ... }] } and exit 0 (it always exits 0: an unknown id simply never appears; a known-unavailable one appears with available:false). forge-5 runs it ONCE (no retries) before launching a non-default agent to (a) validate the resolved id against the advertised id set and (b) report availability in the pre-launch confirmation. Ignored on the default path and when agentArgument is absent."
122
+ },
123
+ "defaultAgent": {
124
+ "type": "string",
125
+ "default": "",
126
+ "description": "Project-default coding agent id, so a project can fix its agent once without specifying it every run. Empty string ⇒ no project default (the runner's own default — claude-cli for rauf — applies, behaving exactly as today). Overridden by the per-run agent selector (run > project precedence, resolved inside forge before the single --agent is emitted). Ignored when agentArgument is absent."
127
+ },
128
+ "preconditionFile": {
129
+ "type": "string",
130
+ "default": ".rauf.json",
131
+ "description": "Project-root marker file that must exist (runner installed into the target project)."
132
+ },
133
+ "stateDir": {
134
+ "type": "string",
135
+ "default": ".rauf",
136
+ "description": "Per-backlog state directory name created under the backlog dir."
137
+ },
138
+ "logFile": {
139
+ "type": "string",
140
+ "default": "rauf.log",
141
+ "description": "Human-readable event log filename written under {stateDir}. Substituted as {loopRunner.logFile} in the log-tail fallback Monitor command when eventStreamCommand (events.ndjson) is unavailable. The structured NDJSON path uses the contract-standard name events.ndjson and is not configurable here."
142
+ },
143
+ "setupHint": {
144
+ "type": "string",
145
+ "default": "Run `rauf install .` to install rauf's per-project artifacts (.rauf/, RAUF.md, schema), then re-run forge-5.",
146
+ "description": "Shown when preconditionFile is missing — how to set up the runner IN THIS PROJECT (per-project artifacts)."
147
+ },
148
+ "installHint": {
149
+ "type": "string",
150
+ "default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned rauf@0.6.0 default). Or install/upgrade just the rauf CLI: `curl -fsSL https://raw.githubusercontent.com/garygentry/rauf/main/scripts/install-binary.sh | bash`.",
151
+ "description": "Shown when the runner BINARY is missing or too old (version gate fails, minRunnerVersion floor) — how to obtain/upgrade the CLI itself. Names two distinct binary-provisioning paths: (1) the cross-agent installer (`npx @garygentry/feature-forge install`, the multi-agent provisioning path that pins rauf@0.6.0), and (2) the direct rauf-CLI install/upgrade one-liner. Distinct from setupHint (which installs per-project artifacts); a version-gate failure is ALWAYS this hint, never setupHint."
152
+ },
153
+ "schemaVersion": {
154
+ "type": "string",
155
+ "default": "1",
156
+ "description": "Backlog schemaVersion this runner config targets."
157
+ },
158
+ "minRunnerVersion": {
159
+ "type": "string",
160
+ "default": "0.6.0",
161
+ "description": "Minimum runner version (semver). 0.6.0 is the AGENT-SURFACE FLOOR: the rauf version that ships the coding-agent selection surface (the --agent flag, the `agents` availability probe, and the preset agent registry) that this config's agentArgument/agentsProbeCommand consume. Flooring here guarantees a successful gate implies those surfaces exist. (0.5.0 was the prior grammar/contract-flip floor — unified exit codes, `loop run --detached`, explicit `review` signal, versioned events.ndjson — which predates the agent surface and so could not guarantee it.) forge-5 enforces this via versionCommand before any loop side-effects."
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Feature Forge Pipeline State",
4
+ "description": "Tracks pipeline progress for a single feature across sessions. Lives at {specsDir}/{feature}/.pipeline-state.json",
5
+ "type": "object",
6
+ "required": ["feature", "createdAt", "updatedAt", "currentStage", "stages", "pipelineStatus"],
7
+ "properties": {
8
+ "pipelineStatus": {
9
+ "type": "string",
10
+ "enum": ["active", "paused", "abandoned"],
11
+ "default": "active"
12
+ },
13
+ "feature": {
14
+ "type": "string",
15
+ "description": "Feature name (matches directory name under specsDir)"
16
+ },
17
+ "epic": {
18
+ "type": "string",
19
+ "description": "Back-pointer to the owning epic's name. Absent for standalone features. The epic-manifest.json is canonical on conflict (REQ-STATE-01)."
20
+ },
21
+ "createdAt": {
22
+ "type": "string",
23
+ "format": "date-time"
24
+ },
25
+ "updatedAt": {
26
+ "type": "string",
27
+ "format": "date-time"
28
+ },
29
+ "currentStage": {
30
+ "type": "string",
31
+ "enum": ["forge-1-prd", "forge-2-tech", "forge-3-specs", "forge-4-backlog", "forge-5-loop", "forge-6-docs", "complete", "forge-verify-prd", "forge-verify-tech", "forge-verify-specs", "forge-verify-backlog", "forge-verify-impl", "forge-0-epic", "forge-verify-epic"],
32
+ "description": "The stage currently in progress or next to start"
33
+ },
34
+ "notes": {
35
+ "type": "string",
36
+ "description": "Free-form notes persisted between sessions (user can add context before stepping away)"
37
+ },
38
+ "stages": {
39
+ "type": "object",
40
+ "properties": {
41
+ "forge-0-epic": { "$ref": "#/definitions/stageEntry" },
42
+ "forge-verify-epic": { "$ref": "#/definitions/verifyEntry" },
43
+ "forge-1-prd": { "$ref": "#/definitions/stageEntry" },
44
+ "forge-2-tech": { "$ref": "#/definitions/stageEntry" },
45
+ "forge-3-specs": { "$ref": "#/definitions/stageEntry" },
46
+ "forge-verify-specs": { "$ref": "#/definitions/verifyEntry" },
47
+ "forge-4-backlog": { "$ref": "#/definitions/stageEntry" },
48
+ "forge-verify-backlog": { "$ref": "#/definitions/verifyEntry" },
49
+ "forge-5-loop": { "$ref": "#/definitions/stageEntry" },
50
+ "forge-6-docs": { "$ref": "#/definitions/stageEntry" },
51
+ "forge-verify-impl": { "$ref": "#/definitions/verifyEntry" },
52
+ "forge-verify-prd": { "$ref": "#/definitions/verifyEntry" },
53
+ "forge-verify-tech": { "$ref": "#/definitions/verifyEntry" }
54
+ }
55
+ }
56
+ },
57
+ "definitions": {
58
+ "stageEntry": {
59
+ "type": "object",
60
+ "required": ["status"],
61
+ "properties": {
62
+ "status": {
63
+ "type": "string",
64
+ "enum": ["pending", "in-progress", "complete", "stale"]
65
+ },
66
+ "version": {
67
+ "type": "integer",
68
+ "description": "Incremented each time this stage's artifacts are revised"
69
+ },
70
+ "artifacts": {
71
+ "type": "array",
72
+ "items": { "type": "string" },
73
+ "description": "Relative paths to artifacts produced by this stage"
74
+ },
75
+ "startedAt": { "type": ["string", "null"], "format": "date-time" },
76
+ "completedAt": { "type": ["string", "null"], "format": "date-time" },
77
+ "commitHash": {
78
+ "type": ["string", "null"],
79
+ "description": "Git commit SHA after this stage completed"
80
+ },
81
+ "basedOnVersions": {
82
+ "type": "object",
83
+ "description": "Upstream stage versions this artifact was built against",
84
+ "additionalProperties": { "type": "integer" }
85
+ }
86
+ }
87
+ },
88
+ "verifyEntry": {
89
+ "type": "object",
90
+ "required": ["status"],
91
+ "properties": {
92
+ "status": {
93
+ "type": "string",
94
+ "enum": ["pending", "passed", "findings-reported", "findings-applied", "skipped"]
95
+ },
96
+ "findingsFile": {
97
+ "type": ["string", "null"],
98
+ "description": "Path to the verification findings document"
99
+ },
100
+ "findingsCount": {
101
+ "type": ["integer", "null"],
102
+ "description": "Number of findings reported"
103
+ },
104
+ "verifiedAt": { "type": ["string", "null"], "format": "date-time" },
105
+ "fixedAt": { "type": ["string", "null"], "format": "date-time" },
106
+ "commitHash": { "type": ["string", "null"] }
107
+ }
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,56 @@
1
+ # Portable Script-Root Resolution
2
+
3
+ This file is the **single canonical home** of the feature-forge bootstrap prelude and the
4
+ portable invocation convention. Each fenced shell block an agent runs is a separate process
5
+ with no persisted state, so the plugin root must be re-resolved within the same block as every
6
+ bundled-script call. The prelude below is the fixed, byte-identical snippet that does this by
7
+ discovering and delegating to `scripts/forge-root.sh`. Downstream consumers
8
+ (`forge-agent-adapters-build`, `cross-agent-installer`) and the spec-purity checker treat this
9
+ file as authoritative: the checker's rule 5 compares every prelude occurrence across the canon
10
+ against the fenced block here, byte-for-byte.
11
+
12
+ ## Canonical bootstrap prelude
13
+
14
+ ```bash
15
+ R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
16
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Prepend the prelude to a fenced shell block once, then invoke bundled scripts via `$R`:
22
+ `python3 "$R/scripts/<x>"` or `bash "$R/scripts/<x>"`. One prelude per fenced block — if a block
23
+ makes several calls, add the prelude once and reuse `$R` for each. A fresh block gets its own
24
+ prelude (per-block re-resolution). Worked example:
25
+
26
+ ```bash
27
+ R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
28
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
29
+ python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
30
+ ```
31
+
32
+ ## Invariants (do NOT "fix" these)
33
+
34
+ 1. **Probes paths, not the env var.** The prelude's `for d in …` enumerates directory paths to
35
+ locate an executable `forge-root.sh`; it contains no plugin-root environment variable. That is what lets
36
+ a prelude occurrence satisfy the "zero residual var in canonical surfaces" rule while staying
37
+ portable.
38
+ 2. **First-discoverable-resolver-wins.** The `exec` inside the `$(…)` command substitution means
39
+ the loop stops at the first directory holding an executable `forge-root.sh` and delegates ALL
40
+ final root resolution to that script. The `for` list is a discovery order for `forge-root.sh`
41
+ itself, not a fallback chain for the plugin root. Removing the `exec` to "keep looping" is a
42
+ regression — once `exec`'d, the loop is replaced by the resolver process and never advances.
43
+ 3. **Prelude candidate set is a minimal `$HOME` bootstrap subset.** The prelude's `for d` list
44
+ exists only to bootstrap-discover `forge-root.sh`; the authoritative multi-root probe lives in
45
+ `forge-root.sh` step 2. When adding an install root, update `forge-root.sh` first; extend the
46
+ prelude only if the new root is needed to bootstrap-discover `forge-root.sh` itself.
47
+
48
+ ## The resolver
49
+
50
+ The prelude delegates to [`scripts/forge-root.sh`](../scripts/forge-root.sh) — the portable
51
+ skill/plugin-root resolver. It takes no arguments, prints the absolute plugin root to stdout and
52
+ exits `0`, or writes an actionable message to stderr and exits `1`. It resolves the root by
53
+ self-location → candidate-root probe → plugin-root environment-variable fallback → actionable failure,
54
+ and never sources or executes a discovered path — it only ever prints a directory string. The
55
+ spec-purity checker (rule 5) enforces that every prelude occurrence across the canon is
56
+ byte-identical to the fenced block in this file.