@garygentry/feature-forge 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +1 -1
  2. package/adapters/GENERATION-REPORT.md +5 -1
  3. package/adapters/claude/references/forge-config-schema.json +36 -10
  4. package/adapters/claude/references/pipeline-state-schema.json +4 -0
  5. package/adapters/claude/references/process-overview.md +14 -4
  6. package/adapters/claude/references/shared-conventions.md +46 -0
  7. package/adapters/claude/references/templates/specs-hygiene/AGENTS.md +23 -0
  8. package/adapters/claude/references/templates/specs-hygiene/CLAUDE.md +22 -0
  9. package/adapters/claude/skills/forge-0-epic/SKILL.md +7 -5
  10. package/adapters/claude/skills/forge-1-prd/SKILL.md +4 -2
  11. package/adapters/claude/skills/forge-5-loop/SKILL.md +18 -16
  12. package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +13 -0
  13. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +40 -0
  14. package/adapters/claude/skills/forge-6-docs/SKILL.md +10 -0
  15. package/adapters/claude/skills/forge-bootstrap/SKILL.md +240 -0
  16. package/adapters/claude/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  17. package/adapters/claude/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  18. package/adapters/claude/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  19. package/adapters/claude/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  20. package/adapters/claude/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  21. package/adapters/claude/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  22. package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
  23. package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
  24. package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  25. package/adapters/claude/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  26. package/adapters/claude/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  27. package/adapters/claude/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  28. package/adapters/claude/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  29. package/adapters/claude/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  30. package/adapters/claude/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  31. package/adapters/claude/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  32. package/adapters/claude/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  33. package/adapters/claude/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  34. package/adapters/claude/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  35. package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  36. package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  37. package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  38. package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  39. package/adapters/codex/references/forge-config-schema.json +36 -10
  40. package/adapters/codex/references/pipeline-state-schema.json +4 -0
  41. package/adapters/codex/references/process-overview.md +14 -4
  42. package/adapters/codex/references/shared-conventions.md +46 -0
  43. package/adapters/codex/references/templates/specs-hygiene/AGENTS.md +23 -0
  44. package/adapters/codex/references/templates/specs-hygiene/CLAUDE.md +22 -0
  45. package/adapters/codex/skills/forge-0-epic/forge-0-epic.md +7 -5
  46. package/adapters/codex/skills/forge-1-prd/forge-1-prd.md +4 -2
  47. package/adapters/codex/skills/forge-5-loop/forge-5-loop.md +18 -16
  48. package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +13 -0
  49. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +40 -0
  50. package/adapters/codex/skills/forge-6-docs/forge-6-docs.md +10 -0
  51. package/adapters/codex/skills/forge-bootstrap/forge-bootstrap.md +239 -0
  52. package/adapters/codex/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  53. package/adapters/codex/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  54. package/adapters/codex/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  55. package/adapters/codex/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  56. package/adapters/codex/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  57. package/adapters/codex/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  58. package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
  59. package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
  60. package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  61. package/adapters/codex/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  62. package/adapters/codex/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  63. package/adapters/codex/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  64. package/adapters/codex/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  65. package/adapters/codex/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  66. package/adapters/codex/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  67. package/adapters/codex/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  68. package/adapters/codex/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  69. package/adapters/codex/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  70. package/adapters/codex/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  71. package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  72. package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  73. package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  74. package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  75. package/adapters/copilot/references/forge-config-schema.json +36 -10
  76. package/adapters/copilot/references/pipeline-state-schema.json +4 -0
  77. package/adapters/copilot/references/process-overview.md +14 -4
  78. package/adapters/copilot/references/shared-conventions.md +46 -0
  79. package/adapters/copilot/references/templates/specs-hygiene/AGENTS.md +23 -0
  80. package/adapters/copilot/references/templates/specs-hygiene/CLAUDE.md +22 -0
  81. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +7 -5
  82. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +4 -2
  83. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +18 -16
  84. package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +13 -0
  85. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +40 -0
  86. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +10 -0
  87. package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +239 -0
  88. package/adapters/copilot/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  89. package/adapters/copilot/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  90. package/adapters/copilot/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  91. package/adapters/copilot/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  92. package/adapters/copilot/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  93. package/adapters/copilot/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  94. package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
  95. package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
  96. package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  97. package/adapters/copilot/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  98. package/adapters/copilot/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  99. package/adapters/copilot/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  100. package/adapters/copilot/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  101. package/adapters/copilot/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  102. package/adapters/copilot/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  103. package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  104. package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  105. package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  106. package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  107. package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  108. package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  109. package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  110. package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  111. package/adapters/cursor/references/forge-config-schema.json +36 -10
  112. package/adapters/cursor/references/pipeline-state-schema.json +4 -0
  113. package/adapters/cursor/references/process-overview.md +14 -4
  114. package/adapters/cursor/references/shared-conventions.md +46 -0
  115. package/adapters/cursor/references/templates/specs-hygiene/AGENTS.md +23 -0
  116. package/adapters/cursor/references/templates/specs-hygiene/CLAUDE.md +22 -0
  117. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +7 -5
  118. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +4 -2
  119. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +18 -16
  120. package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +13 -0
  121. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +40 -0
  122. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +10 -0
  123. package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +240 -0
  124. package/adapters/cursor/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  125. package/adapters/cursor/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  126. package/adapters/cursor/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  127. package/adapters/cursor/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  128. package/adapters/cursor/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  129. package/adapters/cursor/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  130. package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
  131. package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
  132. package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  133. package/adapters/cursor/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  134. package/adapters/cursor/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  135. package/adapters/cursor/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  136. package/adapters/cursor/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  137. package/adapters/cursor/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  138. package/adapters/cursor/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  139. package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  140. package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  141. package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  142. package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  143. package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  144. package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  145. package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  146. package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  147. package/adapters/gemini/gemini-extension.json +4 -0
  148. package/adapters/gemini/references/forge-config-schema.json +36 -10
  149. package/adapters/gemini/references/pipeline-state-schema.json +4 -0
  150. package/adapters/gemini/references/process-overview.md +14 -4
  151. package/adapters/gemini/references/shared-conventions.md +46 -0
  152. package/adapters/gemini/references/templates/specs-hygiene/AGENTS.md +23 -0
  153. package/adapters/gemini/references/templates/specs-hygiene/CLAUDE.md +22 -0
  154. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +7 -5
  155. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +4 -2
  156. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +18 -16
  157. package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +13 -0
  158. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +40 -0
  159. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +10 -0
  160. package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +239 -0
  161. package/adapters/gemini/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  162. package/adapters/gemini/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  163. package/adapters/gemini/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  164. package/adapters/gemini/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  165. package/adapters/gemini/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  166. package/adapters/gemini/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  167. package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
  168. package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
  169. package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  170. package/adapters/gemini/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  171. package/adapters/gemini/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  172. package/adapters/gemini/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  173. package/adapters/gemini/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  174. package/adapters/gemini/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  175. package/adapters/gemini/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  176. package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  177. package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  178. package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  179. package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  180. package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  181. package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  182. package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  183. package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  184. package/dist/manifest.d.ts +1 -1
  185. package/dist/rauf.d.ts +4 -4
  186. package/dist/rauf.js +3 -3
  187. package/dist/types.d.ts +1 -1
  188. package/package.json +1 -1
