@garygentry/feature-forge 0.3.2 → 0.3.4

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 (384) hide show
  1. package/adapters/claude/.feature-forge-bundle.json +1 -1
  2. package/adapters/claude/agents/forge-verifier.md +3 -1
  3. package/adapters/claude/references/decisions/single-writer-threat-model.md +53 -0
  4. package/adapters/claude/references/epic-state-schema.json +50 -0
  5. package/adapters/claude/references/forge-config-schema.json +18 -0
  6. package/adapters/claude/references/forge-decisions-schema.json +33 -0
  7. package/adapters/claude/references/pipeline-state-schema.json +34 -2
  8. package/adapters/claude/references/ralph-loop-contract.md +6 -3
  9. package/adapters/claude/references/shared-conventions.md +15 -4
  10. package/adapters/claude/references/stage-exit-protocol.md +55 -11
  11. package/adapters/claude/scripts/epic-manifest.py +82 -4
  12. package/adapters/claude/scripts/fix-sweep.py +1180 -0
  13. package/adapters/claude/scripts/forge-session.py +1124 -26
  14. package/adapters/claude/skills/forge/SKILL.md +5 -5
  15. package/adapters/claude/skills/forge/references/pipeline-state-schema.json +34 -2
  16. package/adapters/claude/skills/forge/references/shared-conventions.md +15 -4
  17. package/adapters/claude/skills/forge/references/stage-exit-protocol.md +55 -11
  18. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +5 -1
  19. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +5 -0
  20. package/adapters/claude/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  21. package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +15 -4
  22. package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +55 -11
  23. package/adapters/claude/skills/forge-1-prd/SKILL.md +3 -1
  24. package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +15 -4
  25. package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +55 -11
  26. package/adapters/claude/skills/forge-2-tech/SKILL.md +5 -1
  27. package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +15 -4
  28. package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +55 -11
  29. package/adapters/claude/skills/forge-3-specs/SKILL.md +5 -1
  30. package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +15 -4
  31. package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +55 -11
  32. package/adapters/claude/skills/forge-4-backlog/SKILL.md +41 -3
  33. package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +15 -4
  34. package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +55 -11
  35. package/adapters/claude/skills/forge-5-loop/SKILL.md +36 -36
  36. package/adapters/claude/skills/forge-5-loop/references/agent-selection.md +16 -0
  37. package/adapters/claude/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  38. package/adapters/claude/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  39. package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +40 -11
  40. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +22 -4
  41. package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +15 -4
  42. package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +55 -11
  43. package/adapters/claude/skills/forge-6-docs/SKILL.md +29 -6
  44. package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +15 -4
  45. package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +55 -11
  46. package/adapters/claude/skills/forge-fix/SKILL.md +34 -0
  47. package/adapters/claude/skills/forge-fix/references/shared-conventions.md +15 -4
  48. package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +55 -11
  49. package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +18 -0
  50. package/adapters/claude/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  51. package/adapters/claude/skills/forge-guide/references/shared-conventions.md +15 -4
  52. package/adapters/claude/skills/forge-verify/SKILL.md +10 -11
  53. package/adapters/claude/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  54. package/adapters/claude/skills/forge-verify/references/findings-template.md +30 -0
  55. package/adapters/claude/skills/forge-verify/references/shared-conventions.md +15 -4
  56. package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +55 -11
  57. package/adapters/claude/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  58. package/adapters/claude/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  59. package/adapters/claude/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  60. package/adapters/codex/.feature-forge-bundle.json +1 -1
  61. package/adapters/codex/agents/forge-verifier.toml +3 -1
  62. package/adapters/codex/references/decisions/single-writer-threat-model.md +53 -0
  63. package/adapters/codex/references/epic-state-schema.json +50 -0
  64. package/adapters/codex/references/forge-config-schema.json +18 -0
  65. package/adapters/codex/references/forge-decisions-schema.json +33 -0
  66. package/adapters/codex/references/pipeline-state-schema.json +34 -2
  67. package/adapters/codex/references/process-overview.md +2 -2
  68. package/adapters/codex/references/ralph-loop-contract.md +6 -3
  69. package/adapters/codex/references/shared-conventions.md +44 -33
  70. package/adapters/codex/references/stage-exit-protocol.md +64 -20
  71. package/adapters/codex/scripts/epic-manifest.py +82 -4
  72. package/adapters/codex/scripts/fix-sweep.py +1180 -0
  73. package/adapters/codex/scripts/forge-session.py +1124 -26
  74. package/adapters/codex/skills/forge/SKILL.md +8 -8
  75. package/adapters/codex/skills/forge/references/pipeline-state-schema.json +34 -2
  76. package/adapters/codex/skills/forge/references/process-overview.md +2 -2
  77. package/adapters/codex/skills/forge/references/shared-conventions.md +44 -33
  78. package/adapters/codex/skills/forge/references/stage-exit-protocol.md +64 -20
  79. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +14 -10
  80. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  81. package/adapters/codex/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  82. package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +44 -33
  83. package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  84. package/adapters/codex/skills/forge-1-prd/SKILL.md +3 -1
  85. package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +44 -33
  86. package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  87. package/adapters/codex/skills/forge-2-tech/SKILL.md +5 -1
  88. package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +44 -33
  89. package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  90. package/adapters/codex/skills/forge-3-specs/SKILL.md +5 -1
  91. package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +44 -33
  92. package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  93. package/adapters/codex/skills/forge-4-backlog/SKILL.md +41 -3
  94. package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  95. package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  96. package/adapters/codex/skills/forge-5-loop/SKILL.md +36 -36
  97. package/adapters/codex/skills/forge-5-loop/references/agent-selection.md +17 -1
  98. package/adapters/codex/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  99. package/adapters/codex/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  100. package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +40 -11
  101. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +26 -8
  102. package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +44 -33
  103. package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  104. package/adapters/codex/skills/forge-6-docs/SKILL.md +29 -6
  105. package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +44 -33
  106. package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  107. package/adapters/codex/skills/forge-fix/SKILL.md +34 -0
  108. package/adapters/codex/skills/forge-fix/references/shared-conventions.md +44 -33
  109. package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  110. package/adapters/codex/skills/forge-guide/SKILL.md +1 -1
  111. package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +18 -0
  112. package/adapters/codex/skills/forge-guide/references/process-overview.md +2 -2
  113. package/adapters/codex/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  114. package/adapters/codex/skills/forge-guide/references/shared-conventions.md +44 -33
  115. package/adapters/codex/skills/forge-init/SKILL.md +1 -1
  116. package/adapters/codex/skills/forge-verify/SKILL.md +11 -12
  117. package/adapters/codex/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  118. package/adapters/codex/skills/forge-verify/references/findings-template.md +32 -2
  119. package/adapters/codex/skills/forge-verify/references/shared-conventions.md +44 -33
  120. package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  121. package/adapters/codex/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  122. package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  123. package/adapters/codex/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  124. package/adapters/codex/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  125. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  126. package/adapters/copilot/agents/forge-verifier.md +3 -1
  127. package/adapters/copilot/references/decisions/single-writer-threat-model.md +53 -0
  128. package/adapters/copilot/references/epic-state-schema.json +50 -0
  129. package/adapters/copilot/references/forge-config-schema.json +18 -0
  130. package/adapters/copilot/references/forge-decisions-schema.json +33 -0
  131. package/adapters/copilot/references/pipeline-state-schema.json +34 -2
  132. package/adapters/copilot/references/process-overview.md +2 -2
  133. package/adapters/copilot/references/ralph-loop-contract.md +6 -3
  134. package/adapters/copilot/references/shared-conventions.md +44 -33
  135. package/adapters/copilot/references/stage-exit-protocol.md +64 -20
  136. package/adapters/copilot/scripts/epic-manifest.py +82 -4
  137. package/adapters/copilot/scripts/fix-sweep.py +1180 -0
  138. package/adapters/copilot/scripts/forge-session.py +1124 -26
  139. package/adapters/copilot/skills/forge/forge.md +8 -8
  140. package/adapters/copilot/skills/forge/references/pipeline-state-schema.json +34 -2
  141. package/adapters/copilot/skills/forge/references/process-overview.md +2 -2
  142. package/adapters/copilot/skills/forge/references/shared-conventions.md +44 -33
  143. package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +64 -20
  144. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +14 -10
  145. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  146. package/adapters/copilot/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  147. package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +44 -33
  148. package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  149. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +3 -1
  150. package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +44 -33
  151. package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  152. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +5 -1
  153. package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +44 -33
  154. package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  155. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +5 -1
  156. package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +44 -33
  157. package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  158. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +41 -3
  159. package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  160. package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  161. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +36 -36
  162. package/adapters/copilot/skills/forge-5-loop/references/agent-selection.md +17 -1
  163. package/adapters/copilot/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  164. package/adapters/copilot/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  165. package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +40 -11
  166. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +26 -8
  167. package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +44 -33
  168. package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  169. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +29 -6
  170. package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +44 -33
  171. package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  172. package/adapters/copilot/skills/forge-fix/forge-fix.md +34 -0
  173. package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +44 -33
  174. package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  175. package/adapters/copilot/skills/forge-guide/forge-guide.md +1 -1
  176. package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +18 -0
  177. package/adapters/copilot/skills/forge-guide/references/process-overview.md +2 -2
  178. package/adapters/copilot/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  179. package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +44 -33
  180. package/adapters/copilot/skills/forge-init/forge-init.md +1 -1
  181. package/adapters/copilot/skills/forge-verify/forge-verify.md +11 -12
  182. package/adapters/copilot/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  183. package/adapters/copilot/skills/forge-verify/references/findings-template.md +32 -2
  184. package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +44 -33
  185. package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  186. package/adapters/copilot/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  187. package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  188. package/adapters/copilot/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  189. package/adapters/copilot/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  190. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  191. package/adapters/cursor/agents/forge-verifier.mdc +3 -1
  192. package/adapters/cursor/references/decisions/single-writer-threat-model.md +53 -0
  193. package/adapters/cursor/references/epic-state-schema.json +50 -0
  194. package/adapters/cursor/references/forge-config-schema.json +18 -0
  195. package/adapters/cursor/references/forge-decisions-schema.json +33 -0
  196. package/adapters/cursor/references/pipeline-state-schema.json +34 -2
  197. package/adapters/cursor/references/process-overview.md +2 -2
  198. package/adapters/cursor/references/ralph-loop-contract.md +6 -3
  199. package/adapters/cursor/references/shared-conventions.md +44 -33
  200. package/adapters/cursor/references/stage-exit-protocol.md +64 -20
  201. package/adapters/cursor/scripts/epic-manifest.py +82 -4
  202. package/adapters/cursor/scripts/fix-sweep.py +1180 -0
  203. package/adapters/cursor/scripts/forge-session.py +1124 -26
  204. package/adapters/cursor/skills/forge/forge.mdc +8 -8
  205. package/adapters/cursor/skills/forge/references/pipeline-state-schema.json +34 -2
  206. package/adapters/cursor/skills/forge/references/process-overview.md +2 -2
  207. package/adapters/cursor/skills/forge/references/shared-conventions.md +44 -33
  208. package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +64 -20
  209. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +14 -10
  210. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  211. package/adapters/cursor/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  212. package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +44 -33
  213. package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  214. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +3 -1
  215. package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +44 -33
  216. package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  217. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +5 -1
  218. package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +44 -33
  219. package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  220. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +5 -1
  221. package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +44 -33
  222. package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  223. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +41 -3
  224. package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  225. package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  226. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +36 -36
  227. package/adapters/cursor/skills/forge-5-loop/references/agent-selection.md +17 -1
  228. package/adapters/cursor/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  229. package/adapters/cursor/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  230. package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +40 -11
  231. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +26 -8
  232. package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +44 -33
  233. package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  234. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +29 -6
  235. package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +44 -33
  236. package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  237. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +34 -0
  238. package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +44 -33
  239. package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  240. package/adapters/cursor/skills/forge-guide/forge-guide.mdc +1 -1
  241. package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +18 -0
  242. package/adapters/cursor/skills/forge-guide/references/process-overview.md +2 -2
  243. package/adapters/cursor/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  244. package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +44 -33
  245. package/adapters/cursor/skills/forge-init/forge-init.mdc +1 -1
  246. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +11 -12
  247. package/adapters/cursor/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  248. package/adapters/cursor/skills/forge-verify/references/findings-template.md +32 -2
  249. package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +44 -33
  250. package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  251. package/adapters/cursor/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  252. package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  253. package/adapters/cursor/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  254. package/adapters/cursor/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  255. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  256. package/adapters/gemini/agents/forge-verifier.md +3 -1
  257. package/adapters/gemini/gemini-extension.json +1 -1
  258. package/adapters/gemini/references/decisions/single-writer-threat-model.md +53 -0
  259. package/adapters/gemini/references/epic-state-schema.json +50 -0
  260. package/adapters/gemini/references/forge-config-schema.json +18 -0
  261. package/adapters/gemini/references/forge-decisions-schema.json +33 -0
  262. package/adapters/gemini/references/pipeline-state-schema.json +34 -2
  263. package/adapters/gemini/references/process-overview.md +2 -2
  264. package/adapters/gemini/references/ralph-loop-contract.md +6 -3
  265. package/adapters/gemini/references/shared-conventions.md +44 -33
  266. package/adapters/gemini/references/stage-exit-protocol.md +64 -20
  267. package/adapters/gemini/scripts/epic-manifest.py +82 -4
  268. package/adapters/gemini/scripts/fix-sweep.py +1180 -0
  269. package/adapters/gemini/scripts/forge-session.py +1124 -26
  270. package/adapters/gemini/skills/forge/forge.md +8 -8
  271. package/adapters/gemini/skills/forge/references/pipeline-state-schema.json +34 -2
  272. package/adapters/gemini/skills/forge/references/process-overview.md +2 -2
  273. package/adapters/gemini/skills/forge/references/shared-conventions.md +44 -33
  274. package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +64 -20
  275. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +14 -10
  276. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  277. package/adapters/gemini/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  278. package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +44 -33
  279. package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
  280. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +3 -1
  281. package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +44 -33
  282. package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
  283. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +5 -1
  284. package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +44 -33
  285. package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
  286. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +5 -1
  287. package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +44 -33
  288. package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
  289. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +41 -3
  290. package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +44 -33
  291. package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
  292. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +36 -36
  293. package/adapters/gemini/skills/forge-5-loop/references/agent-selection.md +17 -1
  294. package/adapters/gemini/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  295. package/adapters/gemini/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  296. package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +40 -11
  297. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +26 -8
  298. package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +44 -33
  299. package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
  300. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +29 -6
  301. package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +44 -33
  302. package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
  303. package/adapters/gemini/skills/forge-fix/forge-fix.md +34 -0
  304. package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +44 -33
  305. package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +64 -20
  306. package/adapters/gemini/skills/forge-guide/forge-guide.md +1 -1
  307. package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +18 -0
  308. package/adapters/gemini/skills/forge-guide/references/process-overview.md +2 -2
  309. package/adapters/gemini/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  310. package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +44 -33
  311. package/adapters/gemini/skills/forge-init/forge-init.md +1 -1
  312. package/adapters/gemini/skills/forge-verify/forge-verify.md +11 -12
  313. package/adapters/gemini/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  314. package/adapters/gemini/skills/forge-verify/references/findings-template.md +32 -2
  315. package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +44 -33
  316. package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +64 -20
  317. package/adapters/gemini/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  318. package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  319. package/adapters/gemini/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  320. package/adapters/gemini/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  321. package/adapters/pi/.feature-forge-bundle.json +1 -1
  322. package/adapters/pi/agents/forge-verifier.md +3 -1
  323. package/adapters/pi/references/decisions/single-writer-threat-model.md +53 -0
  324. package/adapters/pi/references/epic-state-schema.json +50 -0
  325. package/adapters/pi/references/forge-config-schema.json +18 -0
  326. package/adapters/pi/references/forge-decisions-schema.json +33 -0
  327. package/adapters/pi/references/pipeline-state-schema.json +34 -2
  328. package/adapters/pi/references/process-overview.md +2 -2
  329. package/adapters/pi/references/ralph-loop-contract.md +6 -3
  330. package/adapters/pi/references/shared-conventions.md +33 -22
  331. package/adapters/pi/references/stage-exit-protocol.md +63 -19
  332. package/adapters/pi/scripts/epic-manifest.py +82 -4
  333. package/adapters/pi/scripts/fix-sweep.py +1180 -0
  334. package/adapters/pi/scripts/forge-session.py +1124 -26
  335. package/adapters/pi/skills/forge/SKILL.md +5 -5
  336. package/adapters/pi/skills/forge/references/pipeline-state-schema.json +34 -2
  337. package/adapters/pi/skills/forge/references/process-overview.md +2 -2
  338. package/adapters/pi/skills/forge/references/shared-conventions.md +33 -22
  339. package/adapters/pi/skills/forge/references/stage-exit-protocol.md +63 -19
  340. package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +8 -4
  341. package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
  342. package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +34 -2
  343. package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +33 -22
  344. package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +63 -19
  345. package/adapters/pi/skills/forge-1-prd/SKILL.md +3 -1
  346. package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +33 -22
  347. package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +63 -19
  348. package/adapters/pi/skills/forge-2-tech/SKILL.md +5 -1
  349. package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +33 -22
  350. package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +63 -19
  351. package/adapters/pi/skills/forge-3-specs/SKILL.md +5 -1
  352. package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +33 -22
  353. package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +63 -19
  354. package/adapters/pi/skills/forge-4-backlog/SKILL.md +41 -3
  355. package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +33 -22
  356. package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +63 -19
  357. package/adapters/pi/skills/forge-5-loop/SKILL.md +36 -36
  358. package/adapters/pi/skills/forge-5-loop/references/agent-selection.md +16 -0
  359. package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
  360. package/adapters/pi/skills/forge-5-loop/references/recovery-procedure.md +349 -0
  361. package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +40 -11
  362. package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +25 -7
  363. package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +33 -22
  364. package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +63 -19
  365. package/adapters/pi/skills/forge-6-docs/SKILL.md +29 -6
  366. package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +33 -22
  367. package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +63 -19
  368. package/adapters/pi/skills/forge-fix/SKILL.md +34 -0
  369. package/adapters/pi/skills/forge-fix/references/shared-conventions.md +33 -22
  370. package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +63 -19
  371. package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +18 -0
  372. package/adapters/pi/skills/forge-guide/references/process-overview.md +2 -2
  373. package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +6 -3
  374. package/adapters/pi/skills/forge-guide/references/shared-conventions.md +33 -22
  375. package/adapters/pi/skills/forge-verify/SKILL.md +10 -11
  376. package/adapters/pi/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
  377. package/adapters/pi/skills/forge-verify/references/findings-template.md +31 -1
  378. package/adapters/pi/skills/forge-verify/references/shared-conventions.md +33 -22
  379. package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +63 -19
  380. package/adapters/pi/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
  381. package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  382. package/adapters/pi/skills/forge-verify/references/verification-checklists/impl.md +85 -0
  383. package/adapters/pi/skills/forge-verify/references/verification-checklists/specs.md +43 -1
  384. package/package.json +1 -1
