@garygentry/feature-forge 0.3.2 → 0.3.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 (389) hide show
  1. package/README.md +1 -1
  2. package/adapters/claude/.feature-forge-bundle.json +1 -1
  3. package/adapters/claude/agents/forge-verifier.md +3 -1
  4. package/adapters/claude/references/decisions/single-writer-threat-model.md +53 -0
  5. package/adapters/claude/references/epic-state-schema.json +50 -0
  6. package/adapters/claude/references/forge-config-schema.json +20 -2
  7. package/adapters/claude/references/forge-decisions-schema.json +33 -0
  8. package/adapters/claude/references/pipeline-state-schema.json +34 -2
  9. package/adapters/claude/references/ralph-loop-contract.md +6 -3
  10. package/adapters/claude/references/shared-conventions.md +15 -4
  11. package/adapters/claude/references/stage-exit-protocol.md +55 -11
  12. package/adapters/claude/scripts/epic-manifest.py +82 -4
  13. package/adapters/claude/scripts/fix-sweep.py +1180 -0
  14. package/adapters/claude/scripts/forge-session.py +1151 -32
  15. package/adapters/claude/skills/forge/SKILL.md +5 -5
  16. package/adapters/claude/skills/forge/references/pipeline-state-schema.json +34 -2
  17. package/adapters/claude/skills/forge/references/shared-conventions.md +15 -4
  18. package/adapters/claude/skills/forge/references/stage-exit-protocol.md +55 -11
  19. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +5 -1
  20. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +5 -0
  21. package/adapters/claude/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  22. package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +15 -4
  23. package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +55 -11
  24. package/adapters/claude/skills/forge-1-prd/SKILL.md +3 -1
  25. package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +15 -4
  26. package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +55 -11
  27. package/adapters/claude/skills/forge-2-tech/SKILL.md +5 -1
  28. package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +15 -4
  29. package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +55 -11
  30. package/adapters/claude/skills/forge-3-specs/SKILL.md +5 -1
  31. package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +15 -4
  32. package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +55 -11
  33. package/adapters/claude/skills/forge-4-backlog/SKILL.md +41 -3
  34. package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +15 -4
  35. package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +55 -11
  36. package/adapters/claude/skills/forge-5-loop/SKILL.md +36 -36
  37. package/adapters/claude/skills/forge-5-loop/references/agent-selection.md +16 -0
  38. package/adapters/claude/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  39. package/adapters/claude/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  40. package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +40 -11
  41. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +22 -4
  42. package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +15 -4
  43. package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +55 -11
  44. package/adapters/claude/skills/forge-6-docs/SKILL.md +29 -6
  45. package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +15 -4
  46. package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +55 -11
  47. package/adapters/claude/skills/forge-fix/SKILL.md +34 -0
  48. package/adapters/claude/skills/forge-fix/references/shared-conventions.md +15 -4
  49. package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +55 -11
  50. package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +20 -2
  51. package/adapters/claude/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  52. package/adapters/claude/skills/forge-guide/references/shared-conventions.md +15 -4
  53. package/adapters/claude/skills/forge-verify/SKILL.md +10 -11
  54. package/adapters/claude/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  55. package/adapters/claude/skills/forge-verify/references/findings-template.md +30 -0
  56. package/adapters/claude/skills/forge-verify/references/shared-conventions.md +15 -4
  57. package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +55 -11
  58. package/adapters/claude/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  59. package/adapters/claude/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  60. package/adapters/claude/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  61. package/adapters/codex/.feature-forge-bundle.json +1 -1
  62. package/adapters/codex/agents/forge-verifier.toml +3 -1
  63. package/adapters/codex/references/decisions/single-writer-threat-model.md +53 -0
  64. package/adapters/codex/references/epic-state-schema.json +50 -0
  65. package/adapters/codex/references/forge-config-schema.json +20 -2
  66. package/adapters/codex/references/forge-decisions-schema.json +33 -0
  67. package/adapters/codex/references/pipeline-state-schema.json +34 -2
  68. package/adapters/codex/references/process-overview.md +2 -2
  69. package/adapters/codex/references/ralph-loop-contract.md +6 -3
  70. package/adapters/codex/references/shared-conventions.md +44 -33
  71. package/adapters/codex/references/stage-exit-protocol.md +64 -20
  72. package/adapters/codex/scripts/epic-manifest.py +82 -4
  73. package/adapters/codex/scripts/fix-sweep.py +1180 -0
  74. package/adapters/codex/scripts/forge-session.py +1151 -32
  75. package/adapters/codex/skills/forge/SKILL.md +8 -8
  76. package/adapters/codex/skills/forge/references/pipeline-state-schema.json +34 -2
  77. package/adapters/codex/skills/forge/references/process-overview.md +2 -2
  78. package/adapters/codex/skills/forge/references/shared-conventions.md +44 -33
  79. package/adapters/codex/skills/forge/references/stage-exit-protocol.md +64 -20
  80. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +14 -10
  81. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  82. package/adapters/codex/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  83. package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +44 -33
  84. package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  85. package/adapters/codex/skills/forge-1-prd/SKILL.md +3 -1
  86. package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +44 -33
  87. package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  88. package/adapters/codex/skills/forge-2-tech/SKILL.md +5 -1
  89. package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +44 -33
  90. package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  91. package/adapters/codex/skills/forge-3-specs/SKILL.md +5 -1
  92. package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +44 -33
  93. package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  94. package/adapters/codex/skills/forge-4-backlog/SKILL.md +41 -3
  95. package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  96. package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  97. package/adapters/codex/skills/forge-5-loop/SKILL.md +36 -36
  98. package/adapters/codex/skills/forge-5-loop/references/agent-selection.md +17 -1
  99. package/adapters/codex/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  100. package/adapters/codex/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  101. package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +40 -11
  102. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +26 -8
  103. package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +44 -33
  104. package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  105. package/adapters/codex/skills/forge-6-docs/SKILL.md +29 -6
  106. package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +44 -33
  107. package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  108. package/adapters/codex/skills/forge-fix/SKILL.md +34 -0
  109. package/adapters/codex/skills/forge-fix/references/shared-conventions.md +44 -33
  110. package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  111. package/adapters/codex/skills/forge-guide/SKILL.md +1 -1
  112. package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +20 -2
  113. package/adapters/codex/skills/forge-guide/references/process-overview.md +2 -2
  114. package/adapters/codex/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  115. package/adapters/codex/skills/forge-guide/references/shared-conventions.md +44 -33
  116. package/adapters/codex/skills/forge-init/SKILL.md +1 -1
  117. package/adapters/codex/skills/forge-verify/SKILL.md +11 -12
  118. package/adapters/codex/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  119. package/adapters/codex/skills/forge-verify/references/findings-template.md +32 -2
  120. package/adapters/codex/skills/forge-verify/references/shared-conventions.md +44 -33
  121. package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  122. package/adapters/codex/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  123. package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  124. package/adapters/codex/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  125. package/adapters/codex/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  126. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  127. package/adapters/copilot/agents/forge-verifier.md +3 -1
  128. package/adapters/copilot/references/decisions/single-writer-threat-model.md +53 -0
  129. package/adapters/copilot/references/epic-state-schema.json +50 -0
  130. package/adapters/copilot/references/forge-config-schema.json +20 -2
  131. package/adapters/copilot/references/forge-decisions-schema.json +33 -0
  132. package/adapters/copilot/references/pipeline-state-schema.json +34 -2
  133. package/adapters/copilot/references/process-overview.md +2 -2
  134. package/adapters/copilot/references/ralph-loop-contract.md +6 -3
  135. package/adapters/copilot/references/shared-conventions.md +44 -33
  136. package/adapters/copilot/references/stage-exit-protocol.md +64 -20
  137. package/adapters/copilot/scripts/epic-manifest.py +82 -4
  138. package/adapters/copilot/scripts/fix-sweep.py +1180 -0
  139. package/adapters/copilot/scripts/forge-session.py +1151 -32
  140. package/adapters/copilot/skills/forge/forge.md +8 -8
  141. package/adapters/copilot/skills/forge/references/pipeline-state-schema.json +34 -2
  142. package/adapters/copilot/skills/forge/references/process-overview.md +2 -2
  143. package/adapters/copilot/skills/forge/references/shared-conventions.md +44 -33
  144. package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +64 -20
  145. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +14 -10
  146. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  147. package/adapters/copilot/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  148. package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +44 -33
  149. package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  150. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +3 -1
  151. package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +44 -33
  152. package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  153. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +5 -1
  154. package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +44 -33
  155. package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  156. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +5 -1
  157. package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +44 -33
  158. package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  159. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +41 -3
  160. package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  161. package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  162. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +36 -36
  163. package/adapters/copilot/skills/forge-5-loop/references/agent-selection.md +17 -1
  164. package/adapters/copilot/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  165. package/adapters/copilot/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  166. package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +40 -11
  167. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +26 -8
  168. package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +44 -33
  169. package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  170. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +29 -6
  171. package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +44 -33
  172. package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  173. package/adapters/copilot/skills/forge-fix/forge-fix.md +34 -0
  174. package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +44 -33
  175. package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  176. package/adapters/copilot/skills/forge-guide/forge-guide.md +1 -1
  177. package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +20 -2
  178. package/adapters/copilot/skills/forge-guide/references/process-overview.md +2 -2
  179. package/adapters/copilot/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  180. package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +44 -33
  181. package/adapters/copilot/skills/forge-init/forge-init.md +1 -1
  182. package/adapters/copilot/skills/forge-verify/forge-verify.md +11 -12
  183. package/adapters/copilot/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  184. package/adapters/copilot/skills/forge-verify/references/findings-template.md +32 -2
  185. package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +44 -33
  186. package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  187. package/adapters/copilot/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  188. package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  189. package/adapters/copilot/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  190. package/adapters/copilot/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  191. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  192. package/adapters/cursor/agents/forge-verifier.mdc +3 -1
  193. package/adapters/cursor/references/decisions/single-writer-threat-model.md +53 -0
  194. package/adapters/cursor/references/epic-state-schema.json +50 -0
  195. package/adapters/cursor/references/forge-config-schema.json +20 -2
  196. package/adapters/cursor/references/forge-decisions-schema.json +33 -0
  197. package/adapters/cursor/references/pipeline-state-schema.json +34 -2
  198. package/adapters/cursor/references/process-overview.md +2 -2
  199. package/adapters/cursor/references/ralph-loop-contract.md +6 -3
  200. package/adapters/cursor/references/shared-conventions.md +44 -33
  201. package/adapters/cursor/references/stage-exit-protocol.md +64 -20
  202. package/adapters/cursor/scripts/epic-manifest.py +82 -4
  203. package/adapters/cursor/scripts/fix-sweep.py +1180 -0
  204. package/adapters/cursor/scripts/forge-session.py +1151 -32
  205. package/adapters/cursor/skills/forge/forge.mdc +8 -8
  206. package/adapters/cursor/skills/forge/references/pipeline-state-schema.json +34 -2
  207. package/adapters/cursor/skills/forge/references/process-overview.md +2 -2
  208. package/adapters/cursor/skills/forge/references/shared-conventions.md +44 -33
  209. package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +64 -20
  210. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +14 -10
  211. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  212. package/adapters/cursor/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  213. package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +44 -33
  214. package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  215. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +3 -1
  216. package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +44 -33
  217. package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  218. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +5 -1
  219. package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +44 -33
  220. package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  221. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +5 -1
  222. package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +44 -33
  223. package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  224. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +41 -3
  225. package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  226. package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  227. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +36 -36
  228. package/adapters/cursor/skills/forge-5-loop/references/agent-selection.md +17 -1
  229. package/adapters/cursor/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  230. package/adapters/cursor/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  231. package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +40 -11
  232. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +26 -8
  233. package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +44 -33
  234. package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  235. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +29 -6
  236. package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +44 -33
  237. package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  238. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +34 -0
  239. package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +44 -33
  240. package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  241. package/adapters/cursor/skills/forge-guide/forge-guide.mdc +1 -1
  242. package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +20 -2
  243. package/adapters/cursor/skills/forge-guide/references/process-overview.md +2 -2
  244. package/adapters/cursor/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  245. package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +44 -33
  246. package/adapters/cursor/skills/forge-init/forge-init.mdc +1 -1
  247. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +11 -12
  248. package/adapters/cursor/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  249. package/adapters/cursor/skills/forge-verify/references/findings-template.md +32 -2
  250. package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +44 -33
  251. package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  252. package/adapters/cursor/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  253. package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  254. package/adapters/cursor/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  255. package/adapters/cursor/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  256. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  257. package/adapters/gemini/agents/forge-verifier.md +3 -1
  258. package/adapters/gemini/gemini-extension.json +1 -1
  259. package/adapters/gemini/references/decisions/single-writer-threat-model.md +53 -0
  260. package/adapters/gemini/references/epic-state-schema.json +50 -0
  261. package/adapters/gemini/references/forge-config-schema.json +20 -2
  262. package/adapters/gemini/references/forge-decisions-schema.json +33 -0
  263. package/adapters/gemini/references/pipeline-state-schema.json +34 -2
  264. package/adapters/gemini/references/process-overview.md +2 -2
  265. package/adapters/gemini/references/ralph-loop-contract.md +6 -3
  266. package/adapters/gemini/references/shared-conventions.md +44 -33
  267. package/adapters/gemini/references/stage-exit-protocol.md +64 -20
  268. package/adapters/gemini/scripts/epic-manifest.py +82 -4
  269. package/adapters/gemini/scripts/fix-sweep.py +1180 -0
  270. package/adapters/gemini/scripts/forge-session.py +1151 -32
  271. package/adapters/gemini/skills/forge/forge.md +8 -8
  272. package/adapters/gemini/skills/forge/references/pipeline-state-schema.json +34 -2
  273. package/adapters/gemini/skills/forge/references/process-overview.md +2 -2
  274. package/adapters/gemini/skills/forge/references/shared-conventions.md +44 -33
  275. package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +64 -20
  276. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +14 -10
  277. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  278. package/adapters/gemini/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  279. package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +44 -33
  280. package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  281. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +3 -1
  282. package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +44 -33
  283. package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  284. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +5 -1
  285. package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +44 -33
  286. package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  287. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +5 -1
  288. package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +44 -33
  289. package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  290. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +41 -3
  291. package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  292. package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  293. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +36 -36
  294. package/adapters/gemini/skills/forge-5-loop/references/agent-selection.md +17 -1
  295. package/adapters/gemini/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  296. package/adapters/gemini/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  297. package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +40 -11
  298. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +26 -8
  299. package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +44 -33
  300. package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  301. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +29 -6
  302. package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +44 -33
  303. package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  304. package/adapters/gemini/skills/forge-fix/forge-fix.md +34 -0
  305. package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +44 -33
  306. package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  307. package/adapters/gemini/skills/forge-guide/forge-guide.md +1 -1
  308. package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +20 -2
  309. package/adapters/gemini/skills/forge-guide/references/process-overview.md +2 -2
  310. package/adapters/gemini/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  311. package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +44 -33
  312. package/adapters/gemini/skills/forge-init/forge-init.md +1 -1
  313. package/adapters/gemini/skills/forge-verify/forge-verify.md +11 -12
  314. package/adapters/gemini/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  315. package/adapters/gemini/skills/forge-verify/references/findings-template.md +32 -2
  316. package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +44 -33
  317. package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  318. package/adapters/gemini/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  319. package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  320. package/adapters/gemini/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  321. package/adapters/gemini/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  322. package/adapters/pi/.feature-forge-bundle.json +1 -1
  323. package/adapters/pi/agents/forge-verifier.md +3 -1
  324. package/adapters/pi/references/decisions/single-writer-threat-model.md +53 -0
  325. package/adapters/pi/references/epic-state-schema.json +50 -0
  326. package/adapters/pi/references/forge-config-schema.json +20 -2
  327. package/adapters/pi/references/forge-decisions-schema.json +33 -0
  328. package/adapters/pi/references/pipeline-state-schema.json +34 -2
  329. package/adapters/pi/references/process-overview.md +2 -2
  330. package/adapters/pi/references/ralph-loop-contract.md +6 -3
  331. package/adapters/pi/references/shared-conventions.md +33 -22
  332. package/adapters/pi/references/stage-exit-protocol.md +63 -19
  333. package/adapters/pi/scripts/epic-manifest.py +82 -4
  334. package/adapters/pi/scripts/fix-sweep.py +1180 -0
  335. package/adapters/pi/scripts/forge-session.py +1151 -32
  336. package/adapters/pi/skills/forge/SKILL.md +5 -5
  337. package/adapters/pi/skills/forge/references/pipeline-state-schema.json +34 -2
  338. package/adapters/pi/skills/forge/references/process-overview.md +2 -2
  339. package/adapters/pi/skills/forge/references/shared-conventions.md +33 -22
  340. package/adapters/pi/skills/forge/references/stage-exit-protocol.md +63 -19
  341. package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +8 -4
  342. package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
  343. package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  344. package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +33 -22
  345. package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +63 -19
  346. package/adapters/pi/skills/forge-1-prd/SKILL.md +3 -1
  347. package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +33 -22
  348. package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +63 -19
  349. package/adapters/pi/skills/forge-2-tech/SKILL.md +5 -1
  350. package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +33 -22
  351. package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +63 -19
  352. package/adapters/pi/skills/forge-3-specs/SKILL.md +5 -1
  353. package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +33 -22
  354. package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +63 -19
  355. package/adapters/pi/skills/forge-4-backlog/SKILL.md +41 -3
  356. package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +33 -22
  357. package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +63 -19
  358. package/adapters/pi/skills/forge-5-loop/SKILL.md +36 -36
  359. package/adapters/pi/skills/forge-5-loop/references/agent-selection.md +16 -0
  360. package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  361. package/adapters/pi/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  362. package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +40 -11
  363. package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +25 -7
  364. package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +33 -22
  365. package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +63 -19
  366. package/adapters/pi/skills/forge-6-docs/SKILL.md +29 -6
  367. package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +33 -22
  368. package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +63 -19
  369. package/adapters/pi/skills/forge-fix/SKILL.md +34 -0
  370. package/adapters/pi/skills/forge-fix/references/shared-conventions.md +33 -22
  371. package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +63 -19
  372. package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +20 -2
  373. package/adapters/pi/skills/forge-guide/references/process-overview.md +2 -2
  374. package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  375. package/adapters/pi/skills/forge-guide/references/shared-conventions.md +33 -22
  376. package/adapters/pi/skills/forge-verify/SKILL.md +10 -11
  377. package/adapters/pi/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  378. package/adapters/pi/skills/forge-verify/references/findings-template.md +31 -1
  379. package/adapters/pi/skills/forge-verify/references/shared-conventions.md +33 -22
  380. package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +63 -19
  381. package/adapters/pi/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  382. package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  383. package/adapters/pi/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  384. package/adapters/pi/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  385. package/dist/manifest.d.ts +1 -1
  386. package/dist/rauf.d.ts +3 -3
  387. package/dist/rauf.js +2 -2
  388. package/dist/types.d.ts +1 -1
  389. package/package.json +1 -1