@@ -0,0 +1,13 @@
1
+ """Entrypoint module."""
2
+
3
+
4
+ def greet(name: str = "world") -> str:
5
+ """Return a greeting for ``name``.
6
+
7
+ Args:
8
+ name: The subject of the greeting.
9
+
10
+ Returns:
11
+ A greeting string.
12
+ """
13
+ return f"Hello from {name}"
@@ -0,0 +1,8 @@
1
+ """Smoke test for the scaffolded baseline."""
2
+
3
+ from {{PKG}}.main import greet
4
+
5
+
6
+ def test_greet() -> None:
7
+ """greet returns the expected greeting."""
8
+ assert greet("world") == "Hello from world"
@@ -0,0 +1,15 @@
1
+ [package]
2
+ name = "{{PKG}}"
3
+ version = "0.0.0"
4
+ edition = "2021"
5
+ description = "{{PURPOSE}}"
6
+
7
+ [lib]
8
+ name = "{{PKG}}"
9
+ path = "src/lib.rs"
10
+
11
+ [[bin]]
12
+ name = "{{PKG}}"
13
+ path = "src/main.rs"
14
+
15
+ [dependencies]
@@ -0,0 +1,7 @@
1
+ //! Library root for the scaffolded baseline.
2
+
3
+ /// Returns the project greeting for `name`.
4
+ #[must_use]
5
+ pub fn greet(name: &str) -> String {
6
+ format!("Hello from {name}")
7
+ }
@@ -0,0 +1,5 @@
1
+ use {{PKG}}::greet;
2
+
3
+ fn main() {
4
+ println!("{}", greet("{{PROJECT_NAME}}"));
5
+ }
@@ -0,0 +1,6 @@
1
+ use {{PKG}}::greet;
2
+
3
+ #[test]
4
+ fn greet_returns_greeting() {
5
+ assert_eq!(greet("world"), "Hello from world");
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "description": "{{PURPOSE}}",
6
+ "type": "module",
7
+ "scripts": {
8
+ "typecheck": "tsc --noEmit",
9
+ "test": "vitest run"
10
+ },
11
+ "devDependencies": {
12
+ "typescript": "^5.4.0",
13
+ "vitest": "^1.6.0"
14
+ }
15
+ }
@@ -0,0 +1,4 @@
1
+ /** Returns the project's greeting. */
2
+ export function greet(name: string = "{{PROJECT_NAME}}"): string {
3
+ return `Hello from ${name}`;
4
+ }
@@ -0,0 +1,6 @@
1
+ import { expect, test } from "vitest";
2
+ import { greet } from "../src/index.js";
3
+
4
+ test("greet returns a greeting", () => {
5
+ expect(greet("world")).toBe("Hello from world");
6
+ });
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "esModuleInterop": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "types": ["vitest/globals"]
12
+ },
13
+ "include": ["src", "test"]
14
+ }
@@ -34,6 +34,10 @@
34
34
  "name": "forge-6-docs",
35
35
  "description": "Generate developer-focused architecture documentation for a forge pipeline feature. Use when user runs /feature-forge:forge-6-docs or asks to generate docs after implementation is complete. Do NOT trigger for general documentation writing, README creation, or doc generation outside the forge pipeline."
36
36
  },
37
+ {
38
+ "name": "forge-bootstrap",
39
+ "description": "Scaffold a brand-new empty repository to a pipeline-ready, green baseline (structure, toolchain, passing lint+test, forge.config.json), then optionally chain into the pipeline. Use when the user runs /feature-forge:forge-bootstrap or asks to bootstrap/scaffold a new empty project for forge. Do NOT trigger on a non-empty repo (that is forge-init), or for general project setup outside the forge pipeline."
40
+ },
37
41
  {
38
42
  "name": "forge-fix",
39
43
  "description": "Apply fixes from the most recent forge-verify findings document. Use when user runs /feature-forge:forge-fix or asks to apply verification fixes for a forge feature. Do NOT trigger for general code fixes, bug fixes, or repairs outside the forge verification workflow."
@@ -15,8 +15,8 @@
15
15
  "description": "Root directory for generated architecture documentation."
16
16
  },
17
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."
18
+ "type": ["string", "null"],
19
+ "description": "Optional override for backlog location. If set, backlog.json is written here instead of with the feature specs. Default behavior (null): backlog.json is written to {specsDir}/{feature}/backlog.json."
20
20
  },
21
21
  "gitCommitAfterStage": {
22
22
  "type": "boolean",
@@ -28,17 +28,27 @@
28
28
  "default": "forge",
29
29
  "description": "Prefix for conventional commit messages, e.g., forge(auth): complete PRD"
30
30
  },
