@opengsd/gsd-path 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/AGENTS.md +28 -11
  2. package/DOCS.md +6 -5
  3. package/FULL.md +9 -13
  4. package/QUICK.md +3 -3
  5. package/README.md +151 -14
  6. package/RUNTIME.md +7 -1
  7. package/WORKFLOW.md +30 -14
  8. package/package.json +15 -1
  9. package/platforms/shared-agents/dispatch.md +6 -0
  10. package/scripts/archive_milestone.py +10 -118
  11. package/scripts/bootstrap_repository.py +25 -3
  12. package/scripts/build_recovery.py +287 -0
  13. package/scripts/check_docs_audit.py +5 -3
  14. package/scripts/check_handoffs.py +1 -1
  15. package/scripts/detect_project.py +11 -2
  16. package/scripts/dispatch_driver.py +4 -2
  17. package/scripts/git_guard.py +2 -1
  18. package/scripts/install.mjs +2 -0
  19. package/scripts/install.py +2 -0
  20. package/scripts/integration.py +28 -22
  21. package/scripts/isolation.py +9 -1
  22. package/scripts/lean_verification.py +1 -1
  23. package/scripts/pipeline_diagnose.py +12 -3
  24. package/scripts/pipeline_state.py +114 -186
  25. package/scripts/pipeline_undo.py +11 -7
  26. package/scripts/promote_lookahead.py +30 -162
  27. package/scripts/roadmap.py +321 -0
  28. package/scripts/skill-resources.json +79 -1
  29. package/scripts/state_checkpoint.py +109 -72
  30. package/scripts/state_promote.py +42 -44
  31. package/scripts/task_context.py +73 -0
  32. package/scripts/token_budget.py +40 -1
  33. package/scripts/workflow_run.py +116 -7
  34. package/skills/gsd-path/BUILD.md +47 -575
  35. package/skills/gsd-path/DECIDE.md +2 -6
  36. package/skills/gsd-path/DEFINE.md +10 -14
  37. package/skills/gsd-path/INSPECT.md +30 -8
  38. package/skills/gsd-path/PLAN.md +25 -17
  39. package/skills/gsd-path/RESEARCH.md +3 -6
  40. package/skills/gsd-path/ROADMAP.md +22 -58
  41. package/skills/gsd-path/SHIP.md +5 -4
  42. package/skills/gsd-path/SKILL.md +24 -14
  43. package/skills/gsd-path/references/build-abandon.md +33 -0
  44. package/skills/gsd-path/references/build-native.md +494 -0
  45. package/skills/gsd-path/references/build-recovery.md +78 -0
  46. package/skills/gsd-path/references/coder.md +8 -3
  47. package/skills/gsd-path/references/dispatch.md +6 -0
  48. package/skills/gsd-path/references/docs-auditor.md +14 -0
  49. package/skills/gsd-path/references/reviewer-final.md +21 -0
  50. package/skills/gsd-path/references/reviewer-panel.md +17 -0
  51. package/skills/gsd-path/references/reviewer-skeptic.md +20 -0
  52. package/skills/gsd-path/references/reviewer-wave.md +89 -0
  53. package/skills/gsd-path/references/reviewer.md +12 -150
  54. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  55. package/skills/gsd-path/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  56. package/skills/gsd-path/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
  57. package/skills/gsd-path/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
  58. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  59. package/skills/gsd-path/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
  60. package/skills/gsd-path/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  61. package/skills/gsd-path/scripts/__pycache__/discussion_records.cpython-312.pyc +0 -0
  62. package/skills/gsd-path/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  63. package/skills/gsd-path/scripts/__pycache__/integration.cpython-312.pyc +0 -0
  64. package/skills/gsd-path/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  65. package/skills/gsd-path/scripts/__pycache__/loop_run.cpython-312.pyc +0 -0
  66. package/skills/gsd-path/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  67. package/skills/gsd-path/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  68. package/skills/gsd-path/scripts/__pycache__/review_findings.cpython-312.pyc +0 -0
  69. package/skills/gsd-path/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  70. package/skills/gsd-path/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  71. package/skills/gsd-path/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  72. package/skills/gsd-path/scripts/__pycache__/task_context.cpython-312.pyc +0 -0
  73. package/skills/gsd-path/scripts/__pycache__/workflow_run.cpython-312.pyc +0 -0
  74. package/skills/gsd-path/scripts/archive_milestone.py +10 -118
  75. package/skills/gsd-path/scripts/bootstrap_repository.py +25 -3
  76. package/skills/gsd-path/scripts/build_recovery.py +287 -0
  77. package/skills/gsd-path/scripts/check_docs_audit.py +5 -3
  78. package/skills/gsd-path/scripts/check_handoffs.py +1 -1
  79. package/skills/gsd-path/scripts/detect_project.py +11 -2
  80. package/skills/gsd-path/scripts/dispatch_driver.py +4 -2
  81. package/skills/gsd-path/scripts/integration.py +28 -22
  82. package/skills/gsd-path/scripts/isolation.py +9 -1
  83. package/skills/gsd-path/scripts/lean_verification.py +1 -1
  84. package/skills/gsd-path/scripts/pipeline_state.py +114 -186
  85. package/skills/gsd-path/scripts/promote_lookahead.py +30 -162
  86. package/skills/gsd-path/scripts/roadmap.py +321 -0
  87. package/skills/gsd-path/scripts/state_checkpoint.py +109 -72
  88. package/skills/gsd-path/scripts/state_promote.py +42 -44
  89. package/skills/gsd-path/scripts/task_context.py +73 -0
  90. package/skills/gsd-path/scripts/token_budget.py +40 -1
  91. package/skills/gsd-path/scripts/workflow_run.py +116 -7
  92. package/skills/gsd-path/templates/wave-review.md +1 -1
  93. package/skills/gsd-path-build/SKILL.md +47 -575
  94. package/skills/gsd-path-build/references/build-abandon.md +33 -0
  95. package/skills/gsd-path-build/references/build-native.md +494 -0
  96. package/skills/gsd-path-build/references/build-recovery.md +78 -0
  97. package/skills/gsd-path-build/references/coder.md +8 -3
  98. package/skills/gsd-path-build/references/dispatch.md +6 -0
  99. package/skills/gsd-path-build/references/reviewer-final.md +21 -0
  100. package/skills/gsd-path-build/references/reviewer-panel.md +17 -0
  101. package/skills/gsd-path-build/references/reviewer-skeptic.md +20 -0
  102. package/skills/gsd-path-build/references/reviewer-wave.md +89 -0
  103. package/skills/gsd-path-build/references/reviewer.md +12 -150
  104. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  105. package/skills/gsd-path-build/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  106. package/skills/gsd-path-build/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
  107. package/skills/gsd-path-build/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
  108. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  109. package/skills/gsd-path-build/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
  110. package/skills/gsd-path-build/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  111. package/skills/gsd-path-build/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  112. package/skills/gsd-path-build/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  113. package/skills/gsd-path-build/scripts/__pycache__/loop_run.cpython-312.pyc +0 -0
  114. package/skills/gsd-path-build/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  115. package/skills/gsd-path-build/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  116. package/skills/gsd-path-build/scripts/__pycache__/review_findings.cpython-312.pyc +0 -0
  117. package/skills/gsd-path-build/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  118. package/skills/gsd-path-build/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  119. package/skills/gsd-path-build/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  120. package/skills/gsd-path-build/scripts/__pycache__/task_context.cpython-312.pyc +0 -0
  121. package/skills/gsd-path-build/scripts/__pycache__/workflow_run.cpython-312.pyc +0 -0
  122. package/skills/gsd-path-build/scripts/archive_milestone.py +10 -118
  123. package/skills/gsd-path-build/scripts/build_recovery.py +287 -0
  124. package/skills/gsd-path-build/scripts/check_handoffs.py +1 -1
  125. package/skills/gsd-path-build/scripts/detect_project.py +1526 -0
  126. package/skills/gsd-path-build/scripts/dispatch_driver.py +4 -2
  127. package/skills/gsd-path-build/scripts/integration.py +28 -22
  128. package/skills/gsd-path-build/scripts/isolation.py +9 -1
  129. package/skills/gsd-path-build/scripts/pipeline_state.py +114 -186
  130. package/skills/gsd-path-build/scripts/promote_lookahead.py +283 -0
  131. package/skills/gsd-path-build/scripts/roadmap.py +321 -0
  132. package/skills/gsd-path-build/scripts/state_checkpoint.py +109 -72
  133. package/skills/gsd-path-build/scripts/state_promote.py +42 -44
  134. package/skills/gsd-path-build/scripts/task_context.py +73 -0
  135. package/skills/gsd-path-build/scripts/token_budget.py +40 -1
  136. package/skills/gsd-path-build/scripts/workflow_run.py +116 -7
  137. package/skills/gsd-path-build/templates/wave-review.md +1 -1
  138. package/skills/gsd-path-decide/SKILL.md +2 -6
  139. package/skills/gsd-path-decide/references/dispatch.md +6 -0
  140. package/skills/gsd-path-decide/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  141. package/skills/gsd-path-decide/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  142. package/skills/gsd-path-decide/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  143. package/skills/gsd-path-decide/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  144. package/skills/gsd-path-decide/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  145. package/skills/gsd-path-decide/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  146. package/skills/gsd-path-decide/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  147. package/skills/gsd-path-decide/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  148. package/skills/gsd-path-decide/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  149. package/skills/gsd-path-decide/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  150. package/skills/gsd-path-decide/scripts/archive_milestone.py +2157 -0
  151. package/skills/gsd-path-decide/scripts/build_recovery.py +287 -0
  152. package/skills/gsd-path-decide/scripts/check_handoffs.py +1 -1
  153. package/skills/gsd-path-decide/scripts/detect_project.py +1526 -0
  154. package/skills/gsd-path-decide/scripts/discussion_validate.py +1321 -0
  155. package/skills/gsd-path-decide/scripts/integration.py +1439 -0
  156. package/skills/gsd-path-decide/scripts/isolation.py +9 -1
  157. package/skills/gsd-path-decide/scripts/pipeline_state.py +114 -186
  158. package/skills/gsd-path-decide/scripts/promote_lookahead.py +283 -0
  159. package/skills/gsd-path-decide/scripts/review_panel.py +553 -0
  160. package/skills/gsd-path-decide/scripts/roadmap.py +321 -0
  161. package/skills/gsd-path-decide/scripts/state_checkpoint.py +109 -72
  162. package/skills/gsd-path-decide/scripts/state_promote.py +42 -44
  163. package/skills/gsd-path-define/SKILL.md +10 -14
  164. package/skills/gsd-path-define/references/build-recovery.md +78 -0
  165. package/skills/gsd-path-define/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  166. package/skills/gsd-path-define/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  167. package/skills/gsd-path-define/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  168. package/skills/gsd-path-define/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  169. package/skills/gsd-path-define/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  170. package/skills/gsd-path-define/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  171. package/skills/gsd-path-define/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  172. package/skills/gsd-path-define/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  173. package/skills/gsd-path-define/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  174. package/skills/gsd-path-define/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  175. package/skills/gsd-path-define/scripts/archive_milestone.py +2157 -0
  176. package/skills/gsd-path-define/scripts/build_recovery.py +287 -0
  177. package/skills/gsd-path-define/scripts/check_handoffs.py +1 -1
  178. package/skills/gsd-path-define/scripts/detect_project.py +11 -2
  179. package/skills/gsd-path-define/scripts/discussion_validate.py +1321 -0
  180. package/skills/gsd-path-define/scripts/integration.py +1439 -0
  181. package/skills/gsd-path-define/scripts/isolation.py +9 -1
  182. package/skills/gsd-path-define/scripts/pipeline_state.py +114 -186
  183. package/skills/gsd-path-define/scripts/promote_lookahead.py +283 -0
  184. package/skills/gsd-path-define/scripts/review_panel.py +553 -0
  185. package/skills/gsd-path-define/scripts/roadmap.py +321 -0
  186. package/skills/gsd-path-define/scripts/state_checkpoint.py +109 -72
  187. package/skills/gsd-path-define/scripts/state_promote.py +42 -44
  188. package/skills/gsd-path-docs-audit/references/dispatch.md +6 -0
  189. package/skills/gsd-path-docs-audit/references/docs-auditor.md +14 -0
  190. package/skills/gsd-path-docs-audit/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  191. package/skills/gsd-path-docs-audit/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  192. package/skills/gsd-path-docs-audit/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
  193. package/skills/gsd-path-docs-audit/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  194. package/skills/gsd-path-docs-audit/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  195. package/skills/gsd-path-docs-audit/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  196. package/skills/gsd-path-docs-audit/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  197. package/skills/gsd-path-docs-audit/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  198. package/skills/gsd-path-docs-audit/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  199. package/skills/gsd-path-docs-audit/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  200. package/skills/gsd-path-docs-audit/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  201. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +2157 -0
  202. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +287 -0
  203. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +5 -3
  204. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +1 -1
  205. package/skills/gsd-path-docs-audit/scripts/detect_project.py +1526 -0
  206. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +1321 -0
  207. package/skills/gsd-path-docs-audit/scripts/integration.py +1439 -0
  208. package/skills/gsd-path-docs-audit/scripts/isolation.py +9 -1
  209. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +114 -186
  210. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +283 -0
  211. package/skills/gsd-path-docs-audit/scripts/review_panel.py +553 -0
  212. package/skills/gsd-path-docs-audit/scripts/roadmap.py +321 -0
  213. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +109 -72
  214. package/skills/gsd-path-docs-audit/scripts/state_promote.py +42 -44
  215. package/skills/gsd-path-forensics/scripts/__pycache__/pipeline_undo.cpython-312.pyc +0 -0
  216. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +12 -3
  217. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +11 -7
  218. package/skills/gsd-path-inspect/SKILL.md +30 -8
  219. package/skills/gsd-path-inspect/references/dispatch.md +6 -0
  220. package/skills/gsd-path-inspect/references/docs-auditor.md +14 -0
  221. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  222. package/skills/gsd-path-inspect/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  223. package/skills/gsd-path-inspect/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
  224. package/skills/gsd-path-inspect/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  225. package/skills/gsd-path-inspect/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  226. package/skills/gsd-path-inspect/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  227. package/skills/gsd-path-inspect/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  228. package/skills/gsd-path-inspect/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  229. package/skills/gsd-path-inspect/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  230. package/skills/gsd-path-inspect/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  231. package/skills/gsd-path-inspect/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  232. package/skills/gsd-path-inspect/scripts/archive_milestone.py +2157 -0
  233. package/skills/gsd-path-inspect/scripts/build_recovery.py +287 -0
  234. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +5 -3
  235. package/skills/gsd-path-inspect/scripts/check_handoffs.py +1 -1
  236. package/skills/gsd-path-inspect/scripts/detect_project.py +11 -2
  237. package/skills/gsd-path-inspect/scripts/discussion_validate.py +1321 -0
  238. package/skills/gsd-path-inspect/scripts/integration.py +1439 -0
  239. package/skills/gsd-path-inspect/scripts/isolation.py +9 -1
  240. package/skills/gsd-path-inspect/scripts/pipeline_state.py +114 -186
  241. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +283 -0
  242. package/skills/gsd-path-inspect/scripts/review_panel.py +553 -0
  243. package/skills/gsd-path-inspect/scripts/roadmap.py +321 -0
  244. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +109 -72
  245. package/skills/gsd-path-inspect/scripts/state_promote.py +42 -44
  246. package/skills/gsd-path-inspect/scripts/workflow_run.py +226 -0
  247. package/skills/gsd-path-plan/SKILL.md +25 -17
  248. package/skills/gsd-path-plan/references/build-recovery.md +78 -0
  249. package/skills/gsd-path-plan/references/dispatch.md +6 -0
  250. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  251. package/skills/gsd-path-plan/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  252. package/skills/gsd-path-plan/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  253. package/skills/gsd-path-plan/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  254. package/skills/gsd-path-plan/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  255. package/skills/gsd-path-plan/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  256. package/skills/gsd-path-plan/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  257. package/skills/gsd-path-plan/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  258. package/skills/gsd-path-plan/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  259. package/skills/gsd-path-plan/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  260. package/skills/gsd-path-plan/scripts/archive_milestone.py +2157 -0
  261. package/skills/gsd-path-plan/scripts/build_recovery.py +287 -0
  262. package/skills/gsd-path-plan/scripts/check_handoffs.py +1 -1
  263. package/skills/gsd-path-plan/scripts/detect_project.py +1526 -0
  264. package/skills/gsd-path-plan/scripts/discussion_validate.py +1321 -0
  265. package/skills/gsd-path-plan/scripts/integration.py +1439 -0
  266. package/skills/gsd-path-plan/scripts/isolation.py +9 -1
  267. package/skills/gsd-path-plan/scripts/pipeline_state.py +114 -186
  268. package/skills/gsd-path-plan/scripts/promote_lookahead.py +283 -0
  269. package/skills/gsd-path-plan/scripts/roadmap.py +321 -0
  270. package/skills/gsd-path-plan/scripts/state_checkpoint.py +109 -72
  271. package/skills/gsd-path-plan/scripts/state_promote.py +42 -44
  272. package/skills/gsd-path-plan/scripts/workflow_run.py +116 -7
  273. package/skills/gsd-path-research/SKILL.md +3 -6
  274. package/skills/gsd-path-research/references/dispatch.md +6 -0
  275. package/skills/gsd-path-research/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  276. package/skills/gsd-path-research/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  277. package/skills/gsd-path-research/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  278. package/skills/gsd-path-research/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  279. package/skills/gsd-path-research/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  280. package/skills/gsd-path-research/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  281. package/skills/gsd-path-research/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  282. package/skills/gsd-path-research/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  283. package/skills/gsd-path-research/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  284. package/skills/gsd-path-research/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  285. package/skills/gsd-path-research/scripts/archive_milestone.py +2157 -0
  286. package/skills/gsd-path-research/scripts/build_recovery.py +287 -0
  287. package/skills/gsd-path-research/scripts/check_handoffs.py +1 -1
  288. package/skills/gsd-path-research/scripts/detect_project.py +1526 -0
  289. package/skills/gsd-path-research/scripts/discussion_validate.py +1321 -0
  290. package/skills/gsd-path-research/scripts/integration.py +1439 -0
  291. package/skills/gsd-path-research/scripts/isolation.py +9 -1
  292. package/skills/gsd-path-research/scripts/pipeline_state.py +114 -186
  293. package/skills/gsd-path-research/scripts/promote_lookahead.py +283 -0
  294. package/skills/gsd-path-research/scripts/review_panel.py +553 -0
  295. package/skills/gsd-path-research/scripts/roadmap.py +321 -0
  296. package/skills/gsd-path-research/scripts/state_checkpoint.py +109 -72
  297. package/skills/gsd-path-research/scripts/state_promote.py +42 -44
  298. package/skills/gsd-path-roadmap/SKILL.md +22 -58
  299. package/skills/gsd-path-roadmap/references/dispatch.md +6 -0
  300. package/skills/gsd-path-roadmap/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  301. package/skills/gsd-path-roadmap/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  302. package/skills/gsd-path-roadmap/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  303. package/skills/gsd-path-roadmap/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  304. package/skills/gsd-path-roadmap/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  305. package/skills/gsd-path-roadmap/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  306. package/skills/gsd-path-roadmap/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  307. package/skills/gsd-path-roadmap/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  308. package/skills/gsd-path-roadmap/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  309. package/skills/gsd-path-roadmap/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  310. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +10 -118
  311. package/skills/gsd-path-roadmap/scripts/build_recovery.py +287 -0
  312. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +1 -1
  313. package/skills/gsd-path-roadmap/scripts/detect_project.py +11 -2
  314. package/skills/gsd-path-roadmap/scripts/integration.py +28 -22
  315. package/skills/gsd-path-roadmap/scripts/isolation.py +9 -1
  316. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +114 -186
  317. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +30 -162
  318. package/skills/gsd-path-roadmap/scripts/roadmap.py +321 -0
  319. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +109 -72
  320. package/skills/gsd-path-roadmap/scripts/state_promote.py +42 -44
  321. package/skills/gsd-path-ship/SKILL.md +5 -4
  322. package/skills/gsd-path-ship/references/dispatch.md +6 -0
  323. package/skills/gsd-path-ship/references/reviewer-final.md +21 -0
  324. package/skills/gsd-path-ship/references/reviewer-panel.md +17 -0
  325. package/skills/gsd-path-ship/references/reviewer-skeptic.md +20 -0
  326. package/skills/gsd-path-ship/references/reviewer-wave.md +89 -0
  327. package/skills/gsd-path-ship/references/reviewer.md +12 -150
  328. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  329. package/skills/gsd-path-ship/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
  330. package/skills/gsd-path-ship/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
  331. package/skills/gsd-path-ship/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
  332. package/skills/gsd-path-ship/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  333. package/skills/gsd-path-ship/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
  334. package/skills/gsd-path-ship/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
  335. package/skills/gsd-path-ship/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
  336. package/skills/gsd-path-ship/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
  337. package/skills/gsd-path-ship/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
  338. package/skills/gsd-path-ship/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
  339. package/skills/gsd-path-ship/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
  340. package/skills/gsd-path-ship/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
  341. package/skills/gsd-path-ship/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
  342. package/skills/gsd-path-ship/scripts/archive_milestone.py +10 -118
  343. package/skills/gsd-path-ship/scripts/build_recovery.py +287 -0
  344. package/skills/gsd-path-ship/scripts/check_handoffs.py +1 -1
  345. package/skills/gsd-path-ship/scripts/detect_project.py +1526 -0
  346. package/skills/gsd-path-ship/scripts/integration.py +28 -22
  347. package/skills/gsd-path-ship/scripts/isolation.py +9 -1
  348. package/skills/gsd-path-ship/scripts/lean_verification.py +1 -1
  349. package/skills/gsd-path-ship/scripts/pipeline_state.py +114 -186
  350. package/skills/gsd-path-ship/scripts/promote_lookahead.py +283 -0
  351. package/skills/gsd-path-ship/scripts/roadmap.py +321 -0
  352. package/skills/gsd-path-ship/scripts/state_checkpoint.py +109 -72
  353. package/skills/gsd-path-ship/scripts/state_promote.py +42 -44
  354. package/skills/gsd-path-ship/scripts/workflow_run.py +116 -7
  355. package/skills/gsd-path-ship/templates/wave-review.md +1 -1
  356. package/skills/gsd-path-undo/scripts/pipeline_undo.py +11 -7
  357. package/skills/path/BUILD.md +47 -575
  358. package/skills/path/DECIDE.md +2 -6
  359. package/skills/path/DEFINE.md +10 -14
  360. package/skills/path/INSPECT.md +30 -8
  361. package/skills/path/PLAN.md +25 -17
  362. package/skills/path/RESEARCH.md +3 -6
  363. package/skills/path/ROADMAP.md +22 -58
  364. package/skills/path/SHIP.md +5 -4
  365. package/skills/path/SKILL.md +24 -14
  366. package/skills/path/references/build-abandon.md +33 -0
  367. package/skills/path/references/build-native.md +494 -0
  368. package/skills/path/references/build-recovery.md +78 -0
  369. package/skills/path/references/coder.md +8 -3
  370. package/skills/path/references/dispatch.md +6 -0
  371. package/skills/path/references/docs-auditor.md +14 -0
  372. package/skills/path/references/reviewer-final.md +21 -0
  373. package/skills/path/references/reviewer-panel.md +17 -0
  374. package/skills/path/references/reviewer-skeptic.md +20 -0
  375. package/skills/path/references/reviewer-wave.md +89 -0
  376. package/skills/path/references/reviewer.md +12 -150
  377. package/skills/path/scripts/archive_milestone.py +10 -118
  378. package/skills/path/scripts/bootstrap_repository.py +25 -3
  379. package/skills/path/scripts/build_recovery.py +287 -0
  380. package/skills/path/scripts/check_docs_audit.py +5 -3
  381. package/skills/path/scripts/check_handoffs.py +1 -1
  382. package/skills/path/scripts/detect_project.py +11 -2
  383. package/skills/path/scripts/dispatch_driver.py +4 -2
  384. package/skills/path/scripts/integration.py +28 -22
  385. package/skills/path/scripts/isolation.py +9 -1
  386. package/skills/path/scripts/lean_verification.py +1 -1
  387. package/skills/path/scripts/pipeline_state.py +114 -186
  388. package/skills/path/scripts/promote_lookahead.py +30 -162
  389. package/skills/path/scripts/roadmap.py +321 -0
  390. package/skills/path/scripts/state_checkpoint.py +109 -72
  391. package/skills/path/scripts/state_promote.py +42 -44
  392. package/skills/path/scripts/task_context.py +73 -0
  393. package/skills/path/scripts/token_budget.py +40 -1
  394. package/skills/path/scripts/workflow_run.py +116 -7
  395. package/skills/path/templates/wave-review.md +1 -1