@@ -15,11 +15,11 @@ If no feature name is provided:
15
15
 
16
16
  ## User Input Protocol
17
17
 
18
- ### CRITICAL GUARDRAIL: Use AskUserQuestion for All Questions
18
+ ### CRITICAL GUARDRAIL: Use the host's question mechanism for All Questions
19
19
 
20
- You MUST use the `AskUserQuestion` tool whenever you need the user's input before proceeding. This includes yes/no confirmations, choices between options, interview questions, and feedback on artifacts. NEVER output questions as inline prose text — the user may not be prompted and the session will stall.
20
+ You MUST use the host's question mechanism whenever you need the user's input before proceeding. This includes yes/no confirmations, choices between options, interview questions, and feedback on artifacts. NEVER output questions as inline prose text — the user may not be prompted and the session will stall.
21
21
 
22
- **Required turn structure:** Output your analysis, findings, or context as regular text. Then call `AskUserQuestion` with your questions. Do NOT mix questions into your text output.
22
+ **Required turn structure:** Output your analysis, findings, or context as regular text. Then call the host's question mechanism with your questions. Do NOT mix questions into your text output.
23
23
 
24
24
  **WRONG — questions as inline prose (causes stalling):**
25
25
  ```
@@ -31,14 +31,14 @@ I found that the codebase uses React and TanStack Router. Here are my questions:
31
31
  **RIGHT — context as text, questions via tool:**
32
32
  ```