31
- "stack": {
31
+ "branchPerFeature": {
32
+ "type": "boolean",
33
+ "default": true,
34
+ "description": "Offer to create an isolated git branch when a feature/epic starts on the default branch (main/master). Gated only on the project using git — independent of gitCommitAfterStage. When false, forge never prompts for a branch and works on whatever branch is checked out. See the Branch Setup block in references/shared-conventions.md."
35
+ },
36
+ "branchPrefix": {
32
37
  "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'."
38
+ "default": "forge/",
39
+ "description": "Prefix for the branch name suggested by Branch Setup, e.g. 'forge/' yields 'forge/{feature}' or 'forge/{epic}'. Ignored when branchPerFeature is false."
40
+ },
41
+ "stack": {
42
+ "type": ["string", "null"],
43
+ "description": "Detected or configured project stack identifier. Selects guidance from references/stacks/{stack}.md. Set during forge-2-tech or manually (null until then). Examples: 'typescript', 'python', 'go', 'rust'."
34
44
  },
35
45
  "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."
46
+ "type": ["string", "null"],
47
+ "description": "Command to verify type correctness or lint. Null until set. Examples: 'bun run typecheck', 'mypy .', 'go vet ./...'. Used in acceptance criteria and verification."
38
48
  },
39
49
  "testCommand": {
40
- "type": "string",
41
- "description": "Command to run tests. Examples: 'bun test', 'pytest', 'go test ./...'. Used in acceptance criteria and verification."
50
+ "type": ["string", "null"],
51
+ "description": "Command to run tests. Null until set. Examples: 'bun test', 'pytest', 'go test ./...'. Used in acceptance criteria and verification."
42
52
  },
43
53
  "loopIterationMultiplier": {
44
54
  "type": "number",
@@ -46,6 +56,22 @@
46
56
  "minimum": 1,
47
57
  "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
58
  },
59
+ "workspaces": {
60
+ "type": "array",
61
+ "description": "Monorepo members. Absent for single-package projects.",
62
+ "items": {
63
+ "type": "object",
64
+ "required": ["name", "path", "stack"],
65
+ "additionalProperties": false,
66
+ "properties": {
67
+ "name": {"type": "string"},
68
+ "path": {"type": "string", "description": "Repo-relative member dir"},
69
+ "stack": {"type": "string"},
70
+ "typeCheckCommand": {"type": ["string", "null"]},
71
+ "testCommand": {"type": ["string", "null"]}
72
+ }
73
+ }
74
+ },
49
75
  "loopRunner": {
50
76
  "type": "object",
51
77
  "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.",
@@ -147,8 +173,8 @@
147
173
  },
148
174
  "installHint": {
149
175
  "type": "string",
150
- "default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.7.0 default). Or install/upgrade just the rauf CLI: `npx @garygentry/rauf@0.7.0 --version`, or `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 @garygentry/rauf@0.7.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."
176
+ "default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.8.0 default). Or install/upgrade just the rauf CLI: `npx @garygentry/rauf@0.8.0 --version`, or `curl -fsSL https://raw.githubusercontent.com/garygentry/rauf/main/scripts/install-binary.sh | bash`.",
177
+ "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 @garygentry/rauf@0.8.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
178
  },
153
179
  "schemaVersion": {
154
180
  "type": "string",
@@ -18,6 +18,10 @@
18
18
  "type": "string",
19
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
20
  },
