@garygentry/feature-forge 0.3.6 → 0.3.7

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 (753) hide show
  1. package/README.md +1 -1
  2. package/adapters/GENERATION-REPORT.md +20 -0
  3. package/adapters/claude/.claude-plugin/plugin.json +16 -0
  4. package/adapters/claude/.feature-forge-bundle.json +1 -1
  5. package/adapters/claude/agents/forge-verifier.md +16 -5
  6. package/adapters/claude/references/forge-config-schema.json +3 -3
  7. package/adapters/claude/references/portable-root.md +20 -16
  8. package/adapters/claude/references/preflight-and-self-heal.md +183 -0
  9. package/adapters/claude/references/process-overview.md +1 -1
  10. package/adapters/claude/references/select-outcome.md +138 -0
  11. package/adapters/claude/references/shared-conventions.md +175 -22
  12. package/adapters/claude/references/skill-frontmatter.schema.json +3 -1
  13. package/adapters/claude/references/stack-resolution.md +1 -1
  14. package/adapters/claude/references/stage-exit-protocol.md +19 -4
  15. package/adapters/claude/references/templates/root-hygiene/AGENTS.md +14 -0
  16. package/adapters/claude/references/templates/root-hygiene/CLAUDE.md +14 -0
  17. package/adapters/claude/references/templates/specs-hygiene/AGENTS.md +3 -1
  18. package/adapters/claude/references/templates/specs-hygiene/CLAUDE.md +2 -1
  19. package/adapters/claude/references/verifier-patterns/MEMORY.md +35 -0
  20. package/adapters/claude/references/verifier-patterns/pattern_absence_claims.md +36 -0
  21. package/adapters/claude/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  22. package/adapters/claude/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  23. package/adapters/claude/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  24. package/adapters/claude/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  25. package/adapters/claude/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  26. package/adapters/claude/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  27. package/adapters/claude/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  28. package/adapters/claude/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  29. package/adapters/claude/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  30. package/adapters/claude/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  31. package/adapters/claude/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  32. package/adapters/claude/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  33. package/adapters/claude/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  34. package/adapters/claude/references/verifier-patterns/pattern_test_count_units.md +20 -0
  35. package/adapters/claude/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  36. package/adapters/claude/references/verify-state.md +98 -0
  37. package/adapters/claude/scripts/forge-bootstrap.py +23 -2
  38. package/adapters/claude/scripts/forge-root.sh +104 -21
  39. package/adapters/claude/scripts/forge-session.py +620 -6973
  40. package/adapters/claude/scripts/forge_session/__init__.py +11 -0
  41. package/adapters/claude/scripts/forge_session/_common.py +1566 -0
  42. package/adapters/claude/scripts/forge_session/_doctor_util.py +218 -0
  43. package/adapters/claude/scripts/forge_session/cli.py +1067 -0
  44. package/adapters/claude/scripts/forge_session/decisions.py +355 -0
  45. package/adapters/claude/scripts/forge_session/discover.py +472 -0
  46. package/adapters/claude/scripts/forge_session/doctor.py +2144 -0
  47. package/adapters/claude/scripts/forge_session/exit.py +1081 -0
  48. package/adapters/claude/scripts/forge_session/outcomes.py +574 -0
  49. package/adapters/claude/scripts/forge_session/routes.py +1162 -0
  50. package/adapters/claude/scripts/forge_session/state.py +1479 -0
  51. package/adapters/claude/scripts/forge_session/topology.py +443 -0
  52. package/adapters/claude/skills/forge/SKILL.md +7 -7
  53. package/adapters/claude/skills/forge/references/process-overview.md +1 -1
  54. package/adapters/claude/skills/forge/references/shared-conventions.md +175 -22
  55. package/adapters/claude/skills/forge/references/stage-exit-protocol.md +19 -4
  56. package/adapters/claude/skills/forge-0-epic/SKILL.md +7 -7
  57. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +9 -5
  58. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
  59. package/adapters/claude/skills/forge-0-epic/references/portable-root.md +20 -16
  60. package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +175 -22
  61. package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +19 -4
  62. package/adapters/claude/skills/forge-1-prd/SKILL.md +7 -7
  63. package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +175 -22
  64. package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +19 -4
  65. package/adapters/claude/skills/forge-2-tech/SKILL.md +7 -7
  66. package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +175 -22
  67. package/adapters/claude/skills/forge-2-tech/references/stack-resolution.md +1 -1
  68. package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +19 -4
  69. package/adapters/claude/skills/forge-3-specs/SKILL.md +5 -5
  70. package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +175 -22
  71. package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +19 -4
  72. package/adapters/claude/skills/forge-4-backlog/SKILL.md +16 -8
  73. package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +175 -22
  74. package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +19 -4
  75. package/adapters/claude/skills/forge-4-backlog/references/verify-state.md +98 -0
  76. package/adapters/claude/skills/forge-5-loop/SKILL.md +36 -41
  77. package/adapters/claude/skills/forge-5-loop/references/agent-selection.md +4 -0
  78. package/adapters/claude/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  79. package/adapters/claude/skills/forge-5-loop/references/recovery-procedure.md +10 -0
  80. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +15 -5
  81. package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +175 -22
  82. package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +19 -4
  83. package/adapters/claude/skills/forge-5-loop/references/verify-state.md +98 -0
  84. package/adapters/claude/skills/forge-6-docs/SKILL.md +21 -14
  85. package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +175 -22
  86. package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +19 -4
  87. package/adapters/claude/skills/forge-6-docs/references/verify-state.md +98 -0
  88. package/adapters/claude/skills/forge-bootstrap/SKILL.md +19 -10
  89. package/adapters/claude/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  90. package/adapters/claude/skills/forge-fix/SKILL.md +15 -18
  91. package/adapters/claude/skills/forge-fix/references/select-outcome.md +138 -0
  92. package/adapters/claude/skills/forge-fix/references/shared-conventions.md +175 -22
  93. package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +19 -4
  94. package/adapters/claude/skills/forge-guide/SKILL.md +87 -1
  95. package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +3 -3
  96. package/adapters/claude/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  97. package/adapters/claude/skills/forge-guide/references/process-overview.md +1 -1
  98. package/adapters/claude/skills/forge-guide/references/shared-conventions.md +175 -22
  99. package/adapters/claude/skills/forge-guide/references/stack-resolution.md +1 -1
  100. package/adapters/claude/skills/forge-init/SKILL.md +58 -7
  101. package/adapters/claude/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  102. package/adapters/claude/skills/forge-init/references/shared-conventions.md +572 -0
  103. package/adapters/claude/skills/forge-verify/SKILL.md +20 -23
  104. package/adapters/claude/skills/forge-verify/references/findings-template.md +2 -2
  105. package/adapters/claude/skills/forge-verify/references/select-outcome.md +138 -0
  106. package/adapters/claude/skills/forge-verify/references/shared-conventions.md +175 -22
  107. package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +19 -4
  108. package/adapters/claude/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  109. package/adapters/claude/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  110. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  111. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  112. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  113. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  114. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  115. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  116. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  117. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  118. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  119. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  120. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  121. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  122. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  123. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  124. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  125. package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  126. package/adapters/codex/.feature-forge-bundle.json +1 -1
  127. package/adapters/codex/agents/forge-researcher.toml +1 -1
  128. package/adapters/codex/agents/forge-verifier.toml +17 -6
  129. package/adapters/codex/references/forge-config-schema.json +5 -5
  130. package/adapters/codex/references/portable-root.md +20 -16
  131. package/adapters/codex/references/preflight-and-self-heal.md +183 -0
  132. package/adapters/codex/references/process-overview.md +10 -10
  133. package/adapters/codex/references/select-outcome.md +138 -0
  134. package/adapters/codex/references/shared-conventions.md +188 -35
  135. package/adapters/codex/references/skill-frontmatter.schema.json +3 -1
  136. package/adapters/codex/references/stack-resolution.md +1 -1
  137. package/adapters/codex/references/stage-exit-protocol.md +22 -7
  138. package/adapters/codex/references/templates/root-hygiene/AGENTS.md +14 -0
  139. package/adapters/codex/references/templates/root-hygiene/CLAUDE.md +14 -0
  140. package/adapters/codex/references/templates/specs-hygiene/AGENTS.md +3 -1
  141. package/adapters/codex/references/templates/specs-hygiene/CLAUDE.md +2 -1
  142. package/adapters/codex/references/verifier-patterns/MEMORY.md +35 -0
  143. package/adapters/codex/references/verifier-patterns/pattern_absence_claims.md +36 -0
  144. package/adapters/codex/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  145. package/adapters/codex/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  146. package/adapters/codex/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  147. package/adapters/codex/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  148. package/adapters/codex/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  149. package/adapters/codex/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  150. package/adapters/codex/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  151. package/adapters/codex/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  152. package/adapters/codex/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  153. package/adapters/codex/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  154. package/adapters/codex/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  155. package/adapters/codex/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  156. package/adapters/codex/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  157. package/adapters/codex/references/verifier-patterns/pattern_test_count_units.md +20 -0
  158. package/adapters/codex/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  159. package/adapters/codex/references/verify-state.md +98 -0
  160. package/adapters/codex/scripts/forge-bootstrap.py +23 -2
  161. package/adapters/codex/scripts/forge-root.sh +104 -21
  162. package/adapters/codex/scripts/forge-session.py +620 -6973
  163. package/adapters/codex/scripts/forge_session/__init__.py +11 -0
  164. package/adapters/codex/scripts/forge_session/_common.py +1566 -0
  165. package/adapters/codex/scripts/forge_session/_doctor_util.py +218 -0
  166. package/adapters/codex/scripts/forge_session/cli.py +1067 -0
  167. package/adapters/codex/scripts/forge_session/decisions.py +355 -0
  168. package/adapters/codex/scripts/forge_session/discover.py +472 -0
  169. package/adapters/codex/scripts/forge_session/doctor.py +2144 -0
  170. package/adapters/codex/scripts/forge_session/exit.py +1081 -0
  171. package/adapters/codex/scripts/forge_session/outcomes.py +574 -0
  172. package/adapters/codex/scripts/forge_session/routes.py +1162 -0
  173. package/adapters/codex/scripts/forge_session/state.py +1479 -0
  174. package/adapters/codex/scripts/forge_session/topology.py +443 -0
  175. package/adapters/codex/skills/forge/SKILL.md +40 -40
  176. package/adapters/codex/skills/forge/references/process-overview.md +10 -10
  177. package/adapters/codex/skills/forge/references/shared-conventions.md +188 -35
  178. package/adapters/codex/skills/forge/references/stage-exit-protocol.md +22 -7
  179. package/adapters/codex/skills/forge-0-epic/SKILL.md +15 -15
  180. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +14 -10
  181. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  182. package/adapters/codex/skills/forge-0-epic/references/portable-root.md +20 -16
  183. package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +188 -35
  184. package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
  185. package/adapters/codex/skills/forge-1-prd/SKILL.md +15 -15
  186. package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +188 -35
  187. package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
  188. package/adapters/codex/skills/forge-2-tech/SKILL.md +15 -15
  189. package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +188 -35
  190. package/adapters/codex/skills/forge-2-tech/references/stack-resolution.md +1 -1
  191. package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
  192. package/adapters/codex/skills/forge-3-specs/SKILL.md +10 -10
  193. package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +188 -35
  194. package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
  195. package/adapters/codex/skills/forge-4-backlog/SKILL.md +19 -11
  196. package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +188 -35
  197. package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
  198. package/adapters/codex/skills/forge-4-backlog/references/verify-state.md +98 -0
  199. package/adapters/codex/skills/forge-5-loop/SKILL.md +48 -53
  200. package/adapters/codex/skills/forge-5-loop/references/agent-selection.md +5 -1
  201. package/adapters/codex/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  202. package/adapters/codex/skills/forge-5-loop/references/recovery-procedure.md +14 -4
  203. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +18 -8
  204. package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +188 -35
  205. package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
  206. package/adapters/codex/skills/forge-5-loop/references/verify-state.md +98 -0
  207. package/adapters/codex/skills/forge-6-docs/SKILL.md +27 -20
  208. package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +188 -35
  209. package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
  210. package/adapters/codex/skills/forge-6-docs/references/verify-state.md +98 -0
  211. package/adapters/codex/skills/forge-bootstrap/SKILL.md +23 -15
  212. package/adapters/codex/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  213. package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
  214. package/adapters/codex/skills/forge-fix/SKILL.md +27 -30
  215. package/adapters/codex/skills/forge-fix/references/select-outcome.md +138 -0
  216. package/adapters/codex/skills/forge-fix/references/shared-conventions.md +188 -35
  217. package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +22 -7
  218. package/adapters/codex/skills/forge-guide/SKILL.md +84 -7
  219. package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +5 -5
  220. package/adapters/codex/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  221. package/adapters/codex/skills/forge-guide/references/process-overview.md +10 -10
  222. package/adapters/codex/skills/forge-guide/references/shared-conventions.md +188 -35
  223. package/adapters/codex/skills/forge-guide/references/stack-resolution.md +1 -1
  224. package/adapters/codex/skills/forge-init/SKILL.md +62 -12
  225. package/adapters/codex/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  226. package/adapters/codex/skills/forge-init/references/shared-conventions.md +572 -0
  227. package/adapters/codex/skills/forge-verify/SKILL.md +27 -30
  228. package/adapters/codex/skills/forge-verify/references/findings-template.md +2 -2
  229. package/adapters/codex/skills/forge-verify/references/select-outcome.md +138 -0
  230. package/adapters/codex/skills/forge-verify/references/shared-conventions.md +188 -35
  231. package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +22 -7
  232. package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +2 -2
  233. package/adapters/codex/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  234. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  235. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  236. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  237. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  238. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  239. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  240. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  241. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  242. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  243. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  244. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  245. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  246. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  247. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  248. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  249. package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  250. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  251. package/adapters/copilot/agents/forge-researcher.md +1 -1
  252. package/adapters/copilot/agents/forge-verifier.md +17 -6
  253. package/adapters/copilot/references/forge-config-schema.json +5 -5
  254. package/adapters/copilot/references/portable-root.md +20 -16
  255. package/adapters/copilot/references/preflight-and-self-heal.md +183 -0
  256. package/adapters/copilot/references/process-overview.md +10 -10
  257. package/adapters/copilot/references/select-outcome.md +138 -0
  258. package/adapters/copilot/references/shared-conventions.md +188 -35
  259. package/adapters/copilot/references/skill-frontmatter.schema.json +3 -1
  260. package/adapters/copilot/references/stack-resolution.md +1 -1
  261. package/adapters/copilot/references/stage-exit-protocol.md +22 -7
  262. package/adapters/copilot/references/templates/root-hygiene/AGENTS.md +14 -0
  263. package/adapters/copilot/references/templates/root-hygiene/CLAUDE.md +14 -0
  264. package/adapters/copilot/references/templates/specs-hygiene/AGENTS.md +3 -1
  265. package/adapters/copilot/references/templates/specs-hygiene/CLAUDE.md +2 -1
  266. package/adapters/copilot/references/verifier-patterns/MEMORY.md +35 -0
  267. package/adapters/copilot/references/verifier-patterns/pattern_absence_claims.md +36 -0
  268. package/adapters/copilot/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  269. package/adapters/copilot/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  270. package/adapters/copilot/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  271. package/adapters/copilot/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  272. package/adapters/copilot/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  273. package/adapters/copilot/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  274. package/adapters/copilot/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  275. package/adapters/copilot/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  276. package/adapters/copilot/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  277. package/adapters/copilot/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  278. package/adapters/copilot/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  279. package/adapters/copilot/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  280. package/adapters/copilot/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  281. package/adapters/copilot/references/verifier-patterns/pattern_test_count_units.md +20 -0
  282. package/adapters/copilot/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  283. package/adapters/copilot/references/verify-state.md +98 -0
  284. package/adapters/copilot/scripts/forge-bootstrap.py +23 -2
  285. package/adapters/copilot/scripts/forge-root.sh +104 -21
  286. package/adapters/copilot/scripts/forge-session.py +620 -6973
  287. package/adapters/copilot/scripts/forge_session/__init__.py +11 -0
  288. package/adapters/copilot/scripts/forge_session/_common.py +1566 -0
  289. package/adapters/copilot/scripts/forge_session/_doctor_util.py +218 -0
  290. package/adapters/copilot/scripts/forge_session/cli.py +1067 -0
  291. package/adapters/copilot/scripts/forge_session/decisions.py +355 -0
  292. package/adapters/copilot/scripts/forge_session/discover.py +472 -0
  293. package/adapters/copilot/scripts/forge_session/doctor.py +2144 -0
  294. package/adapters/copilot/scripts/forge_session/exit.py +1081 -0
  295. package/adapters/copilot/scripts/forge_session/outcomes.py +574 -0
  296. package/adapters/copilot/scripts/forge_session/routes.py +1162 -0
  297. package/adapters/copilot/scripts/forge_session/state.py +1479 -0
  298. package/adapters/copilot/scripts/forge_session/topology.py +443 -0
  299. package/adapters/copilot/skills/forge/forge.md +40 -40
  300. package/adapters/copilot/skills/forge/references/process-overview.md +10 -10
  301. package/adapters/copilot/skills/forge/references/shared-conventions.md +188 -35
  302. package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +22 -7
  303. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +15 -15
  304. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +14 -10
  305. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  306. package/adapters/copilot/skills/forge-0-epic/references/portable-root.md +20 -16
  307. package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +188 -35
  308. package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
  309. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +15 -15
  310. package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +188 -35
  311. package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
  312. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +15 -15
  313. package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +188 -35
  314. package/adapters/copilot/skills/forge-2-tech/references/stack-resolution.md +1 -1
  315. package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
  316. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +10 -10
  317. package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +188 -35
  318. package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
  319. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +19 -11
  320. package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +188 -35
  321. package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
  322. package/adapters/copilot/skills/forge-4-backlog/references/verify-state.md +98 -0
  323. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +48 -53
  324. package/adapters/copilot/skills/forge-5-loop/references/agent-selection.md +5 -1
  325. package/adapters/copilot/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  326. package/adapters/copilot/skills/forge-5-loop/references/recovery-procedure.md +14 -4
  327. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +18 -8
  328. package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +188 -35
  329. package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
  330. package/adapters/copilot/skills/forge-5-loop/references/verify-state.md +98 -0
  331. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +27 -20
  332. package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +188 -35
  333. package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
  334. package/adapters/copilot/skills/forge-6-docs/references/verify-state.md +98 -0
  335. package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +23 -15
  336. package/adapters/copilot/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  337. package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
  338. package/adapters/copilot/skills/forge-fix/forge-fix.md +27 -30
  339. package/adapters/copilot/skills/forge-fix/references/select-outcome.md +138 -0
  340. package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +188 -35
  341. package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +22 -7
  342. package/adapters/copilot/skills/forge-guide/forge-guide.md +84 -7
  343. package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +5 -5
  344. package/adapters/copilot/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  345. package/adapters/copilot/skills/forge-guide/references/process-overview.md +10 -10
  346. package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +188 -35
  347. package/adapters/copilot/skills/forge-guide/references/stack-resolution.md +1 -1
  348. package/adapters/copilot/skills/forge-init/forge-init.md +62 -12
  349. package/adapters/copilot/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  350. package/adapters/copilot/skills/forge-init/references/shared-conventions.md +572 -0
  351. package/adapters/copilot/skills/forge-verify/forge-verify.md +27 -30
  352. package/adapters/copilot/skills/forge-verify/references/findings-template.md +2 -2
  353. package/adapters/copilot/skills/forge-verify/references/select-outcome.md +138 -0
  354. package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +188 -35
  355. package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +22 -7
  356. package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +2 -2
  357. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  358. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  359. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  360. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  361. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  362. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  363. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  364. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  365. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  366. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  367. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  368. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  369. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  370. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  371. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  372. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  373. package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  374. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  375. package/adapters/cursor/agents/forge-researcher.mdc +1 -1
  376. package/adapters/cursor/agents/forge-verifier.mdc +17 -6
  377. package/adapters/cursor/references/forge-config-schema.json +5 -5
  378. package/adapters/cursor/references/portable-root.md +20 -16
  379. package/adapters/cursor/references/preflight-and-self-heal.md +183 -0
  380. package/adapters/cursor/references/process-overview.md +10 -10
  381. package/adapters/cursor/references/select-outcome.md +138 -0
  382. package/adapters/cursor/references/shared-conventions.md +188 -35
  383. package/adapters/cursor/references/skill-frontmatter.schema.json +3 -1
  384. package/adapters/cursor/references/stack-resolution.md +1 -1
  385. package/adapters/cursor/references/stage-exit-protocol.md +22 -7
  386. package/adapters/cursor/references/templates/root-hygiene/AGENTS.md +14 -0
  387. package/adapters/cursor/references/templates/root-hygiene/CLAUDE.md +14 -0
  388. package/adapters/cursor/references/templates/specs-hygiene/AGENTS.md +3 -1
  389. package/adapters/cursor/references/templates/specs-hygiene/CLAUDE.md +2 -1
  390. package/adapters/cursor/references/verifier-patterns/MEMORY.md +35 -0
  391. package/adapters/cursor/references/verifier-patterns/pattern_absence_claims.md +36 -0
  392. package/adapters/cursor/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  393. package/adapters/cursor/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  394. package/adapters/cursor/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  395. package/adapters/cursor/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  396. package/adapters/cursor/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  397. package/adapters/cursor/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  398. package/adapters/cursor/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  399. package/adapters/cursor/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  400. package/adapters/cursor/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  401. package/adapters/cursor/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  402. package/adapters/cursor/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  403. package/adapters/cursor/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  404. package/adapters/cursor/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  405. package/adapters/cursor/references/verifier-patterns/pattern_test_count_units.md +20 -0
  406. package/adapters/cursor/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  407. package/adapters/cursor/references/verify-state.md +98 -0
  408. package/adapters/cursor/scripts/forge-bootstrap.py +23 -2
  409. package/adapters/cursor/scripts/forge-root.sh +104 -21
  410. package/adapters/cursor/scripts/forge-session.py +620 -6973
  411. package/adapters/cursor/scripts/forge_session/__init__.py +11 -0
  412. package/adapters/cursor/scripts/forge_session/_common.py +1566 -0
  413. package/adapters/cursor/scripts/forge_session/_doctor_util.py +218 -0
  414. package/adapters/cursor/scripts/forge_session/cli.py +1067 -0
  415. package/adapters/cursor/scripts/forge_session/decisions.py +355 -0
  416. package/adapters/cursor/scripts/forge_session/discover.py +472 -0
  417. package/adapters/cursor/scripts/forge_session/doctor.py +2144 -0
  418. package/adapters/cursor/scripts/forge_session/exit.py +1081 -0
  419. package/adapters/cursor/scripts/forge_session/outcomes.py +574 -0
  420. package/adapters/cursor/scripts/forge_session/routes.py +1162 -0
  421. package/adapters/cursor/scripts/forge_session/state.py +1479 -0
  422. package/adapters/cursor/scripts/forge_session/topology.py +443 -0
  423. package/adapters/cursor/skills/forge/forge.mdc +40 -40
  424. package/adapters/cursor/skills/forge/references/process-overview.md +10 -10
  425. package/adapters/cursor/skills/forge/references/shared-conventions.md +188 -35
  426. package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +22 -7
  427. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +15 -15
  428. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +14 -10
  429. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  430. package/adapters/cursor/skills/forge-0-epic/references/portable-root.md +20 -16
  431. package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +188 -35
  432. package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
  433. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +15 -15
  434. package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +188 -35
  435. package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
  436. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +15 -15
  437. package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +188 -35
  438. package/adapters/cursor/skills/forge-2-tech/references/stack-resolution.md +1 -1
  439. package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
  440. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +10 -10
  441. package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +188 -35
  442. package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
  443. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +19 -11
  444. package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +188 -35
  445. package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
  446. package/adapters/cursor/skills/forge-4-backlog/references/verify-state.md +98 -0
  447. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +48 -53
  448. package/adapters/cursor/skills/forge-5-loop/references/agent-selection.md +5 -1
  449. package/adapters/cursor/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  450. package/adapters/cursor/skills/forge-5-loop/references/recovery-procedure.md +14 -4
  451. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +18 -8
  452. package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +188 -35
  453. package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
  454. package/adapters/cursor/skills/forge-5-loop/references/verify-state.md +98 -0
  455. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +27 -20
  456. package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +188 -35
  457. package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
  458. package/adapters/cursor/skills/forge-6-docs/references/verify-state.md +98 -0
  459. package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +23 -15
  460. package/adapters/cursor/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  461. package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
  462. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +27 -30
  463. package/adapters/cursor/skills/forge-fix/references/select-outcome.md +138 -0
  464. package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +188 -35
  465. package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +22 -7
  466. package/adapters/cursor/skills/forge-guide/forge-guide.mdc +84 -7
  467. package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +5 -5
  468. package/adapters/cursor/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  469. package/adapters/cursor/skills/forge-guide/references/process-overview.md +10 -10
  470. package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +188 -35
  471. package/adapters/cursor/skills/forge-guide/references/stack-resolution.md +1 -1
  472. package/adapters/cursor/skills/forge-init/forge-init.mdc +62 -12
  473. package/adapters/cursor/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  474. package/adapters/cursor/skills/forge-init/references/shared-conventions.md +572 -0
  475. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +27 -30
  476. package/adapters/cursor/skills/forge-verify/references/findings-template.md +2 -2
  477. package/adapters/cursor/skills/forge-verify/references/select-outcome.md +138 -0
  478. package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +188 -35
  479. package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +22 -7
  480. package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +2 -2
  481. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  482. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  483. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  484. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  485. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  486. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  487. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  488. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  489. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  490. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  491. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  492. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  493. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  494. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  495. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  496. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  497. package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  498. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  499. package/adapters/gemini/agents/forge-researcher.md +1 -1
  500. package/adapters/gemini/agents/forge-verifier.md +17 -6
  501. package/adapters/gemini/gemini-extension.json +13 -13
  502. package/adapters/gemini/references/forge-config-schema.json +5 -5
  503. package/adapters/gemini/references/portable-root.md +20 -16
  504. package/adapters/gemini/references/preflight-and-self-heal.md +183 -0
  505. package/adapters/gemini/references/process-overview.md +10 -10
  506. package/adapters/gemini/references/select-outcome.md +138 -0
  507. package/adapters/gemini/references/shared-conventions.md +188 -35
  508. package/adapters/gemini/references/skill-frontmatter.schema.json +3 -1
  509. package/adapters/gemini/references/stack-resolution.md +1 -1
  510. package/adapters/gemini/references/stage-exit-protocol.md +22 -7
  511. package/adapters/gemini/references/templates/root-hygiene/AGENTS.md +14 -0
  512. package/adapters/gemini/references/templates/root-hygiene/CLAUDE.md +14 -0
  513. package/adapters/gemini/references/templates/specs-hygiene/AGENTS.md +3 -1
  514. package/adapters/gemini/references/templates/specs-hygiene/CLAUDE.md +2 -1
  515. package/adapters/gemini/references/verifier-patterns/MEMORY.md +35 -0
  516. package/adapters/gemini/references/verifier-patterns/pattern_absence_claims.md +36 -0
  517. package/adapters/gemini/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  518. package/adapters/gemini/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  519. package/adapters/gemini/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  520. package/adapters/gemini/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  521. package/adapters/gemini/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  522. package/adapters/gemini/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  523. package/adapters/gemini/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  524. package/adapters/gemini/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  525. package/adapters/gemini/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  526. package/adapters/gemini/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  527. package/adapters/gemini/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  528. package/adapters/gemini/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  529. package/adapters/gemini/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  530. package/adapters/gemini/references/verifier-patterns/pattern_test_count_units.md +20 -0
  531. package/adapters/gemini/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  532. package/adapters/gemini/references/verify-state.md +98 -0
  533. package/adapters/gemini/scripts/forge-bootstrap.py +23 -2
  534. package/adapters/gemini/scripts/forge-root.sh +104 -21
  535. package/adapters/gemini/scripts/forge-session.py +620 -6973
  536. package/adapters/gemini/scripts/forge_session/__init__.py +11 -0
  537. package/adapters/gemini/scripts/forge_session/_common.py +1566 -0
  538. package/adapters/gemini/scripts/forge_session/_doctor_util.py +218 -0
  539. package/adapters/gemini/scripts/forge_session/cli.py +1067 -0
  540. package/adapters/gemini/scripts/forge_session/decisions.py +355 -0
  541. package/adapters/gemini/scripts/forge_session/discover.py +472 -0
  542. package/adapters/gemini/scripts/forge_session/doctor.py +2144 -0
  543. package/adapters/gemini/scripts/forge_session/exit.py +1081 -0
  544. package/adapters/gemini/scripts/forge_session/outcomes.py +574 -0
  545. package/adapters/gemini/scripts/forge_session/routes.py +1162 -0
  546. package/adapters/gemini/scripts/forge_session/state.py +1479 -0
  547. package/adapters/gemini/scripts/forge_session/topology.py +443 -0
  548. package/adapters/gemini/skills/forge/forge.md +40 -40
  549. package/adapters/gemini/skills/forge/references/process-overview.md +10 -10
  550. package/adapters/gemini/skills/forge/references/shared-conventions.md +188 -35
  551. package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +22 -7
  552. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +15 -15
  553. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +14 -10
  554. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
  555. package/adapters/gemini/skills/forge-0-epic/references/portable-root.md +20 -16
  556. package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +188 -35
  557. package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
  558. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +15 -15
  559. package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +188 -35
  560. package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
  561. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +15 -15
  562. package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +188 -35
  563. package/adapters/gemini/skills/forge-2-tech/references/stack-resolution.md +1 -1
  564. package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
  565. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +10 -10
  566. package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +188 -35
  567. package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
  568. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +19 -11
  569. package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +188 -35
  570. package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
  571. package/adapters/gemini/skills/forge-4-backlog/references/verify-state.md +98 -0
  572. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +48 -53
  573. package/adapters/gemini/skills/forge-5-loop/references/agent-selection.md +5 -1
  574. package/adapters/gemini/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  575. package/adapters/gemini/skills/forge-5-loop/references/recovery-procedure.md +14 -4
  576. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +18 -8
  577. package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +188 -35
  578. package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
  579. package/adapters/gemini/skills/forge-5-loop/references/verify-state.md +98 -0
  580. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +27 -20
  581. package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +188 -35
  582. package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
  583. package/adapters/gemini/skills/forge-6-docs/references/verify-state.md +98 -0
  584. package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +23 -15
  585. package/adapters/gemini/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  586. package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
  587. package/adapters/gemini/skills/forge-fix/forge-fix.md +27 -30
  588. package/adapters/gemini/skills/forge-fix/references/select-outcome.md +138 -0
  589. package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +188 -35
  590. package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +22 -7
  591. package/adapters/gemini/skills/forge-guide/forge-guide.md +84 -7
  592. package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +5 -5
  593. package/adapters/gemini/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  594. package/adapters/gemini/skills/forge-guide/references/process-overview.md +10 -10
  595. package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +188 -35
  596. package/adapters/gemini/skills/forge-guide/references/stack-resolution.md +1 -1
  597. package/adapters/gemini/skills/forge-init/forge-init.md +62 -12
  598. package/adapters/gemini/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  599. package/adapters/gemini/skills/forge-init/references/shared-conventions.md +572 -0
  600. package/adapters/gemini/skills/forge-verify/forge-verify.md +27 -30
  601. package/adapters/gemini/skills/forge-verify/references/findings-template.md +2 -2
  602. package/adapters/gemini/skills/forge-verify/references/select-outcome.md +138 -0
  603. package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +188 -35
  604. package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +22 -7
  605. package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +2 -2
  606. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  607. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  608. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  609. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  610. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  611. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  612. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  613. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  614. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  615. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  616. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  617. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  618. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  619. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  620. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  621. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  622. package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  623. package/adapters/pi/.feature-forge-bundle.json +1 -1
  624. package/adapters/pi/agents/forge-verifier.md +16 -5
  625. package/adapters/pi/extensions/forge-invocation-args/README.md +106 -0
  626. package/adapters/pi/extensions/forge-invocation-args/index.ts +31 -0
  627. package/adapters/pi/extensions/forge-invocation-args/wiring.ts +172 -0
  628. package/adapters/pi/package.json +1 -0
  629. package/adapters/pi/references/forge-config-schema.json +3 -3
  630. package/adapters/pi/references/portable-root.md +20 -16
  631. package/adapters/pi/references/preflight-and-self-heal.md +183 -0
  632. package/adapters/pi/references/select-outcome.md +138 -0
  633. package/adapters/pi/references/shared-conventions.md +175 -22
  634. package/adapters/pi/references/skill-frontmatter.schema.json +3 -1
  635. package/adapters/pi/references/stack-resolution.md +1 -1
  636. package/adapters/pi/references/stage-exit-protocol.md +19 -4
  637. package/adapters/pi/references/templates/root-hygiene/AGENTS.md +14 -0
  638. package/adapters/pi/references/templates/root-hygiene/CLAUDE.md +14 -0
  639. package/adapters/pi/references/templates/specs-hygiene/AGENTS.md +3 -1
  640. package/adapters/pi/references/templates/specs-hygiene/CLAUDE.md +2 -1
  641. package/adapters/pi/references/verifier-patterns/MEMORY.md +35 -0
  642. package/adapters/pi/references/verifier-patterns/pattern_absence_claims.md +36 -0
  643. package/adapters/pi/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  644. package/adapters/pi/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  645. package/adapters/pi/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  646. package/adapters/pi/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  647. package/adapters/pi/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  648. package/adapters/pi/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  649. package/adapters/pi/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  650. package/adapters/pi/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  651. package/adapters/pi/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  652. package/adapters/pi/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  653. package/adapters/pi/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  654. package/adapters/pi/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  655. package/adapters/pi/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  656. package/adapters/pi/references/verifier-patterns/pattern_test_count_units.md +20 -0
  657. package/adapters/pi/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  658. package/adapters/pi/references/verify-state.md +98 -0
  659. package/adapters/pi/scripts/forge-bootstrap.py +23 -2
  660. package/adapters/pi/scripts/forge-root.sh +104 -21
  661. package/adapters/pi/scripts/forge-session.py +620 -6973
  662. package/adapters/pi/scripts/forge_session/__init__.py +11 -0
  663. package/adapters/pi/scripts/forge_session/_common.py +1566 -0
  664. package/adapters/pi/scripts/forge_session/_doctor_util.py +218 -0
  665. package/adapters/pi/scripts/forge_session/cli.py +1067 -0
  666. package/adapters/pi/scripts/forge_session/decisions.py +355 -0
  667. package/adapters/pi/scripts/forge_session/discover.py +472 -0
  668. package/adapters/pi/scripts/forge_session/doctor.py +2144 -0
  669. package/adapters/pi/scripts/forge_session/exit.py +1081 -0
  670. package/adapters/pi/scripts/forge_session/outcomes.py +574 -0
  671. package/adapters/pi/scripts/forge_session/routes.py +1162 -0
  672. package/adapters/pi/scripts/forge_session/state.py +1479 -0
  673. package/adapters/pi/scripts/forge_session/topology.py +443 -0
  674. package/adapters/pi/skills/forge/SKILL.md +9 -8
  675. package/adapters/pi/skills/forge/references/shared-conventions.md +175 -22
  676. package/adapters/pi/skills/forge/references/stage-exit-protocol.md +19 -4
  677. package/adapters/pi/skills/forge-0-epic/SKILL.md +9 -8
  678. package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +9 -5
  679. package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
  680. package/adapters/pi/skills/forge-0-epic/references/portable-root.md +20 -16
  681. package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +175 -22
  682. package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +19 -4
  683. package/adapters/pi/skills/forge-1-prd/SKILL.md +9 -8
  684. package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +175 -22
  685. package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +19 -4
  686. package/adapters/pi/skills/forge-2-tech/SKILL.md +8 -7
  687. package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +175 -22
  688. package/adapters/pi/skills/forge-2-tech/references/stack-resolution.md +1 -1
  689. package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +19 -4
  690. package/adapters/pi/skills/forge-3-specs/SKILL.md +7 -6
  691. package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +175 -22
  692. package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +19 -4
  693. package/adapters/pi/skills/forge-4-backlog/SKILL.md +18 -9
  694. package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +175 -22
  695. package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +19 -4
  696. package/adapters/pi/skills/forge-4-backlog/references/verify-state.md +98 -0
  697. package/adapters/pi/skills/forge-5-loop/SKILL.md +38 -42
  698. package/adapters/pi/skills/forge-5-loop/references/agent-selection.md +4 -0
  699. package/adapters/pi/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
  700. package/adapters/pi/skills/forge-5-loop/references/recovery-procedure.md +10 -0
  701. package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +15 -5
  702. package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +175 -22
  703. package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +19 -4
  704. package/adapters/pi/skills/forge-5-loop/references/verify-state.md +98 -0
  705. package/adapters/pi/skills/forge-6-docs/SKILL.md +23 -15
  706. package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +175 -22
  707. package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +19 -4
  708. package/adapters/pi/skills/forge-6-docs/references/verify-state.md +98 -0
  709. package/adapters/pi/skills/forge-bootstrap/SKILL.md +20 -11
  710. package/adapters/pi/skills/forge-bootstrap/references/shared-conventions.md +572 -0
  711. package/adapters/pi/skills/forge-fix/SKILL.md +17 -19
  712. package/adapters/pi/skills/forge-fix/references/select-outcome.md +138 -0
  713. package/adapters/pi/skills/forge-fix/references/shared-conventions.md +175 -22
  714. package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +19 -4
  715. package/adapters/pi/skills/forge-guide/SKILL.md +79 -1
  716. package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +3 -3
  717. package/adapters/pi/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
  718. package/adapters/pi/skills/forge-guide/references/shared-conventions.md +175 -22
  719. package/adapters/pi/skills/forge-guide/references/stack-resolution.md +1 -1
  720. package/adapters/pi/skills/forge-init/SKILL.md +59 -8
  721. package/adapters/pi/skills/forge-init/references/preflight-and-self-heal.md +183 -0
  722. package/adapters/pi/skills/forge-init/references/shared-conventions.md +572 -0
  723. package/adapters/pi/skills/forge-verify/SKILL.md +17 -19
  724. package/adapters/pi/skills/forge-verify/references/findings-template.md +1 -1
  725. package/adapters/pi/skills/forge-verify/references/select-outcome.md +138 -0
  726. package/adapters/pi/skills/forge-verify/references/shared-conventions.md +175 -22
  727. package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +19 -4
  728. package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +1 -1
  729. package/adapters/pi/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
  730. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
  731. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
  732. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
  733. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
  734. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
  735. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
  736. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
  737. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
  738. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
  739. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
  740. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
  741. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
  742. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
  743. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
  744. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
  745. package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
  746. package/dist/manifest.d.ts +1 -1
  747. package/dist/rauf.d.ts +3 -3
  748. package/dist/rauf.js +2 -2
  749. package/dist/source.d.ts +5 -2
  750. package/dist/source.js +5 -2
  751. package/dist/types.d.ts +1 -1
  752. package/dist/types.js +1 -1
  753. package/package.json +2 -1