@@ -0,0 +1,349 @@
1
+ # forge-5-loop — Post-Run Recovery Procedure
2
+
3
+ The named procedure that turns a needs-human / blocked loop stop into a resumable backlog
4
+ without losing the operator's decision. It runs **after** a loop run ends — entered
5
+ **unconditionally** from SKILL Step 4c on every run close, whatever the counts say (the
6
+ `needs_human` / `item_blocked` live-event handling in `runner-contract.md` collects
7
+ answers early for it, but is **not** the entry condition) — and it runs again as the
8
+ **re-entry point** on a fresh session (§3).
9
+ Its seven ordered steps: **enumerate → cluster → consolidated prompts →
10
+ record-at-collection → apply → prove → gate & exit**.
11
+
12
+ Notation: `{backlogDir}` is the resolved backlog directory (SKILL Step 2b);
13
+ `{stateDir}` is the effective-config `loopRunner.stateDir` (default `.rauf`); `$R` is the
14
+ plugin root the SKILL's bootstrap prelude resolves; runner commands are the substituted
15
+ `loopRunner.*Command` forms with the SKILL's token substitution (`{bin}` etc.).
16
+
17
+ ## 1. Scope and the failure rule
18
+
19
+ The procedure orchestrates scripted substrate; it never improvises state. Decisions live
20
+ in `{backlogDir}/{stateDir}/forge-decisions.json` — append-only, written **only** by the
21
+ `decision-record` / `decision-list` / `decision-apply` verbs of
22
+ `scripts/forge-session.py` (schema: `references/forge-decisions-schema.json`), never by
23
+ hand. Being under the git-ignored state dir, the record survives session end and context
24
+ clear but never dirties the working tree that §4 inspects.
25
+
26
+ **The failure rule (applies to every step).** Any scripted step that exits non-zero, and
27
+ any runner invocation that errors or returns unparseable output, is surfaced **verbatim**
28
+ and **STOPS** the procedure with a **failed recovery** report — never reported as
29
+ recorded/succeeded. A failed *apply* (step 5) is distinguishable from a
30
+ ran-but-nothing-moved *proof* failure (step 6) because the former never reaches step 6
31
+ (§6).
32
+
33
+ ## 2. The seven steps
34
+
35
+ ### Step 1 — Enumerate
36
+
37
+ - **Input:** `{backlogDir}`; the runner's authoritative item list.
38
+ - **CLI:**
39
+ ```
40
+ python3 "$R/scripts/forge-session.py" decision-list --backlog-dir {backlogDir} --unapplied --json
41
+ {bin} backlog list . --backlog {backlogDir} --json # the substituted listCommand
42
+ ```
43
+ The unapplied set is the **latest entry per `itemId` with `appliedAt == null`** —
44
+ deferrals included, applied items excluded.
45
+ - **Decision point:** if the unapplied set is **empty** and no item is
46
+ `blocked`/`needsHuman`, there is nothing to decide or apply: **skip steps 2–6 and go
47
+ straight to step 7 — never exit around it.** Step 7's §4 tree reconciliation still
48
+ runs (it is what catches work stranded without any signal), and its `resolved` gate
49
+ does not apply — **an empty affected set never selects `resolved`**; the SKILL Step 7
50
+ ladder falls through to its count-based rungs. Combined with the clean-tree silence
51
+ of §4.1, this keeps a happy-path run free of any new prompt; the only new happy-path
52
+ output is the Step 2a depth line.
53
+ - **Output:** the unapplied-decision set (each entry's `itemId`, `question`,
54
+ `answer|null`, `deferred`, `clusterId?`), and the live blocked/needs-human item set.
55
+ - **Error:** a `decision-list` exit 2 (unknown dir, unparseable record) stops the
56
+ procedure. A failed `listCommand` read stops it as a failed recovery.
57
+
58
+ ### Step 2 — Cluster
59
+
60
+ - **Input:** the blocked/needs-human items from step 1, each carrying its
61
+ `blockedReason` (where the runner lands the `RAUF_NEEDS_HUMAN:<reason>` text).
62
+ - **CLI:**
63
+ ```
64
+ python3 "$R/scripts/forge-session.py" backlog-topology --items-stdin --cluster --json < items.json
65
+ ```
66
+ fed the **same** `listCommand` JSON already obtained (single data source — never a
67
+ `backlog.json` path). Returns `clusters[]`: each with `memberIds`, `memberReasons`,
68
+ `sharedTokens`, and the **union** of members' gated subtrees (`gatedIds` +
69
+ `gatedCount`).
70
+ - **Decision point:** you **may merge or refine** candidate clusters by judgment —
71
+ under-clustering is the deliberately-chosen failure direction of the scripted helper,
72
+ so its clusters are a floor, not a ceiling. You have no scripted *split* authority.
73
+ - **Output:** the final cluster set (scripted candidates ± your merges), each with its
74
+ member ids and blast-radius numbers.
75
+ - **Error:** a `backlog-topology` exit 2 stops the procedure.
76
+
77
+ ### Step 3 — Consolidated prompts
78
+
79
+ - **Input:** the final cluster set from step 2.
80
+ - **Mechanism:** `AskUserQuestion` (never inline prose).
81
+ - For any cluster of **two or more** items: emit **exactly one** consolidated question
82
+ that **names every affected item id** and states the **full gated subtree** the
83
+ cluster gates. Frame it by **blast radius** — e.g. *"This one decision gates 13 of
84
+ 16 backlog items (items 2, 3, …). Answer it once."* — never one prompt per member.
85
+ - Singleton clusters prompt per item (today's per-item shape).
86
+ - **Security:** prompts **MUST NOT solicit secrets**. Ask for the *decision* (which
87
+ path, which policy), never a credential/token/key value. The decision record has no
88
+ credential-shaped field and is treated as repo-visible content.
89
+ - **Decision point:** the operator may **answer**, **defer** the decision, or request
90
+ **cancel the run early** — all three branches proceed to step 4 (nothing is acted on
91
+ before it is recorded).
92
+ - **Output:** per cluster/item, one of {answer text, deferral, cancel-early}.
93
+ - **Citation:** the blast-radius framing is derived from `backlog-topology --cluster`
94
+ gated-subtree output (member ids + counts) — the prompt cites that source; a
95
+ "gates N/M" claim the topology output contradicts is a defect.
96
+
97
+ ### Step 4 — Record at collection
98
+
99
+ - **Input:** every branch outcome from step 3.
100
+ - **CLI (one call per decision, BEFORE anything is applied):**
101
+ ```
102
+ # answered singleton
103
+ python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
104
+ --item ID --question "Q" --answer "A"
105
+ # deferred, or cancel-early (both record a deferral: no --answer)
106
+ python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
107
+ --item ID --question "Q" --deferred
108
+ # consolidated answer: one entry per affected item, shared clusterId
109
+ python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
110
+ --item ID1 --item ID2 --item ID3 --question "Q" --answer "A" --cluster c1
111
+ ```
112
+ (`--actor` defaults to `forge-5-loop@<host>` — a machine label, never user identity.)
113
+ - **Decision point:** a decision is recorded on **every** branch — answered, deferred,
114
+ **and** cancel-early — and it is recorded **before** step 5 acts on anything. A
115
+ cancel-early is recorded as a **deferral** (`answer: null`, `deferred: true`,
116
+ `question` carrying the original needs-human text) — there is no third entry form. A
117
+ recorded-but-unapplied entry (`appliedAt == null`) is exactly what step 1 re-surfaces
118
+ on the next launch (§3).
119
+ - **Consolidated:** one entry per affected item, all sharing one `clusterId` (minted
120
+ `c` + lowest member id). Items stay **independently re-decidable**: a later per-item
121
+ entry supersedes the cluster entry for that item only.
122
+ - **Output:** durable append-only entries in `forge-decisions.json`; the write is
123
+ atomic.
124
+ - **Error:** any `decision-record` exit 2 (both/neither of `--answer`/`--deferred`,
125
+ unknown dir, failed atomic write) is surfaced verbatim and stops the procedure. The
126
+ answer is **not** applied if it was not recorded.
127
+
128
+ ### Step 5 — Apply
129
+
130
+ - **Version probe (once, at the start of this step):** run the substituted
131
+ `loopRunner.versionCommand` (default `{bin} version --json`), parse
132
+ `{ "version": "<semver>" }`, and numerically semver-compare it against
133
+ `RECOVERY_MIN_RUNNER_VERSION` (a `scripts/forge-session.py` module constant, `0.14.0`
134
+ — the capability threshold for `{bin} backlog answer`; **not**
135
+ `loopRunner.minRunnerVersion`, which stays the launch floor). A probe miss
136
+ (missing/old/unparseable version) is **never** a hard failure — it selects the
137
+ degraded path and is reported with `loopRunner.installHint`.
138
+ - **Apply per item** (full dispatch table in §5):
139
+ - needs-human item, runner **≥** threshold →
140
+ `{bin} backlog answer . {id} "{answer}" --backlog {backlogDir} --json`
141
+ (the answer text is threaded into the next iteration's prompt).
142
+ - needs-human item, runner **<** threshold → **degraded path:**
143
+ `{bin} backlog unblock . {id} --backlog {backlogDir} --json` — the item is genuinely
144
+ unblocked and the answer stays durable in `forge-decisions.json`, but the recovery
145
+ report **must state explicitly** that the answer was **not** injected into the next
146
+ iteration's prompt, with the `installHint` upgrade hint attached.
147
+ - plain (non-needs-human) blocked item → `{bin} backlog unblock` at **every** runner
148
+ version.
149
+ - **Stamp:** after each runner apply **succeeds**, run
150
+ ```
151
+ python3 "$R/scripts/forge-session.py" decision-apply --backlog-dir {backlogDir} --item ID
152
+ ```
153
+ which stamps `appliedAt`/`appliedBy` on the item's latest entry. `decision-apply` is
154
+ called **only after** the runner apply returned success — a stamped record means the
155
+ runner actually accepted the change.
156
+ - **Error:** a runner apply that **errors** (non-zero exit — item missing, not
157
+ `blocked`, or any failure) is a **failed apply**: surface it verbatim, do **not** call
158
+ `decision-apply`, stop the procedure, report failed recovery. This is distinct from a
159
+ version-probe miss (which routes to the degraded path, not a failure) and from step
160
+ 6's ran-but-nothing-moved failure (§6).
161
+
162
+ ### Step 6 — Prove
163
+
164
+ - **Input:** the affected item set that step 5 applied.
165
+ - **CLI:** re-read per-item state via the substituted `loopRunner.listCommand`
166
+ (`{bin} backlog list . --backlog {backlogDir} --json`) and test **each** affected
167
+ item: `status != "blocked"` — which, per the runner's derivation
168
+ (needs-human ⇔ `status=="blocked" && needsHuman==true`), also removes it from the
169
+ needs-human count, so the single test covers both flags. Aggregate `backlogSummary`
170
+ counts are **never** the test. An affected item **missing** from the re-read counts
171
+ as a non-mover.
172
+ - **Decision point:** **all** affected items moved → proceed to step 7. **Any**
173
+ non-mover — including a partial move where some items moved and others did not — is a
174
+ **failed recovery**: report it, **naming the movers and the non-movers** from their
175
+ item `status` fields.
176
+ - **Output:** either "all moved → continue" or a failed-recovery report.
177
+ - **Citation:** the movers/non-movers are named from the per-item `listCommand` re-read
178
+ (`status` fields), never from aggregate counts — a report that contradicts the
179
+ per-item read is a defect.
180
+
181
+ ### Step 7 — Gate & exit
182
+
183
+ - **Tree reconciliation first.** Before any outcome is selected, run the **Post-Run
184
+ Tree Reconciliation** section (§4). It runs on every recovery pass — including passes
185
+ with no needs-human items — and is silent on a clean tree.
186
+ - **Evaluate the `resolved` gate — all three must hold:**
187
+ 1. `decision-list --unapplied` is **empty for the affected items**. The verb returns
188
+ the **global** latest-unapplied-per-item set, so **intersect** that payload's
189
+ entries (each carries `itemId`) with this session's affected-item set and test
190
+ only that intersection for emptiness — an unrelated item's stray deferral must not
191
+ suppress a legitimate `resolved`.
192
+ 2. `git status --porcelain` is **clean** (git-ignored `{stateDir}` artifacts are
193
+ invisible to porcelain — the exclusion holds by construction).
194
+ 3. the per-item re-read (step 6) shows **every** affected item left
195
+ `blocked`/`needsHuman`.
196
+ - **Select the outcome:** on all-three-pass, select `resolved` — the first rung of the
197
+ ladder in `result-reporting.md`, so a resolved stop never re-triggers the needs-human
198
+ branch its own recovery just cleared. **Any one gate failing falls the ladder
199
+ through** to `needs-human` / `blocked` / `deferred` / `partial` / `complete` exactly
200
+ as today. `resolved` routes **resume** — its NEXT-STEPS block fences
201
+ `/feature-forge:forge-5-loop {feature}`, never the navigator.
202
+ - **CLI:** the close runs through the Scripted Stage Exit (SKILL Step 7):
203
+ `stage-exit … --outcome resolved …`. `stage-exit` does **not** re-verify the gate
204
+ server-side (it has no runner access) — enforcement is procedural: this step.
205
+ - **Citation:** the `resolved` outcome text cites the three gate evaluations
206
+ (`decision-list --unapplied` empty, porcelain empty, per-item re-read all-moved).
207
+ Claiming `resolved` without those preconditions is a reportable defect.
208
+
209
+ ## 3. Fresh-session re-entry
210
+
211
+ The procedure is the **re-entry point** on a fresh session / next launch — this is what
212
+ makes a decision survive session end and context clear.
213
+
214
+ On a new session, **step 1** enumerates every entry with `appliedAt == null` from a
215
+ *previous* session — answered-but-not-yet-applied decisions, deferrals, and cancel-early
216
+ deferrals alike. Those entries are re-surfaced:
217
+
218
+ - An entry that already carries an **answer** (`answer != null`, `deferred == false`,
219
+ `appliedAt == null`) **skips step 3's prompt** for that item — the operator already
220
+ decided; the procedure proceeds straight to step 5 (apply) and step 6 (prove). The
221
+ answer collected last session is applied this session without re-asking.
222
+ - A **deferral** (`deferred == true`) re-surfaces through step 3 as an open decision —
223
+ the operator is asked again, and their new answer appends a **new** entry
224
+ (append-only); the deferral's audit fields are never destroyed.
225
+
226
+ Because entries are durable and untracked, a session boundary, crash, or context clear
227
+ between "operator answered" and "answer applied" never costs the decision — step 1 of
228
+ the next launch finds it.
229
+
230
+ ## 4. Post-Run Tree Reconciliation
231
+
232
+ Invoked from step 7 after the run ends and **before** any outcome is selected. It runs
233
+ on **every** recovery pass — including passes with no needs-human items, which step 1
234
+ routes here directly, and SKILL Step 4c enters the procedure on every run close —
235
+ because it is the "tree" half of recovery. Four sub-steps.
236
+
237
+ ### 4.1 Detect
238
+
239
+ - **CLI:** `git status --porcelain`.
240
+ - **Clean tree → SILENT.** Empty output ⇒ no prompt, no output, no operator decision.
241
+ The decision record and all runner state under `{stateDir}` are git-ignored and
242
+ therefore never appear in porcelain output — decision writes never dirty the tree
243
+ this step inspects.
244
+ - **Dirty tree → proceed to 4.2.**
245
+ - **Error:** a `git status` failure (not a git repo, git error) is surfaced verbatim;
246
+ reconciliation is skipped (there is nothing git-native to reconcile), the rest of the
247
+ procedure continues.
248
+
249
+ ### 4.2 Attribute (best-effort, runner-native)
250
+
251
+ Best-effort attribution of dirty paths to the backlog item(s) that produced them, from
252
+ runner-native evidence — reliable per-item provenance is **not** a prerequisite.
253
+
254
+ - **Read `{backlogDir}/{stateDir}/state.json`** (the runner's loop state):
255
+ `baseCommitHash` (the HEAD captured at run start — the baseline for
256
+ `git log {baseCommitHash}..HEAD`), `completedItems` / `blockedItems` (item ids that
257
+ finished / blocked), `currentItem` (the item in flight when the run stopped — a
258
+ strong candidate for uncommitted changes), `startedAt` and
259
+ `iteration`/`maxIterations` (run identity + budget).
260
+ - **Read `{backlogDir}/{stateDir}/events.ndjson`** — one JSON object per line; parse
261
+ line-by-line (there is **no** runner CLI for events; the file is read directly). The
262
+ per-iteration `item_selected`, `llm_spawned`, and `llm_exited` records — each
263
+ carrying an `itemId` and a `timestamp` — name which items ran during the window and
264
+ in what order.
265
+ - **Map dirty paths → candidate items:** the `currentItem` and the most recent
266
+ `item_selected`/`llm_spawned` without a matching clean `llm_exited` are the items "in
267
+ flight when the run died"; `git log {baseCommitHash}..HEAD` names what was already
268
+ committed for which item (the runner commits `[rauf] <id>: <title>`). Present the
269
+ mapping as **CANDIDATES, never asserted**.
270
+ - **Degradation (detection never aborts):** if `state.json` or `events.ndjson` is
271
+ missing, unreadable, or unparseable, **degrade** to the fully-unattributed path —
272
+ everything goes into 4.3's single consolidated decision. Detection (4.1) is never
273
+ aborted by an evidence-parse failure.
274
+ - **Citation:** the presentation cites `git status --porcelain` paths +
275
+ `{stateDir}/state.json` / `events.ndjson` run evidence, with every attribution
276
+ explicitly labelled a **candidate**.
277
+
278
+ ### 4.3 Decide
279
+
280
+ - **Mechanism:** `AskUserQuestion` (never inline prose).
281
+ - **One question per attributed item-group:** for each candidate item-group from 4.2,
282
+ offer **commit-for-that-item** / **stash** / **discard**.
283
+ - **Unattributable changes → ONE consolidated decision:** everything that could not
284
+ be attributed is presented as a single grouped question, not dropped.
285
+ - **Discard guard:** **discard is NEVER the default** and requires its **own explicit
286
+ confirmation** — a second, dedicated question via `AskUserQuestion` confirming the specific paths
287
+ to be discarded before any `git checkout`/`git restore`/`git clean` runs. No path is
288
+ discarded on a single click.
289
+ - **Output:** per group, an executed reconciliation (commit / stash / confirmed
290
+ discard) or a deferral the operator can revisit.
291
+
292
+ ### 4.4 Launch blocker
293
+
294
+ The next launch's `### 1g. Stranded-Work Pre-flight` (SKILL Step 1) STOPS on a dirty
295
+ tree when a prior run's `{backlogDir}/{stateDir}/state.json` exists, names that run
296
+ (its `startedAt`, `currentItem`, `blockedItems`), and points at this section to
297
+ commit / stash / discard the stranded work before relaunch. The runner's own
298
+ uncommitted-changes launch refusal remains the backstop for a dirty tree with no
299
+ prior-run state.
300
+
301
+ ## 5. Apply-mechanism dispatch (version gate & the degraded path)
302
+
303
+ | Runner version | Item kind | Apply mechanism | What the report says |
304
+ |---|---|---|---|
305
+ | `≥ RECOVERY_MIN_RUNNER_VERSION` | needs-human (has an answer) | `{bin} backlog answer . {id} "{answer}" --backlog {backlogDir} --json` | Answer applied and threaded into the next iteration's prompt. |
306
+ | `≥ RECOVERY_MIN_RUNNER_VERSION` | plain blocked | `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked. |
307
+ | `< RECOVERY_MIN_RUNNER_VERSION` (or probe miss) | needs-human | **DEGRADE:** `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked; **answer was NOT injected into the next prompt** (durable in `forge-decisions.json`); `{installHint}` — upgrade to a runner that ships `backlog answer` to thread it. |
308
+ | any version (incl. probe miss) | plain blocked | `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked. |
309
+
310
+ Key properties:
311
+
312
+ - **Plain blocked items always use `unblock`, at every version** — they carry no answer
313
+ to thread. The version gate only ever changes the needs-human path.
314
+ - **The degraded needs-human path genuinely unblocks** (the runner clears
315
+ `status`/`blockedReason`/`needsHuman`/`deferred`), so recovery works across the whole
316
+ supported runner floor. The only capability lost below the threshold is
317
+ prompt-threading — the answer remains durable in the decision record and re-surfaces
318
+ via `decision-list --unapplied` if re-decided.
319
+ - **The report is honest either way:** the degraded path states explicitly that the
320
+ answer was not threaded, with the upgrade hint.
321
+
322
+ ## 6. Failure taxonomy
323
+
324
+ | Failure | When it occurs | Reaches the step-6 per-item test? | Report |
325
+ |---|---|---|---|
326
+ | **Failed apply** | `{bin} backlog answer` / `unblock` exits non-zero (corrupt backlog, I/O error, not-blocked/not-found refusal); or the post-apply re-read is unparseable | **No** — stops *before* the test | Verbatim runner error + which item; **failed recovery**; procedure stops; never claimed succeeded |
327
+ | **Ran-but-nothing-moved** | Every apply exited 0, but the step-6 per-item test finds a non-mover | **Yes** — *is* the test failing | Movers/non-movers named from `status` fields; **failed recovery** |
328
+ | **Version-probe miss** | `versionCommand` missing/unparseable, or version `< RECOVERY_MIN_RUNNER_VERSION` | N/A — selects the degraded path (§5) | Degraded path proceeds; not-threaded caveat + `installHint`; **not** a failed recovery |
329
+
330
+ Rules: never report recorded/succeeded past a failed step; a failed apply stops before
331
+ the per-item test, so a runner that errored is never conflated with a runner that ran
332
+ cleanly but moved nothing; `decision-apply` is not called for a failed item — the record
333
+ stays unapplied and re-surfaces next launch; a probe miss degrades, it never fails
334
+ recovery.
335
+
336
+ ## 7. Report citations (REQ-OBS-01)
337
+
338
+ Every report surface this procedure produces names the authoritative source it derived
339
+ its claims from; a claim that source contradicts is a reportable defect. Each report
340
+ surface names the authoritative source it derives its claims from:
341
+
342
+ | Report surface | Authoritative citation basis |
343
+ |---|---|
344
+ | Pending / starvation template | `backlogSummary` counts + `backlog-topology` output over `listCommand` JSON; iteration counters from `state.json` (`iteration`/`maxIterations`) |
345
+ | Failed-recovery report (§2 step 6) | The per-item `listCommand` re-read — movers/non-movers named from item `status`, never aggregate counts |
346
+ | `resolved` outcome text | The three gate evaluations: `decision-list --unapplied` (empty), `git status --porcelain` (empty), per-item re-read (all affected left `blocked`) |
347
+ | Consolidated blast-radius prompt (§2 step 3) | `backlog-topology --cluster` gated-subtree output (member ids + counts) |
348
+ | Tree-reconciliation presentation (§4) | `git status --porcelain` paths + `state.json`/`events.ndjson` run evidence, attributions explicitly presented as **candidates** |
349
+ | Step 2a depth line | The same `backlog-topology` output (`maxChainDepth`) |
@@ -64,28 +64,57 @@ Loop completed for {feature}.
64
64
  Deferred: {deferred} items (no signal after retries — likely just need another pass)
65
65
  ```
66
66
 
67
- **Some items still pending (iteration limit reached):**
67
+ **Some items still pending** — the parenthetical cause is chosen, never hardcoded:
68
68
  ```
69
69
  Loop completed for {feature}.
70
70
  Completed: {done}/{total}
71
- Pending: {pending} items (iteration limit reached)
71
+ Pending: {pending} items ({cause})
72
72
  Blocked: {blocked} items
73
73
  ```
74
+ Render `{cause}` as "iteration limit reached" **only** when `iteration == maxIterations`
75
+ AND `selectable > 0` — cite the `iteration`/`maxIterations` counters from
76
+ `{loopRunner.stateDir}/state.json` and `selectable` from `backlog-topology --items-stdin
77
+ --json` run over the same authoritative item JSON as the counts above. Otherwise —
78
+ `selectable == 0` with items still pending while `iteration < maxIterations` — the
79
+ iteration limit was NOT the constraint: drop the parenthetical and render this
80
+ dependency-starvation report instead, naming each blocking root and its gated-subtree
81
+ size from `backlog-topology`'s `starvation.blockingRoots[].{id, gatedCount}` and
82
+ `itemCount`, then close the stage with `--cause dependency-starvation` in Step 7:
83
+ ```
84
+ Loop stopped for {feature} with {pending} item(s) still pending, but the iteration
85
+ limit was NOT the constraint ({iteration}/{maxIterations} iterations used).
86
+ No pending item was selectable — every one is gated behind unblocked roots:
87
+ - {rootId}: {rootTitle} — gates {gatedCount}/{itemCount} items
88
+ Unblock these roots (their subtrees free up on the next run), then run the loop again.
89
+ ```
90
+ Both branches cite their authoritative source: the iteration-limit branch the
91
+ `state.json` iteration counters, the starvation branch the backlog summary counts plus
92
+ the `backlog-topology` output (`selectable`, `blockingRoots`, `gatedCount`,
93
+ `itemCount`). A cause any of those counters contradicts — e.g. "iteration limit
94
+ reached" while `iteration < maxIterations` — is a reportable defect.
74
95
 
75
96
  ## Selecting the one `LoopOutcome` (Step 7)
76
97
 
77
98
  After Step 5's `state-complete`, select exactly **one** `LoopOutcome` from Step 4a's
78
99
  authoritative final counts. Walk this ladder in order and stop at the first match:
79
100
 
80
- 1. **`needs-human`** — `needsHuman > 0`. This wins even when blocked items also
81
- exist: a decision only a human can make outranks work that merely could not
82
- proceed.
83
- 2. **`blocked`** — otherwise, genuine `blocked > 0`.
84
- 3. **`deferred`** — otherwise, runner-deferred items exist (the "false blocks" the
101
+ 1. **`resolved`** — the Post-Run Recovery Procedure
102
+ (`references/recovery-procedure.md`) ran this session with a **non-empty**
103
+ affected-item set and its gate passed: every affected needs-human item has an
104
+ applied decision record, the working tree is clean, and each affected item left
105
+ `blocked`/`needsHuman` per the per-item re-read. This outranks `needs-human` so a
106
+ stop the recovery just cleared is not re-reported as still needing a human. (Step
107
+ 4c runs the procedure on every close, so an empty affected set is the common case —
108
+ it never selects `resolved`; fall through.)
109
+ 2. **`needs-human`** — otherwise, `needsHuman > 0`. This wins even when blocked
110
+ items also exist: a decision only a human can make outranks work that merely
111
+ could not proceed.
112
+ 3. **`blocked`** — otherwise, genuine `blocked > 0`.
113
+ 4. **`deferred`** — otherwise, runner-deferred items exist (the "false blocks" the
85
114
  runner gave up on after retries).
86
- 4. **`partial`** — otherwise, `pending`/`in_progress` items remain because the
115
+ 5. **`partial`** — otherwise, `pending`/`in_progress` items remain because the
87
116
  iteration limit was reached.
88
- 5. **`complete`** — otherwise, and **only** when every item is `done`.
117
+ 6. **`complete`** — otherwise, and **only** when every item is `done`.
89
118
 
90
119
  This is a priority order, not a set. A run reporting both a needs-human and a blocked
91
120
  count renders both reports above and still exits `needs-human`.
@@ -95,8 +124,8 @@ reported only that its process finished; the final backlog state decides. A clea
95
124
  exit 0 that still leaves pending items is `partial`, never `complete` — and
96
125
  `complete` is legitimate only when the counts show every item `done`.
97
126
 
98
- **Retrying the non-complete outcomes.** `partial` and `deferred` fence the loop
99
- resume; `blocked` and `needs-human` fence the navigator. Whichever you land on, the
127
+ **Retrying the non-complete outcomes.** `partial`, `deferred`, and `resolved` fence
128
+ the loop resume; `blocked` and `needs-human` fence the navigator. Whichever you land on, the
100
129
  runner's own retry flags still apply to the next run — e.g. rauf's `--retry-blocked`
101
130
  picks the set-aside blocked and deferred items back up at Step 2d. Mention that as
102
131
  plain prose in the report if it helps; never as a second command block.
@@ -31,7 +31,7 @@ pass after all iterations complete (an extra agent session that re-examines the
31
31
  finished work and can file follow-up backlog items). feature-forge treats **running
32
32
  with review as the recommended default** — a review pass is cheap relative to the
33
33
  loop it audits, and catches gaps before the pipeline moves on to docs. So Step 2d
34
- adds a **"Run mode"** question to the confirmation's `AskUserQuestion` surface with a
34
+ adds a **"Run mode"** question, via `AskUserQuestion`, to the confirmation surface with a
35
35
  **fixed, non-improvised option order** (determinism is the point — the option set
36
36
  must not vary run-to-run):
37
37
 
@@ -47,6 +47,19 @@ Run mode:
47
47
  review pass and also unblocks/retries the previously blocked items.
48
48
  ```
49
49
 
50
+ **`loopRunner.reviewMode` gate (`"prompt"` default | `"always"` | `"never"`).**
51
+ The Run-mode question above is presented only when the effective
52
+ `loopRunner.reviewMode` is `"prompt"` — the default, byte-identical to today.
53
+ `"always"` **skips the question** and appends `--review` unconditionally; the
54
+ confirmation's rendered command line still shows `--review`, so the choice is
55
+ never hidden. `"never"` **skips the question** and launches the bare rendered
56
+ command. Under `"always"`/`"never"`, when — and only when — the Step 2a tally has
57
+ `blocked > 0`, present a **narrower situational question** in the question's
58
+ place offering only the retry-blocked choice (on yes, additionally append
59
+ `--retry-blocked`; the `--review` decision is already fixed by the mode and is
60
+ **not** re-asked); with no blocked items, the Run-mode surface asks nothing. An
61
+ unrecognized value behaves as `"prompt"`.
62
+
50
63
  Notes:
51
64
 
52
65
  - **Option 1 is the default** and the confirmation's rendered command line shows
@@ -179,12 +192,17 @@ high and the noise low:
179
192
  immediately** and send a **`PushNotification`** (an hours-long run means the user has
180
193
  likely stepped away). **Important — the loop is NOT paused:** the runner has set that
181
194
  item aside and kept working other items. So report *what* needs a human and *which*
182
- item, then either (a) collect the user's answer via `AskUserQuestion` to **stage a
183
- post-run retry**, or (b) offer to **cancel the run early** if the answer changes the
184
- whole plan. Do not tell the user the loop is waiting on their reply — it isn't.
195
+ item, then either (a) collect the user's answer via `AskUserQuestion` and **record it via
196
+ `decision-record` now** — SKILL Step 4c's unconditional **Post-Run Recovery Procedure**
197
+ pass (`references/recovery-procedure.md`) applies it after the run ends — or (b) offer
198
+ to **cancel the run early** (also recorded via `decision-record` — a deferral) if the
199
+ answer changes the whole plan. Do not tell the user the loop is waiting on their reply
200
+ — it isn't.
185
201
  - **`item_blocked`** → surface the blocked item + reason now (visibility) and
186
202
  accumulate for the final summary. Use `{rendered statusJsonCommand}` to distinguish a
187
203
  genuine `blocked` from a runner-`deferred` "false block" (`backlogSummary.deferred`).
204
+ No action is needed now: Step 4c's recovery pass offers the unblock after the run
205
+ ends — a blocked-only run (no `needs_human` event) still enters it.
188
206
  - **`loop_error`** → a real failure (this is also what a circuit-breaker halt — too many
189
207
  consecutive infra failures — emits). Surface now and `PushNotification`. Offer
190
208
  inspection / `--force` / re-run as appropriate.
@@ -36,7 +36,7 @@ I found that the codebase uses React and TanStack Router.
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 `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:
40
40
 
41
41
  - **Lead with a recommended option.** Place it first and label it `(recommended)` (matching the `AskUserQuestion` "(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.
@@ -53,6 +53,17 @@ For genuinely comparable artifacts (competing module structures, two code snippe
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 `AskUserQuestion`; 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.
@@ -130,7 +141,7 @@ 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
147
  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')"
@@ -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
 
@@ -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 `AskUserQuestion` ("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