33
33
  I found that the codebase uses React and TanStack Router.
34
- [then call AskUserQuestion with: "1. Where should this component live? 2. Should we use server-side rendering?"]
34
+ [then call the host's question mechanism with: "1. Where should this component live? 2. Should we use server-side rendering?"]
35
35
  ```
36
36
 
37
37
  ### Decision Support: Help the User Choose
38
38
 
39
- When an `AskUserQuestion` carries substantive options (a real choice — not a trivial yes/no confirmation), do not just list them. The interview stages have already done codebase research and integration analysis; surfacing that synthesis at the decision moment is the whole point. For every such question:
39
+ When a question posed through the host's question mechanism carries substantive options (a real choice — not a trivial yes/no confirmation), do not just list them. The interview stages have already done codebase research and integration analysis; surfacing that synthesis at the decision moment is the whole point. For every such question:
40
40
 
41
- - **Lead with a recommended option.** Place it first and label it `(recommended)` (matching the `AskUserQuestion` "(Recommended)" convention).
41
+ - **Lead with a recommended option.** Place it first and label it `(recommended)` (matching the host's question mechanism "(Recommended)" convention).
42
42
  - **Put the trade-off in each option's `description`.** Say why you'd pick it and what you give up versus the alternatives — the cost, not just the benefit.
43
43
  - **State a one-line rationale** in the text before the question for *why* the recommendation wins.
44
44
 
@@ -49,10 +49,21 @@ Two modes, and make clear which one you're in:
49
49
 
50
50
  **The only thing to avoid is false confidence** — recommending as if evidence-backed when it's really preference. Never respond to the absence of a clear winner by going silent: a defaulted recommendation with honest trade-offs always beats a neutral option dump.
51
51
 
52
- For genuinely comparable artifacts (competing module structures, two code snippets, layout variants), use the `AskUserQuestion` `preview` field to show them side-by-side.
52
+ For genuinely comparable artifacts (competing module structures, two code snippets, layout variants), use the host's question mechanism `preview` field to show them side-by-side.
53
53
 
54
54
  The **Branch Setup** block below is the reference pattern: a strong recommendation as the first option, rationale inline, the alternative still available, never a hard-stop.
55
55
 
56
+ ## Stage Review Gate
57
+
58
+ Every authoring stage ends its "Review with User" step in exactly one of two shapes. Which shape a stage uses is declared **here, once** — each stage's review step points at this block by title, and the shape is never re-derived from the surrounding prose or inferred from how sibling stages behave (three stages block and one does not; majority-shape inference is precisely the failure this block exists to prevent):
59
+
60
+ - **Blocking review (gate).** The stage presents the artifact and collects feedback through the host's question mechanism; it does **not** proceed until the user answers, iterating until they confirm. Stages: **forge-1-prd** (Step 5), **forge-2-tech** (Step 6), **forge-3-specs** (Step 6).
61
+ - **Non-blocking review (invitation).** The stage states the artifact is ready and invites adjustments **as a statement, not a question** — and then **proceeds to the next step in the same turn unless the user asks for changes**. The invitation obliges the agent to *continue*: emitting the invitation sentence and stopping treats the non-gate as a gate and strands the stage `in-progress` with its completion step unrun — a defect, not caution. Stage: **forge-4-backlog** (Step 6).
62
+
63
+ **Why the shapes differ.** A blocking review guards an artifact whose content was just authored from open-ended interview or synthesis — the user is the only authority on "complete", so the stage must wait. forge-4's backlog is *derived* from specs the user already approved, was planned interactively in its Step 3, and is machine-validated in its Step 5; a second hard gate would re-ask a settled question, and the loop never launches without forge-5-loop's own Step 2d confirmation anyway. The invitation is a courtesy checkpoint, not an approval gate (removed deliberately in #78's consistency sweep).
64
+
65
+ A stage that changes shape changes it **in this block first**; the per-stage pointer stays a pointer.
66
+
56
67
  ## Configuration Reading
57
68
 
58
69
  Read `forge.config.json` from the project root. If it doesn't exist, use defaults.
@@ -68,10 +79,10 @@ Extract these config values (use defaults if not present):
68
79
  - `branchPerFeature` (default: true)
69
80
  - `branchPrefix` (default: `forge/`)
70
81
  - `loopIterationMultiplier` (default: `1.5`)
71
- - `autoInvokeNextStage` (default: `true` — the `/feature-forge:forge` navigator auto-invokes the next stage via the `Skill` tool after the user confirms; `false` keeps copy-paste behavior. Navigator-only.)
82
+ - `autoInvokeNextStage` (default: `true` — the `/feature-forge:forge` navigator auto-invokes the next stage via the host's skill-invocation mechanism after the user confirms; `false` keeps copy-paste behavior. Navigator-only.)
72
83
  - `contextWindowTokens` (default: `null` — context window used by the navigator's context-usage check; `null` infers from the session model and falls back to 200000. Set to the model's window, e.g. `1000000` on a 1M model. Navigator-only.)
73
84
  - `contextWarnThreshold` (default: `0.7` — fraction of the window past which the navigator recommends a clean session. Navigator-only.)
74
- - `autoVerify` (default: `false` — when `true`, `forge-verify` runs automatically after a stage completes, no prompt. **In-stage-primary:** the just-completed authoring stage runs it itself, in-session, before the exit block (honoring the verify-before-clear principle). The navigator runs it only as a **catch-up** when verify is still pending (a host that could not dispatch a clean-room subagent, or a stage run before this behavior landed). Either way it runs in a fresh clean-room subagent, so it never needs a `/clear` and costs only a compact digest.)
85
+ - `autoVerify` (default: `false` — when `true`, `forge-verify` runs automatically after a stage completes, no prompt. **In-stage-primary:** the just-completed authoring stage runs it itself, in-session, before the exit block (honoring the verify-before-clear principle). The navigator runs it only as a **catch-up** when verify is still pending (a host that could not dispatch a clean-room subagent, or a stage run before this behavior landed). Either way it runs in a fresh clean-room subagent, so it never needs a session clear and costs only a compact digest.)
75
86
  - `autoVerifyStages` (default: `{}` — per-stage overrides for `autoVerify`, e.g. `{"forge-1-prd": false}`. Effective value = `autoVerifyStages[stage]` if present, else `autoVerify`. Keys are constrained to the five verify-capable stages; a typo is a config error surfaced as `invalidAutoVerifyKeys`. Both the in-stage run and the navigator catch-up read this same effective value.)
76
87
  - `autoFix` (default: `false` — when `true`, `forge-fix` is chained after an auto-verify that finds issues — by the in-stage run (primary) or the navigator catch-up — but only when auto-verify is on for that stage AND preconditions hold (zero unresolved decisions, clean tree, passing re-verify); otherwise a digest is surfaced and the gate is presented.)
77
88
  - `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`.)
@@ -81,7 +92,7 @@ Extract these config values (use defaults if not present):
81
92
  Before any file I/O against a feature's artifacts, resolve its directory through the deterministic helper rather than hardcoding `{specsDir}/{feature}/`. This makes flat (`{specsDir}/{feature}/`) and nested (`{specsDir}/{epic}/{feature}/`) layouts both resolve from a bare feature name (REQ-DIR-03), with standalone features behaving exactly as today.
82
93
 
83
94
  ```bash
84
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
95
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
85
96
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
86
97
  resolvedFeatureDir=$(python3 "$R/scripts/epic-manifest.py" \
87
98
  resolve "<feature>" --specs-dir "<specsDir>")
@@ -96,12 +107,12 @@ In both failure cases, do not fall back to a guessed path.
96
107
  **On `not-found`, check other branches before stopping.** With `branchPerFeature`, the feature's directory (and its `.pipeline-state.json`) may exist only on its topic branch — invisible from the default branch of a fresh clone. Before concluding the pipeline does not exist, run the read-only cross-branch discovery:
97
108
 
98
109
  ```bash
99
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
110
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
100
111
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
101
112
  python3 "$R/scripts/forge-session.py" discover-feature "<feature>" --specs-dir "<specsDir>" --json
102
113
  ```
103
114
 
104
- - **Candidates found** (`candidates` and/or `remoteCandidates` non-empty): summarize them as text (branch, recorded stage, whether the state's own `branch` field matches), then use `AskUserQuestion`: **Switch to `{branch}` (recommended)** — run the candidate's `switchCommand` · **Fetch + switch** — for a `needsFetch` remote candidate, run its `fetchCommand` then `switchCommand` (note its contents were matched by name only, not inspected) · **Treat `{feature}` as new on this branch** · **Stop**. A checkout is a mutation inside an otherwise read-only flow: perform it ONLY on the user's explicit accept AND with a clean working tree (`git status --porcelain` prints nothing) — never auto-switch, never with uncommitted changes. After a successful switch, re-run this Feature Directory Resolution block from the top.
115
+ - **Candidates found** (`candidates` and/or `remoteCandidates` non-empty): summarize them as text (branch, recorded stage, whether the state's own `branch` field matches), then use the host's question mechanism: **Switch to `{branch}` (recommended)** — run the candidate's `switchCommand` · **Fetch + switch** — for a `needsFetch` remote candidate, run its `fetchCommand` then `switchCommand` (note its contents were matched by name only, not inspected) · **Treat `{feature}` as new on this branch** · **Stop**. A checkout is a mutation inside an otherwise read-only flow: perform it ONLY on the user's explicit accept AND with a clean working tree (`git status --porcelain` prints nothing) — never auto-switch, never with uncommitted changes. After a successful switch, re-run this Feature Directory Resolution block from the top.
105
116
  - **Nothing found** (both lists empty): the pipeline genuinely does not exist anywhere discoverable — STOP and surface the original `not-found` stderr line verbatim (or, where the caller offers to start a new pipeline, offer that).
106
117
 
107
118
  **Anti-fabrication guard.** Never describe pipeline state that resolution or discovery did not return: if both come back empty, the pipeline does not exist — say exactly that, and never reconstruct stages, backlogs, or history from conversational memory.
@@ -124,16 +135,16 @@ Whenever a stage creates the specs tree for the first time (the first PRD or epi
124
135
  Run this after creating the feature/epic directory, before the stage's git commit:
125
136
 
126
137
  ```bash
127
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
138
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
128
139
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
129
140
  mkdir -p "<specsDir>"
130
141
  [ -f "<specsDir>/AGENTS.md" ] || cp "$R/references/templates/specs-hygiene/AGENTS.md" "<specsDir>/AGENTS.md"
131
142
  ```
132
143
 
133
- If the host is Claude (the `AskUserQuestion` tool is available), also ensure the Claude-framed variant:
144
+ If the host is Claude (the Claude-native question tool is available), also ensure the Claude-framed variant:
134
145
 
135
146
  ```bash
136
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
147
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
137
148
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
138
149
  [ -f "<specsDir>/CLAUDE.md" ] || cp "$R/references/templates/specs-hygiene/CLAUDE.md" "<specsDir>/CLAUDE.md"
139
150
  ```
@@ -153,7 +164,7 @@ After resolving the feature directory, check the feature's `.pipeline-state.json
153
164
  To obtain the manifest contracts and the live completion status of each dependency in one deterministic call, run `render-status` and read the per-feature `status` and the `consumes`/`exposes` arrays rather than re-deriving them:
154
165
 
155
166
  ```bash
156
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
167
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
157
168
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
158
169
  python3 "$R/scripts/epic-manifest.py" \
159
170
  render-status "<epic>" --specs-dir "<specsDir>" --json
@@ -168,7 +179,7 @@ If `render-status` fails, proceed with **only** EPIC.md + charter (a corrupt man
168
179
  Defense-in-depth for the split-brain-epic failure (Issue #125). Invoke this block in the authoring stages (`forge-1-prd`..`forge-4-backlog`) once the feature has resolved — right after **Epic Context Injection** for the stages that run it (`forge-1-prd`..`forge-3-specs`), and right after **Feature Directory Resolution** for `forge-4-backlog`. It confirms that a **resolved nested epic member** actually sits on a branch that contains the epic's manifest. Without this, a member reached from a branch cut *before* the epic-manifest commit (or that otherwise lacks it) would author specs against an epic decomposition that is not present — the exact drift that produces a disjoint, split-brain member. **Skip if not a git repo or `branchPerFeature` is false.**
169
180
 
170
181
  ```bash
171
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
182
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
172
183
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
173
184
  python3 "$R/scripts/forge-session.py" check-epic-base --feature "{feature}" --specs-dir "{specsDir}" --json
174
185
  ```
@@ -191,7 +202,7 @@ Pipeline state is written by the `state-*` verbs of `scripts/forge-session.py`
191
202
 
192
203
  If a `state-*` verb exits 2, surface the plain `Error:` line from stderr verbatim, do **not** proceed to the next step of the surrounding protocol, and do **not** hand-author the JSON as a workaround. The stage remains resumable because the entry stamp is already on disk — re-run the verb once the cause is fixed.
193
204
 
194
- **The eight `state-*` verbs.** `state-enter` (Stage-Entry Guard), `state-artifact` (incremental artifact tracking), `state-complete` (Git Commit Protocol), `state-branch` (Branch Setup and Branch Reconciliation), `state-note` (the Immediate Downstream Note below, and the optional completion note at stage closure), `state-decision` (deferred decisions), `state-ecr` (epic change requests), and `state-verify` (one `forge-verify-*` verification transition — below). The `--epic` member requirement and the exit-2 failure protocol above apply to **every** one of them, `state-verify` included; no verify entry is ever hand-authored.
205
+ **The nine `state-*` verbs.** `state-enter` (Stage-Entry Guard), `state-artifact` (incremental artifact tracking), `state-complete` (Git Commit Protocol), `state-skip` (the deliberate forge-6-docs documentation skip — scoped to that one stage; writes `status: "skipped"` + `skippedAt`, refuses to erase a record of docs that exist, and is the only sanctioned writer of a skipped docs stage), `state-branch` (Branch Setup and Branch Reconciliation), `state-note` (the Immediate Downstream Note below, and the optional completion note at stage closure), `state-decision` (deferred decisions), `state-ecr` (epic change requests), and `state-verify` (one `forge-verify-*` verification transition — below). The `--epic` member requirement and the exit-2 failure protocol above apply to **every** one of them, `state-verify` included; no verify entry is ever hand-authored.
195
206
 
196
207
  ### `state-verify` — verification results and provenance
197
208
 
@@ -200,7 +211,7 @@ If a `state-*` verb exits 2, surface the plain `Error:` line from stderr verbati
200
211
  **`auto-verify-pending` is not a skill-facing status.** It is written by `stage-exit`'s scheduling boundary, which records the debt automatically when auto-verify is effective for a stage. The value is accepted on this CLI so the entry stays inspectable and repairable, not so a skill can hand-schedule verification: no skill body and no reference passes it, and none should. Every other status in the list is the recorded *result* of a verification that ran (or was explicitly skipped); this one records that one was *owed*.
201
212
 
202
213
  ```bash
203
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
214
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
204
215
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
205
216
  python3 "$R/scripts/forge-session.py" state-verify \
206
217
  --feature "{feature}" --stage "{served-production-stage}" --status "<status>" \
@@ -210,7 +221,7 @@ python3 "$R/scripts/forge-session.py" state-verify \
210
221
  Provenance follows the same two-commit sequence as `state-complete`: the result transition above writes `commitHash: null`, Commit 1 records the findings document and the state, and a second `state-verify` call records the full 40-hex hash of Commit 1 and touches nothing else (never `--amend`; an abbreviated hash is refused rather than expanded). Add `--epic "{epic}"` for an epic member — required, per the member rule above:
211
222
 
212
223
  ```bash
213
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
224
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
214
225
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
215
226
  python3 "$R/scripts/forge-session.py" state-verify \
216
227
  --feature "{feature}" --stage "{served-production-stage}" \
@@ -220,7 +231,7 @@ python3 "$R/scripts/forge-session.py" state-verify \
220
231
  Epic-scoped verification is the single exception to the member rule: with `--stage forge-0-epic`, `--feature` names the **epic** and `--epic` must be absent or exactly equal to it. That call writes `{specsDir}/{epic}/.epic-state.json` and never a member's `.pipeline-state.json`, and its freshness version is the epic manifest's `revision`, never a member's stage version:
221
232
 
222
233
  ```bash
223
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
234
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
224
235
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
225
236
  python3 "$R/scripts/forge-session.py" state-verify \
226
237
  --feature "{epic}" --stage forge-0-epic --status "<status>" \
@@ -242,7 +253,7 @@ Frame the choice with its cost: re-running re-derives this stage from the curren
242
253
  When an interview raises a concern that belongs to a *later stage of this same feature*, acknowledge it and persist it **immediately, at the moment it is raised** — not at stage closure — by running `state-note` with a concise one-line statement of the concern. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol above; omitting it for a member is an error and must never be allowed to fall back to a same-named flat feature.
243
254
 
244
255
  ```bash
245
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
256
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
246
257
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
247
258
  python3 "$R/scripts/forge-session.py" state-note \
248
259
  --feature "{feature}" --note "<concise downstream concern>" \
@@ -275,7 +286,7 @@ Invoke this block at the **very start** of a pipeline entry point — `forge-1-p
275
286
  1. Read the current branch: `git rev-parse --abbrev-ref HEAD`.
276
287
  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.
277
288
  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.
278
- 4. **If the current branch IS the default branch** → use `AskUserQuestion` with a **strong recommendation** (still optional):
289
+ 4. **If the current branch IS the default branch** → use the host's question mechanism with a **strong recommendation** (still optional):
279
290
 
280
291
  > "You're on `{defaultBranch}`. Strongly recommended: create `{branchPrefix}{label}` so this {scope}'s work stays isolated and reviewable as one branch. Create it?"
281
292
  > Options: **Create `{branchPrefix}{label}` (recommended)** · **Stay on `{defaultBranch}`**
@@ -286,7 +297,7 @@ Invoke this block at the **very start** of a pipeline entry point — `forge-1-p
286
297
  **Record the branch.** After this block resolves, record the resulting branch name in the feature's top-level `branch` field by running `state-branch` (create/update it when the state file is first written for this stage). Emit the call **once the feature directory exists** — i.e. after Feature Directory Resolution and the Entry Stamp, **not** at this block: Branch Setup runs at the very start of the entry point, before any directory resolution, and a brand-new standalone feature may have no directory yet. Add `--epic "{epic}"` to the call when this feature is an epic member — required, per the Pipeline State Protocol.
287
298
 
288
299
  ```bash
289
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
300
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
290
301
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
291
302
  python3 "$R/scripts/forge-session.py" state-branch \
292
303
  --feature "{feature}" --branch "<name>" --specs-dir "{specsDir}"
@@ -299,20 +310,20 @@ Downstream stages and `forge-5-loop` read it to detect drift back onto the defau
299
310
  The recorded `branch` is a **self-healing hint, not gospel.** A hosted environment (Claude.ai remote, cloud agents) can impose an arbitrary session branch (e.g. `claude/<slug>`) that Branch Setup silently records; the user may then move the work to the intended topic branch, leaving the recorded field stale. Every branch-aware mechanism (the `forge-5-loop` guard, `discover-feature`) keys off that field, so a stale value actively misleads — the loop would offer to switch you *back* to the imposed branch. Invoke this block from `forge-5-loop`'s pre-flight (and any stage that acts on the recorded branch) to reconcile deterministically. Skip if not a git repo or `branchPerFeature` is false.
300
311
 
301
312
  ```bash
302
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
313
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
303
314
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
304
315
  python3 "$R/scripts/forge-session.py" reconcile-branch --feature "{feature}" --specs-dir "{specsDir}" --json
305
316
  ```
306
317
 
307
318
  Act on the emitted `action` (source of truth is where the state actually resolves, not the recorded field):
308
319
  - **`adopt-current`** — you are on a non-default topic branch where the state resolves, and the recorded `branch` differs (a stale/imposed value). Run `state-branch` (below) to write `newBranch` into the state `branch` field, with a **visible one-line note** ("recorded branch was `{stateBranch}`; work is on `{currentBranch}` — updating to match") — never silently, and **never push the user back** to the recorded branch (offer that only as a plain alternative).
309
- - **`warn-drift`** — you are on the **default** branch and the state records a topic branch. Via `AskUserQuestion`, strongly recommend creating/switching to `{branchPrefix}{feature}` (then record it), still allowing **proceed on the default branch**. Never hard-stop.
320
+ - **`warn-drift`** — you are on the **default** branch and the state records a topic branch. Via the host's question mechanism, strongly recommend creating/switching to `{branchPrefix}{feature}` (then record it), still allowing **proceed on the default branch**. Never hard-stop.
310
321
  - **`none`** / **`not-resolved`** — nothing to do; proceed.
311
322
 
312
323
  The `adopt-current` write, with the portable plugin-root prelude. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol:
313
324
 
314
325
  ```bash
315
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
326
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
316
327
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
317
328
  python3 "$R/scripts/forge-session.py" state-branch \
318
329
  --feature "{feature}" --branch "{newBranch}" --specs-dir "{specsDir}"
@@ -338,7 +349,7 @@ When `gitCommitAfterStage` is true, follow this exact order to avoid state incon
338
349
  The two `state-complete` calls, with the portable plugin-root prelude. Add `--epic "{epic}"` to each when this feature is an epic member — required, per the Pipeline State Protocol:
339
350
 
340
351
  ```bash
341
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
352
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
342
353
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
343
354
  # Commit 1 — before `git commit`
344
355
  python3 "$R/scripts/forge-session.py" state-complete \
@@ -360,15 +371,15 @@ Invoke this block at the **start of an authoring stage** (`forge-1-prd`..`forge-
360
371
 
361
372
  2. **Interrupted** (`status: "in-progress"`) — a previous run of THIS stage was interrupted before it committed (the exit commit is what flips it to `complete`, so `in-progress` on entry always means a crash/abandon). Do **not** silently re-author. Instead:
362
373
  - **Inventory on-disk artifacts:** list the files this stage produces that already exist in `{resolvedFeatureDir}/` (e.g. `PRD.md`; `tech-spec.md`; the `##-*.md` suite + `TRACEABILITY.md`; `backlog.json`), and cross-check against the `stages.{stage}.artifacts` array (written incrementally during the previous run).
363
- - **Gate via `AskUserQuestion`** (Decision Support protocol): present the inventory as text, then ask "This {stage} run was interrupted — {N} artifact(s) from the previous run are on disk: {list}. Resume the in-progress draft, or start a new version from scratch?" Options: **Resume (recommended)** — continue from the first artifact not yet written/complete, reusing the existing files; do **not** re-stamp or bump the version. · **Start a new version** — treat it as a fresh authoring pass (proceed to the Entry Stamp; the version increments at exit).
374
+ - **Gate via the host's question mechanism** (Decision Support protocol): present the inventory as text, then ask "This {stage} run was interrupted — {N} artifact(s) from the previous run are on disk: {list}. Resume the in-progress draft, or start a new version from scratch?" Options: **Resume (recommended)** — continue from the first artifact not yet written/complete, reusing the existing files; do **not** re-stamp or bump the version. · **Start a new version** — treat it as a fresh authoring pass (proceed to the Entry Stamp; the version increments at exit).
364
375
  - Skip artifact regeneration for files that already exist and are complete (non-empty, properly structured); continue from the next unwritten artifact.
365
376
 
366
- 3. **Re-authoring** (`status: "complete"` or `"stale"`) — a finished draft exists. Warn via `AskUserQuestion` before overwriting: "A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?" On confirm, proceed to the Entry Stamp and author a new version (the version increments at exit, per that stage's Update-Pipeline-State step).
377
+ 3. **Re-authoring** (`status: "complete"` or `"stale"`) — a finished draft exists. Warn via the host's question mechanism before overwriting: "A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?" On confirm, proceed to the Entry Stamp and author a new version (the version increments at exit, per that stage's Update-Pipeline-State step).
367
378
 
368
379
  **Entry Stamp** (fresh, restart, and re-author paths — NOT the resume path). Before authoring, record the entry stamp by running `state-enter` — one atomic write that sets `stages.{stage}.status` → `"in-progress"`, `stages.{stage}.startedAt` → current ISO-8601 UTC timestamp, top-level `currentStage` → `"{stage}"` (where the pipeline IS, per O1), and refreshes `updatedAt`. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol:
369
380
 
370
381
  ```bash
371
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
382
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
372
383
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
373
384
  python3 "$R/scripts/forge-session.py" state-enter \
374
385
  --feature "{feature}" --stage "{stage}" --specs-dir "{specsDir}"
@@ -381,7 +392,7 @@ This write is **left uncommitted**: it is staged and committed as part of this s
381
392
  **Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), run `state-artifact --feature {feature} --stage {stage} --path <file>` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol.
382
393
 
383
394
  ```bash
384
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
395
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
385
396
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
386
397
  python3 "$R/scripts/forge-session.py" state-artifact \
387
398
  --feature "{feature}" --stage "{stage}" --path "<file>" --specs-dir "{specsDir}"
@@ -395,7 +406,7 @@ Invoke this block **at the head of any post-entry step that writes a stage artif
395
406
 
396
407
  1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
397
408
 
398
- 2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
409
+ 2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same warning via the host's question mechanism ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
399
410
 
400
411
  When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
401
412
 
@@ -4,7 +4,7 @@ The single source of truth for how every forge stage closes. **One** scripted co
4
4
  covers all **nine** covered direct exits — the seven production stages `forge-0-epic`
5
5
  through `forge-6-docs`, plus direct `forge-verify` and direct `forge-fix`. It replaces the
6
6
  old ad-hoc "Next steps:" bullet lists with one fixed, correctly-ordered sequence:
7
- **verify (if missing or stale) → `/clear` → run the next command.**
7
+ **verify (if missing or stale) → clear your session / start a fresh session → run the next command.**
8
8
 
9
9
  Two principles this protocol encodes (do not relitigate — they are locked product
10
10
  decisions):
@@ -18,7 +18,7 @@ decisions):
18
18
  session, so the findings digest and any fix decision land where the context to act on
19
19
  them still exists. This holds for auto-verify too: the stage skill dispatches the
20
20
  clean-room verify (and any autoFix) at stage end, in-session, before the exit — it is
21
- **not** deferred to the navigator, which runs *after* the `/clear` with none of the
21
+ **not** deferred to the navigator, which runs *after* the session clear with none of the
22
22
  authoring context. Clearing first throws that context away.
23
23
 
24
24
  ## How this file is used
@@ -47,8 +47,8 @@ an epic member. Only the flags below are stage-specific; pass no others.
47
47
  |---|---|---|
48
48
  | `forge-0-epic` | `forge-0-epic` | `--next-feature "{member}"` when a concrete member exists |
49
49
  | `forge-1-prd` … `forge-4-backlog` | that stage's own id | none beyond identity/capability |
50
- | `forge-5-loop` | `forge-5-loop` | `--outcome` — one of `complete`, `partial`, `blocked`, `needs-human`, `deferred` |
51
- | `forge-6-docs` | `forge-6-docs` | `--outcome` — `complete` or `blocked` |
50
+ | `forge-5-loop` | `forge-5-loop` | `--outcome` — one of `complete`, `partial`, `blocked`, `needs-human`, `deferred`, `resolved`; optional `--cause dependency-starvation` with `--outcome partial` |
51
+ | `forge-6-docs` | `forge-6-docs` | `--outcome` — `complete`, `blocked`, or `skipped` (deliberate docs skip, persisted via `state-skip` before the exit; routes like `complete` with honest wording) |
52
52
  | direct `forge-verify` | `forge-verify` | `--owner direct`, `--outcome` (`passed`, `findings`, `skipped`, `failed`), and served-stage metadata |
53
53
  | nested `forge-verify` | `forge-verify` | `--owner nested`, plus the same outcome and served-stage metadata |
54
54
  | direct/nested `forge-fix` | `forge-fix` | the matching `--owner`, a `FixOutcome` (`no-findings`, `decisions`, `failed`, `applied`, `reverified`, `reverify-findings`, `deferred`), and served-stage metadata |
@@ -90,19 +90,19 @@ resolves before running the command, exactly as elsewhere.
90
90
  **Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
91
91
 
92
92
  ```bash
93
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
93
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
94
94
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
95
- python3 "$R/scripts/forge-session.py" stage-exit {stage-exit-args} --specs-dir "{specsDir}" --host claude --verify-capability "{verify-capability}"
95
+ python3 "$R/scripts/forge-session.py" stage-exit {stage-exit-args} --specs-dir "{specsDir}" --host generic --verify-capability "{verify-capability}"
96
96
  ```
97
97
 
98
98
  Obey the DIRECTIVES it prints, in the consumption order this protocol fixes: surface `invalidAutoVerifyKeys` and every `warnings` entry first; `runInStageVerify: true` → run the in-stage clean-room verify chain now (honoring `autoFixEligible`, and asking through the Standard Verify Gate first when you may not dispatch unsolicited); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user and do **not** dispatch inline. Then, and only when `terminalOwnedBy` is `"self"`, **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.** A `terminalOwnedBy: "outer"` payload carries `nextSteps: null`: return your structured result to the caller and print no terminal block at all.
99
99
  <!-- END: scripted-stage-exit-stamp -->
100
100
 
101
- The stamp is shown with `--host claude`; the adapter build substitutes `pi`/`generic` per
101
+ The stamp is shown with `--host generic`; the adapter build substitutes `pi`/`generic` per
102
102
  target, and §"Host and capability determination" below governs the value. The literal is
103
- deliberate — `scripts/build-adapters.py` keys its host translation on the exact string
104
- `--host claude`, and the stamp sites are compared byte-for-byte, so it is the one token in
105
- that line that is not a placeholder.
103
+ deliberate — `scripts/build-adapters.py` keys its host translation on the exact canon
104
+ value of that flag, and the stamp sites are compared byte-for-byte, so it is the one token
105
+ in that line that is not a placeholder.
106
106
 
107
107
  ## Host and capability determination
108
108
 
@@ -110,12 +110,13 @@ Before the call, compute the two inputs independently. They are unrelated: **a h
110
110
  implies a capability**, and the script takes `--verify-capability` at face value.
111
111
 
112
112
  **`--host`** describes only the active adapter command surface — `claude`, `pi`, or
113
- `generic`. It selects command syntax (`/feature-forge:` vs `/skill:` vs host-neutral) and
114
- fresh-session wording (`/clear` vs `/new` vs neutral prose). Nothing else.
113
+ `generic`. It selects command syntax (Claude's stage-command prefix vs Pi's `/skill:` vs
114
+ host-neutral) and fresh-session wording (Claude's clear command vs Pi's `/new` vs neutral
115
+ prose). Nothing else.
115
116
 
116
117
  **`--verify-capability interactive`** is passed only when **both** of these hold:
117
118
 
118
- - **(a)** a question mechanism equivalent to `AskUserQuestion` is available, **and**
119
+ - **(a)** a question mechanism equivalent to the host's question mechanism is available, **and**
119
120
  - **(b)** a clean-room `forge-verifier` subagent can be dispatched.
120
121
 
121
122
  If either is absent, or capability cannot be established, pass `manual`.
@@ -151,7 +152,8 @@ production successor** while verification is unresolved.
151
152
  - a capable Pi session is `--host pi --verify-capability interactive`, and receives the
152
153
  same logical gate a capable Claude session does;
153
154
  - Pi without a dispatchable verifier is `--host pi --verify-capability manual`;
154
- - a Claude session that cannot dispatch is `--host claude --verify-capability manual`.
155
+ - a Claude session that cannot dispatch keeps the Claude host value with
156
+ `--verify-capability manual`.
155
157
 
156
158
  Interactive gate options keep their explicit labels, their recommended default, and their
157
159
  one-line trade-off descriptions (below). The manual path prints the verify command as the
@@ -199,6 +201,44 @@ second sentinel-terminated block **inside** an outer stage's exit, breaking the
199
201
  exactly-one-terminal-block rule — and the canon guard cannot catch it, because both
200
202
  wordings legitimately appear in the same file. Judge the token, not the phrasing.
201
203
 
204
+ ## Caller-side resumption: the declared resume point
205
+
206
+ The `owner:` token and `terminalOwnedBy` arbitrate who prints — but they specify only
207
+ the **callee** side: a nested skill stays quiet and returns its structured result. This
208
+ section is the reciprocal, caller-side half of that contract.
209
+
210
+ **On a sub-skill's return, the caller re-owns the terminal.** Every closing instruction
211
+ in the callee's own body — its report-and-stop posture, its "confirm the result" close,
212
+ its own next-steps habits — is void for this turn. The caller resumes at its **declared
213
+ resume point**, in the same turn, and its remaining steps run to its own terminal.
214
+
215
+ **Every Skill-tool delegation site declares, at the invocation, what happens on
216
+ return.** Suppression without resumption is the failure mode this section closes: the
217
+ callee's closing posture is the freshest instruction in context while the caller's next
218
+ step is the oldest, so an undeclared return silently ends the run one layer too early —
219
+ the caller's remaining steps (validation, state writes, commit, stage exit) dropped,
220
+ with no error surfaced. An implicit "let it run to its natural stopping point" is that
221
+ bug spelled politely, and it is banned on delegation sites. A site takes one of two
222
+ declared postures:
223
+
224
+ - **Delegate-and-resume** — the callee is a sub-step of the caller: the site names the
225
+ caller's own step that control returns to, and the caller continues there in the same
226
+ turn. The callee never owns the caller's terminal. The worked instance is
227
+ `forge-4-backlog` Step 4's **Return contract** for the `author-backlog` delegation
228
+ (control returns at Step 5; the sub-skill's direct-invocation posture — its approval
229
+ gate and its validate-and-confirm close — is explicitly disapplied on the delegated
230
+ path). New delegation sites follow that pattern rather than re-deriving it.
231
+ - **Terminal handoff** — the caller's job ends at the invocation and the invoked skill
232
+ owns the terminal from there on (e.g. the navigator's `autoInvokeNextStage`
233
+ "continue in this session" advance into the next production stage). Declaring the
234
+ handoff is what keeps it distinct from an accidental drop.
235
+
236
+ Scope: this contract governs **Skill-tool delegation within one session**. The
237
+ truncated-verifier-return guard (forge-verify's `findings-template.md`, "Truncated
238
+ Verifier Returns") is a different mechanism — it polices what an **Agent-dispatched
239
+ subagent's** return payload must contain, not where a caller resumes. A dispatch site
240
+ can be subject to both; satisfy each on its own terms.
241
+
202
242
  ## Directive consumption order
203
243
 
204
244
  `stage-exit` emits a DIRECTIVES object and (for a direct owner) a NEXT-STEPS block. The
@@ -243,7 +283,7 @@ reformat, merge, or summarize them, and never dump the state file they were deri
243
283
 
244
284
  Auto-verify is effective for this stage and verification is outstanding — verify **now,
245
285
  in this session** (principle #2 applied to auto-verify: the digest and any fix decision
246
- land here, where the authoring context still exists — not deferred to a post-`/clear`
286
+ land here, where the authoring context still exists — not deferred to a post-clear
247
287
  navigator). The `auto-verify-pending` debt is already durable on disk at this point, so a
248
288
  declined or deferred gate leaves recorded debt rather than a silent pass.
249
289
 
@@ -252,7 +292,7 @@ declined or deferred gate leaves recorded debt rather than a silent pass.
252
292
  same path the navigator uses (`skills/forge-verify/SKILL.md`). Dispatch it
253
293
  **synchronously and await its digest inline** — do **not** run it in the background or
254
294
  announce it as "still running"; the digest and any fix decision must land in this
255
- session. It inherits none of this session's context, so no `/clear` is needed and only
295
+ session. It inherits none of this session's context, so no session clear is needed and only
256
296
  a compact digest returns.
257
297
  **If you may not dispatch unsolicited**, present the consent form of the Standard
258
298
  Verify Gate first and dispatch on the affirmative choice — see "Consent variant on a
@@ -299,7 +339,11 @@ first:
299
339
  a stage's artifact commit.
300
340
  - **Skip for now** — go straight to the NEXT-STEPS block without verifying. Record this
301
341
  stage's verify status as `skipped` in pipeline state (via `state-verify`, never by hand)
302
- **only** on an explicit skip — a skip does not go stale.
342
+ **only** on an explicit skip — a skip does not go stale. Exception: if the existing
343
+ entry records `passed` or `findings-applied` (a resolved result whose freshness has
344
+ merely lapsed), write **nothing** — `state-verify` refuses to demote a resolved status
345
+ to `skipped` (#203), and the recorded result stands on its own; the user's decline is
346
+ honored by simply not re-verifying.
303
347
 
304
348
  **Advancement is allowed only after a pass, or after an explicit skip has been
305
349
  persisted.** Choosing to stop, or losing the interaction, produces no advancing terminal
@@ -358,8 +402,8 @@ directive is informational — you do **not** re-derive the wording:
358
402
  unchanged; the block appends a non-blocking reminder line ("You also flagged N epic
359
403
  change(s) to reconcile when convenient …"). This is *finish-then-edit*.
360
404
 
361
- Either way the added lines are host-neutral (no literal `/clear`) and sit **above** the
362
- sentinel; just print the NEXT-STEPS block verbatim as always.
405
+ Either way the added lines are host-neutral (they name no fresh-session command) and sit
406
+ **above** the sentinel; just print the NEXT-STEPS block verbatim as always.
363
407
 
364
408
  ### Deferred decisions — do not solicit next-stage decisions at this exit
365
409
 
@@ -376,7 +420,7 @@ a `deferredDecisions[]` entry on this feature's `.pipeline-state.json` by runnin
376
420
  epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`:
377
421
 
378
422
  ```bash
379
- R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
423
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
380
424
  [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
381
425
  python3 "$R/scripts/forge-session.py" state-decision \
382
426
  --feature "{feature}" --question "<phrased for the target stage>" \
@@ -45,6 +45,8 @@ python3 "$R/scripts/forge-session.py" effective-config --config ./forge.config.j
45
45
 
46
46
  **Prerequisite check:** Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode, stages `forge-1-prd`, `forge-2-tech`, and `forge-3-specs` must all be `complete`. If not, STOP and tell the user which prerequisites are missing.
47
47
 
48
+ **Carried-over note check.** If that state's top-level `notes` is a non-empty string, surface it verbatim before proceeding and treat it as input to this stage — it was persisted for exactly this cross-session handoff (often at the previous stage's exit), and it can carry backlog-shaping constraints (e.g. "no item may create file X"). It never overrides the specs or config; raise any conflict instead of silently following either side.
49
+
48
50
  After the prerequisite check, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-4-backlog` — it detects an interrupted or complete `backlog.json`, runs the resume/restart or new-version gate, and stamps entry before Step 2 loads the specs. (The backlog is a single artifact, so "resume" means: reuse the existing `backlog.json` if the previous run wrote it, rather than re-authoring from scratch.)
49
51
 
50
52
  Then invoke the **Epic-Member Base Guard** block in `references/shared-conventions.md` (this stage does not run Epic Context Injection, so invoke it explicitly here). It self-gates to a no-op for standalone features; for a nested epic member on a branch that lacks the epic manifest it stops with a home-branch pointer (Issue #125).
@@ -92,6 +94,8 @@ After presenting the plan as text, use the host's question mechanism following t
92
94
 
93
95
  `author-backlog` owns all item-quality rules (granularity hard limits, self-contained descriptions, acceptance criteria, `agentDelegation`, the correct `type`/`status` enums, `dependsOn`, `specReferences`, the schema source). Do not re-encode them here — follow whatever it produces.
94
96
 
97
+ **Return contract.** This is the **delegate-and-resume** posture of "Caller-side resumption: the declared resume point" in `references/stage-exit-protocol.md`. `author-backlog` is a sub-skill of this stage, not its terminal: when it returns, control returns to **this skill, at Step 5** — forge-4 still owns the stage and its terminal output. Two of the sub-skill's own instructions do not apply on this delegated path (it also serves direct user invocation, and those instructions are its direct-invocation posture): its wait-for-user-approval-before-writing gate is already satisfied by Step 3's approved plan — do not re-ask; and its closing "run `rauf backlog validate` … and confirm the validated result" posture is subsumed by Step 5, which owns validation (see Step 5's ownership note). Do not adopt the sub-skill's report-and-stop terminal — it is the freshest instruction in context after the return, but it belongs to the sub-skill: continue to Step 5 in the same turn; Steps 6 and 7 still run, and the stage closes only at Step 7's exit.
98
+
95
99
  > **If the rauf plugin / `author-backlog` skill is not available:** fall back to
96
100
  > authoring inline using the schema source rule (prefer the project's installed
97
101
  > `{stateDir}/backlog.schema.json`, else the published `$id`
@@ -108,6 +112,8 @@ After presenting the plan as text, use the host's question mechanism following t
108
112
 
109
113
  ## Step 5: Validate via the loop runner
110
114
 
115
+ **Validation ownership.** This step is authoritative for validation, whether or not `author-backlog` already ran its own `rauf backlog validate`: this stage carries the degradation rules for a missing/old/not-set-up runner (below) that the sub-skill does not, and this step's result is what Step 6 reports. A validate the sub-skill already ran cleanly makes this a cheap idempotent re-run, never a reason to skip it — and the sub-skill's validate never discharges this step.
116
+
111
117
  Validate the generated backlog by running the runner's **validate command**
112
118
  (`loopRunner.validateCommand`), rendered with `{resolvedBacklogDir}` and `{specsDir}`
113
119
  substituted — the rauf default:
@@ -132,11 +138,43 @@ Interpret the result:
132
138
  > (`validate` reports the project marker missing), likewise warn and continue
133
139
  > — validation will run cleanly once `rauf install .` has been done.
134
140
 
141
+ ## Step 5b: Topology Report (advisory)
142
+
143
+ After validation (or a recorded skip), report the backlog's dependency topology. Pipe the runner's **list command** (`loopRunner.listCommand`, rendered with `{resolvedBacklogDir}` — the rauf default shown below) into the topology verb. It is a pure function over the runner's item array and never takes a `backlog.json` path:
144
+
145
+ ```bash
146
+ R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
147
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
148
+ rauf backlog list . --backlog {resolvedBacklogDir} --json | python3 "$R/scripts/forge-session.py" backlog-topology --items-stdin --json
149
+ ```
150
+
151
+ ALWAYS print the metrics, citing the runner counts from the payload:
152
+
153
+ ```
154
+ Topology: {itemCount} items, {rootCount} roots, max chain depth {maxChainDepth}.
155
+ Per-root fan-out (gated subtree size): {id}→{gatedCount}, … (largest first).
156
+ ```
157
+
158
+ Only when the payload's `warnings` array is non-empty, also render this block, including only the bullet(s) for warnings that actually fired:
159
+
160
+ ```
161
+ ⚠️ Fragile topology (advisory — does not block authoring):
162
+ - single-root-fanout: root {id} gates {gatedCount}/{itemCount} items (≥50%).
163
+ - chain-depth: max chain depth {maxChainDepth} is ≥50% of {itemCount} items.
164
+ A single defect in a high-fan-out root or a long chain can strand most of the backlog
165
+ (the loop-recovery incident: 3 roots gating 81%, 13-deep chain). Consider splitting the
166
+ gating root's subtree or flattening the chain — this is a heads-up, not a gate.
167
+ ```
168
+
169
+ This step is **guidance only — it never fails authoring**. If the topology command itself errors, note the error and continue to Step 6 (advisory).
170
+
135
171
  ## Step 6: Review with User
136
172
 
137
173
  Present a summary: total items N, dependency-chain depth, estimated loop iterations (`ceil(pendingItems * loopIterationMultiplier)`). Note whether validation passed or was skipped (runner not yet available).
138
174
 
139
- State that the backlog is ready and invite adjustments before committing — a statement, not a forced gate: "Backlog is ready. Tell me if you want any items split, merged, or reordered; otherwise I'll record state and commit." Proceed to Step 7 unless the user asks for changes.
175
+ This is a **non-blocking review (invitation)** — per the **Stage Review Gate** in `references/shared-conventions.md`: sibling stages block here; this stage deliberately does not, and the invitation obliges you to continue, not stop.
176
+
177
+ State that the backlog is ready and invite adjustments before committing — a statement, not a forced gate: "Backlog is ready. Tell me if you want any items split, merged, or reordered; otherwise I'll record state and commit." **Proceed to Step 7 in this same turn** unless the user asks for changes — emitting the invitation and stopping strands the stage before Step 7 runs.
140
178
 
141
179
  ## Step 7: Update Pipeline State and Commit
142
180
 
@@ -145,7 +183,7 @@ Before writing state or running the stage exit, invoke the **Stage-Completion Re
145
183
  Pipeline state is written by the `state-*` verbs — see the Pipeline State Protocol in `references/shared-conventions.md`. Follow the Git Commit Protocol in `references/shared-conventions.md`.
146
184
 
147
185
  1. Record completion by running `state-complete` (below) with `--version`, `--artifact backlog.json`, and `--based-on forge-1-prd=<current version> --based-on forge-2-tech=<current version> --based-on forge-3-specs=<current version>`. It sets `status: "complete"`, `completedAt`, the version and `basedOnVersions`, and applies the downstream staleness cascade deterministically, so no downstream status is set by hand.
148
- 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
186
+ 2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it via `state-note` — it **overwrites** the single `notes` string (latest note wins), so fold any still-relevant existing note into the one combined string; otherwise proceed. The next stage's Step 1 reads and surfaces this note.
149
187
  3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol: stage files, attempt commit (marking `stages.forge-4-backlog.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
150
188
  4. If verification was available but the user chose to skip it, persist that skip through `state-verify` using the fence below — never by hand. The choice to proceed unverified is durable state owned by the scripted writer.
151
189
  5. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Lead with the item count ("Backlog complete with {N} items."), then:
@@ -164,7 +202,7 @@ python3 "$R/scripts/forge-session.py" state-note \
164
202
  --feature "{feature}" --note "<what the user volunteered>" --specs-dir "{specsDir}"
165
203
  ```
166
204
 
167
- The `state-verify` call for item 4 — **only** when verification was available and the user explicitly chose to skip it. A verifier that could not be dispatched is not a skip, so do not run this on an unavailable-tool path. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`:
205
+ The `state-verify` call for item 4 — **only** when verification was available and the user explicitly chose to skip it. A verifier that could not be dispatched is not a skip, so do not run this on an unavailable-tool path. And only over an entry that is absent or unresolved: if `stages.forge-verify-backlog` already records `passed` or `findings-applied`, do **not** run the call — those statuses are resolved, the verb refuses to demote them to `skipped` (#203), and the existing result stands with nothing written. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`:
168
206
 
169
207
  ```bash
170
208
  R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"