@@ -0,0 +1,1067 @@
1
+ """Argument parsing and command dispatch for the forge-session CLI (#279 P4.1).
2
+
3
+ ``main()`` is the single entry point the hyphen-named shim ``scripts/forge-session.py``
4
+ calls. Every verb's business logic lives in a sibling package module
5
+ (``discover``/``doctor``/``outcomes``/``state``/``exit``/``routes``/``decisions``/
6
+ ``topology``); this module owns only the argparse construction, the per-verb dispatch,
7
+ the ``rank-features``/``context-usage``/``effective-config`` verbs (the small read-only
8
+ reporters that never earned their own module), and the shared ``_emit`` helper.
9
+
10
+ All verb names, flags, exit codes, and JSON shapes are frozen — this module is a pure
11
+ relocation of the dispatch that used to live in the shim body.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+ from typing import Callable, Final, NoReturn, get_args
21
+
22
+ from forge_session._common import (
23
+ ExitOwner,
24
+ FeatureRow,
25
+ PRODUCTION_STAGES,
26
+ UsageError,
27
+ VERIFY_MODE_TO_STAGE,
28
+ VERIFY_RESULT_STATUSES,
29
+ VERIFY_STAGES,
30
+ VERIFY_TOKEN_BY_STAGE,
31
+ VerifyCapability,
32
+ EXIT_HOSTS,
33
+ EXIT_STAGES,
34
+ _counts,
35
+ _default_schema_path,
36
+ load_effective_config,
37
+ build_rows,
38
+ invalid_auto_verify_keys,
39
+ resolve_loop_runner_layers,
40
+ )
41
+ from forge_session.decisions import (
42
+ _default_actor,
43
+ _print_decision_apply,
44
+ _print_decision_list,
45
+ _print_decision_record,
46
+ cmd_decision_apply,
47
+ cmd_decision_list,
48
+ cmd_decision_record,
49
+ )
50
+ from forge_session.discover import (
51
+ _print_check_epic_base,
52
+ _print_discover,
53
+ _print_discover_all,
54
+ _print_reconcile,
55
+ check_epic_base,
56
+ discover_all,
57
+ discover_feature,
58
+ reconcile_branch,
59
+ )
60
+ from forge_session.doctor import (
61
+ DOCTOR_CHECK_IDS,
62
+ _print_doctor,
63
+ doctor_report,
64
+ )
65
+ from forge_session.exit import (
66
+ _EXIT_PRODUCTION_STAGES,
67
+ _print_stage_exit,
68
+ stage_exit,
69
+ )
70
+ from forge_session.outcomes import (
71
+ select_outcome,
72
+ verify_state_for_stage,
73
+ )
74
+ from forge_session.state import (
75
+ _parse_based_on,
76
+ _parse_bool,
77
+ _print_state_artifact,
78
+ _print_state_branch,
79
+ _print_state_complete,
80
+ _print_state_decision,
81
+ _print_state_ecr,
82
+ _print_state_enter,
83
+ _print_state_note,
84
+ _print_state_skip,
85
+ _print_state_verify,
86
+ cmd_state_artifact,
87
+ cmd_state_branch,
88
+ cmd_state_complete,
89
+ cmd_state_decision,
90
+ cmd_state_ecr,
91
+ cmd_state_enter,
92
+ cmd_state_note,
93
+ cmd_state_skip,
94
+ cmd_state_verify,
95
+ )
96
+ from forge_session.topology import (
97
+ _load_topology_items,
98
+ _print_topology,
99
+ cmd_backlog_topology,
100
+ )
101
+
102
+
103
+ # --------------------------------------------------------------------------- #
104
+ # CLI-only argparse-choice domains
105
+ #
106
+ # These enumerations exist ONLY to constrain a flag's `choices`; no package module
107
+ # imports them (they are referenced only in main()'s argparse), so they live here
108
+ # beside the parser that uses them rather than in the shared _common layer.
109
+ # --------------------------------------------------------------------------- #
110
+
111
+ #: The --stage domain for the state-write verbs: the six PRODUCTION_STAGES (order-
112
+ #: sensitive) plus forge-0-epic, which also carries a stageEntry but is excluded from
113
+ #: the next-stage walk.
114
+ STATE_VERB_STAGES: Final[tuple[str, ...]] = ("forge-0-epic", *PRODUCTION_STAGES)
115
+
116
+ #: The `--raised-by` / `--target-stage` domains for `state-decision`, and the
117
+ #: `--kind` / `--raised-by` domains for `state-ecr`. SOURCE OF TRUTH:
118
+ #: references/pipeline-state-schema.json (the `deferredDecisions` and
119
+ #: `epicChangeRequests` array item enums). Mirrored here so an out-of-enum value is
120
+ #: rejected at parse time; a drift guard asserts they still match the schema.
121
+ DECISION_RAISED_BY: Final[tuple[str, ...]] = (
122
+ "forge-1-prd",
123
+ "forge-2-tech",
124
+ "forge-3-specs",
125
+ "forge-4-backlog",
126
+ )
127
+ DECISION_TARGET_STAGES: Final[tuple[str, ...]] = (
128
+ "forge-1-prd",
129
+ "forge-2-tech",
130
+ "forge-3-specs",
131
+ "forge-4-backlog",
132
+ "forge-5-loop",
133
+ "forge-6-docs",
134
+ )
135
+ ECR_KINDS: Final[tuple[str, ...]] = ("add-feature", "redep", "move-boundary", "split")
136
+ ECR_RAISED_BY: Final[tuple[str, ...]] = ("forge-1-prd", "forge-2-tech")
137
+
138
+
139
+ # --------------------------------------------------------------------------- #
140
+ # Context-window usage (the `context-usage` verb)
141
+ # --------------------------------------------------------------------------- #
142
+
143
+ #: Default context window when the model can't be inferred and config is silent.
144
+ _DEFAULT_WINDOW: Final = 200_000
145
+ #: Window for 1M-context models (model id carries a `[1m]` / `-1m` marker).
146
+ _WIDE_WINDOW: Final = 1_000_000
147
+ #: Default fraction of the window past which a clean session is recommended.
148
+ _DEFAULT_THRESHOLD: Final = 0.7
149
+
150
+
151
+ def _cwd_slug(cwd: Path) -> str:
152
+ """Map a working directory to its Claude Code project-dir slug.
153
+
154
+ Claude Code names the per-project transcript dir by replacing path
155
+ separators (and dots) in the absolute cwd with hyphens, e.g.
156
+ ``/home/u/proj`` -> ``-home-u-proj``.
157
+ """
158
+ return str(cwd.resolve()).replace("/", "-").replace(".", "-")
159
+
160
+
161
+ def _latest_transcript(cwd: Path) -> Path | None:
162
+ """Return the most-recently-modified transcript JSONL for this cwd, if any."""
163
+ project_dir = Path.home() / ".claude" / "projects" / _cwd_slug(cwd)
164
+ if not project_dir.is_dir():
165
+ return None
166
+ transcripts = [p for p in project_dir.glob("*.jsonl") if p.is_file()]
167
+ if not transcripts:
168
+ return None
169
+ return max(transcripts, key=lambda p: p.stat().st_mtime)
170
+
171
+
172
+ def _last_usage(transcript: Path) -> tuple[int, str | None] | None:
173
+ """Scan a transcript from the end for the last `usage` record.
174
+
175
+ Returns ``(token_total, model_id)`` where the total sums
176
+ ``input_tokens + cache_creation_input_tokens + cache_read_input_tokens +
177
+ output_tokens`` of the most recent message carrying a usage object — i.e. the
178
+ current context occupancy. Returns ``None`` if no usable record is found.
179
+ """
180
+ try:
181
+ lines = transcript.read_text(encoding="utf-8").splitlines()
182
+ except OSError:
183
+ return None
184
+ for line in reversed(lines):
185
+ line = line.strip()
186
+ if not line or '"usage"' not in line:
187
+ continue
188
+ try:
189
+ record = json.loads(line)
190
+ except json.JSONDecodeError:
191
+ continue
192
+ message = record.get("message")
193
+ usage = message.get("usage") if isinstance(message, dict) else record.get("usage")
194
+ if not isinstance(usage, dict):
195
+ continue
196
+ # A malformed transcript may carry a non-numeric usage field; skip that
197
+ # record rather than crash the whole context-usage read (ValueError/TypeError).
198
+ try:
199
+ total = (
200
+ int(usage.get("input_tokens", 0) or 0)
201
+ + int(usage.get("cache_creation_input_tokens", 0) or 0)
202
+ + int(usage.get("cache_read_input_tokens", 0) or 0)
203
+ + int(usage.get("output_tokens", 0) or 0)
204
+ )
205
+ except (TypeError, ValueError):
206
+ continue
207
+ if total <= 0:
208
+ continue
209
+ model = message.get("model") if isinstance(message, dict) else record.get("model")
210
+ return total, (model if isinstance(model, str) else None)
211
+ return None
212
+
213
+
214
+ def _infer_window(model: str | None) -> int:
215
+ """Infer the context window from a model id (1M-context markers -> wide)."""
216
+ if model and ("[1m]" in model.lower() or "-1m" in model.lower()):
217
+ return _WIDE_WINDOW
218
+ return _DEFAULT_WINDOW
219
+
220
+
221
+ def context_usage(
222
+ config_path: Path,
223
+ window_override: int | None,
224
+ threshold_override: float | None,
225
+ ) -> dict:
226
+ """Compute live context-window occupancy for the current session.
227
+
228
+ Window precedence: ``--window`` > config ``contextWindowTokens`` > inferred
229
+ from the transcript's model id > ``_DEFAULT_WINDOW``. When inferring (no
230
+ override, no config) and the observed token total already exceeds the default
231
+ window, the window is auto-bumped to ``_WIDE_WINDOW`` — observed tokens above
232
+ 200k prove a wider (1M-beta) window is active, so this corrects the reading
233
+ without ever under-reporting a genuine 200k session. Threshold precedence:
234
+ ``--threshold`` > config ``contextWarnThreshold`` > ``_DEFAULT_THRESHOLD``.
235
+
236
+ Returns a dict with ``available: True`` and ``{tokens, windowTokens, pct,
237
+ overThreshold, recommendation, model}`` when usage is found, or
238
+ ``{available: False, reason}`` otherwise. Never raises for a missing
239
+ transcript — that is the expected non-Claude / fresh-session path.
240
+ """
241
+ # One read of the effective config (committed + machine-local overlay) for both keys —
242
+ # not once per key (#324: load_effective_config touches two files).
243
+ config = load_effective_config(config_path)
244
+ threshold = threshold_override
245
+ if threshold is None:
246
+ cfg_threshold = config.get("contextWarnThreshold")
247
+ threshold = (
248
+ float(cfg_threshold)
249
+ if isinstance(cfg_threshold, (int, float))
250
+ else _DEFAULT_THRESHOLD
251
+ )
252
+
253
+ transcript = _latest_transcript(Path.cwd())
254
+ if transcript is None:
255
+ return {"available": False, "reason": "no session transcript found"}
256
+ found = _last_usage(transcript)
257
+ if found is None:
258
+ return {"available": False, "reason": "no usage record in transcript"}
259
+ tokens, model = found
260
+
261
+ window = window_override
262
+ if window is None or window <= 0:
263
+ cfg_window = config.get("contextWindowTokens")
264
+ if isinstance(cfg_window, int) and cfg_window > 0:
265
+ window = cfg_window
266
+ else:
267
+ # Inferring (no override, no config). Start from the model marker /
268
+ # conservative default, then auto-bump: observed tokens above the
269
+ # default window PROVE a wider window is active (a 200k session can
270
+ # never exceed 200k), so widen to 1M rather than report a nonsensical
271
+ # >100%. Never under-reports a real 200k session, which can't trip it.
272
+ window = _infer_window(model)
273
+ if tokens > window:
274
+ window = _WIDE_WINDOW
275
+
276
+ pct = round(tokens / window, 4)
277
+ over = pct >= threshold
278
+ if over:
279
+ recommendation = "clean-session"
280
+ else:
281
+ recommendation = "continue"
282
+ return {
283
+ "available": True,
284
+ "tokens": tokens,
285
+ "windowTokens": window,
286
+ "pct": pct,
287
+ "threshold": threshold,
288
+ "overThreshold": over,
289
+ "recommendation": recommendation,
290
+ "model": model,
291
+ }
292
+
293
+
294
+ # --------------------------------------------------------------------------- #
295
+ # CLI dispatch
296
+ # --------------------------------------------------------------------------- #
297
+
298
+
299
+ def _emit(payload: dict, json_output: bool, printer: Callable[[dict], None]) -> None:
300
+ """Emit a state-verb result: the full JSON echo on --json, else the printer.
301
+
302
+ Args:
303
+ payload: The verb's resulting state dict.
304
+ json_output: The ``--json`` flag.
305
+ printer: The verb's one-line human-readable printer.
306
+ """
307
+ if json_output:
308
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
309
+ else:
310
+ printer(payload)
311
+
312
+
313
+ def _print_rank_table(rows: list[FeatureRow], counts: dict[str, int]) -> None:
314
+ """Print a human-readable recency-ranked feature list."""
315
+ print(
316
+ f"Active: {counts['active']} "
317
+ f"(paused: {counts['paused']}, abandoned: {counts['abandoned']})"
318
+ )
319
+ if not rows:
320
+ print(" (no active feature pipelines)")
321
+ return
322
+ for idx, row in enumerate(rows):
323
+ marker = "→" if idx == 0 else " "
324
+ label = row["name"] + (f" [{row['epic']}]" if row["epic"] else "")
325
+ nxt = row["nextCommand"] or "complete"
326
+ print(f" {marker} {label}: {row['currentStage']} — next: {nxt}")
327
+ if row["verifyPending"]:
328
+ # Owed automatic verification is an obligation, not an offer — the
329
+ # full diagnostic sentence went to stderr, so keep this line honest
330
+ # rather than repeating it (REQ-DEBT-02).
331
+ offer = (
332
+ "automatic verification owed"
333
+ if row["verifyState"] == "auto-pending"
334
+ else "verify available"
335
+ )
336
+ print(f" ({offer}: {row['verifyCommand']})")
337
+
338
+
339
+ def _print_context(usage: dict) -> None:
340
+ """Print a one-line human-readable context-usage summary."""
341
+ if not usage.get("available"):
342
+ print(f"context usage: unavailable ({usage.get('reason', 'unknown')})")
343
+ return
344
+ pct = round(usage["pct"] * 100, 1)
345
+ flag = " — over threshold, clean session recommended" if usage["overThreshold"] else ""
346
+ print(
347
+ f"context: {usage['tokens']:,} / {usage['windowTokens']:,} tokens "
348
+ f"(~{pct}%){flag}"
349
+ )
350
+
351
+
352
+ def _print_effective_config(
353
+ resolved: dict[str, object], layers: dict[str, object] | None = None
354
+ ) -> None:
355
+ """Print the resolved loopRunner config as an aligned key: value table.
356
+
357
+ Args:
358
+ resolved: The resolved loopRunner object from ``resolve_loop_runner``.
359
+ layers: Optional per-field provenance (env/local/committed/default, #324); when
360
+ given, each row is annotated with the layer that set it.
361
+ """
362
+ print("Effective loopRunner config:")
363
+ width = max((len(k) for k in resolved), default=0)
364
+ for key in sorted(resolved):
365
+ suffix = f" [{layers[key]}]" if layers and key in layers else ""
366
+ print(f" {key.ljust(width)} : {resolved[key]!r}{suffix}")
367
+
368
+
369
+ class _ErrorPrefixParser(argparse.ArgumentParser):
370
+ """An argparse parser whose failures use this CLI's ``Error: ...`` exit-2 form.
371
+
372
+ ``stage-exit`` carries two contracts that argparse cannot satisfy together out
373
+ of the box: its enum flags MUST be registered with typed ``choices`` drawn from
374
+ the shared literal domains, AND any invalid input must print
375
+ ``Error: <actionable message>`` to stderr and return exit 2 with no payload and
376
+ no sentinel. Stock argparse leads with ``usage:``, so the reconciliation lives
377
+ here rather than in a hand-rolled second validation pass that would drift from
378
+ the ``choices`` it duplicates.
379
+
380
+ ``parse_args`` runs before ``main``'s ``UsageError`` handler, so this exits
381
+ directly instead of raising. ``add_subparsers`` defaults ``parser_class`` to
382
+ ``type(self)``, so every subcommand inherits the same form — matching the
383
+ ``UsageError`` path they already share.
384
+ """
385
+
386
+ def error(self, message: str) -> NoReturn: # noqa: D102 - argparse override
387
+ self.exit(2, f"Error: {message}\nTry '{self.prog} --help' for usage.\n")
388
+
389
+
390
+ def main() -> int:
391
+ parser = _ErrorPrefixParser(prog="forge-session.py", description=__doc__)
392
+ sub = parser.add_subparsers(dest="cmd", required=True)
393
+
394
+ p_rank = sub.add_parser("rank-features", help="Rank active features by recency")
395
+ p_rank.add_argument("--specs-dir", default="./specs", help="Specs directory")
396
+ p_rank.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
397
+ p_rank.add_argument("--json", action="store_true", dest="json_output")
398
+
399
+ p_ctx = sub.add_parser("context-usage", help="Report live context-window usage")
400
+ p_ctx.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
401
+ p_ctx.add_argument("--window", type=int, default=None, help="Override context window size")
402
+ p_ctx.add_argument("--threshold", type=float, default=None, help="Override warn fraction (0-1)")
403
+ p_ctx.add_argument("--json", action="store_true", dest="json_output")
404
+
405
+ p_doc = sub.add_parser("doctor", help="Capture pipeline ground truth for debugging")
406
+ p_doc.add_argument("--specs-dir", default="./specs", help="Specs directory")
407
+ p_doc.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
408
+ p_doc.add_argument(
409
+ "--schema", default=None,
410
+ help="Override the bundled forge-config-schema.json (chiefly for tests)",
411
+ )
412
+ p_doc.add_argument(
413
+ "--check", action="append", dest="checks", metavar="ID", choices=DOCTOR_CHECK_IDS,
414
+ help="Run only this check (repeatable); legacy fields are always reported",
415
+ )
416
+ p_doc.add_argument(
417
+ "--verbose", action="store_true",
418
+ help="Also print the ok/na check lines in the human report",
419
+ )
420
+ p_doc.add_argument("--json", action="store_true", dest="json_output")
421
+
422
+ p_disc = sub.add_parser(
423
+ "discover-feature", help="Find a feature's pipeline state across all branches"
424
+ )
425
+ p_disc.add_argument("name", nargs="?", default=None,
426
+ help="Feature name to discover (omit with --all)")
427
+ p_disc.add_argument("--all", action="store_true", dest="discover_all",
428
+ help="Discover every feature across all branches (empty-dashboard)")
429
+ p_disc.add_argument("--specs-dir", default="./specs", help="Specs directory")
430
+ p_disc.add_argument("--json", action="store_true", dest="json_output")
431
+
432
+ p_recon = sub.add_parser(
433
+ "reconcile-branch",
434
+ help="Decide whether a feature's recorded branch should adopt the current branch",
435
+ )
436
+ p_recon.add_argument("--feature", required=True, help="Feature name")
437
+ p_recon.add_argument("--specs-dir", default="./specs", help="Specs directory")
438
+ p_recon.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
439
+ p_recon.add_argument("--epic", default=None, help="Epic name for a nested member")
440
+ p_recon.add_argument("--json", action="store_true", dest="json_output")
441
+
442
+ p_base = sub.add_parser(
443
+ "check-epic-base",
444
+ help="Verify HEAD contains the epic manifest for a resolved nested member",
445
+ )
446
+ p_base.add_argument("--feature", required=True, help="Feature name")
447
+ p_base.add_argument("--specs-dir", default="./specs", help="Specs directory")
448
+ p_base.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
449
+ p_base.add_argument("--epic", default=None, help="Epic name for a nested member")
450
+ p_base.add_argument("--json", action="store_true", dest="json_output")
451
+
452
+ p_exit = sub.add_parser(
453
+ "stage-exit", help="Emit the Scripted Stage Exit directives + NEXT-STEPS block"
454
+ )
455
+ p_exit.add_argument("--feature", required=True,
456
+ help="Feature name (the epic name for forge-0-epic)")
457
+ p_exit.add_argument("--stage", required=True, choices=EXIT_STAGES,
458
+ help="The just-completed stage (or branch skill)")
459
+ p_exit.add_argument("--served-stage", default=None, dest="served_stage",
460
+ choices=_EXIT_PRODUCTION_STAGES,
461
+ help="Production stage a verify/fix diversion served")
462
+ p_exit.add_argument("--verify-mode", default=None, dest="verify_mode",
463
+ choices=tuple(VERIFY_MODE_TO_STAGE),
464
+ help="Verify mode; maps to --served-stage when unique")
465
+ # No argparse `choices`: the accepted outcome domain differs per stage, which
466
+ # argparse cannot express. `stage_exit` validates it against EXIT_OUTCOMES.
467
+ p_exit.add_argument("--outcome", default=None,
468
+ help="Stage-specific outcome (loop/docs/verify/fix only)")
469
+ p_exit.add_argument(
470
+ "--cause", default=None, dest="cause", choices=("dependency-starvation",),
471
+ help="Pending-attribution cause; valid only with "
472
+ "--stage forge-5-loop --outcome partial",
473
+ )
474
+ p_exit.add_argument("--owner", default=None, choices=get_args(ExitOwner),
475
+ help="Branch terminal ownership (forge-verify/forge-fix only)")
476
+ p_exit.add_argument("--verify-capability", default="manual",
477
+ dest="verify_capability", choices=get_args(VerifyCapability),
478
+ help="interactive only with BOTH a question mechanism and "
479
+ "permitted clean-room verifier dispatch")
480
+ p_exit.add_argument("--specs-dir", default="./specs", help="Specs directory")
481
+ p_exit.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
482
+ p_exit.add_argument("--epic", default=None, help="Epic name for a nested member")
483
+ p_exit.add_argument("--next-feature", default=None, dest="next_feature",
484
+ help="First actionable feature (epic handoff next-command arg)")
485
+ p_exit.add_argument("--host", default="claude", choices=EXIT_HOSTS,
486
+ help="Host wording for the NEXT-STEPS block")
487
+ p_exit.add_argument("--json", action="store_true", dest="json_output")
488
+
489
+ p_sel = sub.add_parser(
490
+ "select-outcome",
491
+ help="Derive the deterministic stage-exit --outcome for a verify/fix run",
492
+ )
493
+ p_sel.add_argument("--feature", required=True, help="Feature name")
494
+ p_sel.add_argument("--served-stage", required=True, dest="served_stage",
495
+ choices=tuple(VERIFY_TOKEN_BY_STAGE),
496
+ help="Production stage the verify/fix run served")
497
+ p_sel.add_argument("--skill", required=True, choices=("verify", "fix"),
498
+ help="Which branch skill is choosing its exit outcome")
499
+ p_sel.add_argument("--specs-dir", default="./specs", help="Specs directory")
500
+ p_sel.add_argument("--epic", default=None, help="Epic name for a nested member")
501
+ # Runtime signals for the outcomes disk cannot record (see references/select-outcome.md).
502
+ p_sel.add_argument("--op-failure", action="store_true", dest="op_failure",
503
+ help="a dispatch/step/validation/commit/state-write failed → failed")
504
+ p_sel.add_argument("--user-deferred", action="store_true", dest="user_deferred",
505
+ help="fix only: user explicitly deferred the fix/re-verify → deferred")
506
+ p_sel.add_argument("--decisions-open", action="store_true", dest="decisions_open",
507
+ help="fix only: unresolved user decisions block fixes → decisions")
508
+ p_sel.add_argument("--json", action="store_true", dest="json_output")
509
+
510
+ p_vst = sub.add_parser(
511
+ "verify-state",
512
+ help="Classify a served stage's verification into one VerifyStateCase",
513
+ )
514
+ p_vst.add_argument("--feature", required=True, help="Feature name")
515
+ p_vst.add_argument("--for-stage", required=True, dest="for_stage",
516
+ choices=tuple(VERIFY_TOKEN_BY_STAGE),
517
+ help="Production stage whose forge-verify-* entry to classify")
518
+ p_vst.add_argument("--specs-dir", default="./specs", help="Specs directory")
519
+ p_vst.add_argument("--epic", default=None, help="Epic name for a nested member")
520
+ p_vst.add_argument("--json", action="store_true", dest="json_output")
521
+
522
+ p_eff = sub.add_parser(
523
+ "effective-config",
524
+ help="Resolve the loopRunner config from schema defaults + user overrides",
525
+ )
526
+ p_eff.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
527
+ p_eff.add_argument(
528
+ "--schema", default=None,
529
+ help="forge-config-schema.json path (default: bundled references/ copy)",
530
+ )
531
+ p_eff.add_argument("--json", action="store_true", dest="json_output")
532
+
533
+ p_enter = sub.add_parser(
534
+ "state-enter", help="Stamp a stage as in-progress (Entry Stamp)"
535
+ )
536
+ p_enter.add_argument("--feature", required=True, help="Feature name")
537
+ p_enter.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
538
+ help="The stage being entered")
539
+ p_enter.add_argument("--specs-dir", default="./specs", help="Specs directory")
540
+ p_enter.add_argument("--epic", default=None, help="Epic name for a nested member")
541
+ p_enter.add_argument("--json", action="store_true", dest="json_output")
542
+
543
+ p_art = sub.add_parser(
544
+ "state-artifact", help="Append artifact paths to a stage (de-duplicating)"
545
+ )
546
+ p_art.add_argument("--feature", required=True, help="Feature name")
547
+ p_art.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
548
+ help="The stage producing the artifact")
549
+ p_art.add_argument("--path", required=True, action="append", dest="paths",
550
+ metavar="PATH",
551
+ help="Artifact path relative to the feature dir (repeatable)")
552
+ p_art.add_argument("--specs-dir", default="./specs", help="Specs directory")
553
+ p_art.add_argument("--epic", default=None, help="Epic name for a nested member")
554
+ p_art.add_argument("--json", action="store_true", dest="json_output")
555
+
556
+ p_comp = sub.add_parser(
557
+ "state-complete", help="Mark a stage complete; bump version; cascade staleness"
558
+ )
559
+ p_comp.add_argument("--feature", required=True, help="Feature name")
560
+ p_comp.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
561
+ help="The stage being completed")
562
+ p_comp.add_argument("--version", type=int, required=True,
563
+ help="This stage's new version (integer)")
564
+ p_comp.add_argument("--based-on", action="append", default=[], dest="based_on",
565
+ metavar="STAGE=N",
566
+ help="Upstream version this artifact was built on (repeatable)")
567
+ p_comp.add_argument("--artifact", action="append", default=[], dest="artifacts",
568
+ metavar="PATH",
569
+ help="Artifact path produced by this stage (repeatable)")
570
+ p_comp.add_argument("--commit-hash", default=None, dest="commit_hash",
571
+ help="Commit 2 follow-up: record the artifact commit's hash")
572
+ p_comp.add_argument("--status", default=None,
573
+ choices=("complete", "in-progress"),
574
+ help="Terminal status to record (default: complete). "
575
+ "Use in-progress for a partial forge-5-loop run -- the "
576
+ "stage still records completedAt/version/basedOnVersions/"
577
+ "artifacts; only the status differs.")
578
+ p_comp.add_argument("--resumable", action="store_true",
579
+ help="Failed-Commit-1 revert (L245): record ONLY status="
580
+ "in-progress, leaving completedAt/version/basedOnVersions/"
581
+ "artifacts/commitHash untouched and firing no cascade. "
582
+ "Implies --status in-progress.")
583
+ p_comp.add_argument("--preserve-commit-hash", action="store_true",
584
+ dest="preserve_commit_hash",
585
+ help="Do not reset commitHash to null on completion "
586
+ "(the Git Commit Protocol's 'Nothing to commit' branch)")
587
+ p_comp.add_argument("--specs-dir", default="./specs", help="Specs directory")
588
+ p_comp.add_argument("--epic", default=None, help="Epic name for a nested member")
589
+ p_comp.add_argument("--json", action="store_true", dest="json_output")
590
+
591
+ p_skip = sub.add_parser(
592
+ "state-skip", help="Record forge-6-docs as deliberately skipped (#197)"
593
+ )
594
+ p_skip.add_argument("--feature", required=True, help="Feature name")
595
+ p_skip.add_argument("--stage", required=True, choices=("forge-6-docs",),
596
+ help="The stage being skipped (only forge-6-docs is skippable)")
597
+ p_skip.add_argument("--specs-dir", default="./specs", help="Specs directory")
598
+ p_skip.add_argument("--epic", default=None, help="Epic name for a nested member")
599
+ p_skip.add_argument("--json", action="store_true", dest="json_output")
600
+
601
+ p_br = sub.add_parser("state-branch", help="Set the top-level branch field")
602
+ p_br.add_argument("--feature", required=True, help="Feature name")
603
+ p_br.add_argument("--branch", required=True, help="Branch name to record")
604
+ p_br.add_argument("--specs-dir", default="./specs", help="Specs directory")
605
+ p_br.add_argument("--epic", default=None, help="Epic name for a nested member")
606
+ p_br.add_argument("--json", action="store_true", dest="json_output")
607
+
608
+ p_note = sub.add_parser("state-note", help="Set the top-level notes field")
609
+ p_note.add_argument("--feature", required=True, help="Feature name")
610
+ p_note.add_argument("--note", required=True, help="Note text to persist")
611
+ p_note.add_argument("--specs-dir", default="./specs", help="Specs directory")
612
+ p_note.add_argument("--epic", default=None, help="Epic name for a nested member")
613
+ p_note.add_argument("--json", action="store_true", dest="json_output")
614
+
615
+ p_dec = sub.add_parser(
616
+ "state-decision", help="Append a deferred decision (status: open)"
617
+ )
618
+ p_dec.add_argument("--feature", required=True, help="Feature name")
619
+ p_dec.add_argument("--question", required=True,
620
+ help="The deferred decision, phrased for the target stage")
621
+ p_dec.add_argument("--raised-by", required=True, dest="raised_by",
622
+ choices=DECISION_RAISED_BY,
623
+ help="The stage deferring the decision")
624
+ p_dec.add_argument("--rationale", default=None, help="Why it is deferred (optional)")
625
+ p_dec.add_argument("--target-stage", default=None, dest="target_stage",
626
+ choices=DECISION_TARGET_STAGES,
627
+ help="The stage that should resolve it (optional)")
628
+ p_dec.add_argument("--specs-dir", default="./specs", help="Specs directory")
629
+ p_dec.add_argument("--epic", default=None, help="Epic name for a nested member")
630
+ p_dec.add_argument("--json", action="store_true", dest="json_output")
631
+
632
+ p_ecr = sub.add_parser(
633
+ "state-ecr", help="Append an epic change request (status: open)"
634
+ )
635
+ p_ecr.add_argument("--feature", required=True, help="Feature name")
636
+ p_ecr.add_argument("--kind", required=True, choices=ECR_KINDS,
637
+ help="The decomposition change kind")
638
+ p_ecr.add_argument("--target", required=True,
639
+ help="The sibling feature to add, or the feature/boundary affected")
640
+ p_ecr.add_argument("--rationale", required=True, help="Why the epic must change")
641
+ p_ecr.add_argument("--raised-by", required=True, dest="raised_by",
642
+ choices=ECR_RAISED_BY,
643
+ help="The stage that detected the epic-level concern")
644
+ p_ecr.add_argument("--blocks-current", required=True, dest="blocks_current",
645
+ metavar="true|false",
646
+ help="true → pause-now (reconcile before proceeding); "
647
+ "false → finish-then-edit")
648
+ p_ecr.add_argument("--specs-dir", default="./specs", help="Specs directory")
649
+ p_ecr.add_argument("--epic", default=None, help="Epic name for a nested member")
650
+ p_ecr.add_argument("--json", action="store_true", dest="json_output")
651
+
652
+ p_ver = sub.add_parser(
653
+ "state-verify", help="Write one forge-verify-* transition (result or provenance)"
654
+ )
655
+ p_ver.add_argument("--feature", required=True,
656
+ help="Feature name (the EPIC name for --stage forge-0-epic)")
657
+ p_ver.add_argument("--stage", required=True, choices=VERIFY_STAGES,
658
+ help="The production stage this verify entry serves "
659
+ "(forge-6-docs has no verification token)")
660
+ p_ver.add_argument("--status", default=None, choices=VERIFY_RESULT_STATUSES,
661
+ help="Result mode: the transition to record "
662
+ "(mutually exclusive with --commit-hash)")
663
+ p_ver.add_argument("--findings-file", default=None, dest="findings_file",
664
+ metavar="PATH",
665
+ help="Findings document, relative to and contained by the "
666
+ "feature directory (required by findings-reported)")
667
+ p_ver.add_argument("--findings-count", type=int, default=None,
668
+ dest="findings_count", metavar="N",
669
+ help="Number of findings in --findings-file (0 is meaningful)")
670
+ p_ver.add_argument("--verified-stage-version", type=int, default=None,
671
+ dest="verified_stage_version", metavar="N",
672
+ help="The served stage's current version, for the freshness "
673
+ "ledger (rejected by findings-applied)")
674
+ p_ver.add_argument("--commit-hash", default=None, dest="commit_hash",
675
+ help="Commit-2 provenance mode: the full 40-hex Commit-1 hash")
676
+ p_ver.add_argument("--specs-dir", default="./specs", help="Specs directory")
677
+ p_ver.add_argument("--epic", default=None, help="Epic name for a nested member")
678
+ p_ver.add_argument("--json", action="store_true", dest="json_output")
679
+
680
+ p_drec = sub.add_parser(
681
+ "decision-record", help="Append a needs-human decision entry (append-only)"
682
+ )
683
+ p_drec.add_argument("--backlog-dir", required=True, dest="backlog_dir",
684
+ help="Resolved backlog directory (e.g. specs/loop-recovery)")
685
+ p_drec.add_argument("--item", required=True, action="append", dest="item_ids",
686
+ metavar="ID", help="Backlog item id (repeatable — one entry per id)")
687
+ p_drec.add_argument("--question", required=True, help="The needs-human question text")
688
+ _ans = p_drec.add_mutually_exclusive_group(required=True)
689
+ _ans.add_argument("--answer", default=None, help="The operator's answer")
690
+ _ans.add_argument("--deferred", action="store_true",
691
+ help="Record a deferral / cancel-early (answer: null)")
692
+ p_drec.add_argument("--cluster", default=None, dest="cluster_id", metavar="CID",
693
+ help="Shared clusterId for one consolidated decision (REQ-CLU-04)")
694
+ p_drec.add_argument("--actor", default=None,
695
+ help="Session/actor label for recordedBy (default forge-5-loop@<host>)")
696
+ p_drec.add_argument("--state-dir", default=None, dest="state_dir",
697
+ help="State-dir name (default: effective loopRunner.stateDir)")
698
+ p_drec.add_argument("--config", default="./forge.config.json",
699
+ help="forge.config.json path")
700
+ p_drec.add_argument("--json", action="store_true", dest="json_output")
701
+
702
+ p_dlist = sub.add_parser(
703
+ "decision-list", help="Read the decision record (or the unapplied set)"
704
+ )
705
+ p_dlist.add_argument("--backlog-dir", required=True, dest="backlog_dir",
706
+ help="Resolved backlog directory")
707
+ p_dlist.add_argument("--unapplied", action="store_true",
708
+ help="Return only the latest-unapplied-per-item set (REQ-DEC-05)")
709
+ p_dlist.add_argument("--state-dir", default=None, dest="state_dir",
710
+ help="State-dir name (default: effective loopRunner.stateDir)")
711
+ p_dlist.add_argument("--config", default="./forge.config.json",
712
+ help="forge.config.json path")
713
+ p_dlist.add_argument("--json", action="store_true", dest="json_output")
714
+
715
+ p_dapply = sub.add_parser(
716
+ "decision-apply", help="Mark the latest decision for an item applied"
717
+ )
718
+ p_dapply.add_argument("--backlog-dir", required=True, dest="backlog_dir",
719
+ help="Resolved backlog directory")
720
+ p_dapply.add_argument("--item", required=True, dest="item_id", metavar="ID",
721
+ help="Backlog item whose latest decision to stamp applied")
722
+ p_dapply.add_argument("--actor", default=None,
723
+ help="Session/actor label for appliedBy (default forge-5-loop@<host>)")
724
+ p_dapply.add_argument("--state-dir", default=None, dest="state_dir",
725
+ help="State-dir name (default: effective loopRunner.stateDir)")
726
+ p_dapply.add_argument("--config", default="./forge.config.json",
727
+ help="forge.config.json path")
728
+ p_dapply.add_argument("--json", action="store_true", dest="json_output")
729
+
730
+ p_topo = sub.add_parser(
731
+ "backlog-topology",
732
+ help="Dependency-topology metrics + advisory warnings over a runner item array",
733
+ )
734
+ topo_src = p_topo.add_mutually_exclusive_group(required=True)
735
+ topo_src.add_argument(
736
+ "--items-json", help="Path to the loopRunner listCommand JSON output"
737
+ )
738
+ topo_src.add_argument(
739
+ "--items-stdin", action="store_true",
740
+ help="Read the listCommand JSON from stdin",
741
+ )
742
+ p_topo.add_argument(
743
+ "--cluster", action="store_true", dest="with_clusters",
744
+ help="Append blocked-item clusters for consolidated prompts",
745
+ )
746
+ p_topo.add_argument("--json", action="store_true", dest="json_output")
747
+
748
+ args = parser.parse_args()
749
+
750
+ try:
751
+ if args.cmd == "rank-features":
752
+ specs_dir = Path(args.specs_dir)
753
+ config = load_effective_config(Path(args.config))
754
+ rows = build_rows(specs_dir, config)
755
+ counts = _counts(specs_dir)
756
+ invalid_keys = invalid_auto_verify_keys(config)
757
+ if args.json_output:
758
+ payload = {"active": rows, "counts": counts}
759
+ if invalid_keys:
760
+ payload["invalidAutoVerifyKeys"] = invalid_keys
761
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
762
+ else:
763
+ _print_rank_table(rows, counts)
764
+ if invalid_keys:
765
+ print(
766
+ " ! invalid autoVerifyStages keys (ignored): "
767
+ + ", ".join(invalid_keys)
768
+ )
769
+ return 0
770
+
771
+ if args.cmd == "context-usage":
772
+ usage = context_usage(Path(args.config), args.window, args.threshold)
773
+ if args.json_output:
774
+ print(json.dumps(usage, indent=2, ensure_ascii=False))
775
+ else:
776
+ _print_context(usage)
777
+ return 0
778
+
779
+ if args.cmd == "doctor":
780
+ # Check details carry non-ASCII (em dash, ellipsis); a terminal whose
781
+ # encoding cannot represent them must not turn the diagnostic into a
782
+ # traceback (INV-3). Only the doctor path reconfigures.
783
+ reconfigure = getattr(sys.stdout, "reconfigure", None)
784
+ if reconfigure is not None:
785
+ try:
786
+ reconfigure(errors="backslashreplace")
787
+ except (ValueError, OSError):
788
+ pass
789
+ report = doctor_report(
790
+ Path(args.specs_dir),
791
+ Path(args.config),
792
+ schema_path=Path(args.schema) if args.schema else None,
793
+ only=frozenset(args.checks) if args.checks else None,
794
+ )
795
+ if args.json_output:
796
+ print(json.dumps(report, indent=2, ensure_ascii=False))
797
+ else:
798
+ _print_doctor(report, verbose=args.verbose or bool(args.checks))
799
+ return 0
800
+
801
+ if args.cmd == "discover-feature":
802
+ if args.discover_all:
803
+ payload = discover_all(args.specs_dir)
804
+ printer = _print_discover_all
805
+ elif args.name:
806
+ payload = discover_feature(args.name, args.specs_dir)
807
+ printer = _print_discover
808
+ else:
809
+ parser.error("discover-feature requires a NAME or --all")
810
+ if args.json_output:
811
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
812
+ else:
813
+ printer(payload)
814
+ return 0
815
+
816
+ if args.cmd == "reconcile-branch":
817
+ payload = reconcile_branch(
818
+ args.feature, Path(args.specs_dir), Path(args.config), args.epic
819
+ )
820
+ if args.json_output:
821
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
822
+ else:
823
+ _print_reconcile(payload)
824
+ return 0
825
+
826
+ if args.cmd == "check-epic-base":
827
+ payload = check_epic_base(
828
+ args.feature, Path(args.specs_dir), Path(args.config), args.epic
829
+ )
830
+ if args.json_output:
831
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
832
+ else:
833
+ _print_check_epic_base(payload)
834
+ return 0
835
+
836
+ if args.cmd == "stage-exit":
837
+ payload = stage_exit(
838
+ args.feature,
839
+ args.stage,
840
+ Path(args.specs_dir),
841
+ Path(args.config),
842
+ args.epic,
843
+ args.host,
844
+ args.next_feature,
845
+ args.served_stage,
846
+ args.verify_mode,
847
+ args.outcome,
848
+ args.owner,
849
+ args.verify_capability,
850
+ args.cause,
851
+ )
852
+ if args.json_output:
853
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
854
+ else:
855
+ _print_stage_exit(payload)
856
+ return 0
857
+
858
+ if args.cmd == "select-outcome":
859
+ payload = select_outcome(
860
+ args.feature,
861
+ args.served_stage,
862
+ args.skill,
863
+ Path(args.specs_dir),
864
+ args.epic,
865
+ op_failure=args.op_failure,
866
+ user_deferred=args.user_deferred,
867
+ decisions_open=args.decisions_open,
868
+ )
869
+ if args.json_output:
870
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
871
+ else:
872
+ print(f"{payload['outcome']}: {payload['reason']}")
873
+ for line in payload["evidence"]:
874
+ print(f" - {line}")
875
+ return 0
876
+
877
+ if args.cmd == "verify-state":
878
+ payload = verify_state_for_stage(
879
+ args.feature,
880
+ args.for_stage,
881
+ Path(args.specs_dir),
882
+ args.epic,
883
+ )
884
+ if args.json_output:
885
+ print(json.dumps(payload, indent=2, ensure_ascii=False))
886
+ else:
887
+ flags = []
888
+ if payload["verified"]:
889
+ flags.append("verified")
890
+ if payload["stale"]:
891
+ flags.append("stale")
892
+ suffix = f" [{', '.join(flags)}]" if flags else ""
893
+ print(f"{payload['case']}{suffix}: {payload['message']}")
894
+ if payload["nextCommand"]:
895
+ print(f" next: {payload['nextCommand']}")
896
+ return 0
897
+
898
+ if args.cmd == "effective-config":
899
+ schema_path = Path(args.schema) if args.schema else _default_schema_path()
900
+ layered = resolve_loop_runner_layers(Path(args.config), schema_path)
901
+ resolved = {field: info["value"] for field, info in layered.items()}
902
+ layers = {field: info["layer"] for field, info in layered.items()}
903
+ if args.json_output:
904
+ # --json shape is frozen (spec 04): the flat resolved block, no provenance.
905
+ # The per-key layer lives in the human view here and in `doctor --json` (#324).
906
+ print(json.dumps(resolved, indent=2, ensure_ascii=False))
907
+ else:
908
+ _print_effective_config(resolved, layers)
909
+ return 0
910
+
911
+ if args.cmd == "state-enter":
912
+ payload = cmd_state_enter(
913
+ args.feature, args.stage, Path(args.specs_dir), args.epic
914
+ )
915
+ _emit(payload, args.json_output, _print_state_enter)
916
+ return 0
917
+
918
+ if args.cmd == "state-artifact":
919
+ payload = cmd_state_artifact(
920
+ args.feature, args.stage, args.paths, Path(args.specs_dir), args.epic
921
+ )
922
+ _emit(
923
+ payload,
924
+ args.json_output,
925
+ lambda state: _print_state_artifact(state, args.stage, args.paths),
926
+ )
927
+ return 0
928
+
929
+ if args.cmd == "state-complete":
930
+ payload = cmd_state_complete(
931
+ args.feature,
932
+ args.stage,
933
+ args.version,
934
+ _parse_based_on(args.based_on),
935
+ args.artifacts,
936
+ args.commit_hash,
937
+ Path(args.specs_dir),
938
+ args.epic,
939
+ status=args.status,
940
+ preserve_commit_hash=args.preserve_commit_hash,
941
+ resumable=args.resumable,
942
+ )
943
+ _emit(
944
+ payload,
945
+ args.json_output,
946
+ lambda state: _print_state_complete(
947
+ state, args.stage, args.commit_hash, args.resumable
948
+ ),
949
+ )
950
+ return 0
951
+
952
+ if args.cmd == "state-skip":
953
+ payload = cmd_state_skip(
954
+ args.feature, args.stage, Path(args.specs_dir), args.epic
955
+ )
956
+ _emit(
957
+ payload,
958
+ args.json_output,
959
+ lambda state: _print_state_skip(state, args.stage),
960
+ )
961
+ return 0
962
+
963
+ if args.cmd == "state-branch":
964
+ payload = cmd_state_branch(
965
+ args.feature, args.branch, Path(args.specs_dir), args.epic
966
+ )
967
+ _emit(payload, args.json_output, _print_state_branch)
968
+ return 0
969
+
970
+ if args.cmd == "state-note":
971
+ payload = cmd_state_note(
972
+ args.feature, args.note, Path(args.specs_dir), args.epic
973
+ )
974
+ _emit(payload, args.json_output, _print_state_note)
975
+ return 0
976
+
977
+ if args.cmd == "state-decision":
978
+ payload = cmd_state_decision(
979
+ args.feature,
980
+ args.question,
981
+ args.raised_by,
982
+ args.rationale,
983
+ args.target_stage,
984
+ Path(args.specs_dir),
985
+ args.epic,
986
+ )
987
+ _emit(payload, args.json_output, _print_state_decision)
988
+ return 0
989
+
990
+ if args.cmd == "state-ecr":
991
+ payload = cmd_state_ecr(
992
+ args.feature,
993
+ args.kind,
994
+ args.target,
995
+ args.rationale,
996
+ args.raised_by,
997
+ _parse_bool(args.blocks_current, "--blocks-current"),
998
+ Path(args.specs_dir),
999
+ args.epic,
1000
+ )
1001
+ _emit(payload, args.json_output, _print_state_ecr)
1002
+ return 0
1003
+
1004
+ if args.cmd == "state-verify":
1005
+ payload = cmd_state_verify(
1006
+ args.feature,
1007
+ args.stage,
1008
+ Path(args.specs_dir),
1009
+ args.epic,
1010
+ status=args.status,
1011
+ findings_file=args.findings_file,
1012
+ findings_count=args.findings_count,
1013
+ verified_stage_version=args.verified_stage_version,
1014
+ commit_hash=args.commit_hash,
1015
+ )
1016
+ _emit(
1017
+ payload,
1018
+ args.json_output,
1019
+ lambda result: _print_state_verify(result, args.commit_hash),
1020
+ )
1021
+ return 0
1022
+
1023
+ if args.cmd == "decision-record":
1024
+ payload = cmd_decision_record(
1025
+ Path(args.backlog_dir),
1026
+ args.item_ids,
1027
+ args.question,
1028
+ args.answer,
1029
+ args.deferred,
1030
+ args.cluster_id,
1031
+ args.actor or _default_actor(),
1032
+ args.state_dir,
1033
+ Path(args.config),
1034
+ _default_schema_path(),
1035
+ )
1036
+ _emit(payload, args.json_output, _print_decision_record)
1037
+ return 0
1038
+
1039
+ if args.cmd == "decision-list":
1040
+ payload = cmd_decision_list(
1041
+ Path(args.backlog_dir), args.unapplied, args.state_dir,
1042
+ Path(args.config), _default_schema_path(),
1043
+ )
1044
+ _emit(payload, args.json_output, _print_decision_list)
1045
+ return 0
1046
+
1047
+ if args.cmd == "decision-apply":
1048
+ payload = cmd_decision_apply(
1049
+ Path(args.backlog_dir), args.item_id, args.actor or _default_actor(),
1050
+ args.state_dir, Path(args.config), _default_schema_path(),
1051
+ )
1052
+ _emit(payload, args.json_output, _print_decision_apply)
1053
+ return 0
1054
+
1055
+ if args.cmd == "backlog-topology":
1056
+ items = _load_topology_items(args)
1057
+ payload = cmd_backlog_topology(items, with_clusters=args.with_clusters)
1058
+ _emit(payload, args.json_output, _print_topology)
1059
+ return 0
1060
+
1061
+ raise UsageError(f"unknown command: {args.cmd}")
1062
+ except UsageError as exc:
1063
+ print(f"Error: {exc}", file=sys.stderr)
1064
+ return 2
1065
+ except OSError as exc:
1066
+ print(f"Error: {exc}", file=sys.stderr)
1067
+ return 2