@@ -2016,7 +2016,15 @@ def _recovery_task_inventory(
2016
2016
  relative_posix_dir = PurePosixPath(relative_dir.as_posix())
2017
2017
  revisions = [head]
2018
2018
  parents = git_output(primary, "show", "-s", "--format=%P", head).split()
2019
- if parents:
2019
+ # A recovery plan checkpoint owns replacement of unstarted task briefs.
2020
+ # Ordinary commits still require the parent inventory so a deletion cannot
2021
+ # silently hide a task from recovery.
2022
+ if __package__:
2023
+ from scripts import build_recovery
2024
+ else:
2025
+ import build_recovery
2026
+ replaced = build_recovery.inventory_checkpoint(primary, head)
2027
+ if parents and not replaced:
2020
2028
  revisions.append(parents[0])
2021
2029
  tracked = set()
2022
2030
  for revision in revisions:
@@ -32,8 +32,9 @@ try:
32
32
  collect_artifact_recoveries,
33
33
  )
34
34
  import _common
35
+ import roadmap
35
36
  except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
36
- if error.name not in {"isolation", "_common"}:
37
+ if error.name not in {"isolation", "_common", "roadmap"}:
37
38
  raise
38
39
  from scripts.isolation import (
39
40
  IsolationError,
@@ -41,7 +42,7 @@ except ModuleNotFoundError as error: # pragma: no cover - package imports used
41
42
  checkpoint as isolation_checkpoint,
42
43
  collect_artifact_recoveries,
43
44
  )
44
- from scripts import _common
45
+ from scripts import _common, roadmap
45
46
 
46
47
  try: # pragma: no cover - exercised only on Windows
47
48
  import fcntl
@@ -82,7 +83,6 @@ SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
82
83
  BOUND_BRANCH_RE = _common.BOUND_BRANCH_RE
83
84
  ARCHIVE_RE = re.compile(r"^\.project/archive/(\d{3,})-([a-z0-9][a-z0-9-]*)/?$")
84
85
  FRONTMATTER_RE = re.compile(r"^([a-z_]+):\s*([^#]*?)(?:\s+#.*)?$")
85
- ROADMAP_HEADING_RE = re.compile(r"^### (M\d{3,}) — ([a-z0-9][a-z0-9-]*)\s*$")
86
86
  TASK_ID_RE = re.compile(r"^T\d{3,}$")
87
87
  TASK_FILE_RE = re.compile(r"^(T\d{3,})-[a-z0-9][a-z0-9-]*\.md$")
88
88
  PLAN_APPROVAL_SUBJECT = "plan: build plan approved"
@@ -110,7 +110,7 @@ LOOKAHEAD_EVIDENCE_RE = re.compile(r"^research/evidence-[a-z0-9][a-z0-9-]*\.md$"
110
110
  PROMOTION_RESIDUAL = ".gsd-path-promote-next-residual"
111
111
  CHECKPOINT_SCHEMA = "gsd-path/state-checkpoint/v1"
112
112
  CHECKPOINT_JOURNAL_NAME = "gsd-path-state-checkpoint.json"
113
- CHECKPOINT_KINDS = ("plan", "roadmap")
113
+ CHECKPOINT_KINDS = ("plan", "roadmap", "roadmap-reslice")
114
114
  SHIPMENT_SCHEMA = "gsd-path/shipment/v1"
115
115
  SHIPMENT_JOURNAL_NAME = "gsd-path-shipment.json"
116
116
  UNDO_TRANSACTION_SCHEMA = "gsd-path/undo-transaction/v2"
@@ -126,6 +126,8 @@ CROSS_PHASE_TRANSITIONS = {
126
126
  ("decide", "done", "plan", "active"),
127
127
  ("roadmap", "done", "define", "active"),
128
128
  ("plan", "done", "build", "active"),
129
+ ("build", "blocked", "define", "active"),
130
+ ("build", "blocked", "plan", "active"),
129
131
  ("build", "active", "ship", "active"),
130
132
  ("build", "done", "ship", "active"),
131
133
  ("ship", "active", "shipped", "done"),
@@ -166,99 +168,10 @@ class ApprovedTaskContract:
166
168
  files: tuple[str, ...]
167
169
 
168
170
 
169
- # state_checkpoint and state_promote call back into this module through a
170
- # module reference and import the constants and classes above, so this import
171
- # must stay below those definitions.
172
- if __package__: # imported as scripts.pipeline_state
173
- from .state_checkpoint import (
174
- _sha256,
175
- _tree_digest,
176
- _checkpoint_artifact_digest,
177
- _roadmap_status,
178
- _activate_roadmap_milestone,
179
- _approval_details,
180
- _checkpoint_request_fields,
181
- _checkpoint_file,
182
- _approval_journal,
183
- _remove_checkpoint_temporary,
184
- _converge_checkpoint_file,
185
- _unlink_checkpoint_journal,
186
- _resume_checkpoint_locked,
187
- checkpoint_approval,
188
- _checkpoint_deferral_error,
189
- defer_approval,
190
- resume_checkpoint,
191
- _task_files,
192
- _approval_checkpoint,
193
- _validate_approval_track,
194
- _safe_declared_paths,
195
- _git_text_at,
196
- _approved_task_contracts,
197
- _task_contracts_at,
198
- _classify_plan_drift,
199
- )
200
- from .state_promote import (
201
- _render_roadmap,
202
- _promotion_event,
203
- _promotion_state,
204
- _head_with_exact_message,
205
- _tree_entries,
206
- _promotion_tree_mapping,
207
- _completed_promotion,
208
- _prepare_promotion,
209
- _require_journal_request,
210
- _resume_track_moves,
211
- _resume_metadata,
212
- _resume_next_removal,
213
- _commit_promotion,
214
- promote_next,
215
- )
216
- else: # standalone script or sibling import
217
- if __name__ == "__main__":
218
- sys.modules.setdefault("pipeline_state", sys.modules[__name__])
219
- from state_checkpoint import (
220
- _sha256,
221
- _tree_digest,
222
- _checkpoint_artifact_digest,
223
- _roadmap_status,
224
- _activate_roadmap_milestone,
225
- _approval_details,
226
- _checkpoint_request_fields,
227
- _checkpoint_file,
228
- _approval_journal,
229
- _remove_checkpoint_temporary,
230
- _converge_checkpoint_file,
231
- _unlink_checkpoint_journal,
232
- _resume_checkpoint_locked,
233
- checkpoint_approval,
234
- _checkpoint_deferral_error,
235
- defer_approval,
236
- resume_checkpoint,
237
- _task_files,
238
- _approval_checkpoint,
239
- _validate_approval_track,
240
- _safe_declared_paths,
241
- _git_text_at,
242
- _approved_task_contracts,
243
- _task_contracts_at,
244
- _classify_plan_drift,
245
- )
246
- from state_promote import (
247
- _render_roadmap,
248
- _promotion_event,
249
- _promotion_state,
250
- _head_with_exact_message,
251
- _tree_entries,
252
- _promotion_tree_mapping,
253
- _completed_promotion,
254
- _prepare_promotion,
255
- _require_journal_request,
256
- _resume_track_moves,
257
- _resume_metadata,
258
- _resume_next_removal,
259
- _commit_promotion,
260
- promote_next,
261
- )
171
+ # Standalone transaction imports must reuse this state module and its types.
172
+ if __name__ == "__main__":
173
+ sys.modules.setdefault("pipeline_state", sys.modules[__name__])
174
+
262
175
 
263
176
  def _run_git(
264
177
  repo: Path,
@@ -693,6 +606,21 @@ def _next_skill(route: Mapping[str, object]) -> Optional[str]:
693
606
  return None
694
607
 
695
608
 
609
+ def _completion_status(repo: Path, state: Mapping[str, object], project_dir: str) -> dict:
610
+ if project_dir != ".project" or state.get("phase") != "shipped":
611
+ return {"status": "not-shipped"}
612
+ if __package__:
613
+ from . import integration
614
+ else:
615
+ import integration
616
+ try:
617
+ proof = integration.validate_integrated(
618
+ repo, str(state.get("milestone") or ""), refresh=False)
619
+ except (integration.ArchiveError, OSError) as error:
620
+ return {"status": "unverified", "reason": str(error)}
621
+ return {"status": "verified", "proof": proof}
622
+
623
+
696
624
  def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
697
625
  """Report owned state, route, and git facts without advancing a phase."""
698
626
  resolved = _repo_root(repo)
@@ -726,9 +654,11 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
726
654
  "undo": None,
727
655
  "collect_artifact": None,
728
656
  }
657
+ completion = _completion_status(resolved, state, project_dir)
729
658
  return {
730
659
  "schema": STATUS_SCHEMA,
731
660
  "advance": False,
661
+ "completion": completion,
732
662
  "state": state,
733
663
  "route": route,
734
664
  "path": str(_track_root(resolved, project_dir) / "STATE.md"),
@@ -753,6 +683,28 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
753
683
  "lookahead": lookahead.exists() or lookahead.is_symlink(),
754
684
  "journals": journals,
755
685
  "next_skill": _next_skill(route if isinstance(route, dict) else {}),
686
+ "handoff": phase_handoff(state, route, _track_root(resolved, project_dir) / "STATE.md", completion),
687
+ }
688
+
689
+
690
+ def phase_handoff(state: Mapping[str, object], route: Mapping[str, object], path: Path,
691
+ completion: Mapping[str, object]) -> dict[str, str]:
692
+ """Present the authoritative route without granting continuation authority."""
693
+ action = route["action"]
694
+ if action == "run-phase":
695
+ next_action = f"Invoke $gsd-path to continue with {route['phase']}."
696
+ router_next = f"Continue with {route['phase']}; honor its input and approval gates."
697
+ else:
698
+ next_action = router_next = f"{action}: {route['reason']}"
699
+ outcome = f"{state['phase']}/{state['status']}"
700
+ if completion["status"] == "unverified":
701
+ outcome = f"Unverified: {outcome}"
702
+ return {
703
+ "outcome": outcome,
704
+ "review": str(path),
705
+ "next": next_action,
706
+ "phase_next": next_action,
707
+ "router_next": router_next,
756
708
  }
757
709
 
758
710
 
@@ -784,50 +736,11 @@ def _intent_lane(track: Path) -> Optional[str]:
784
736
 
785
737
 
786
738
  def _active_roadmap_has_questions(project: Path, milestone: Optional[str] = None) -> bool:
787
- """Report open questions for the active entry, or for ``milestone`` when given."""
788
739
  text = _read_real_file(project / "ROADMAP.md", "ROADMAP.md")
789
- lines = text.splitlines()
790
- active_section: Optional[list[str]] = None
791
- for index, line in enumerate(lines):
792
- heading = ROADMAP_HEADING_RE.fullmatch(line)
793
- if heading is None:
794
- continue
795
- if int(heading.group(1).removeprefix("M")) < 1:
796
- raise PipelineStateError(
797
- f"ROADMAP.md has invalid milestone id: {heading.group(1)}"
798
- )
799
- end = next(
800
- (
801
- cursor
802
- for cursor in range(index + 1, len(lines))
803
- if ROADMAP_HEADING_RE.fullmatch(lines[cursor]) is not None
804
- ),
805
- len(lines),
806
- )
807
- section = lines[index:end]
808
- if milestone is not None:
809
- if heading.group(2) == milestone:
810
- active_section = section
811
- continue
812
- if any(re.fullmatch(r"Status:\s*active(?:\s+#.*)?", item) for item in section):
813
- if active_section is not None:
814
- raise PipelineStateError("ROADMAP.md has more than one active milestone")
815
- active_section = section
816
- if active_section is None:
817
- if milestone is not None:
818
- raise PipelineStateError(f"ROADMAP.md is missing lookahead milestone: {milestone}")
819
- raise PipelineStateError("ROADMAP.md has no active milestone")
820
740
  try:
821
- start = active_section.index("Open questions") + 1
822
- except ValueError as error:
823
- raise PipelineStateError("active roadmap milestone has no Open questions") from error
824
- questions = [
825
- line[2:].strip()
826
- for line in active_section[start:]
827
- if line.startswith("- ")
828
- ]
829
- return any(question.lower() != "none" for question in questions)
830
-
741
+ return roadmap.has_questions(text, milestone)
742
+ except roadmap.RoadmapError as error:
743
+ raise PipelineStateError(str(error)) from error
831
744
 
832
745
  def _valid_patch_findings(repo: Path) -> bool:
833
746
  validator = Path(__file__).resolve().with_name("check_handoffs.py")
@@ -1106,6 +1019,14 @@ def route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
1106
1019
  """Route ordinary phase work only when its pending discussion owner can enter."""
1107
1020
  result = _route_state(repo, project_dir)
1108
1021
  route = result["route"]
1022
+ if project_dir == ".project" and route["action"] == "run-phase":
1023
+ recovery = _build_recovery().context(_repo_root(repo))
1024
+ if recovery and recovery["active"]:
1025
+ result["recovery"] = recovery
1026
+ if route.get("phase") == "define":
1027
+ route["mode"] = "corrections"
1028
+ elif route.get("phase") == "plan":
1029
+ route["mode"] = "build-repair"
1109
1030
  if route["action"] == "run-phase" and result["state"]["archive"] is None:
1110
1031
  reason = _pending_discussion_block(_repo_root(repo), route.get("phase"))
1111
1032
  if reason:
@@ -1159,7 +1080,11 @@ def _route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
1159
1080
  return result
1160
1081
  checkpoint_journal = _git_path(resolved, CHECKPOINT_JOURNAL_NAME)
1161
1082
  if checkpoint_journal.exists() or checkpoint_journal.is_symlink():
1162
- transaction = _approval_journal(
1083
+ if __package__:
1084
+ from . import state_checkpoint
1085
+ else:
1086
+ import state_checkpoint
1087
+ transaction = state_checkpoint._approval_journal(
1163
1088
  resolved,
1164
1089
  _read_json(checkpoint_journal),
1165
1090
  )
@@ -1736,6 +1661,16 @@ def transition_state(
1736
1661
  event,
1737
1662
  project_dir,
1738
1663
  )
1664
+ recovery_context = _build_recovery().context(resolved, text) if project_dir == ".project" else None
1665
+ if recovery_context and recovery_context["active"]:
1666
+ if (state.milestone, state.branch, state.archive) != (after.milestone, after.branch, after.archive):
1667
+ raise PipelineStateError("build recovery must preserve milestone identity")
1668
+ if state.phase == "build" and after.phase in {"define", "plan"}:
1669
+ recovery = _build_recovery().begin(resolved, state, after, event)
1670
+ rendered = _append_event(
1671
+ rendered, after.phase,
1672
+ _build_recovery().MARKER + json.dumps(recovery, sort_keys=True),
1673
+ )
1739
1674
  if after.status != "blocked":
1740
1675
  reason = _pending_discussion_block(
1741
1676
  resolved, after.phase if after.status == "active" else None
@@ -1767,6 +1702,14 @@ def transition_state(
1767
1702
  }
1768
1703
 
1769
1704
 
1705
+ def _build_recovery():
1706
+ if __package__:
1707
+ from scripts import build_recovery
1708
+ else:
1709
+ import build_recovery
1710
+ return build_recovery
1711
+
1712
+
1770
1713
  def configure_integration(
1771
1714
  repo: Path,
1772
1715
  scope: str,
@@ -1786,7 +1729,9 @@ def configure_integration(
1786
1729
  project = _track_root(resolved, project_dir)
1787
1730
  with _state_lock(project):
1788
1731
  state, text, path = load_state(resolved, project_dir)
1789
- if state.phase in {"build", "ship", "shipped"}:
1732
+ if state.phase in {"build", "ship", "shipped"} or (
1733
+ project_dir == ".project" and _build_recovery().context(resolved, text)
1734
+ ):
1790
1735
  raise PipelineStateError("integration mode is locked when build starts")
1791
1736
  if scope == "default":
1792
1737
  integration = (
@@ -2022,49 +1967,18 @@ def _render_transition(
2022
1967
 
2023
1968
 
2024
1969
  def _roadmap_sections(text: str) -> dict[str, tuple[str, int, int]]:
2025
- lines = text.splitlines(keepends=True)
2026
- headings: list[tuple[str, str, int]] = []
2027
- for index, line in enumerate(lines):
2028
- match = ROADMAP_HEADING_RE.fullmatch(line.rstrip("\r\n"))
2029
- if match:
2030
- if int(match.group(1).removeprefix("M")) < 1:
2031
- raise PipelineStateError(f"ROADMAP.md has invalid milestone id: {match.group(1)}")
2032
- headings.append((match.group(1), match.group(2), index))
2033
- sections: dict[str, tuple[str, int, int]] = {}
2034
- for position, (milestone_id, slug, start) in enumerate(headings):
2035
- end = headings[position + 1][2] if position + 1 < len(headings) else len(lines)
2036
- if slug in sections:
2037
- raise PipelineStateError(f"ROADMAP.md repeats milestone slug: {slug}")
2038
- sections[slug] = (milestone_id, start, end)
2039
- return sections
2040
-
1970
+ try:
1971
+ return roadmap.strict_sections(text)
1972
+ except roadmap.RoadmapError as error:
1973
+ raise PipelineStateError(str(error)) from error
2041
1974
 
2042
1975
  def _replace_roadmap_field(
2043
- lines: list[str],
2044
- start: int,
2045
- end: int,
2046
- field: str,
2047
- expected: set[str],
2048
- value: str,
1976
+ lines: list[str], start: int, end: int, field: str, expected: set[str], value: str,
2049
1977
  ) -> None:
2050
- found: Optional[int] = None
2051
- for index in range(start, end):
2052
- raw = lines[index].rstrip("\r\n")
2053
- ending = lines[index][len(raw) :]
2054
- match = re.match(rf"^({re.escape(field)}:\s*)(\S+)(.*)$", raw)
2055
- if match is None:
2056
- continue
2057
- if found is not None:
2058
- raise PipelineStateError(f"ROADMAP.md repeats {field} in one milestone")
2059
- if match.group(2) not in expected:
2060
- raise PipelineStateError(
2061
- f"ROADMAP.md {field} is {match.group(2)}, expected {sorted(expected)}"
2062
- )
2063
- lines[index] = f"{match.group(1)}{value}{match.group(3)}{ending}"
2064
- found = index
2065
- if found is None:
2066
- raise PipelineStateError(f"ROADMAP.md milestone is missing {field}")
2067
-
1978
+ try:
1979
+ return roadmap.replace_field(lines, start, end, field, expected, value)
1980
+ except roadmap.RoadmapError as error:
1981
+ raise PipelineStateError(str(error)) from error
2068
1982
 
2069
1983
  def _git_path(repo: Path, name: str) -> Path:
2070
1984
  value = _run_git(repo, "rev-parse", "--git-path", name).stdout.strip()
@@ -2163,7 +2077,7 @@ def _specified_fields(arguments: argparse.Namespace, prefix: str) -> dict[str, O
2163
2077
  def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
2164
2078
  parser = argparse.ArgumentParser(description=__doc__)
2165
2079
  subparsers = parser.add_subparsers(dest="command", required=True)
2166
- for command in ("validate", "route", "status"):
2080
+ for command in ("validate", "route", "status", "prepare-build-recovery"):
2167
2081
  subparser = subparsers.add_parser(command)
2168
2082
  subparser.add_argument("--repo", required=True, type=Path)
2169
2083
  subparser.add_argument("--project-dir", default=".project")
@@ -2204,6 +2118,16 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
2204
2118
 
2205
2119
  def main(argv: Optional[Sequence[str]] = None) -> int:
2206
2120
  args = parse_args(argv)
2121
+ if args.command in {"approve", "resume-checkpoint"}:
2122
+ if __package__:
2123
+ from . import state_checkpoint
2124
+ else:
2125
+ import state_checkpoint
2126
+ elif args.command == "promote-next":
2127
+ if __package__:
2128
+ from . import state_promote
2129
+ else:
2130
+ import state_promote
2207
2131
  try:
2208
2132
  if args.command == "validate":
2209
2133
  result = validate_state(args.repo, args.project_dir)
@@ -2211,6 +2135,10 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2211
2135
  result = route_state(args.repo, args.project_dir)
2212
2136
  elif args.command == "status":
2213
2137
  result = status_state(args.repo, args.project_dir)
2138
+ elif args.command == "prepare-build-recovery":
2139
+ if args.project_dir != ".project":
2140
+ raise PipelineStateError("build recovery requires the active track")
2141
+ result = _build_recovery().prepare(args.repo)
2214
2142
  elif args.command == "transition":
2215
2143
  result = transition_state(
2216
2144
  args.repo,
@@ -2224,7 +2152,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2224
2152
  raise PipelineStateError(
2225
2153
  "--expected-head is not accepted with --defer-checkpoint or --patch"
2226
2154
  )
2227
- result = defer_approval(
2155
+ result = state_checkpoint.defer_approval(
2228
2156
  args.repo,
2229
2157
  args.kind,
2230
2158
  args.project_dir,
@@ -2236,7 +2164,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2236
2164
  raise PipelineStateError(
2237
2165
  "approve requires --expected-head unless --defer-checkpoint or --patch"
2238
2166
  )
2239
- result = checkpoint_approval(
2167
+ result = state_checkpoint.checkpoint_approval(
2240
2168
  args.repo,
2241
2169
  args.kind,
2242
2170
  args.expected_head,
@@ -2244,7 +2172,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2244
2172
  args.milestone,
2245
2173
  )
2246
2174
  elif args.command == "resume-checkpoint":
2247
- result = resume_checkpoint(args.repo)
2175
+ result = state_checkpoint.resume_checkpoint(args.repo)
2248
2176
  elif args.command == "promote-next":
2249
2177
  if args.integrate is not None and (
2250
2178
  args.base is not None or args.landing is not None
@@ -2262,7 +2190,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2262
2190
  raise PipelineStateError(
2263
2191
  "promote-next requires --base or legacy --integrate"
2264
2192
  )
2265
- result = promote_next(
2193
+ result = state_promote.promote_next(
2266
2194
  args.repo,
2267
2195
  args.milestone,
2268
2196
  args.branch,