21
+ "branch": {
22
+ "type": "string",
23
+ "description": "Git branch this feature's pipeline work is intended to land on, recorded by the Branch Setup block (shared-conventions.md) at the entry stage. Absent when the project isn't a git repo or branchPerFeature is false. Downstream stages and forge-5-loop compare the current branch against this to detect drift back onto the default branch before committing."
24
+ },
21
25
  "createdAt": {
22
26
  "type": "string",
23
27
  "format": "date-time"
@@ -2,12 +2,20 @@
2
2
 
3
3
  This document describes the end-to-end feature development pipeline managed by the feature-forge plugin. All forge skills reference this document to understand the overall flow and their position within it.
4
4
 
5
+ The pipeline compiles a fuzzy feature idea into a machine-executable `backlog.json`. Each stage narrows the idea down and adds structure, verification gates catch gaps before they reach later stages, and a swappable autonomous loop runner (rauf by default) implements the backlog in fresh per-item sessions.
6
+
5
7
  ## Pipeline Stages
6
8
 
7
9
  ```
8
- forge-1-prd → forge-2-tech → forge-3-specs → forge-verify → forge-4-backlog → forge-verify → forge-5-loop → forge-verify → forge-6-docs
10
+ [forge-0-epic] → forge-1-prd → forge-2-tech → forge-3-specs → forge-verify → forge-4-backlog → forge-verify → forge-5-loop → forge-verify → forge-6-docs
11
+ (optional)
9
12
  ```
10
13
 
14
+ ### Stage 0: Epic (`/feature-forge:forge-0-epic <epic>`), optional
15
+ **Input:** A change too large for one feature
16
+ **Output:** `{specsDir}/{epic}/epic-manifest.json` + `EPIC.md` + one member-feature dir per feature
17
+ **Method:** Decomposition interview splitting the change into member features with declared dependencies and `exposes`/`consumes` contracts. Purely additive: single-feature flows are unchanged. See [docs/architecture/epic-orchestration/README.md](../docs/architecture/epic-orchestration/README.md).
18
+
11
19
  ### Stage 1: PRD (`/feature-forge:forge-1-prd <feature>`)
12
20
  **Input:** User's feature idea and domain knowledge
13
21
  **Output:** `{specsDir}/{feature}/PRD.md`
@@ -35,13 +43,13 @@ After verification, fixes can be applied via:
35
43
 
36
44
  ### Stage 4: Backlog (`/feature-forge:forge-4-backlog <feature>`)
37
45
  **Input:** Full spec suite
38
- **Output:** `{specsDir}/{feature}/backlog.json` (or `{backlogDir}/backlog.json` if backlogDir is configured)
46
+ **Output:** `{specsDir}/{feature}/backlog.json` (or `{backlogDir}/{feature}/backlog.json` if backlogDir is configured)
39
47
  **Method:** Generate structured backlog items with spec references, acceptance criteria, and dependencies. Backlog is collocated with feature specs by default.
40
48
 
41
49
  ### Stage 5: Rauf Loop (`/feature-forge:forge-5-loop <feature>`)
42
50
  **Input:** `backlog.json` from Stage 4
43
51
  **Output:** Implemented source code (committed per-item by rauf)
44
- **Method:** Execute the rauf autonomous coding loop against the feature's backlog. Spawns a fresh Claude Code session per backlog item with full spec context.
52
+ **Method:** Execute the autonomous coding loop against the feature's backlog. Spawns a fresh session per backlog item with full spec context. rauf is the default runner but is swappable via the `loopRunner` block in `forge.config.json`; see [`references/ralph-loop-contract.md`](./ralph-loop-contract.md).
45
53
 
46
54
  ### Stage 6: Documentation (`/feature-forge:forge-6-docs <feature>`)
47
55
  **Input:** Specs + implementation
@@ -71,7 +79,9 @@ Read `forge.config.json` from project root for path overrides. See `references/f
71
79
 
72
80
  ## Git Workflow
73
81
 
74
- Recommended: create a `forge/{feature}` branch before starting the pipeline. All forge commits go to this branch. After implementation, merge to your development branch.
82
+ Recommended: forge work lives on an isolated `forge/{feature}` (or `forge/{epic}`) branch so all commits land together and review as one branch. The entry stages (`forge-1-prd`, `forge-0-epic`) detect whether you're on the default branch (main/master) and **strongly recommend** creating that branch when you are — still letting you decline and stay. The chosen branch is recorded in `.pipeline-state.json`, and `forge-5-loop` re-checks it before the autonomous loop starts committing per item. After implementation, merge to your development branch.
83
+
84
+ To customize: `branchPrefix` (default `forge/`) sets the branch name, and `branchPerFeature: false` disables the prompt entirely (forge then works on whatever branch is checked out). Branch Setup is gated only on the project using git — independent of `gitCommitAfterStage`.
75
85
 
76
86
  If you prefer manual commit control, set `gitCommitAfterStage: false` in `forge.config.json`.
77
87
 
@@ -48,6 +48,8 @@ Extract these config values (use defaults if not present):
48
48
  - `backlogDir` (default: null — backlog lives at `{specsDir}/{feature}/backlog.json`; when `backlogDir` is configured, forge-4 composes `{backlogDir}/{feature}/`)
49
49
  - `gitCommitAfterStage` (default: true)
50
50
  - `commitPrefix` (default: `forge`)
51
+ - `branchPerFeature` (default: true)
52
+ - `branchPrefix` (default: `forge/`)
51
53
  - `loopIterationMultiplier` (default: `1.5`)
52
54
  - `loopRunner` (optional object — the loop runner to drive; **defaults to rauf** when absent, with every command templated. See `references/forge-config-schema.json` and `references/ralph-loop-contract.md`.)
53
55
 
@@ -79,6 +81,27 @@ A directory counts as a **feature** only if it directly contains a `.pipeline-st
79
81
 
80
82
  **Compatibility:** for a standalone feature the resolver returns its flat path with no epic logic engaged (REQ-COMPAT-01/02) — standalone-feature behavior is unchanged. A pre-existing latent name collision is reported for manual cleanup by the navigator / forge-verify epic mode (CHECK-E08), not by aborting an unrelated command whose name resolves to exactly one dir (tech-spec §3.4).
81
83
 
84
+ ## Specs Directory Hygiene
85
+
86
+ Whenever a stage creates the specs tree for the first time (the first PRD or epic written under `{specsDir}/`), ensure a spec-directory agent-instruction file exists at the **specsDir root**. This tells coding agents in the project that the specs here are pre-implementation artifacts — not live contracts to enforce against the code. It is **idempotent: never overwrite an existing file** (the project may have edited it).
87
+
88
+ Run this after creating the feature/epic directory, before the stage's git commit:
89
+
90
+ ```bash
91
+ 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)"
92
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
93
+ mkdir -p "<specsDir>"
94
+ [ -f "<specsDir>/AGENTS.md" ] || cp "$R/references/templates/specs-hygiene/AGENTS.md" "<specsDir>/AGENTS.md"
95
+ ```
96
+
97
+ If the host is Claude (the `AskUserQuestion` tool is available), also ensure the Claude-framed variant:
98
+
99
+ ```bash
100
+ [ -f "<specsDir>/CLAUDE.md" ] || cp "$R/references/templates/specs-hygiene/CLAUDE.md" "<specsDir>/CLAUDE.md"
101
+ ```
102
+
103
+ Stage any file this writes (`{specsDir}/AGENTS.md`, and `{specsDir}/CLAUDE.md` when written) as part of the stage's existing git commit.
104
+
82
105
  ## Epic Context Injection
83
106
 
84
107
  After resolving the feature directory, check the feature's `.pipeline-state.json` for an `epic` back-pointer. **If absent, skip this block entirely** (standalone feature — REQ-COMPAT-01; standalone-feature behavior is unchanged). **If present**, load exactly the following context, and nothing transitive (REQ-CTX-01):
@@ -110,6 +133,29 @@ When loading upstream artifacts as prerequisites, check `basedOnVersions` in the
110
133
 
111
134
  > "This stage was built against {upstream} v{old}, but {upstream} is now at v{new}. The current artifacts may be outdated. Consider re-running this stage, or use --force to proceed with potentially stale inputs."
112
135
 
136
+ ## Branch Setup
137
+
138
+ Invoke this block at the **very start** of a pipeline entry point — `forge-1-prd` (standalone feature) and `forge-0-epic` (epic) — **before** any directory resolution or interview, so the rest of the run lands on the intended branch. `{label}` is the feature name (forge-1-prd) or epic name (forge-0-epic); `{scope}` is `feature` or `epic` correspondingly.
139
+
140
+ **Gate.** Run this block only when the project uses git (a `.git` directory resolves) **and** `branchPerFeature` is true. It is **independent of `gitCommitAfterStage`** — branch isolation matters whether or not forge auto-commits. If `branchPerFeature` is false, skip silently.
141
+
142
+ **Epic-member inheritance.** In `forge-1-prd`, if the feature has an `epic` back-pointer (an `epic` field resolves via Epic Context Injection, or the directory is nested under an epic), the epic already established the branch in `forge-0-epic`. Skip the prompt — inherit the current branch.
143
+
144
+ **Detection, then a branch-aware prompt:**
145
+
146
+ 1. Read the current branch: `git rev-parse --abbrev-ref HEAD`.
147
+ 2. Determine the default branch: `git symbolic-ref --quiet refs/remotes/origin/HEAD` (strip to the last path segment); if that fails, fall back to `main`, else `master` — whichever the repo has.
148
+ 3. **If the current branch is NOT the default branch** (the user is already on a topic/`{branchPrefix}*` branch) → record it (see below) and proceed silently. Do not prompt.
149
+ 4. **If the current branch IS the default branch** → use `AskUserQuestion` with a **strong recommendation** (still optional):
150
+
151
+ > "You're on `{defaultBranch}`. Strongly recommended: create `{branchPrefix}{label}` so this {scope}'s work stays isolated and reviewable as one branch. Create it?"
152
+ > Options: **Create `{branchPrefix}{label}` (recommended)** · **Stay on `{defaultBranch}`**
153
+
154
+ - **Create** → `git switch -c {branchPrefix}{label}` (or `git checkout -b` if `switch` is unavailable). If the branch already exists, `git switch {branchPrefix}{label}`.
155
+ - **Stay** → proceed on the default branch; note that subsequent commits (and any `forge-5-loop` run) will land directly on `{defaultBranch}`.
156
+
157
+ **Record the branch.** After this block resolves, write the resulting branch name to the feature's `.pipeline-state.json` top-level `branch` field (create/update it when the state file is first written for this stage). Downstream stages and `forge-5-loop` read it to detect drift back onto the default branch.
158
+
113
159
  ## Git Commit Protocol
114
160
 
115
161
  When `gitCommitAfterStage` is true, follow this exact order to avoid state inconsistency:
@@ -0,0 +1,23 @@
1
+ # Agent Instructions — `specs/` (feature-forge)
2
+
3
+ This directory holds **pre-implementation design artifacts** produced by the
4
+ feature-forge pipeline (PRDs, technical specs, numbered implementation specs,
5
+ traceability matrices, and per-feature `backlog.json` files).
6
+
7
+ ## How to treat these specs
8
+
9
+ - **Specs are not live contracts.** They exist to plan the work and establish the
10
+ backlog. They are intentionally **not kept in sync** with the implementation as
11
+ the code evolves.
12
+ - **Do not flag spec↔code divergence.** Once a spec is finalized and its backlog has
13
+ been implemented, the code is the source of truth for behavior. Do not "fix" the
14
+ implementation to match a spec, or the spec to match the code, unless a human
15
+ explicitly asks for it.
16
+ - **Read freely; reference deliberately.** It is fine — encouraged, even — for
17
+ pipeline artifacts here (specs, `backlog.json`) to cite each other for provenance
18
+ and context. But implementation artifacts shipped into the project (source code,
19
+ generated skills/agents, configs, docs) should be self-contained and should **not**
20
+ reference files under `specs/`, which may be archived or deleted after a feature
21
+ ships.
22
+
23
+ This file was generated by feature-forge. Edit or remove it to suit your project.
@@ -0,0 +1,22 @@
1
+ # Claude Instructions — `specs/` (feature-forge)
2
+
3
+ This directory holds **pre-implementation design artifacts** produced by the
4
+ feature-forge pipeline (PRDs, technical specs, numbered implementation specs,
5
+ traceability matrices, and per-feature `backlog.json` files).
6
+
7
+ ## How to treat these specs
8
+
9
+ - **Specs are not live contracts.** They exist to plan the work and establish the
10
+ backlog. They are intentionally **not kept in sync** with the implementation as
11
+ the code evolves.
12
+ - **Do not flag spec↔code divergence.** Once a spec is finalized and its backlog has
13
+ been implemented, the code is the source of truth for behavior. Don't "fix" the
14
+ implementation to match a spec, or the spec to match the code, unless I explicitly
15
+ ask you to.
16
+ - **Read freely; reference deliberately.** It's fine — encouraged, even — for pipeline
17
+ artifacts here (specs, `backlog.json`) to cite each other for provenance and context.
18
+ But implementation artifacts shipped into the project (source code, generated
19
+ skills/agents, configs, docs) should be self-contained and should **not** reference
20
+ files under `specs/`, which may be archived or deleted after a feature ships.
21
+
22
+ This file was generated by feature-forge. Edit or remove it to suit your project.
@@ -86,11 +86,13 @@ python3 "$R/scripts/epic-manifest.py" check-name "{epic}" --specs-dir "{specsDir
86
86
 
87
87
  ## Creation Branch
88
88
 
89
- ### Step 1 — Branch Setup (optional)
89
+ ### Step 1 — Branch Setup
90
90
 
91
- If `gitCommitAfterStage` is true and the project uses git, use `AskUserQuestion`:
92
- "Create a `forge/{epic}` branch for this epic? (Recommended keeps epic work isolated.)"
93
- If yes, create and checkout the branch before proceeding.
91
+ Invoke the **Branch Setup** block in `references/shared-conventions.md` with `{label}` = `{epic}` and
92
+ `{scope}` = `epic`. It self-gates (skips when not a git repo or when `branchPerFeature` is false),
93
+ detects whether you're on the default branch, and strongly recommends — still optionally — creating
94
+ `{branchPrefix}{epic}` when you are. Each member feature's `forge-1-prd` inherits this branch rather
95
+ than prompting again.
94
96
 
95
97
  ### Step C1 — Epic Framing Interview
96
98
 
@@ -175,7 +177,7 @@ Compose the full `epic-manifest.json` per the 00 §2 schema, setting:
175
177
 
176
178
  Write the composed JSON to `{specsDir}/{epic}/epic-manifest.json` (creating the epic dir first).
177
179
  For the *initial* creation write the skill writes the file directly — atomic guarantees are only
178
- required for in-place mutation, which is the helper mutators' job. Then validate:
180
+ 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:
179
181
 
180
182
  ```bash
181
183
  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)"
@@ -15,7 +15,7 @@ Read and follow `references/shared-conventions.md` for feature name validation,
15
15
  ## Step 1: Read Configuration and Check State
16
16
 
17
17
  ### Branch Setup (if using git)
18
- If `gitCommitAfterStage` is true and the project uses git, use `AskUserQuestion` to offer: "Want me to create a `forge/{feature}` branch for this pipeline? (Recommendedkeeps forge work isolated.)" If yes, create and checkout the branch before proceeding.
18
+ Invoke the **Branch Setup** block in `references/shared-conventions.md` with `{label}` = `{feature}` and `{scope}` = `feature`. It self-gates (skips when not a git repo, when `branchPerFeature` is false, or for an epic member that inherits the epic's branch), detects whether you're on the default branch, and strongly recommends still optionally creating `{branchPrefix}{feature}` when you are. Do this before directory resolution.
19
19
 
20
20
  Set the working directory by invoking the **Feature Directory Resolution** block in `references/shared-conventions.md`, which yields `{resolvedFeatureDir}`. Note one PRD-specific caveat: at PRD time a brand-new standalone feature may have NO directory yet, so resolution is expected to fail `not-found` for a never-started standalone feature — in that case forge-1 creates `{specsDir}/{feature}/` as today. For an epic member the directory already exists (created empty by forge-0-epic with an `epic` back-pointer), so resolution succeeds and yields the nested path.
21
21
 
@@ -86,6 +86,8 @@ Once the interview is thorough, write `{resolvedFeatureDir}/PRD.md` following th
86
86
 
87
87
  Every requirement MUST have a unique ID (e.g., REQ-AUTH-01, REQ-PERF-01). These IDs are referenced by all downstream documents.
88
88
 
89
+ After writing the PRD (this is the point where `{specsDir}/{feature}/` is first created for a standalone feature), invoke the **Specs Directory Hygiene** block in `references/shared-conventions.md` to ensure `{specsDir}/AGENTS.md` (and `{specsDir}/CLAUDE.md` on the Claude host) exists. It is idempotent — it never overwrites an existing file.
90
+
89
91
  ## Step 5: Review with User
90
92
 
91
93
  Present the complete PRD to the user. Ask:
@@ -109,7 +111,7 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
109
111
  - Check downstream stages (`forge-2-tech`, `forge-3-specs`, `forge-4-backlog`, `forge-5-loop`, `forge-6-docs`). If any have `basedOnVersions` referencing an older version of `forge-1-prd`, set their status to `stale`.
110
112
  2. Use `AskUserQuestion` to ask: "Anything you want to note before we wrap? (preserved across sessions)"
111
113
  - If yes, store in the `notes` field
112
- 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"`, then set `stages.forge-1-prd.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
114
+ 3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (including `{specsDir}/AGENTS.md` / `{specsDir}/CLAUDE.md` if the Specs Directory Hygiene step just wrote them), attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"`, then set `stages.forge-1-prd.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
113
115
  5. Tell the user: "PRD complete. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the PRD\n - `/feature-forge:forge-2-tech {feature}` to start the tech spec\n - `/feature-forge:forge {feature}` to see full pipeline status"
114
116
 
115
117
  ## Gotchas
@@ -100,13 +100,8 @@ For the version-too-old case, phrase it concretely, e.g.: "Your rauf is {reporte
100
100
 
101
101
  Check that `loopRunner.preconditionFile` (default `.rauf.json`) exists in the project root. If not:
102
102
 
103
- - **If `loopRunner.name == "rauf"` and a legacy `.ralph.json` (or `.ralph/` directory) exists**, this is an un-migrated Ralph project. STOP and tell the user:
104
-
105
- "This project is still on the legacy **Ralph** layout. Run `rauf migrate .` first (the loop runner only understands `.rauf/` and `RAUF_*` signals), then re-run `/feature-forge:forge-5-loop {feature}`."
106
-
107
- - **Otherwise**, STOP and show `loopRunner.setupHint` (default: "Run `rauf install .` …"), e.g.:
108
-
109
- "The loop runner isn't set up in this project ({preconditionFile} is missing). {setupHint}"
103
+ - **If `loopRunner.name == "rauf"` and a legacy `.ralph.json` (or `.ralph/` directory) exists**, this is an un-migrated Ralph project. STOP: "This project is still on the legacy **Ralph** layout. Run `rauf migrate .` first (the loop runner only understands `.rauf/` and `RAUF_*` signals), then re-run `/feature-forge:forge-5-loop {feature}`."
104
+ - **Otherwise**, STOP and show `loopRunner.setupHint` (default: "Run `rauf install .` …"), e.g. "The loop runner isn't set up in this project ({preconditionFile} is missing). {setupHint}"
110
105
 
111
106
  ### 1e. Backlog File Check
112
107
 
@@ -116,6 +111,10 @@ Resolve the backlog file path (matching forge-4-backlog's composition rule, item
116
111
 
117
112
  Verify the file exists on disk. If not, STOP and tell the user: "No backlog.json found at {path}. Run `/feature-forge:forge-4-backlog {feature}` to generate it."
118
113
 
114
+ ### 1f. Branch Pre-flight (if using git)
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 `AskUserQuestion` (offer **switch back** or **proceed here**). Otherwise, if the current branch **is** the default, strongly recommend via `AskUserQuestion` 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.
117
+
119
118
  ## Step 2: Construct the Loop Command
120
119
 
121
120
  ### 2a. Analyze Backlog
@@ -179,6 +178,7 @@ For the full loop-runner contract — event-stream vs. log-fallback launch, the
179
178
  - **(b) Agent question.** Add an **"agent"** question to the same `AskUserQuestion` surface: **one option per advertised row** labelled `"{displayName} ({id}) — available/not found"`, **plus an explicit `"default (claude-cli)"` choice mapping to `run_selection = None`**. Resolve the pick (run > project, empty/whitespace unset, an explicit runner-default pick collapses to the default path) into `{resolved.agent, resolved.source}`. Precedence: `item.provider > --agent > project defaultAgent > runner default` (forge never reads a backlog item's provider).
180
179
  - **(c) Availability listing.** From the **same** parsed `agents[]` (no second probe), list `id` / `displayName` / available (`yes`/`no`, `detail` on unavailable rows).
181
180
  - **(d) Verdict** — only for a **non-default** resolved agent (default path `None`/`claude-cli` → no probe, byte-identical to today). Classify by **membership** then `available` (never by exit code): **UNKNOWN** (`∉` set) → **hard-reject BEFORE any loop side-effect**, error lists the **sorted** valid ids, **NO proceed-anyway**; **UNAVAILABLE** (member, `available False`) → warn with `detail`, `AskUserQuestion` offering **proceed-anyway OR choose-another** (re-presents the same `agents[]`), never silent; **AVAILABLE** → proceed, the validated id fills `{agent}`; **probe failure** (non-zero exit / unparseable / missing or empty `agents[]` / row lacking `id`) → surface it, offer **choose-another OR abort**, **never launch the non-default agent unvalidated** and never silently fall back to the default.
181
+ - **(d-model) Claude-only model-alias guard.** Runs **only** when the resolved agent is **non-default** (not the default / `claude-cli` path). Read the backlog.json (Step 1e path); collect items whose `model` is a **Claude-specific alias** (tier `opus`/`sonnet`/`haiku` or a `claude-*` id). **If none, skip silently.** Otherwise warn before launch via `AskUserQuestion` (NOT prose): `item.model` outranks `--agent`, so the alias is forwarded verbatim to `{agent}`, which will likely reject it (e.g. codex 400 *"The 'sonnet' model is not supported…"*) — every spawn exits 1 and rauf circuit-breaks (*"3 consecutive infra failures — halting"*) with no hint of the cause. Offer: **(1) Strip `model` for this run (recommended)** — rewrite backlog.json removing the `model` key from each affected item (persistent edit; re-run forge-4-backlog to restore), then proceed; **(2) Proceed as-is** — only safe if `{agent}` understands the pinned ids. forge touches only `model`, never `provider`. Full rationale: `references/runner-contract.md`.
182
182
  - **(e) Optional-flags line.** Replace the confirmation's optional-flags line with one that lists `--agent <id>` first plus the agent precedence pointer (`item.provider > --agent > project defaultAgent > runner default`) alongside the model precedence.
183
183
  - **(f) Resolved-agent line.** Add to the confirmation block: `Agent: {resolved.agent or claude-cli} (source: {sourceLabel})` — `sourceLabel`: `RUN` → `"per-run selection"`, `PROJECT` → `"project default (loopRunner.defaultAgent)"`, `DEFAULT` → `"runner default — claude-cli"`.
184
184
 
@@ -192,11 +192,11 @@ Before launching, update `{resolvedFeatureDir}/.pipeline-state.json`:
192
192
  - Set `currentStage` to `forge-5-loop`
193
193
  - Update `updatedAt`
194
194
 
195
- ### 3b. Launch Background Process
195
+ Then commit this state write before launching (mandatory). The runner refuses to run with uncommitted changes (*"…pass --force"*), and this marker is itself one — so an otherwise-clean repo fails its first launch unless committed. Commit it via the shared-conventions **Git Commit Protocol** (epic members: stage `{specsDir}/{epic}/`): `{commitPrefix}({feature}): forge-5-loop in-progress` — a launch precondition, required regardless of `gitCommitAfterStage`. Unrelated leftover changes still trip the refusal; surface it, never auto-pass `--force`. See `references/runner-contract.md`.
196
196
 
197
- Launch the loop **backgrounded** (`run_in_background: true`) so it survives session end and does not block the session, and prefer the machine-readable event stream (`loopRunner.eventStreamCommand`, default for rauf) redirected to a stable `events.ndjson` so the session can supervise it live; fall back to the plain `runCommand` (tailing the human log) when no `eventStreamCommand` is configured. The background task's exit notification is the single authoritative terminal signal (Step 4). For the exact launch commands (incl. the `mkdir -p` state-dir guard) and the event-stream vs. log-fallback detail, read `references/runner-contract.md`.
197
+ ### 3b. Launch Background Process
198
198
 
199
- Loop runs can take significant time (minutes to hours depending on backlog size).
199
+ Launch the loop **backgrounded** (`run_in_background: true`) so it survives session end and does not block the session, and prefer the machine-readable event stream (`loopRunner.eventStreamCommand`, default for rauf) redirected to a stable `events.ndjson` so the session can supervise it live; fall back to the plain `runCommand` (tailing the human log) when no `eventStreamCommand` is configured. The background task's exit notification is the single authoritative terminal signal (Step 4). Loop runs can take significant time (minutes to hours depending on backlog size). For the exact launch commands (incl. the `mkdir -p` state-dir guard) and the event-stream vs. log-fallback detail, read `references/runner-contract.md`.
200
200
 
201
201
  ### 3c. Inform User
202
202
 
@@ -245,7 +245,7 @@ Run the **status-json command** (`loopRunner.statusJsonCommand`) and read
245
245
  `backlogSummary` for the authoritative counts — it separates the three non-done
246
246
  outcomes: genuine `blocked`, `needsHuman`, and runner-`deferred` ("false blocks").
247
247
  Fall back to the **list command** (`loopRunner.listCommand`) if `statusJsonCommand`
248
- is not configured. You will already have most of this from the live tally in 3e.
248
+ is not configured. You will already have most of this from the live tally in 3e. If the run used a review flag (e.g. rauf's `--review`), also read any `review_completed` event (event stream, or `{loopRunner.stateDir}/events.ndjson`) for its `itemsCreated`/`summary` to surface in 4b — see `references/result-reporting.md`.
249
249
 
250
250
  ### 4b. Report Results
251
251
 
@@ -266,13 +266,15 @@ Update `{resolvedFeatureDir}/.pipeline-state.json`:
266
266
  2. If all items complete: set `currentStage` to `"forge-6-docs"`
267
267
  3. Update `updatedAt`
268
268
 
269
- **No git commit is needed** — the loop runner commits atomically per completed item during the run. The implementation code is already committed.
269
+ **No git commit is needed** — the loop runner commits implementation code atomically per completed item during the run. (Step 6's commit, epic members only, is of pipeline state / manifest — a distinct artifact.)
270
+
271
+ ## Step 5b: Offer Impl-Verify (standalone path)
270
272
 
271
- > **Note:** Step 5's "no git commit needed" remark refers to *implementation code*, which the runner commits per-item. The epic handoff's commit in Step 6 below is of *pipeline state / manifest* a distinct artifact and applies only to epic members.
273
+ **Gate:** run only if (a) the feature's `.pipeline-state.json` has **no** `epic` key **and** (b) Step 5 set `stages.forge-5-loop.status` to `complete`. Otherwise **skip** partial runs end as today, and epic members get the equivalent offer in Step 6.1 (do **not** prompt twice). This standalone counterpart to Step 6.1 nudges verification interactively rather than via the easily-missed "Next steps" text. Use `AskUserQuestion` (NOT inline prose) to offer: *"{feature}'s loop is complete. Recommended: run `/feature-forge:forge-verify {feature} impl` to audit the implementation before generating docs. Run it now, or skip to forge-6-docs?"* On **run**, hand off to `/feature-forge:forge-verify {feature} impl`. On **skip**, record `stages.forge-verify-impl.status` as `"skipped"` (mirrors `forge-4-backlog`'s skip handling) and point the user at `/feature-forge:forge-6-docs {feature}` — the forge-6-docs backstop re-surfaces the skip.
272
274
 
273
275
  ## Step 6: Epic Handoff
274
276
 
275
- **Gate:** only run this step if (a) the resolved feature's `.pipeline-state.json` has an `epic` key **and** (b) Step 5 set `stages.forge-5-loop.status` to `complete` (all backlog items done). If either is false, **skip** — standalone features and partial runs end exactly as today (REQ-COMPAT-01).
277
+ **Gate:** only run this step if (a) the resolved feature's `.pipeline-state.json` has an `epic` key **and** (b) Step 5 set `stages.forge-5-loop.status` to `complete` (all backlog items done). If either is false, **skip** — standalone completed features are handled by Step 5b, and partial runs end as today (REQ-COMPAT-01).
276
278
 
277
279
  1. **Offer impl-verify first (recommended, skippable).** Per the completion rule (`00-core-definitions.md §7`), a feature whose `forge-verify-impl.status == findings-reported` does **not** unblock dependents. Use `AskUserQuestion` (NOT inline prose) to offer:
278
280
 
@@ -296,7 +298,7 @@ Update `{resolvedFeatureDir}/.pipeline-state.json`:
296
298
  - rauf resolves `RAUF.md` with fallback: checks `{backlogDir}/.rauf/RAUF.md` first, then the project's `.rauf/RAUF.md`. As long as the runner is installed in the project, the prompt template will be found.
297
299
  - State files (state.json, {loopRunner.logFile}, etc.) are created at `{backlogDir}/{loopRunner.stateDir}/` — this is within the feature's spec directory and is expected. State is isolated per backlog dir, so concurrent features don't collide.
298
300
  - If the session disconnects during a long-running loop, the runner process continues independently. The user can check results later with the status / list commands.
299
- - Never run the run command in the foreground (without `run_in_background`) — it blocks and will hit the Bash tool timeout for any non-trivial backlog. "Don't block the foreground" is NOT "stay silent": supervise via the `Monitor` tool (3d), which is harness-driven, not a sleep loop. Never `sleep`/poll in the foreground to wait for the loop.
300
- - The `Monitor` must use `persistent: true` (not a bounded `timeout_ms`), watch the **structured** surface (`events.ndjson`), and never filter on raw `RAUF_*` tokens — they appear in agent prose and false-match. A `needs_human`/`blocked`/`review` signal does **not** pause the loop — the runner sets the item aside and keeps going; surface it live but don't tell the user the loop is waiting. See `references/runner-contract.md` for the full monitoring rules.
301
+ - Never run the run command in the foreground (without `run_in_background`) — it blocks and will hit the Bash tool timeout for any non-trivial backlog. "Don't block the foreground" is NOT "stay silent": supervise via the `Monitor` tool (3d), never `sleep`/poll in the foreground. The `Monitor` must use `persistent: true` (not a bounded `timeout_ms`), watch the **structured** surface (`events.ndjson`), and never filter on raw `RAUF_*` tokens — they appear in agent prose and false-match. A `needs_human`/`blocked`/`review` signal does **not** pause the loop the runner sets the item aside and keeps going; surface it live but don't tell the user the loop is waiting. See `references/runner-contract.md` for the full monitoring rules.
301
302
  - If a previous loop run left a stale lock, the user may need to pass `--force` to clear it. rauf will report this error clearly.
302
303
  - The version gate (1c) uses the `--json` form on purpose; never parse `rauf version`'s human output.
304
+ - **Implementation artifacts must not cite specs.** The loop should **read** the specs and `backlog.json` freely — they are the source of truth for what to build, and the backlog rightly references specs for provenance. But the artifacts the loop **writes into the target repo** (source code, generated `SKILL.md`/agent files, configs, code comments) must be **self-contained**: they must NOT reference feature-forge spec files (no `See specs/{feature}/NN-*.md`, no "source spec" provenance notes in shipped output). Specs are pre-implementation inputs that may be archived or deleted once the feature ships; the implementation must stand on its own. This applies only to shipped implementation output — never to the backlog or spec documents, which should keep citing specs.
@@ -13,6 +13,19 @@ Next steps:
13
13
  - /feature-forge:forge-6-docs {feature} Generate architecture docs
14
14
  ```
15
15
 
16
+ **Runner review pass.** A review flag (e.g. rauf's `--review`) makes the runner run
17
+ a post-loop review that **auto-creates and implements fix items** rather than handing
18
+ findings to the user — distinct from `forge-verify impl` (a clean-context audit that
19
+ writes a findings doc). When Step 4a captured a `review_completed` event, add a line
20
+ **above** "Next steps" so the pass's effect is visible and not mistaken for "nothing
21
+ happened":
22
+ ```
23
+ Runner review pass: {itemsCreated} fix item(s) created and implemented.
24
+ {summary}
25
+ ```
26
+ Omit this line when no `review_completed` event was emitted (no review flag passed).
27
+ The created items are already counted in the totals above.
28
+
16
29
  **Some items need a human:**
17
30
  ```
18
31
  Loop completed for {feature}.