@garygentry/feature-forge 0.2.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/README.md +6 -3
  2. package/adapters/GENERATION-REPORT.md +20 -0
  3. package/adapters/claude/.feature-forge-bundle.json +1 -1
  4. package/adapters/claude/references/epic-manifest-schema.json +5 -0
  5. package/adapters/claude/references/forge-config-schema.json +2 -2
  6. package/adapters/claude/references/shared-conventions.md +12 -0
  7. package/adapters/claude/references/stacks/_generic.md +21 -0
  8. package/adapters/claude/references/stacks/go.md +19 -0
  9. package/adapters/claude/references/stacks/python.md +21 -0
  10. package/adapters/claude/references/stacks/rust.md +19 -0
  11. package/adapters/claude/references/stacks/typescript.md +23 -0
  12. package/adapters/claude/scripts/epic-manifest.py +75 -5
  13. package/adapters/claude/scripts/forge-root.sh +102 -14
  14. package/adapters/claude/scripts/forge-session.py +68 -9
  15. package/adapters/claude/skills/forge/references/shared-conventions.md +12 -0
  16. package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +12 -0
  17. package/adapters/claude/skills/forge-1-prd/SKILL.md +2 -0
  18. package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +12 -0
  19. package/adapters/claude/skills/forge-2-tech/SKILL.md +2 -0
  20. package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +12 -0
  21. package/adapters/claude/skills/forge-2-tech/references/stacks/_generic.md +21 -0
  22. package/adapters/claude/skills/forge-2-tech/references/stacks/go.md +19 -0
  23. package/adapters/claude/skills/forge-2-tech/references/stacks/python.md +21 -0
  24. package/adapters/claude/skills/forge-2-tech/references/stacks/rust.md +19 -0
  25. package/adapters/claude/skills/forge-2-tech/references/stacks/typescript.md +23 -0
  26. package/adapters/claude/skills/forge-3-specs/SKILL.md +2 -0
  27. package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +12 -0
  28. package/adapters/claude/skills/forge-3-specs/references/stacks/_generic.md +21 -0
  29. package/adapters/claude/skills/forge-3-specs/references/stacks/go.md +19 -0
  30. package/adapters/claude/skills/forge-3-specs/references/stacks/python.md +21 -0
  31. package/adapters/claude/skills/forge-3-specs/references/stacks/rust.md +19 -0
  32. package/adapters/claude/skills/forge-3-specs/references/stacks/typescript.md +23 -0
  33. package/adapters/claude/skills/forge-4-backlog/SKILL.md +5 -0
  34. package/adapters/claude/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  35. package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +12 -0
  36. package/adapters/claude/skills/forge-5-loop/SKILL.md +7 -9
  37. package/adapters/claude/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  38. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +41 -0
  39. package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +12 -0
  40. package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +12 -0
  41. package/adapters/claude/skills/forge-fix/references/shared-conventions.md +12 -0
  42. package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +2 -2
  43. package/adapters/claude/skills/forge-guide/references/shared-conventions.md +12 -0
  44. package/adapters/claude/skills/forge-guide/references/stacks/_generic.md +21 -0
  45. package/adapters/claude/skills/forge-guide/references/stacks/go.md +19 -0
  46. package/adapters/claude/skills/forge-guide/references/stacks/python.md +21 -0
  47. package/adapters/claude/skills/forge-guide/references/stacks/rust.md +19 -0
  48. package/adapters/claude/skills/forge-guide/references/stacks/typescript.md +23 -0
  49. package/adapters/claude/skills/forge-verify/SKILL.md +3 -3
  50. package/adapters/claude/skills/forge-verify/references/shared-conventions.md +12 -0
  51. package/adapters/claude/skills/forge-verify/references/verification-checklists.md +82 -3
  52. package/adapters/codex/.feature-forge-bundle.json +1 -1
  53. package/adapters/codex/references/epic-manifest-schema.json +5 -0
  54. package/adapters/codex/references/forge-config-schema.json +2 -2
  55. package/adapters/codex/references/shared-conventions.md +12 -0
  56. package/adapters/codex/references/stacks/_generic.md +21 -0
  57. package/adapters/codex/references/stacks/go.md +19 -0
  58. package/adapters/codex/references/stacks/python.md +21 -0
  59. package/adapters/codex/references/stacks/rust.md +19 -0
  60. package/adapters/codex/references/stacks/typescript.md +23 -0
  61. package/adapters/codex/scripts/epic-manifest.py +75 -5
  62. package/adapters/codex/scripts/forge-root.sh +102 -14
  63. package/adapters/codex/scripts/forge-session.py +68 -9
  64. package/adapters/codex/skills/forge/references/shared-conventions.md +12 -0
  65. package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +12 -0
  66. package/adapters/codex/skills/forge-1-prd/SKILL.md +2 -0
  67. package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +12 -0
  68. package/adapters/codex/skills/forge-2-tech/SKILL.md +2 -0
  69. package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +12 -0
  70. package/adapters/codex/skills/forge-2-tech/references/stacks/_generic.md +21 -0
  71. package/adapters/codex/skills/forge-2-tech/references/stacks/go.md +19 -0
  72. package/adapters/codex/skills/forge-2-tech/references/stacks/python.md +21 -0
  73. package/adapters/codex/skills/forge-2-tech/references/stacks/rust.md +19 -0
  74. package/adapters/codex/skills/forge-2-tech/references/stacks/typescript.md +23 -0
  75. package/adapters/codex/skills/forge-3-specs/SKILL.md +2 -0
  76. package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +12 -0
  77. package/adapters/codex/skills/forge-3-specs/references/stacks/_generic.md +21 -0
  78. package/adapters/codex/skills/forge-3-specs/references/stacks/go.md +19 -0
  79. package/adapters/codex/skills/forge-3-specs/references/stacks/python.md +21 -0
  80. package/adapters/codex/skills/forge-3-specs/references/stacks/rust.md +19 -0
  81. package/adapters/codex/skills/forge-3-specs/references/stacks/typescript.md +23 -0
  82. package/adapters/codex/skills/forge-4-backlog/SKILL.md +5 -0
  83. package/adapters/codex/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  84. package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +12 -0
  85. package/adapters/codex/skills/forge-5-loop/SKILL.md +7 -9
  86. package/adapters/codex/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  87. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +41 -0
  88. package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +12 -0
  89. package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +12 -0
  90. package/adapters/codex/skills/forge-fix/references/shared-conventions.md +12 -0
  91. package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +2 -2
  92. package/adapters/codex/skills/forge-guide/references/shared-conventions.md +12 -0
  93. package/adapters/codex/skills/forge-guide/references/stacks/_generic.md +21 -0
  94. package/adapters/codex/skills/forge-guide/references/stacks/go.md +19 -0
  95. package/adapters/codex/skills/forge-guide/references/stacks/python.md +21 -0
  96. package/adapters/codex/skills/forge-guide/references/stacks/rust.md +19 -0
  97. package/adapters/codex/skills/forge-guide/references/stacks/typescript.md +23 -0
  98. package/adapters/codex/skills/forge-verify/SKILL.md +3 -3
  99. package/adapters/codex/skills/forge-verify/references/shared-conventions.md +12 -0
  100. package/adapters/codex/skills/forge-verify/references/verification-checklists.md +82 -3
  101. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  102. package/adapters/copilot/references/epic-manifest-schema.json +5 -0
  103. package/adapters/copilot/references/forge-config-schema.json +2 -2
  104. package/adapters/copilot/references/shared-conventions.md +12 -0
  105. package/adapters/copilot/references/stacks/_generic.md +21 -0
  106. package/adapters/copilot/references/stacks/go.md +19 -0
  107. package/adapters/copilot/references/stacks/python.md +21 -0
  108. package/adapters/copilot/references/stacks/rust.md +19 -0
  109. package/adapters/copilot/references/stacks/typescript.md +23 -0
  110. package/adapters/copilot/scripts/epic-manifest.py +75 -5
  111. package/adapters/copilot/scripts/forge-root.sh +102 -14
  112. package/adapters/copilot/scripts/forge-session.py +68 -9
  113. package/adapters/copilot/skills/forge/references/shared-conventions.md +12 -0
  114. package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +12 -0
  115. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +2 -0
  116. package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +12 -0
  117. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +2 -0
  118. package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +12 -0
  119. package/adapters/copilot/skills/forge-2-tech/references/stacks/_generic.md +21 -0
  120. package/adapters/copilot/skills/forge-2-tech/references/stacks/go.md +19 -0
  121. package/adapters/copilot/skills/forge-2-tech/references/stacks/python.md +21 -0
  122. package/adapters/copilot/skills/forge-2-tech/references/stacks/rust.md +19 -0
  123. package/adapters/copilot/skills/forge-2-tech/references/stacks/typescript.md +23 -0
  124. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +2 -0
  125. package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +12 -0
  126. package/adapters/copilot/skills/forge-3-specs/references/stacks/_generic.md +21 -0
  127. package/adapters/copilot/skills/forge-3-specs/references/stacks/go.md +19 -0
  128. package/adapters/copilot/skills/forge-3-specs/references/stacks/python.md +21 -0
  129. package/adapters/copilot/skills/forge-3-specs/references/stacks/rust.md +19 -0
  130. package/adapters/copilot/skills/forge-3-specs/references/stacks/typescript.md +23 -0
  131. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +5 -0
  132. package/adapters/copilot/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  133. package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +12 -0
  134. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +7 -9
  135. package/adapters/copilot/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  136. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +41 -0
  137. package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +12 -0
  138. package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +12 -0
  139. package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +12 -0
  140. package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +2 -2
  141. package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +12 -0
  142. package/adapters/copilot/skills/forge-guide/references/stacks/_generic.md +21 -0
  143. package/adapters/copilot/skills/forge-guide/references/stacks/go.md +19 -0
  144. package/adapters/copilot/skills/forge-guide/references/stacks/python.md +21 -0
  145. package/adapters/copilot/skills/forge-guide/references/stacks/rust.md +19 -0
  146. package/adapters/copilot/skills/forge-guide/references/stacks/typescript.md +23 -0
  147. package/adapters/copilot/skills/forge-verify/forge-verify.md +3 -3
  148. package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +12 -0
  149. package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +82 -3
  150. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  151. package/adapters/cursor/references/epic-manifest-schema.json +5 -0
  152. package/adapters/cursor/references/forge-config-schema.json +2 -2
  153. package/adapters/cursor/references/shared-conventions.md +12 -0
  154. package/adapters/cursor/references/stacks/_generic.md +21 -0
  155. package/adapters/cursor/references/stacks/go.md +19 -0
  156. package/adapters/cursor/references/stacks/python.md +21 -0
  157. package/adapters/cursor/references/stacks/rust.md +19 -0
  158. package/adapters/cursor/references/stacks/typescript.md +23 -0
  159. package/adapters/cursor/scripts/epic-manifest.py +75 -5
  160. package/adapters/cursor/scripts/forge-root.sh +102 -14
  161. package/adapters/cursor/scripts/forge-session.py +68 -9
  162. package/adapters/cursor/skills/forge/references/shared-conventions.md +12 -0
  163. package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +12 -0
  164. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +2 -0
  165. package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +12 -0
  166. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +2 -0
  167. package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +12 -0
  168. package/adapters/cursor/skills/forge-2-tech/references/stacks/_generic.md +21 -0
  169. package/adapters/cursor/skills/forge-2-tech/references/stacks/go.md +19 -0
  170. package/adapters/cursor/skills/forge-2-tech/references/stacks/python.md +21 -0
  171. package/adapters/cursor/skills/forge-2-tech/references/stacks/rust.md +19 -0
  172. package/adapters/cursor/skills/forge-2-tech/references/stacks/typescript.md +23 -0
  173. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +2 -0
  174. package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +12 -0
  175. package/adapters/cursor/skills/forge-3-specs/references/stacks/_generic.md +21 -0
  176. package/adapters/cursor/skills/forge-3-specs/references/stacks/go.md +19 -0
  177. package/adapters/cursor/skills/forge-3-specs/references/stacks/python.md +21 -0
  178. package/adapters/cursor/skills/forge-3-specs/references/stacks/rust.md +19 -0
  179. package/adapters/cursor/skills/forge-3-specs/references/stacks/typescript.md +23 -0
  180. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +5 -0
  181. package/adapters/cursor/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  182. package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +12 -0
  183. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +7 -9
  184. package/adapters/cursor/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  185. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +41 -0
  186. package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +12 -0
  187. package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +12 -0
  188. package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +12 -0
  189. package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +2 -2
  190. package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +12 -0
  191. package/adapters/cursor/skills/forge-guide/references/stacks/_generic.md +21 -0
  192. package/adapters/cursor/skills/forge-guide/references/stacks/go.md +19 -0
  193. package/adapters/cursor/skills/forge-guide/references/stacks/python.md +21 -0
  194. package/adapters/cursor/skills/forge-guide/references/stacks/rust.md +19 -0
  195. package/adapters/cursor/skills/forge-guide/references/stacks/typescript.md +23 -0
  196. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +3 -3
  197. package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +12 -0
  198. package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +82 -3
  199. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  200. package/adapters/gemini/gemini-extension.json +1 -1
  201. package/adapters/gemini/references/epic-manifest-schema.json +5 -0
  202. package/adapters/gemini/references/forge-config-schema.json +2 -2
  203. package/adapters/gemini/references/shared-conventions.md +12 -0
  204. package/adapters/gemini/references/stacks/_generic.md +21 -0
  205. package/adapters/gemini/references/stacks/go.md +19 -0
  206. package/adapters/gemini/references/stacks/python.md +21 -0
  207. package/adapters/gemini/references/stacks/rust.md +19 -0
  208. package/adapters/gemini/references/stacks/typescript.md +23 -0
  209. package/adapters/gemini/scripts/epic-manifest.py +75 -5
  210. package/adapters/gemini/scripts/forge-root.sh +102 -14
  211. package/adapters/gemini/scripts/forge-session.py +68 -9
  212. package/adapters/gemini/skills/forge/references/shared-conventions.md +12 -0
  213. package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +12 -0
  214. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +2 -0
  215. package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +12 -0
  216. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +2 -0
  217. package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +12 -0
  218. package/adapters/gemini/skills/forge-2-tech/references/stacks/_generic.md +21 -0
  219. package/adapters/gemini/skills/forge-2-tech/references/stacks/go.md +19 -0
  220. package/adapters/gemini/skills/forge-2-tech/references/stacks/python.md +21 -0
  221. package/adapters/gemini/skills/forge-2-tech/references/stacks/rust.md +19 -0
  222. package/adapters/gemini/skills/forge-2-tech/references/stacks/typescript.md +23 -0
  223. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +2 -0
  224. package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +12 -0
  225. package/adapters/gemini/skills/forge-3-specs/references/stacks/_generic.md +21 -0
  226. package/adapters/gemini/skills/forge-3-specs/references/stacks/go.md +19 -0
  227. package/adapters/gemini/skills/forge-3-specs/references/stacks/python.md +21 -0
  228. package/adapters/gemini/skills/forge-3-specs/references/stacks/rust.md +19 -0
  229. package/adapters/gemini/skills/forge-3-specs/references/stacks/typescript.md +23 -0
  230. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +5 -0
  231. package/adapters/gemini/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  232. package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +12 -0
  233. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +7 -9
  234. package/adapters/gemini/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  235. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +41 -0
  236. package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +12 -0
  237. package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +12 -0
  238. package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +12 -0
  239. package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +2 -2
  240. package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +12 -0
  241. package/adapters/gemini/skills/forge-guide/references/stacks/_generic.md +21 -0
  242. package/adapters/gemini/skills/forge-guide/references/stacks/go.md +19 -0
  243. package/adapters/gemini/skills/forge-guide/references/stacks/python.md +21 -0
  244. package/adapters/gemini/skills/forge-guide/references/stacks/rust.md +19 -0
  245. package/adapters/gemini/skills/forge-guide/references/stacks/typescript.md +23 -0
  246. package/adapters/gemini/skills/forge-verify/forge-verify.md +3 -3
  247. package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +12 -0
  248. package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +82 -3
  249. package/adapters/pi/.feature-forge-bundle.json +6 -0
  250. package/adapters/pi/agents/forge-researcher.md +139 -0
  251. package/adapters/pi/agents/forge-spec-writer.md +116 -0
  252. package/adapters/pi/agents/forge-verifier.md +126 -0
  253. package/adapters/pi/extensions/ask-user-question/LICENSE +21 -0
  254. package/adapters/pi/extensions/ask-user-question/README.md +91 -0
  255. package/adapters/pi/extensions/ask-user-question/ask-user-question.ts +298 -0
  256. package/adapters/pi/extensions/ask-user-question/config.ts +78 -0
  257. package/adapters/pi/extensions/ask-user-question/events.ts +57 -0
  258. package/adapters/pi/extensions/ask-user-question/index.ts +61 -0
  259. package/adapters/pi/extensions/ask-user-question/locales/de.json +27 -0
  260. package/adapters/pi/extensions/ask-user-question/locales/en.json +27 -0
  261. package/adapters/pi/extensions/ask-user-question/locales/es.json +27 -0
  262. package/adapters/pi/extensions/ask-user-question/locales/fr.json +27 -0
  263. package/adapters/pi/extensions/ask-user-question/locales/pt-BR.json +27 -0
  264. package/adapters/pi/extensions/ask-user-question/locales/pt.json +27 -0
  265. package/adapters/pi/extensions/ask-user-question/locales/ru.json +27 -0
  266. package/adapters/pi/extensions/ask-user-question/locales/uk.json +27 -0
  267. package/adapters/pi/extensions/ask-user-question/locales/zh.json +29 -0
  268. package/adapters/pi/extensions/ask-user-question/reconcile.ts +49 -0
  269. package/adapters/pi/extensions/ask-user-question/rpc-fallback.ts +168 -0
  270. package/adapters/pi/extensions/ask-user-question/state/build-questionnaire.ts +302 -0
  271. package/adapters/pi/extensions/ask-user-question/state/i18n-bridge.ts +53 -0
  272. package/adapters/pi/extensions/ask-user-question/state/key-router.ts +277 -0
  273. package/adapters/pi/extensions/ask-user-question/state/questionnaire-session.ts +234 -0
  274. package/adapters/pi/extensions/ask-user-question/state/row-intent.ts +145 -0
  275. package/adapters/pi/extensions/ask-user-question/state/selectors/contract.ts +26 -0
  276. package/adapters/pi/extensions/ask-user-question/state/selectors/derivations.ts +42 -0
  277. package/adapters/pi/extensions/ask-user-question/state/selectors/focus.ts +19 -0
  278. package/adapters/pi/extensions/ask-user-question/state/selectors/projections.ts +101 -0
  279. package/adapters/pi/extensions/ask-user-question/state/state-reducer.ts +292 -0
  280. package/adapters/pi/extensions/ask-user-question/state/state.ts +55 -0
  281. package/adapters/pi/extensions/ask-user-question/tool/format-answer.ts +31 -0
  282. package/adapters/pi/extensions/ask-user-question/tool/response-envelope.ts +49 -0
  283. package/adapters/pi/extensions/ask-user-question/tool/types.ts +147 -0
  284. package/adapters/pi/extensions/ask-user-question/tool/validate-questionnaire.ts +58 -0
  285. package/adapters/pi/extensions/ask-user-question/vendor-config-shim.ts +65 -0
  286. package/adapters/pi/extensions/ask-user-question/view/component-binding.ts +47 -0
  287. package/adapters/pi/extensions/ask-user-question/view/components/inline-input.ts +98 -0
  288. package/adapters/pi/extensions/ask-user-question/view/components/multi-select-view.ts +193 -0
  289. package/adapters/pi/extensions/ask-user-question/view/components/option-list-view.ts +70 -0
  290. package/adapters/pi/extensions/ask-user-question/view/components/preview/markdown-content-cache.ts +79 -0
  291. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-block-renderer.ts +111 -0
  292. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-box-renderer.ts +88 -0
  293. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-layout-decider.ts +202 -0
  294. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-pane.ts +228 -0
  295. package/adapters/pi/extensions/ask-user-question/view/components/submit-picker.ts +67 -0
  296. package/adapters/pi/extensions/ask-user-question/view/components/tab-bar.ts +59 -0
  297. package/adapters/pi/extensions/ask-user-question/view/components/wrapping-select.ts +293 -0
  298. package/adapters/pi/extensions/ask-user-question/view/dialog-builder.ts +224 -0
  299. package/adapters/pi/extensions/ask-user-question/view/props-adapter.ts +125 -0
  300. package/adapters/pi/extensions/ask-user-question/view/stateful-view.ts +26 -0
  301. package/adapters/pi/extensions/ask-user-question/view/tab-components.ts +18 -0
  302. package/adapters/pi/extensions/ask-user-question/view/tab-content-strategy.ts +252 -0
  303. package/adapters/pi/package.json +26 -0
  304. package/adapters/pi/references/epic-manifest-schema.json +125 -0
  305. package/adapters/pi/references/forge-config-schema.json +236 -0
  306. package/adapters/pi/references/pipeline-state-schema.json +191 -0
  307. package/adapters/pi/references/portable-root.md +71 -0
  308. package/adapters/pi/references/process-overview.md +143 -0
  309. package/adapters/pi/references/ralph-loop-contract.md +221 -0
  310. package/adapters/pi/references/shared-conventions.md +295 -0
  311. package/adapters/pi/references/skill-frontmatter.schema.json +17 -0
  312. package/adapters/pi/references/stack-resolution.md +54 -0
  313. package/adapters/pi/references/stacks/_generic.md +111 -0
  314. package/adapters/pi/references/stacks/go.md +157 -0
  315. package/adapters/pi/references/stacks/python.md +184 -0
  316. package/adapters/pi/references/stacks/rust.md +170 -0
  317. package/adapters/pi/references/stacks/typescript.md +134 -0
  318. package/adapters/pi/references/stage-exit-protocol.md +258 -0
  319. package/adapters/pi/references/templates/specs-hygiene/AGENTS.md +32 -0
  320. package/adapters/pi/references/templates/specs-hygiene/CLAUDE.md +31 -0
  321. package/adapters/pi/references/vendor-construct-inventory.md +50 -0
  322. package/adapters/pi/scripts/epic-manifest.py +1694 -0
  323. package/adapters/pi/scripts/forge-bootstrap.py +1070 -0
  324. package/adapters/pi/scripts/forge-init.sh +58 -0
  325. package/adapters/pi/scripts/forge-root.sh +179 -0
  326. package/adapters/pi/scripts/forge-session.py +1888 -0
  327. package/adapters/pi/scripts/validate-traceability.py +150 -0
  328. package/adapters/pi/skills/forge/SKILL.md +243 -0
  329. package/adapters/pi/skills/forge/references/pipeline-state-schema.json +191 -0
  330. package/adapters/pi/skills/forge/references/process-overview.md +143 -0
  331. package/adapters/pi/skills/forge/references/shared-conventions.md +295 -0
  332. package/adapters/pi/skills/forge/references/stage-exit-protocol.md +258 -0
  333. package/adapters/pi/skills/forge-0-epic/SKILL.md +308 -0
  334. package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +266 -0
  335. package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +75 -0
  336. package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +191 -0
  337. package/adapters/pi/skills/forge-0-epic/references/portable-root.md +71 -0
  338. package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +295 -0
  339. package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +258 -0
  340. package/adapters/pi/skills/forge-1-prd/SKILL.md +164 -0
  341. package/adapters/pi/skills/forge-1-prd/references/pipeline-state-schema.json +191 -0
  342. package/adapters/pi/skills/forge-1-prd/references/prd-template.md +106 -0
  343. package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +295 -0
  344. package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +258 -0
  345. package/adapters/pi/skills/forge-2-tech/SKILL.md +225 -0
  346. package/adapters/pi/skills/forge-2-tech/references/pipeline-state-schema.json +191 -0
  347. package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +295 -0
  348. package/adapters/pi/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  349. package/adapters/pi/skills/forge-2-tech/references/stack-resolution.md +54 -0
  350. package/adapters/pi/skills/forge-2-tech/references/stacks/_generic.md +111 -0
  351. package/adapters/pi/skills/forge-2-tech/references/stacks/go.md +157 -0
  352. package/adapters/pi/skills/forge-2-tech/references/stacks/python.md +184 -0
  353. package/adapters/pi/skills/forge-2-tech/references/stacks/rust.md +170 -0
  354. package/adapters/pi/skills/forge-2-tech/references/stacks/typescript.md +134 -0
  355. package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +258 -0
  356. package/adapters/pi/skills/forge-3-specs/SKILL.md +178 -0
  357. package/adapters/pi/skills/forge-3-specs/references/pipeline-state-schema.json +191 -0
  358. package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +295 -0
  359. package/adapters/pi/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  360. package/adapters/pi/skills/forge-3-specs/references/spec-examples.md +71 -0
  361. package/adapters/pi/skills/forge-3-specs/references/stacks/_generic.md +111 -0
  362. package/adapters/pi/skills/forge-3-specs/references/stacks/go.md +157 -0
  363. package/adapters/pi/skills/forge-3-specs/references/stacks/python.md +184 -0
  364. package/adapters/pi/skills/forge-3-specs/references/stacks/rust.md +170 -0
  365. package/adapters/pi/skills/forge-3-specs/references/stacks/typescript.md +134 -0
  366. package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +258 -0
  367. package/adapters/pi/skills/forge-4-backlog/SKILL.md +175 -0
  368. package/adapters/pi/skills/forge-4-backlog/references/forge-config-schema.json +236 -0
  369. package/adapters/pi/skills/forge-4-backlog/references/pipeline-state-schema.json +191 -0
  370. package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +295 -0
  371. package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +258 -0
  372. package/adapters/pi/skills/forge-5-loop/SKILL.md +314 -0
  373. package/adapters/pi/skills/forge-5-loop/references/forge-config-schema.json +236 -0
  374. package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +221 -0
  375. package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +85 -0
  376. package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +341 -0
  377. package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +295 -0
  378. package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +258 -0
  379. package/adapters/pi/skills/forge-6-docs/SKILL.md +202 -0
  380. package/adapters/pi/skills/forge-6-docs/references/doc-conventions.md +126 -0
  381. package/adapters/pi/skills/forge-6-docs/references/pipeline-state-schema.json +191 -0
  382. package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +295 -0
  383. package/adapters/pi/skills/forge-bootstrap/SKILL.md +250 -0
  384. package/adapters/pi/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  385. package/adapters/pi/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  386. package/adapters/pi/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  387. package/adapters/pi/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  388. package/adapters/pi/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  389. package/adapters/pi/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  390. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +35 -0
  391. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +36 -0
  392. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  393. package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  394. package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  395. package/adapters/pi/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  396. package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  397. package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  398. package/adapters/pi/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  399. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  400. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  401. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  402. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  403. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  404. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  405. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  406. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  407. package/adapters/pi/skills/forge-fix/SKILL.md +98 -0
  408. package/adapters/pi/skills/forge-fix/references/shared-conventions.md +295 -0
  409. package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +258 -0
  410. package/adapters/pi/skills/forge-guide/SKILL.md +192 -0
  411. package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +236 -0
  412. package/adapters/pi/skills/forge-guide/references/process-overview.md +143 -0
  413. package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +221 -0
  414. package/adapters/pi/skills/forge-guide/references/shared-conventions.md +295 -0
  415. package/adapters/pi/skills/forge-guide/references/stack-resolution.md +54 -0
  416. package/adapters/pi/skills/forge-guide/references/stacks/_generic.md +111 -0
  417. package/adapters/pi/skills/forge-guide/references/stacks/go.md +157 -0
  418. package/adapters/pi/skills/forge-guide/references/stacks/python.md +184 -0
  419. package/adapters/pi/skills/forge-guide/references/stacks/rust.md +170 -0
  420. package/adapters/pi/skills/forge-guide/references/stacks/typescript.md +134 -0
  421. package/adapters/pi/skills/forge-init/SKILL.md +72 -0
  422. package/adapters/pi/skills/forge-verify/SKILL.md +273 -0
  423. package/adapters/pi/skills/forge-verify/references/pipeline-state-schema.json +191 -0
  424. package/adapters/pi/skills/forge-verify/references/shared-conventions.md +295 -0
  425. package/adapters/pi/skills/forge-verify/references/verification-checklists.md +477 -0
  426. package/dist/agent-targets.d.ts +1 -1
  427. package/dist/agent-targets.js +23 -3
  428. package/dist/detect.d.ts +1 -1
  429. package/dist/detect.js +2 -1
  430. package/dist/manifest.d.ts +1 -1
  431. package/dist/manifest.js +2 -2
  432. package/dist/placements.js +5 -1
  433. package/dist/rauf.d.ts +4 -4
  434. package/dist/rauf.js +3 -3
  435. package/dist/types.d.ts +31 -6
  436. package/dist/types.js +6 -3
  437. package/package.json +14 -3
@@ -153,6 +153,60 @@ Detailed checklists for each verification mode. Execute EVERY check — do not s
153
153
  - [ ] **CHECK-B24**: There are items for tests (or testing is included in each feature item's acceptance criteria)
154
154
  - [ ] **CHECK-B25**: No large items that try to do too many things (should be broken down)
155
155
 
156
+ ### Generated-Artifact Freshness
157
+ - [ ] **CHECK-B26**: **Generated-artifact freshness vs. `testCommand` `--check` gates** (#145). When a
158
+ project's configured `testCommand` (forge.config.json) gates on **staleness of generated artifacts**
159
+ — sub-commands of the shape `<generator> --check` / `--verify` / `:check` that fail if a checked-in
160
+ generated file is out of date with its source — every backlog item that regenerates *one* gated
161
+ artifact must regenerate (and commit) **all** the sibling artifacts those same `--check` gates
162
+ depend on, or the item will pass locally yet red-gate on the stale-generated check. Verify
163
+ heuristically:
164
+ 1. **Enumerate the gates.** String-scan `testCommand` for `--check`-style freshness sub-commands and
165
+ collect the generator/artifact each one guards (e.g. `build-benchmarks --check` guards
166
+ `partner-program-benchmarks`). If the command shape is unrecognized (no parseable `--check`
167
+ tokens), this check is **advisory / not-applicable** — never a hard fail.
168
+ 2. **A gate with no regenerator.** If a `--check` gate guards an artifact that **no** backlog item
169
+ regenerates, and some item edits that artifact's *source*, flag a `gap`: the source change will
170
+ trip the freshness gate with nothing scheduled to refresh the output.
171
+ 3. **Partial regeneration.** If an item regenerates a proper subset of the artifacts gated by the
172
+ `--check` set it touches (e.g. runs `build-partner-programs` + `build-analysis` but the gate also
173
+ covers `build-benchmarks`), flag an `inconsistency` naming the missing generator(s) and
174
+ recommending they be added to that item's execute + commit sequence. Same posture as the authoring
175
+ guidance in `forge-4-backlog` / rauf `author-backlog`: enumerate the whole `--check`-gated set, not
176
+ just the artifact the item is "about".
177
+
178
+ ### Artifact Lifecycle Consistency
179
+ - [ ] **CHECK-B27**: **No test item forcing a lifecycle transition another item forbids** (#150).
180
+ *Advisory heuristic — keyword/artifact-name based; **not-applicable** when no lifecycle vocabulary is
181
+ present, **never** a hard fail.* A **lifecycle state** (draft / published / released / approved /
182
+ reviewed / signed-off / gated) is a downstream-project concept forge does not itself track — but a
183
+ backlog can still encode a **contradiction** about one named artifact: item A pins artifact `X` as
184
+ *draft* / *unpublished* / *unreviewed* while item B asserts (in its acceptance criteria or a test it
185
+ adds) that `X` is *published* / *released* / *approved*, with **no** publishing/review item for `X`
186
+ anywhere in B's dependency closure. That leaves a **test/e2e item as the only thing forcing the
187
+ transition** — and since the autonomous loop can neither publish a package nor stand in for a human
188
+ reviewer, asked to make such a test green it **fabricates** the publication or sign-off (a provenance
189
+ defect a `--review` pass has caught in the wild). Verify heuristically:
190
+ 1. **Find lifecycle assertions.** Scan item titles/descriptions/`acceptanceCriteria` for a named
191
+ artifact paired with a lifecycle-state keyword — earlier states (`draft` / `unpublished` /
192
+ `pending review` / `unreleased`) vs later states (`published` / `released` / `approved` / `live` /
193
+ `signed-off` / `gated`). If **no** item carries such vocabulary, this check is **not-applicable**.
194
+ 2. **Pair by artifact name.** Group assertions that reference the **same named artifact**. A pair
195
+ where one item requires the *earlier* state and another asserts the *later* state is a candidate.
196
+ 3. **Check the dependency closure.** If the later-state item has **no** publish / review / human-gated
197
+ item for that artifact in its transitive `dependsOn`, flag an `inconsistency`: name the artifact,
198
+ both items, and recommend either (a) adding a `dependsOn` on an explicit human-gated publish/review
199
+ item that legitimately produces the state, or (b) re-asserting the state via a dev-build / fixture
200
+ path — never letting a test item be the sole driver of the transition (mirrors the authoring
201
+ guidance in `forge-4-backlog` / rauf `author-backlog`). **Report, do not repair.**
202
+
203
+ > **Anti-pattern (visible even where the heuristic can't fire):** a test/e2e item whose pass condition
204
+ > is "artifact `X` is published / approved / reviewed" while the backlog contains no human-gated
205
+ > publish or review item producing that state. The autonomous loop cannot publish or sign off on
206
+ > behalf of a human; asked to make such a test green it will **fabricate** the published/reviewed
207
+ > provenance. Any item asserting a human-gated lifecycle state must trace — via `dependsOn` — to the
208
+ > item that legitimately produces it, or assert the state through a dev-build / fixture path instead.
209
+
156
210
  ## Implementation Mode Checklist
157
211
 
158
212
  ### Spec Compliance
@@ -190,13 +244,17 @@ Detailed checklists for each verification mode. Execute EVERY check — do not s
190
244
  > **When these fire:** only at impl-verify **completion** (impl mode runs post-loop), never mid-loop — an early skeleton that only compiles is not punished. **Both degrade gracefully:** a feature with no runnable surface (a pure library with no bootstrap contract) or no configured `smokeCommand` yields an **advisory not-applicable** finding, never a hard fail — the same way a null `{typeCheckCommand}` is handled. These exist because `CHECK-I01..I20` are all static reads + typecheck/lint + "tests exist"; nothing here asserts the assembled application actually **runs**. A bootstrap that is exported and unit-tested (each test calls it manually) but never wired into a runtime entrypoint passes every other check yet serves no real request (#121).
191
245
 
192
246
  - [ ] **CHECK-I21**: **End-to-end smoke passes.** If `smokeCommand` from forge.config.json is set, execute it — it boots the wired entrypoint and drives one happy-path request end-to-end; **pass iff exit 0**. A non-zero exit is an `error` finding (the assembled app does not run — quote the command's failing output). If `smokeCommand` is `null`, this is **advisory**: emit a `not-applicable` finding recommending the user configure a `smokeCommand` so "clean" means "it runs" (never fabricate or guess a command — run only the user-configured one, exactly as `CHECK-I11` runs only a configured `{typeCheckCommand}`).
193
- - [ ] **CHECK-I22**: **Runtime-required bootstrap has a non-test caller.** Every exported bootstrap / `init*` / singleton-populator the specs mark as **required for runtime** must have ≥1 **non-test** call site on a runtime path — an entrypoint such as `main` / `instrumentation` / a route / a layout / a worker, NOT only test files. Statically grep for each such symbol's references (use the stack profile `references/stacks/{stack}.md` for what counts as a runtime entrypoint in this language). A symbol that is exported and covered by tests but referenced **only** from test files is a `gap` — the #121 walking-skeleton (bootstrap wired to nothing). Degrades naturally: a feature whose specs mark no bootstrap symbol as runtime-required is `not-applicable`. Weaker than `CHECK-I21` (it proves a call site exists, not that the boot succeeds), so it complements rather than replaces the smoke.
247
+ - **Prefer the dev runtime the developer actually uses (#149).** Recommend the configured `smokeCommand` boot the app in its **development** mode — the dev server / watch loop / HMR runtime — not only a clean production build. The failure modes that a static typecheck and a prod smoke both miss live in the dev runtime: **module-graph-identity** bugs (a "singleton" duplicated across a re-evaluated module graph, so the initialized instance and the one the request path reads are different objects) and **watch-loop** bugs (an init that fires once but never re-fires on hot reload, or fires on every reload and leaks). A prod build evaluates the graph once and hides both. When the project is served in dev during development, the `smokeCommand` should exercise that same runtime.
248
+ - **For a fix, re-verify in the mode the bug manifested.** When impl-verify runs after a **fix** (not a greenfield build), re-run the smoke in the **same runtime mode where the original bug appeared** — a bug reproduced in dev/watch mode is not proven fixed by a green prod-mode smoke, and vice versa. Note the mode in the finding so "smoke passed" is unambiguous about *which* runtime was exercised.
249
+ - [ ] **CHECK-I22**: **Runtime-required bootstrap has a non-test caller.** Every exported bootstrap / `init*` / singleton-populator the specs mark as **required for runtime** must have ≥1 **non-test** call site on a runtime path — an entrypoint such as `main` / `instrumentation` / a route / a layout / a worker, NOT only test files. Statically grep for each such symbol's references (use the stack profile `references/stacks/{stack}.md` **Runtime Entrypoints & Bootstrap-Wiring Sites** list for what counts as a runtime entrypoint in this language). A symbol that is exported and covered by tests but referenced **only** from test files is a `gap` — the #121 walking-skeleton (bootstrap wired to nothing). Degrades naturally: a feature whose specs mark no bootstrap symbol as runtime-required is `not-applicable`. Weaker than `CHECK-I21` (it proves a call site exists, not that the boot succeeds), so it complements rather than replaces the smoke.
250
+ - [ ] **CHECK-I23**: **Heavy bootstrap wired into a universal startup entry — recommend lazy init** (#149). *Advisory heuristic — a `gap`/`improvement` at most, **never** a hard fail.* When a runtime-required `init`/bootstrap/singleton-populator is wired into a **framework bootstrap entry that runs on every startup** (a Next.js `instrumentation.ts`, an app-server preload/`register` hook, a global setup module) **and** that init pulls in a **large server-only import graph** (DB clients, ORMs, queue/background workers, telemetry exporters, the whole service layer), recommend moving to **lazy initialization at the entry that already loads that graph** — the first route / handler / worker that needs it — rather than eager wiring at the universal entry. Eager wiring drags the heavy graph into every cold start, and in dev into every module re-evaluation (the watch-loop cost `CHECK-I21` also targets). **Detect statically:** from the stack profile's **Runtime Entrypoints & Bootstrap-Wiring Sites** list, identify this stack's universal bootstrap entries; grep those files for imports of the feature's runtime-required bootstrap symbols (`CHECK-I22`) and for the server-only heavy-import markers the profile names. A match → an `improvement`/`gap` finding naming the entry, the heavy graph it pulls, and the lazier call site to move initialization to. Degrades to `not-applicable` when the stack has no universal bootstrap entry, when no heavy init is wired there, or when the profile lists no bootstrap-wiring sites — **report, do not repair.**
194
251
 
195
252
  ## Epic Mode Checklist
196
253
 
197
254
  Run `epic-manifest.py validate "{epic}" --specs-dir "{specsDir}" --json` once; map its
198
- findings to E01/E02/E03/E08. Then perform the judgment checks E04–E07 by reading the
199
- manifest, EPIC.md, and completed members' specs.
255
+ findings to E01/E02/E03/E08. Then perform the judgment checks E04–E07, E09, and E10 by
256
+ reading the manifest, EPIC.md, completed members' specs, and (for E10) sibling members'
257
+ committed tests.
200
258
 
201
259
  ```bash
202
260
  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')"
@@ -242,6 +300,27 @@ python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}"
242
300
  `.blockingEpicChangeRequests`); the per-request `kind`/`target`/`rationale` detail is read
243
301
  from the member `.pipeline-state.json` already loaded in Step 2. This is the pre-emptive
244
302
  surface for the divergence class CHECK-E06/E07 otherwise catch only after the fact.
303
+ - [ ] **CHECK-E10**: **cross-member shared-state test coupling** (#144). A member that writes or
304
+ migrates a file a *sibling's* committed tests already pin will break the sibling's suite the
305
+ moment it runs — blocking every one of its own commits from a green test gate — yet nothing in
306
+ E04–E09 catches it (contracts cover code symbols, not shared data files). Detect it heuristically,
307
+ per member `M`:
308
+ 1. **Collect `M`'s mutated paths.** Take `M`'s `mutatesShared[]` from the manifest if present
309
+ (the authored precision hint). If absent or empty, fall back to grepping `M`'s specs
310
+ (change-maps / "files this writes") and backlog item `execute` steps for project-root-relative
311
+ paths it creates, writes, or migrates (data corpora, generated fixtures, migration outputs —
312
+ not `M`'s own source modules or its own tests).
313
+ 2. **Grep sibling tests for reads of those paths.** For every *other* member `S` that is already
314
+ **`complete`** (derived status — its regression suite is live and gating), grep `S`'s committed
315
+ **test** files/globs for a read/import/load of any path in step 1. Use the stack profile
316
+ (`references/stacks/{stack}.md`) for what a test glob looks like in this language.
317
+ 3. **Emit the finding.** A hit → a non-fatal `inconsistency` finding: name `M`, the shared path,
318
+ the sibling `S` and the specific test, and **recommend a reconciliation backlog item** on `M`
319
+ (regenerate/re-pin `S`'s fixture, or update `S`'s test to the new shape) scheduled *before*
320
+ `M`'s first mutating item — so the coupling is planned, not discovered mid-loop on a red gate.
321
+ **Report, do not repair** (same posture as CHECK-E07/E09). Degrades to a clean no-op when no
322
+ member declares or greps a shared write, or when no completed sibling reads it — never a
323
+ spurious hard-fail.
245
324
 
246
325
  ## Findings Document Template (Step 4)
247
326
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feature-forge",
3
- "version": "0.12.8",
3
+ "version": "0.13.0",
4
4
  "agent": "gemini",
5
5
  "generatedBy": "python3 scripts/build-adapters.py"
6
6
  }
@@ -4,7 +4,7 @@
4
4
  "regenerate": "python3 scripts/build-adapters.py"
5
5
  },
6
6
  "name": "feature-forge",
7
- "version": "0.12.8",
7
+ "version": "0.13.0",
8
8
  "skills": [
9
9
  {
10
10
  "name": "forge-0-epic",
@@ -74,6 +74,11 @@
74
74
  "type": "array",
75
75
  "items": { "$ref": "#/definitions/consumedContract" },
76
76
  "description": "What this feature relies on from its dependencies (REQ-EPIC-03). May be empty."
77
+ },
78
+ "mutatesShared": {
79
+ "type": "array",
80
+ "items": { "type": "string" },
81
+ "description": "OPTIONAL precision hint for cross-member coupling detection (#144): project-root-relative file/glob paths this feature writes or migrates that are shared across the epic (e.g. a corpus a sibling's tests pin). When present, forge-verify CHECK-E10 uses it directly; when absent, CHECK-E10 falls back to grepping specs/backlog for mutated paths. Not a dependency edge — declarative only. May be omitted entirely."
77
82
  }
78
83
  }
79
84
  },
@@ -217,8 +217,8 @@
217
217
  },
218
218
  "installHint": {
219
219
  "type": "string",
220
- "default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.12.0 default). Or install/upgrade just the rauf CLI: `npx @garygentry/rauf@0.12.0 --version`, or `curl -fsSL https://raw.githubusercontent.com/garygentry/rauf/main/scripts/install-binary.sh | bash`.",
221
- "description": "Shown when the runner BINARY is missing or too old (version gate fails, minRunnerVersion floor) — how to obtain/upgrade the CLI itself. Names two distinct binary-provisioning paths: (1) the cross-agent installer (`npx @garygentry/feature-forge install`, the multi-agent provisioning path that pins @garygentry/rauf@0.12.0), and (2) the direct rauf-CLI install/upgrade one-liner. Distinct from setupHint (which installs per-project artifacts); a version-gate failure is ALWAYS this hint, never setupHint."
220
+ "default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.13.0 default). Or install/upgrade just the rauf CLI: `npx @garygentry/rauf@0.13.0 --version`, or `curl -fsSL https://raw.githubusercontent.com/garygentry/rauf/main/scripts/install-binary.sh | bash`.",
221
+ "description": "Shown when the runner BINARY is missing or too old (version gate fails, minRunnerVersion floor) — how to obtain/upgrade the CLI itself. Names two distinct binary-provisioning paths: (1) the cross-agent installer (`npx @garygentry/feature-forge install`, the multi-agent provisioning path that pins @garygentry/rauf@0.13.0), and (2) the direct rauf-CLI install/upgrade one-liner. Distinct from setupHint (which installs per-project artifacts); a version-gate failure is ALWAYS this hint, never setupHint."
222
222
  },
223
223
  "schemaVersion": {
224
224
  "type": "string",
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
274
274
 
275
275
  **Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
276
276
 
277
+ ## Stage-Completion Re-check
278
+
279
+ Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
280
+
281
+ **Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
282
+
283
+ 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.
284
+
285
+ 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.
286
+
287
+ 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).
288
+
277
289
  ## Force Mode
278
290
 
279
291
  If the user passes `--force` as an argument, skip prerequisite validation with a warning:
@@ -79,6 +79,27 @@ Replace stack-specific checks with these generic equivalents:
79
79
  | "JSDoc on every field" | "Documentation comments on every field" |
80
80
  | "tsconfig.json extends root" | "Build configuration follows project conventions" |
81
81
 
82
+ ### Runtime Entrypoints & Bootstrap-Wiring Sites
83
+
84
+ Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
85
+ `CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
86
+ Since no dedicated profile applies, identify these by role rather than exact filename:
87
+
88
+ - **Runtime entrypoints (a legitimate non-test call site):** the process/main entry the build's
89
+ run command actually launches (from the CI/`Makefile`/manifest "start" target), an HTTP/RPC handler
90
+ or route, a scheduled/worker task, or a CLI subcommand — **not** a file in the project's test
91
+ directory or matching its test-file convention.
92
+ - **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** any
93
+ module/hook the framework runs **once per process before serving** — a startup/lifecycle hook, an
94
+ import-time initializer, a global preload, or a shared test-setup module that bootstraps production
95
+ graphs. Side effects here run on every process start (and, under a dev/watch runtime, on every
96
+ reload).
97
+ - **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** database/ORM
98
+ clients and connection pools, message/queue clients, telemetry/observability SDKs, or a broad
99
+ whole-service-layer import. An init pulling any of these into a universal bootstrap entry is the
100
+ CHECK-I23 pattern — recommend lazy initialization at the first handler/worker that needs the graph,
101
+ not eagerly at process start.
102
+
82
103
  ## Acceptance Criteria Patterns
83
104
 
84
105
  Use these placeholder patterns in backlog items. Replace `{typeCheckCommand}`, `{testCommand}`, and `{module}` with values from `forge.config.json` and the project structure:
@@ -84,6 +84,25 @@ When examining a Go project, check for:
84
84
  - **Formatting**: `gofmt -l .` or `goimports -l .` (should produce no output)
85
85
  - **Module tidiness**: `go mod tidy` (ensures `go.mod` and `go.sum` are consistent)
86
86
 
87
+ ### Runtime Entrypoints & Bootstrap-Wiring Sites
88
+
89
+ Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
90
+ `CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
91
+
92
+ - **Runtime entrypoints (a legitimate non-test call site):** `func main()` in a `package main` under
93
+ `cmd/…` or the module root, an HTTP handler registered on a `*http.ServeMux` / router, a gRPC service
94
+ registration, or a worker/consumer goroutine started from `main` — not a `*_test.go` file.
95
+ - **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package-level
96
+ `func init()` that constructs heavy clients, package-level `var` initializers that dial/connect at
97
+ import time, or a single `bootstrap`/`wire` module `main` calls before serving. `init()` and
98
+ package-var side effects run on **every** binary start, before `main` gets control.
99
+ - **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB drivers/pools
100
+ (`database/sql` + a driver, `pgx`, `gorm`, `mongo-driver`), message/queue clients (`sarama`/Kafka,
101
+ `amqp`, `go-redis`), telemetry SDKs (`go.opentelemetry.io/*`, `sentry-go`), or a broad internal
102
+ service package. An `init()` or package-var that dials any of these is the CHECK-I23 pattern —
103
+ recommend a `sync.Once` lazy constructor invoked from the first handler that needs it, not an
104
+ eager package-level connect.
105
+
87
106
  ## Testing
88
107
 
89
108
  - **Framework**: `testing` stdlib package
@@ -111,6 +111,27 @@ async def refresh_session_token(
111
111
  - **Import validation**: `mypy` with `--strict` or `--disallow-untyped-defs` catches missing type annotations
112
112
  - **Module export validation**: `__all__` lists in `__init__.py` match spec's public API
113
113
 
114
+ ### Runtime Entrypoints & Bootstrap-Wiring Sites
115
+
116
+ Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
117
+ `CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
118
+
119
+ - **Runtime entrypoints (a legitimate non-test call site):** a `if __name__ == "__main__":` block, a
120
+ `[project.scripts]` console-script target in `pyproject.toml`, an ASGI/WSGI app object
121
+ (`app = FastAPI()` / Django `wsgi.py` / `asgi.py`), a route/view/handler, a Celery/RQ task module, or
122
+ a management command — not a `test_*.py` / `conftest.py`.
123
+ - **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package
124
+ `__init__.py` that eagerly instantiates heavy clients at import time, a framework startup hook
125
+ (FastAPI `lifespan` / `@app.on_event("startup")`, Django `AppConfig.ready()`, a Gunicorn/uvicorn
126
+ `--preload` module), or a `conftest.py` that bootstraps production graphs. Import-time side effects
127
+ here run on every process start.
128
+ - **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM engines
129
+ (`sqlalchemy.create_engine`, `psycopg`, Django ORM, `pymongo`, `redis`), task queues (`celery`,
130
+ `rq`, `kafka`), telemetry SDKs (`opentelemetry`, `sentry_sdk`), or a whole-service-layer package
131
+ import. An init pulling any of these at a universal entry is the CHECK-I23 pattern — recommend lazy
132
+ init (module-level `@lru_cache` factory, `Depends()` provider, or first-use lazy import) at the
133
+ handler that needs it.
134
+
114
135
  ## Testing
115
136
 
116
137
  - **Framework**: pytest (with `conftest.py` for fixtures)
@@ -90,6 +90,25 @@ When examining a Rust project, check for:
90
90
  - **Formatting**: `cargo fmt --check` (ensures code matches `rustfmt` style)
91
91
  - **Unsafe audit**: `cargo geiger` (if security-sensitive — counts unsafe blocks)
92
92
 
93
+ ### Runtime Entrypoints & Bootstrap-Wiring Sites
94
+
95
+ Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
96
+ `CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
97
+
98
+ - **Runtime entrypoints (a legitimate non-test call site):** `fn main()` in `main.rs` or a `[[bin]]`
99
+ target, an async runtime entry (`#[tokio::main]`), an HTTP handler registered on an axum/actix/warp
100
+ router, or a worker task spawned from `main` — not a `#[cfg(test)]` module or a `tests/` integration
101
+ file.
102
+ - **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a `lazy_static!`
103
+ / `once_cell::sync::Lazy` static that eagerly constructs heavy clients, a single `bootstrap`/`setup`
104
+ fn `main` calls before serving, or a `#[ctor]`-style pre-`main` initializer. A `Lazy` static is only
105
+ a risk when it is *forced* at startup rather than on first use.
106
+ - **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB pools
107
+ (`sqlx::Pool`, `diesel`, `deadpool`, `mongodb`), message/queue clients (`rdkafka`, `lapin`,
108
+ `redis`), telemetry SDKs (`opentelemetry`, `sentry`), or a broad internal service crate. Constructing
109
+ any of these eagerly at a universal entry is the CHECK-I23 pattern — recommend a `OnceCell`/`Lazy`
110
+ forced on **first use** by the handler that needs it, not at process start.
111
+
93
112
  ## Testing
94
113
 
95
114
  - **Framework**: Built-in test harness (`#[test]`, `#[cfg(test)]`)
@@ -64,6 +64,29 @@ When examining a TypeScript project, check for:
64
64
  - **Cross-package type checks**: `bun run typecheck` (or equivalent) passes for both the feature package AND packages that depend on it
65
65
  - **Import path validation**: All import paths resolve correctly per the `exports` map in `package.json`
66
66
 
67
+ ### Runtime Entrypoints & Bootstrap-Wiring Sites
68
+
69
+ Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
70
+ `CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
71
+
72
+ - **Runtime entrypoints (a legitimate non-test call site):** a `package.json` `bin` / CLI `main`; a
73
+ server entry that actually starts listening (`src/server.ts`, `src/index.ts` invoking `listen`); a
74
+ worker/consumer file; and for Next.js — `middleware.ts`, `app/**/route.ts` route handlers,
75
+ `app/**/{page,layout,template}.tsx`, server actions, and `instrumentation.ts`. Express/Hono/Fastify:
76
+ the file that constructs the app and calls `.listen()`.
77
+ - **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** Next.js
78
+ `instrumentation.ts` / `instrumentation.js` (its `register()` runs once per server process before
79
+ any request), an app-server preload/`register`/`--import` hook, a root `app/layout.tsx` that
80
+ eagerly imports server singletons, and global test setup (`vitest.setup.ts`, `jest.setup.ts`) if it
81
+ bootstraps production graphs. Wiring a heavy init here loads it on **every** cold start (and, under
82
+ the dev server, on every module re-evaluation).
83
+ - **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM clients
84
+ (`drizzle-orm`, `@prisma/client`, `pg`, `mongoose`, `kysely`), queue/worker libs (`bullmq`, `bull`,
85
+ `kafkajs`, `ioredis`), telemetry/observability SDKs (`@opentelemetry/*`, `@sentry/node`), and a
86
+ whole-service-layer barrel (`import * as services from "@repo/services"`). An init that pulls any of
87
+ these into a universal bootstrap entry is the CHECK-I23 pattern — recommend lazy init at the first
88
+ route/handler/worker that needs it.
89
+
67
90
  ## Testing
68
91
 
69
92
  - **Framework**: Vitest (most common in modern TS), Jest, or testing-library
@@ -47,6 +47,21 @@ PIPELINE_STATE_FILENAME: Final = ".pipeline-state.json"
47
47
  MANIFEST_FILENAME: Final = "epic-manifest.json"
48
48
  NARRATIVE_FILENAME: Final = "EPIC.md"
49
49
 
50
+ #: The authoritative forge-verify status vocabulary. SOURCE OF TRUTH:
51
+ #: references/pipeline-state-schema.json (definitions.verifyEntry.properties.status.enum).
52
+ #: A member state carrying a forge-verify-*.status outside this set is treated as
53
+ #: incomplete-for-orchestration but SURFACED (never guessed silently) by render_status
54
+ #: — a single typo'd status otherwise poisons the epic rollup + dependency gates (#148).
55
+ #: NOTE: forge-session.py keeps a byte-identical copy of this constant — flat, self-
56
+ #: contained scripts have no shared import module (each is copied verbatim into adapters).
57
+ KNOWN_VERIFY_STATUSES: Final = frozenset(
58
+ {"pending", "passed", "findings-reported", "findings-applied", "skipped"}
59
+ )
60
+ #: The subset of KNOWN_VERIFY_STATUSES that makes a member's forge-verify-impl count as
61
+ #: complete-for-orchestration (00 §7). A STRICT subset — 'findings-reported' (unfixed),
62
+ #: 'skipped', and 'pending' do NOT unblock dependents. Not collapsible into the set above.
63
+ _VERIFY_ORCH_COMPLETE: Final = frozenset({"passed", "findings-applied"})
64
+
50
65
 
51
66
  # --------------------------------------------------------------------------- #
52
67
  # Type Definitions (00-core-definitions.md §4, §5; 02 §8.4)
@@ -139,6 +154,10 @@ class RenderStatus(TypedDict):
139
154
  rollup: Aggregate {complete, total} counts.
140
155
  nextCommand: Recommended next command for the first actionable feature, or
141
156
  None when nothing is actionable (all complete, empty epic, or paused).
157
+ warnings: Human-readable diagnostics that do NOT invalidate the graph but
158
+ need surfacing — currently, members carrying a ``forge-verify-*.status``
159
+ outside ``KNOWN_VERIFY_STATUSES`` (treated as incomplete, but silently so
160
+ would poison the rollup + dependency gates, #148). Empty in the common case.
142
161
  """
143
162
 
144
163
  epic: str
@@ -148,6 +167,7 @@ class RenderStatus(TypedDict):
148
167
  parallelEligible: list[str]
149
168
  rollup: Rollup
150
169
  nextCommand: str | None
170
+ warnings: list[str]
151
171
 
152
172
 
153
173
  # --------------------------------------------------------------------------- #
@@ -542,6 +562,11 @@ _TOP_REQUIRED: Final = (
542
562
  )
543
563
  #: Required keys on each Feature object (00 §2.2).
544
564
  _FEATURE_REQUIRED: Final = ("name", "charter", "dependsOn", "exposes", "consumes")
565
+ #: Optional keys on each Feature object. `mutatesShared` is the #144 precision
566
+ #: hint for cross-member coupling (array of project-root-relative path strings);
567
+ #: schema-legal when present, ignored when absent (mirrors
568
+ #: epic-manifest-schema.json definitions.feature.properties.mutatesShared).
569
+ _FEATURE_OPTIONAL: Final = ("mutatesShared",)
545
570
  #: Required keys on each Contract (exposes[]) object (00 §2.3).
546
571
  _CONTRACT_REQUIRED: Final = ("name", "kind", "summary")
547
572
  #: Required keys on each ConsumedContract (consumes[]) object (00 §2.4).
@@ -617,11 +642,16 @@ def _schema_findings(manifest: dict) -> list[Finding]:
617
642
  findings.append(_schema(f"feature {label!r} missing required key {key!r}", fname))
618
643
  for key in feat:
619
644
  # 'status' is rejected separately above via the dedicated 'cached-status' code.
620
- if key not in _FEATURE_REQUIRED and key != "status":
645
+ if key not in _FEATURE_REQUIRED and key not in _FEATURE_OPTIONAL and key != "status":
621
646
  findings.append(_schema(f"feature {label!r} has unknown key {key!r}", fname))
622
647
  for key in ("name", "charter"):
623
648
  if key in feat and not isinstance(feat[key], str):
624
649
  findings.append(_schema(f"feature {label!r} {key} must be a string", fname))
650
+ if "mutatesShared" in feat and (
651
+ not isinstance(feat["mutatesShared"], list)
652
+ or not all(isinstance(p, str) for p in feat["mutatesShared"])
653
+ ):
654
+ findings.append(_schema(f"feature {label!r} mutatesShared must be an array of strings", fname)) # noqa: E501
625
655
  if "dependsOn" in feat:
626
656
  if not isinstance(feat["dependsOn"], list) or not all(isinstance(d, str) for d in feat["dependsOn"]): # noqa: E501
627
657
  findings.append(_schema(f"feature {label!r} dependsOn must be an array of strings", fname)) # noqa: E501
@@ -792,7 +822,41 @@ def is_complete_for_orchestration(state: dict) -> bool:
792
822
  return True
793
823
  if not isinstance(impl, dict):
794
824
  return False
795
- return impl.get("status") in {"passed", "findings-applied"}
825
+ return impl.get("status") in _VERIFY_ORCH_COMPLETE
826
+
827
+
828
+ def _verify_status_warnings(name: str, state: dict) -> list[str]:
829
+ """Flag any ``forge-verify-*.status`` outside the known vocabulary (#148).
830
+
831
+ An unrecognized status (e.g. the eye-slip ``findings-resolved``, conflated with the
832
+ adjacent ``findingsResolved`` count) is correctly treated as incomplete by
833
+ ``is_complete_for_orchestration`` — but *silently*, so one typo on one member
834
+ under-reports the whole epic rollup and fabricates phantom ``unmetDeps`` on
835
+ dependents. Surfacing it turns that non-local corruption into a visible diagnostic.
836
+
837
+ Non-string / malformed status values (a list, an int) are also flagged, and the
838
+ membership test is guarded so an unhashable value never raises.
839
+ """
840
+ stages = state.get("stages", {})
841
+ if not isinstance(stages, dict):
842
+ return []
843
+ warnings: list[str] = []
844
+ known = ", ".join(sorted(KNOWN_VERIFY_STATUSES))
845
+ for stage_name, entry in stages.items():
846
+ if not (isinstance(stage_name, str) and stage_name.startswith("forge-verify-")):
847
+ continue
848
+ if not isinstance(entry, dict):
849
+ continue
850
+ status = entry.get("status")
851
+ if status is None:
852
+ continue
853
+ if isinstance(status, str) and status in KNOWN_VERIFY_STATUSES:
854
+ continue
855
+ warnings.append(
856
+ f"{name}: unknown {stage_name} status {status!r} "
857
+ f"(treated as incomplete; expected one of {known})"
858
+ )
859
+ return warnings
796
860
 
797
861
 
798
862
  def _read_state_safely(state_path: Path) -> dict:
@@ -927,14 +991,15 @@ def render_status(epic_dir: Path, specs_dir: Path) -> RenderStatus:
927
991
  rows: list[FeatureStatus] = []
928
992
  feature_dir_by_name: dict[str, Path] = {}
929
993
  complete: dict[str, bool] = {}
994
+ warnings: list[str] = []
930
995
  for feat in features:
931
996
  name = feat["name"]
932
997
  member_dir = contained_path(epic_dir, name)
933
998
  feature_dir_by_name[name] = member_dir
934
999
  rows.append(derive_status(member_dir))
935
- complete[name] = is_complete_for_orchestration(
936
- _read_state_safely(member_dir / PIPELINE_STATE_FILENAME)
937
- )
1000
+ member_state = _read_state_safely(member_dir / PIPELINE_STATE_FILENAME)
1001
+ complete[name] = is_complete_for_orchestration(member_state)
1002
+ warnings.extend(_verify_status_warnings(name, member_state))
938
1003
 
939
1004
  # (4) per-feature unmetDeps + blocked. A feature that is itself complete is
940
1005
  # never "blocked" — unmet deps only matter for work not yet finished.
@@ -989,6 +1054,7 @@ def render_status(epic_dir: Path, specs_dir: Path) -> RenderStatus:
989
1054
  "parallelEligible": parallel_eligible,
990
1055
  "rollup": rollup,
991
1056
  "nextCommand": next_command,
1057
+ "warnings": warnings,
992
1058
  }
993
1059
 
994
1060
 
@@ -1414,6 +1480,10 @@ def _print_status_table(status: RenderStatus) -> None:
1414
1480
  marker = "⚠️ BLOCKING" if row["blockingEpicChangeRequests"] else "⚠️"
1415
1481
  line += f" — {marker} {row['openEpicChangeRequests']} pending epic change(s)"
1416
1482
  print(line)
1483
+ if status["warnings"]:
1484
+ print("Warnings:")
1485
+ for warning in status["warnings"]:
1486
+ print(f" ⚠️ {warning}")
1417
1487
  if status["actionable"]:
1418
1488
  print(f"Actionable: {', '.join(status['actionable'])}")
1419
1489
  if status["parallelEligible"]: