@opengsd/gsd-path 1.0.0 → 1.2.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 (498) hide show
  1. package/AGENTS.md +33 -13
  2. package/CHANGELOG.md +68 -0
  3. package/DOCS.md +75 -6
  4. package/FULL.md +12 -15
  5. package/HOOKS.md +18 -9
  6. package/QUICK.md +8 -6
  7. package/README.md +218 -14
  8. package/RUNTIME.md +16 -5
  9. package/UPDATE.md +30 -11
  10. package/WORKFLOW.md +35 -16
  11. package/package.json +23 -1
  12. package/platforms/claude/dispatch.md +4 -4
  13. package/platforms/copilot/dispatch.md +4 -4
  14. package/platforms/cursor/dispatch.md +5 -10
  15. package/platforms/grok/dispatch.md +4 -6
  16. package/platforms/kimi/dispatch.md +4 -4
  17. package/platforms/kiro/dispatch.md +4 -6
  18. package/platforms/opencode/dispatch.md +4 -4
  19. package/platforms/qwen/dispatch.md +4 -4
  20. package/platforms/shared-agents/dispatch.md +12 -19
  21. package/scripts/_common.py +5 -0
  22. package/scripts/archive_milestone.py +30 -124
  23. package/scripts/bootstrap_repository.py +33 -4
  24. package/scripts/build_recovery.py +292 -0
  25. package/scripts/build_state.py +2 -0
  26. package/scripts/check_docs_audit.py +7 -3
  27. package/scripts/check_handoffs.py +7 -1
  28. package/scripts/check_task_briefs.py +3 -0
  29. package/scripts/detect_project.py +22 -3
  30. package/scripts/discussion_records.py +3 -0
  31. package/scripts/discussion_validate.py +8 -3
  32. package/scripts/dispatch_driver.py +233 -22
  33. package/scripts/git_guard.py +14 -5
  34. package/scripts/guard_hook.py +11 -1
  35. package/scripts/install.mjs +54 -1448
  36. package/scripts/install.py +155 -188
  37. package/scripts/integration.py +54 -28
  38. package/scripts/isolation.py +24 -6
  39. package/scripts/jev_review.py +138 -0
  40. package/scripts/lean_verification.py +3 -1
  41. package/scripts/loop_run.py +2 -0
  42. package/scripts/model_policy.py +279 -0
  43. package/scripts/path_config.py +248 -0
  44. package/scripts/pipeline_diagnose.py +15 -3
  45. package/scripts/pipeline_git.py +3 -0
  46. package/scripts/pipeline_state.py +117 -186
  47. package/scripts/pipeline_undo.py +14 -7
  48. package/scripts/promote_lookahead.py +33 -162
  49. package/scripts/review_panel.py +11 -0
  50. package/scripts/roadmap.py +326 -0
  51. package/scripts/runtime_store.py +278 -0
  52. package/scripts/skill-resources.json +182 -4
  53. package/scripts/state_checkpoint.py +114 -72
  54. package/scripts/state_promote.py +47 -44
  55. package/scripts/status_runtime.py +92 -6
  56. package/scripts/task_context.py +73 -0
  57. package/scripts/token_budget.py +40 -1
  58. package/scripts/workflow_run.py +128 -8
  59. package/scripts/worktree_paths.py +94 -0
  60. package/skills/gsd-path/BUILD.md +54 -575
  61. package/skills/gsd-path/DECIDE.md +4 -6
  62. package/skills/gsd-path/DEFINE.md +23 -21
  63. package/skills/gsd-path/DOCS-AUDIT.md +2 -0
  64. package/skills/gsd-path/INSPECT.md +32 -8
  65. package/skills/gsd-path/PLAN.md +29 -19
  66. package/skills/gsd-path/RESEARCH.md +5 -6
  67. package/skills/gsd-path/ROADMAP.md +24 -58
  68. package/skills/gsd-path/SHIP.md +29 -17
  69. package/skills/gsd-path/SKILL.md +46 -22
  70. package/skills/gsd-path/references/build-abandon.md +33 -0
  71. package/skills/gsd-path/references/build-native.md +502 -0
  72. package/skills/gsd-path/references/build-recovery.md +78 -0
  73. package/skills/gsd-path/references/coder.md +8 -3
  74. package/skills/gsd-path/references/config.md +57 -0
  75. package/skills/gsd-path/references/dispatch.md +12 -19
  76. package/skills/gsd-path/references/docs-auditor.md +14 -0
  77. package/skills/gsd-path/references/jev-review.md +82 -0
  78. package/skills/gsd-path/references/model-policy.md +139 -0
  79. package/skills/gsd-path/references/reviewer-final.md +21 -0
  80. package/skills/gsd-path/references/reviewer-panel.md +17 -0
  81. package/skills/gsd-path/references/reviewer-skeptic.md +20 -0
  82. package/skills/gsd-path/references/reviewer-wave.md +89 -0
  83. package/skills/gsd-path/references/reviewer.md +12 -148
  84. package/skills/gsd-path/references/runtime-selection.md +25 -0
  85. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  86. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  87. package/skills/gsd-path/scripts/_common.py +5 -0
  88. package/skills/gsd-path/scripts/archive_milestone.py +30 -124
  89. package/skills/gsd-path/scripts/bootstrap_repository.py +33 -4
  90. package/skills/gsd-path/scripts/build_recovery.py +292 -0
  91. package/skills/gsd-path/scripts/build_state.py +2 -0
  92. package/skills/gsd-path/scripts/check_docs_audit.py +7 -3
  93. package/skills/gsd-path/scripts/check_handoffs.py +7 -1
  94. package/skills/gsd-path/scripts/check_task_briefs.py +3 -0
  95. package/skills/gsd-path/scripts/detect_project.py +22 -3
  96. package/skills/gsd-path/scripts/discussion_records.py +3 -0
  97. package/skills/gsd-path/scripts/discussion_validate.py +8 -3
  98. package/skills/gsd-path/scripts/dispatch_driver.py +233 -22
  99. package/skills/gsd-path/scripts/git_guard.py +768 -0
  100. package/skills/gsd-path/scripts/integration.py +54 -28
  101. package/skills/gsd-path/scripts/isolation.py +24 -6
  102. package/skills/gsd-path/scripts/jev_review.py +138 -0
  103. package/skills/gsd-path/scripts/lean_verification.py +3 -1
  104. package/skills/gsd-path/scripts/loop_run.py +2 -0
  105. package/skills/gsd-path/scripts/model_policy.py +279 -0
  106. package/skills/gsd-path/scripts/path_config.py +248 -0
  107. package/skills/gsd-path/scripts/pipeline_git.py +3 -0
  108. package/skills/gsd-path/scripts/pipeline_state.py +117 -186
  109. package/skills/gsd-path/scripts/promote_lookahead.py +33 -162
  110. package/skills/gsd-path/scripts/review_panel.py +11 -0
  111. package/skills/gsd-path/scripts/roadmap.py +326 -0
  112. package/skills/gsd-path/scripts/state_checkpoint.py +114 -72
  113. package/skills/gsd-path/scripts/state_promote.py +47 -44
  114. package/skills/gsd-path/scripts/status_runtime.py +208 -0
  115. package/skills/gsd-path/scripts/task_context.py +73 -0
  116. package/skills/gsd-path/scripts/token_budget.py +40 -1
  117. package/skills/gsd-path/scripts/workflow_run.py +128 -8
  118. package/skills/gsd-path/scripts/worktree_paths.py +94 -0
  119. package/skills/gsd-path/templates/skeptic.md +1 -1
  120. package/skills/gsd-path/templates/task.md +2 -0
  121. package/skills/gsd-path/templates/wave-panel.md +1 -1
  122. package/skills/gsd-path/templates/wave-review.md +1 -1
  123. package/skills/gsd-path-build/SKILL.md +54 -575
  124. package/skills/gsd-path-build/references/build-abandon.md +33 -0
  125. package/skills/gsd-path-build/references/build-native.md +502 -0
  126. package/skills/gsd-path-build/references/build-recovery.md +78 -0
  127. package/skills/gsd-path-build/references/coder.md +8 -3
  128. package/skills/gsd-path-build/references/dispatch.md +12 -19
  129. package/skills/gsd-path-build/references/jev-review.md +82 -0
  130. package/skills/gsd-path-build/references/model-policy.md +139 -0
  131. package/skills/gsd-path-build/references/reviewer-final.md +21 -0
  132. package/skills/gsd-path-build/references/reviewer-panel.md +17 -0
  133. package/skills/gsd-path-build/references/reviewer-skeptic.md +20 -0
  134. package/skills/gsd-path-build/references/reviewer-wave.md +89 -0
  135. package/skills/gsd-path-build/references/reviewer.md +12 -148
  136. package/skills/gsd-path-build/references/runtime-selection.md +25 -0
  137. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  138. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  139. package/skills/gsd-path-build/scripts/_common.py +5 -0
  140. package/skills/gsd-path-build/scripts/archive_milestone.py +30 -124
  141. package/skills/gsd-path-build/scripts/build_recovery.py +292 -0
  142. package/skills/gsd-path-build/scripts/build_state.py +2 -0
  143. package/skills/gsd-path-build/scripts/check_handoffs.py +7 -1
  144. package/skills/gsd-path-build/scripts/check_task_briefs.py +3 -0
  145. package/skills/gsd-path-build/scripts/detect_project.py +1536 -0
  146. package/skills/gsd-path-build/scripts/discussion_records.py +3 -0
  147. package/skills/gsd-path-build/scripts/discussion_validate.py +8 -3
  148. package/skills/gsd-path-build/scripts/dispatch_driver.py +233 -22
  149. package/skills/gsd-path-build/scripts/integration.py +54 -28
  150. package/skills/gsd-path-build/scripts/isolation.py +24 -6
  151. package/skills/gsd-path-build/scripts/jev_review.py +138 -0
  152. package/skills/gsd-path-build/scripts/loop_run.py +2 -0
  153. package/skills/gsd-path-build/scripts/model_policy.py +279 -0
  154. package/skills/gsd-path-build/scripts/path_config.py +248 -0
  155. package/skills/gsd-path-build/scripts/pipeline_git.py +3 -0
  156. package/skills/gsd-path-build/scripts/pipeline_state.py +117 -186
  157. package/skills/gsd-path-build/scripts/promote_lookahead.py +286 -0
  158. package/skills/gsd-path-build/scripts/review_panel.py +11 -0
  159. package/skills/gsd-path-build/scripts/roadmap.py +326 -0
  160. package/skills/gsd-path-build/scripts/state_checkpoint.py +114 -72
  161. package/skills/gsd-path-build/scripts/state_promote.py +47 -44
  162. package/skills/gsd-path-build/scripts/task_context.py +73 -0
  163. package/skills/gsd-path-build/scripts/token_budget.py +40 -1
  164. package/skills/gsd-path-build/scripts/workflow_run.py +128 -8
  165. package/skills/gsd-path-build/scripts/worktree_paths.py +94 -0
  166. package/skills/gsd-path-build/templates/skeptic.md +1 -1
  167. package/skills/gsd-path-build/templates/task.md +2 -0
  168. package/skills/gsd-path-build/templates/wave-panel.md +1 -1
  169. package/skills/gsd-path-build/templates/wave-review.md +1 -1
  170. package/skills/gsd-path-decide/SKILL.md +4 -6
  171. package/skills/gsd-path-decide/references/dispatch.md +12 -19
  172. package/skills/gsd-path-decide/references/model-policy.md +139 -0
  173. package/skills/gsd-path-decide/references/runtime-selection.md +25 -0
  174. package/skills/gsd-path-decide/scripts/_common.py +5 -0
  175. package/skills/gsd-path-decide/scripts/archive_milestone.py +2171 -0
  176. package/skills/gsd-path-decide/scripts/build_recovery.py +292 -0
  177. package/skills/gsd-path-decide/scripts/check_handoffs.py +7 -1
  178. package/skills/gsd-path-decide/scripts/check_task_briefs.py +3 -0
  179. package/skills/gsd-path-decide/scripts/detect_project.py +1536 -0
  180. package/skills/gsd-path-decide/scripts/discussion_records.py +3 -0
  181. package/skills/gsd-path-decide/scripts/discussion_validate.py +1326 -0
  182. package/skills/gsd-path-decide/scripts/integration.py +1459 -0
  183. package/skills/gsd-path-decide/scripts/isolation.py +24 -6
  184. package/skills/gsd-path-decide/scripts/loop_run.py +839 -0
  185. package/skills/gsd-path-decide/scripts/model_policy.py +279 -0
  186. package/skills/gsd-path-decide/scripts/path_config.py +248 -0
  187. package/skills/gsd-path-decide/scripts/pipeline_git.py +3 -0
  188. package/skills/gsd-path-decide/scripts/pipeline_state.py +117 -186
  189. package/skills/gsd-path-decide/scripts/promote_lookahead.py +286 -0
  190. package/skills/gsd-path-decide/scripts/review_panel.py +564 -0
  191. package/skills/gsd-path-decide/scripts/roadmap.py +326 -0
  192. package/skills/gsd-path-decide/scripts/state_checkpoint.py +114 -72
  193. package/skills/gsd-path-decide/scripts/state_promote.py +47 -44
  194. package/skills/gsd-path-decide/scripts/worktree_paths.py +94 -0
  195. package/skills/gsd-path-define/SKILL.md +23 -21
  196. package/skills/gsd-path-define/references/build-recovery.md +78 -0
  197. package/skills/gsd-path-define/references/runtime-selection.md +25 -0
  198. package/skills/gsd-path-define/scripts/_common.py +5 -0
  199. package/skills/gsd-path-define/scripts/archive_milestone.py +2171 -0
  200. package/skills/gsd-path-define/scripts/build_recovery.py +292 -0
  201. package/skills/gsd-path-define/scripts/check_handoffs.py +7 -1
  202. package/skills/gsd-path-define/scripts/check_task_briefs.py +3 -0
  203. package/skills/gsd-path-define/scripts/detect_project.py +22 -3
  204. package/skills/gsd-path-define/scripts/discussion_records.py +3 -0
  205. package/skills/gsd-path-define/scripts/discussion_validate.py +1326 -0
  206. package/skills/gsd-path-define/scripts/integration.py +1459 -0
  207. package/skills/gsd-path-define/scripts/isolation.py +24 -6
  208. package/skills/gsd-path-define/scripts/loop_run.py +839 -0
  209. package/skills/gsd-path-define/scripts/model_policy.py +279 -0
  210. package/skills/gsd-path-define/scripts/path_config.py +248 -0
  211. package/skills/gsd-path-define/scripts/pipeline_git.py +3 -0
  212. package/skills/gsd-path-define/scripts/pipeline_state.py +117 -186
  213. package/skills/gsd-path-define/scripts/promote_lookahead.py +286 -0
  214. package/skills/gsd-path-define/scripts/review_panel.py +564 -0
  215. package/skills/gsd-path-define/scripts/roadmap.py +326 -0
  216. package/skills/gsd-path-define/scripts/state_checkpoint.py +114 -72
  217. package/skills/gsd-path-define/scripts/state_promote.py +47 -44
  218. package/skills/gsd-path-define/scripts/worktree_paths.py +94 -0
  219. package/skills/gsd-path-discuss/SKILL.md +2 -0
  220. package/skills/gsd-path-discuss/references/runtime-selection.md +25 -0
  221. package/skills/gsd-path-discuss/scripts/_common.py +5 -0
  222. package/skills/gsd-path-discuss/scripts/discussion_records.py +3 -0
  223. package/skills/gsd-path-discuss/scripts/loop_run.py +839 -0
  224. package/skills/gsd-path-discuss/scripts/model_policy.py +279 -0
  225. package/skills/gsd-path-discuss/scripts/path_config.py +248 -0
  226. package/skills/gsd-path-discuss/scripts/review_panel.py +564 -0
  227. package/skills/gsd-path-discuss/scripts/worktree_paths.py +94 -0
  228. package/skills/gsd-path-docs-audit/SKILL.md +2 -0
  229. package/skills/gsd-path-docs-audit/references/dispatch.md +12 -19
  230. package/skills/gsd-path-docs-audit/references/docs-auditor.md +14 -0
  231. package/skills/gsd-path-docs-audit/references/model-policy.md +139 -0
  232. package/skills/gsd-path-docs-audit/references/runtime-selection.md +25 -0
  233. package/skills/gsd-path-docs-audit/scripts/_common.py +5 -0
  234. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +2171 -0
  235. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +292 -0
  236. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +7 -3
  237. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +7 -1
  238. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +3 -0
  239. package/skills/gsd-path-docs-audit/scripts/detect_project.py +1536 -0
  240. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +3 -0
  241. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +1326 -0
  242. package/skills/gsd-path-docs-audit/scripts/integration.py +1459 -0
  243. package/skills/gsd-path-docs-audit/scripts/isolation.py +24 -6
  244. package/skills/gsd-path-docs-audit/scripts/loop_run.py +839 -0
  245. package/skills/gsd-path-docs-audit/scripts/model_policy.py +279 -0
  246. package/skills/gsd-path-docs-audit/scripts/path_config.py +248 -0
  247. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +3 -0
  248. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +117 -186
  249. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +286 -0
  250. package/skills/gsd-path-docs-audit/scripts/review_panel.py +564 -0
  251. package/skills/gsd-path-docs-audit/scripts/roadmap.py +326 -0
  252. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +114 -72
  253. package/skills/gsd-path-docs-audit/scripts/state_promote.py +47 -44
  254. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +94 -0
  255. package/skills/gsd-path-forensics/SKILL.md +9 -5
  256. package/skills/gsd-path-forensics/references/runtime-selection.md +25 -0
  257. package/skills/gsd-path-forensics/scripts/_common.py +5 -0
  258. package/skills/gsd-path-forensics/scripts/discussion_records.py +3 -0
  259. package/skills/gsd-path-forensics/scripts/loop_run.py +839 -0
  260. package/skills/gsd-path-forensics/scripts/model_policy.py +279 -0
  261. package/skills/gsd-path-forensics/scripts/path_config.py +248 -0
  262. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +15 -3
  263. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +14 -7
  264. package/skills/gsd-path-forensics/scripts/review_panel.py +564 -0
  265. package/skills/gsd-path-forensics/scripts/worktree_paths.py +94 -0
  266. package/skills/gsd-path-inspect/SKILL.md +32 -8
  267. package/skills/gsd-path-inspect/references/dispatch.md +12 -19
  268. package/skills/gsd-path-inspect/references/docs-auditor.md +14 -0
  269. package/skills/gsd-path-inspect/references/model-policy.md +139 -0
  270. package/skills/gsd-path-inspect/references/runtime-selection.md +25 -0
  271. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  272. package/skills/gsd-path-inspect/scripts/_common.py +5 -0
  273. package/skills/gsd-path-inspect/scripts/archive_milestone.py +2171 -0
  274. package/skills/gsd-path-inspect/scripts/build_recovery.py +292 -0
  275. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +7 -3
  276. package/skills/gsd-path-inspect/scripts/check_handoffs.py +7 -1
  277. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +3 -0
  278. package/skills/gsd-path-inspect/scripts/detect_project.py +22 -3
  279. package/skills/gsd-path-inspect/scripts/discussion_records.py +3 -0
  280. package/skills/gsd-path-inspect/scripts/discussion_validate.py +1326 -0
  281. package/skills/gsd-path-inspect/scripts/integration.py +1459 -0
  282. package/skills/gsd-path-inspect/scripts/isolation.py +24 -6
  283. package/skills/gsd-path-inspect/scripts/loop_run.py +839 -0
  284. package/skills/gsd-path-inspect/scripts/model_policy.py +279 -0
  285. package/skills/gsd-path-inspect/scripts/path_config.py +248 -0
  286. package/skills/gsd-path-inspect/scripts/pipeline_git.py +3 -0
  287. package/skills/gsd-path-inspect/scripts/pipeline_state.py +117 -186
  288. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +286 -0
  289. package/skills/gsd-path-inspect/scripts/review_panel.py +564 -0
  290. package/skills/gsd-path-inspect/scripts/roadmap.py +326 -0
  291. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +114 -72
  292. package/skills/gsd-path-inspect/scripts/state_promote.py +47 -44
  293. package/skills/gsd-path-inspect/scripts/workflow_run.py +237 -0
  294. package/skills/gsd-path-inspect/scripts/worktree_paths.py +94 -0
  295. package/skills/gsd-path-loop/SKILL.md +2 -0
  296. package/skills/gsd-path-loop/references/runtime-selection.md +25 -0
  297. package/skills/gsd-path-loop/scripts/_common.py +5 -0
  298. package/skills/gsd-path-loop/scripts/discussion_records.py +3 -0
  299. package/skills/gsd-path-loop/scripts/loop_run.py +2 -0
  300. package/skills/gsd-path-loop/scripts/model_policy.py +279 -0
  301. package/skills/gsd-path-loop/scripts/path_config.py +248 -0
  302. package/skills/gsd-path-loop/scripts/review_panel.py +564 -0
  303. package/skills/gsd-path-loop/scripts/worktree_paths.py +94 -0
  304. package/skills/gsd-path-migrate/SKILL.md +2 -0
  305. package/skills/gsd-path-migrate/references/runtime-selection.md +25 -0
  306. package/skills/gsd-path-migrate/scripts/_common.py +185 -0
  307. package/skills/gsd-path-migrate/scripts/discussion_records.py +3 -0
  308. package/skills/gsd-path-migrate/scripts/loop_run.py +839 -0
  309. package/skills/gsd-path-migrate/scripts/model_policy.py +279 -0
  310. package/skills/gsd-path-migrate/scripts/path_config.py +248 -0
  311. package/skills/gsd-path-migrate/scripts/review_panel.py +564 -0
  312. package/skills/gsd-path-plan/SKILL.md +29 -19
  313. package/skills/gsd-path-plan/references/build-recovery.md +78 -0
  314. package/skills/gsd-path-plan/references/dispatch.md +12 -19
  315. package/skills/gsd-path-plan/references/model-policy.md +139 -0
  316. package/skills/gsd-path-plan/references/runtime-selection.md +25 -0
  317. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  318. package/skills/gsd-path-plan/scripts/_common.py +5 -0
  319. package/skills/gsd-path-plan/scripts/archive_milestone.py +2171 -0
  320. package/skills/gsd-path-plan/scripts/build_recovery.py +292 -0
  321. package/skills/gsd-path-plan/scripts/check_handoffs.py +7 -1
  322. package/skills/gsd-path-plan/scripts/check_task_briefs.py +3 -0
  323. package/skills/gsd-path-plan/scripts/detect_project.py +1536 -0
  324. package/skills/gsd-path-plan/scripts/discussion_records.py +3 -0
  325. package/skills/gsd-path-plan/scripts/discussion_validate.py +1326 -0
  326. package/skills/gsd-path-plan/scripts/integration.py +1459 -0
  327. package/skills/gsd-path-plan/scripts/isolation.py +24 -6
  328. package/skills/gsd-path-plan/scripts/loop_run.py +839 -0
  329. package/skills/gsd-path-plan/scripts/model_policy.py +279 -0
  330. package/skills/gsd-path-plan/scripts/path_config.py +248 -0
  331. package/skills/gsd-path-plan/scripts/pipeline_git.py +3 -0
  332. package/skills/gsd-path-plan/scripts/pipeline_state.py +117 -186
  333. package/skills/gsd-path-plan/scripts/promote_lookahead.py +286 -0
  334. package/skills/gsd-path-plan/scripts/review_panel.py +11 -0
  335. package/skills/gsd-path-plan/scripts/roadmap.py +326 -0
  336. package/skills/gsd-path-plan/scripts/state_checkpoint.py +114 -72
  337. package/skills/gsd-path-plan/scripts/state_promote.py +47 -44
  338. package/skills/gsd-path-plan/scripts/workflow_run.py +128 -8
  339. package/skills/gsd-path-plan/scripts/worktree_paths.py +94 -0
  340. package/skills/gsd-path-plan/templates/task.md +2 -0
  341. package/skills/gsd-path-research/SKILL.md +5 -6
  342. package/skills/gsd-path-research/references/dispatch.md +12 -19
  343. package/skills/gsd-path-research/references/model-policy.md +139 -0
  344. package/skills/gsd-path-research/references/runtime-selection.md +25 -0
  345. package/skills/gsd-path-research/scripts/_common.py +5 -0
  346. package/skills/gsd-path-research/scripts/archive_milestone.py +2171 -0
  347. package/skills/gsd-path-research/scripts/build_recovery.py +292 -0
  348. package/skills/gsd-path-research/scripts/check_handoffs.py +7 -1
  349. package/skills/gsd-path-research/scripts/check_task_briefs.py +3 -0
  350. package/skills/gsd-path-research/scripts/detect_project.py +1536 -0
  351. package/skills/gsd-path-research/scripts/discussion_records.py +3 -0
  352. package/skills/gsd-path-research/scripts/discussion_validate.py +1326 -0
  353. package/skills/gsd-path-research/scripts/integration.py +1459 -0
  354. package/skills/gsd-path-research/scripts/isolation.py +24 -6
  355. package/skills/gsd-path-research/scripts/loop_run.py +839 -0
  356. package/skills/gsd-path-research/scripts/model_policy.py +279 -0
  357. package/skills/gsd-path-research/scripts/path_config.py +248 -0
  358. package/skills/gsd-path-research/scripts/pipeline_git.py +3 -0
  359. package/skills/gsd-path-research/scripts/pipeline_state.py +117 -186
  360. package/skills/gsd-path-research/scripts/promote_lookahead.py +286 -0
  361. package/skills/gsd-path-research/scripts/review_panel.py +564 -0
  362. package/skills/gsd-path-research/scripts/roadmap.py +326 -0
  363. package/skills/gsd-path-research/scripts/state_checkpoint.py +114 -72
  364. package/skills/gsd-path-research/scripts/state_promote.py +47 -44
  365. package/skills/gsd-path-research/scripts/worktree_paths.py +94 -0
  366. package/skills/gsd-path-roadmap/SKILL.md +24 -58
  367. package/skills/gsd-path-roadmap/references/dispatch.md +12 -19
  368. package/skills/gsd-path-roadmap/references/model-policy.md +139 -0
  369. package/skills/gsd-path-roadmap/references/runtime-selection.md +25 -0
  370. package/skills/gsd-path-roadmap/scripts/_common.py +5 -0
  371. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +30 -124
  372. package/skills/gsd-path-roadmap/scripts/build_recovery.py +292 -0
  373. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +7 -1
  374. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +3 -0
  375. package/skills/gsd-path-roadmap/scripts/detect_project.py +22 -3
  376. package/skills/gsd-path-roadmap/scripts/discussion_records.py +3 -0
  377. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +8 -3
  378. package/skills/gsd-path-roadmap/scripts/integration.py +54 -28
  379. package/skills/gsd-path-roadmap/scripts/isolation.py +24 -6
  380. package/skills/gsd-path-roadmap/scripts/loop_run.py +839 -0
  381. package/skills/gsd-path-roadmap/scripts/model_policy.py +279 -0
  382. package/skills/gsd-path-roadmap/scripts/path_config.py +248 -0
  383. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +3 -0
  384. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +117 -186
  385. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +33 -162
  386. package/skills/gsd-path-roadmap/scripts/review_panel.py +11 -0
  387. package/skills/gsd-path-roadmap/scripts/roadmap.py +326 -0
  388. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +114 -72
  389. package/skills/gsd-path-roadmap/scripts/state_promote.py +47 -44
  390. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +94 -0
  391. package/skills/gsd-path-ship/SKILL.md +29 -17
  392. package/skills/gsd-path-ship/references/dispatch.md +12 -19
  393. package/skills/gsd-path-ship/references/jev-review.md +82 -0
  394. package/skills/gsd-path-ship/references/model-policy.md +139 -0
  395. package/skills/gsd-path-ship/references/reviewer-final.md +21 -0
  396. package/skills/gsd-path-ship/references/reviewer-panel.md +17 -0
  397. package/skills/gsd-path-ship/references/reviewer-skeptic.md +20 -0
  398. package/skills/gsd-path-ship/references/reviewer-wave.md +89 -0
  399. package/skills/gsd-path-ship/references/reviewer.md +12 -148
  400. package/skills/gsd-path-ship/references/runtime-selection.md +25 -0
  401. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  402. package/skills/gsd-path-ship/scripts/_common.py +5 -0
  403. package/skills/gsd-path-ship/scripts/archive_milestone.py +30 -124
  404. package/skills/gsd-path-ship/scripts/build_recovery.py +292 -0
  405. package/skills/gsd-path-ship/scripts/build_state.py +2 -0
  406. package/skills/gsd-path-ship/scripts/check_handoffs.py +7 -1
  407. package/skills/gsd-path-ship/scripts/check_task_briefs.py +3 -0
  408. package/skills/gsd-path-ship/scripts/detect_project.py +1536 -0
  409. package/skills/gsd-path-ship/scripts/discussion_records.py +3 -0
  410. package/skills/gsd-path-ship/scripts/discussion_validate.py +8 -3
  411. package/skills/gsd-path-ship/scripts/integration.py +54 -28
  412. package/skills/gsd-path-ship/scripts/isolation.py +24 -6
  413. package/skills/gsd-path-ship/scripts/jev_review.py +138 -0
  414. package/skills/gsd-path-ship/scripts/lean_verification.py +3 -1
  415. package/skills/gsd-path-ship/scripts/loop_run.py +839 -0
  416. package/skills/gsd-path-ship/scripts/model_policy.py +279 -0
  417. package/skills/gsd-path-ship/scripts/path_config.py +248 -0
  418. package/skills/gsd-path-ship/scripts/pipeline_git.py +3 -0
  419. package/skills/gsd-path-ship/scripts/pipeline_state.py +117 -186
  420. package/skills/gsd-path-ship/scripts/promote_lookahead.py +286 -0
  421. package/skills/gsd-path-ship/scripts/review_panel.py +11 -0
  422. package/skills/gsd-path-ship/scripts/roadmap.py +326 -0
  423. package/skills/gsd-path-ship/scripts/state_checkpoint.py +114 -72
  424. package/skills/gsd-path-ship/scripts/state_promote.py +47 -44
  425. package/skills/gsd-path-ship/scripts/workflow_run.py +128 -8
  426. package/skills/gsd-path-ship/scripts/worktree_paths.py +94 -0
  427. package/skills/gsd-path-ship/templates/wave-review.md +1 -1
  428. package/skills/gsd-path-undo/SKILL.md +2 -0
  429. package/skills/gsd-path-undo/references/runtime-selection.md +25 -0
  430. package/skills/gsd-path-undo/scripts/_common.py +5 -0
  431. package/skills/gsd-path-undo/scripts/discussion_records.py +3 -0
  432. package/skills/gsd-path-undo/scripts/loop_run.py +839 -0
  433. package/skills/gsd-path-undo/scripts/model_policy.py +279 -0
  434. package/skills/gsd-path-undo/scripts/path_config.py +248 -0
  435. package/skills/gsd-path-undo/scripts/pipeline_undo.py +14 -7
  436. package/skills/gsd-path-undo/scripts/review_panel.py +564 -0
  437. package/skills/gsd-path-undo/scripts/worktree_paths.py +94 -0
  438. package/skills/path/BUILD.md +54 -575
  439. package/skills/path/DECIDE.md +4 -6
  440. package/skills/path/DEFINE.md +23 -21
  441. package/skills/path/DOCS-AUDIT.md +2 -0
  442. package/skills/path/INSPECT.md +32 -8
  443. package/skills/path/PLAN.md +29 -19
  444. package/skills/path/RESEARCH.md +5 -6
  445. package/skills/path/ROADMAP.md +24 -58
  446. package/skills/path/SHIP.md +29 -17
  447. package/skills/path/SKILL.md +46 -22
  448. package/skills/path/references/build-abandon.md +33 -0
  449. package/skills/path/references/build-native.md +502 -0
  450. package/skills/path/references/build-recovery.md +78 -0
  451. package/skills/path/references/coder.md +8 -3
  452. package/skills/path/references/config.md +57 -0
  453. package/skills/path/references/dispatch.md +12 -19
  454. package/skills/path/references/docs-auditor.md +14 -0
  455. package/skills/path/references/jev-review.md +82 -0
  456. package/skills/path/references/model-policy.md +139 -0
  457. package/skills/path/references/reviewer-final.md +21 -0
  458. package/skills/path/references/reviewer-panel.md +17 -0
  459. package/skills/path/references/reviewer-skeptic.md +20 -0
  460. package/skills/path/references/reviewer-wave.md +89 -0
  461. package/skills/path/references/reviewer.md +12 -148
  462. package/skills/path/references/runtime-selection.md +25 -0
  463. package/skills/path/scripts/_common.py +5 -0
  464. package/skills/path/scripts/archive_milestone.py +30 -124
  465. package/skills/path/scripts/bootstrap_repository.py +33 -4
  466. package/skills/path/scripts/build_recovery.py +292 -0
  467. package/skills/path/scripts/build_state.py +2 -0
  468. package/skills/path/scripts/check_docs_audit.py +7 -3
  469. package/skills/path/scripts/check_handoffs.py +7 -1
  470. package/skills/path/scripts/check_task_briefs.py +3 -0
  471. package/skills/path/scripts/detect_project.py +22 -3
  472. package/skills/path/scripts/discussion_records.py +3 -0
  473. package/skills/path/scripts/discussion_validate.py +8 -3
  474. package/skills/path/scripts/dispatch_driver.py +233 -22
  475. package/skills/path/scripts/git_guard.py +768 -0
  476. package/skills/path/scripts/integration.py +54 -28
  477. package/skills/path/scripts/isolation.py +24 -6
  478. package/skills/path/scripts/jev_review.py +138 -0
  479. package/skills/path/scripts/lean_verification.py +3 -1
  480. package/skills/path/scripts/loop_run.py +2 -0
  481. package/skills/path/scripts/model_policy.py +279 -0
  482. package/skills/path/scripts/path_config.py +248 -0
  483. package/skills/path/scripts/pipeline_git.py +3 -0
  484. package/skills/path/scripts/pipeline_state.py +117 -186
  485. package/skills/path/scripts/promote_lookahead.py +33 -162
  486. package/skills/path/scripts/review_panel.py +11 -0
  487. package/skills/path/scripts/roadmap.py +326 -0
  488. package/skills/path/scripts/state_checkpoint.py +114 -72
  489. package/skills/path/scripts/state_promote.py +47 -44
  490. package/skills/path/scripts/status_runtime.py +208 -0
  491. package/skills/path/scripts/task_context.py +73 -0
  492. package/skills/path/scripts/token_budget.py +40 -1
  493. package/skills/path/scripts/workflow_run.py +128 -8
  494. package/skills/path/scripts/worktree_paths.py +94 -0
  495. package/skills/path/templates/skeptic.md +1 -1
  496. package/skills/path/templates/task.md +2 -0
  497. package/skills/path/templates/wave-panel.md +1 -1
  498. package/skills/path/templates/wave-review.md +1 -1
@@ -19,6 +19,9 @@ import shutil
19
19
  import stat
20
20
  import subprocess
21
21
  import sys
22
+
23
+ # Runtime helpers must not modify their immutable installation.
24
+ sys.dont_write_bytecode = True
22
25
  from dataclasses import asdict, dataclass
23
26
  from datetime import date
24
27
  from pathlib import Path, PurePosixPath
@@ -32,8 +35,9 @@ try:
32
35
  collect_artifact_recoveries,
33
36
  )
34
37
  import _common
38
+ import roadmap
35
39
  except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
36
- if error.name not in {"isolation", "_common"}:
40
+ if error.name not in {"isolation", "_common", "roadmap"}:
37
41
  raise
38
42
  from scripts.isolation import (
39
43
  IsolationError,
@@ -41,7 +45,7 @@ except ModuleNotFoundError as error: # pragma: no cover - package imports used
41
45
  checkpoint as isolation_checkpoint,
42
46
  collect_artifact_recoveries,
43
47
  )
44
- from scripts import _common
48
+ from scripts import _common, roadmap
45
49
 
46
50
  try: # pragma: no cover - exercised only on Windows
47
51
  import fcntl
@@ -82,7 +86,6 @@ SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
82
86
  BOUND_BRANCH_RE = _common.BOUND_BRANCH_RE
83
87
  ARCHIVE_RE = re.compile(r"^\.project/archive/(\d{3,})-([a-z0-9][a-z0-9-]*)/?$")
84
88
  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
89
  TASK_ID_RE = re.compile(r"^T\d{3,}$")
87
90
  TASK_FILE_RE = re.compile(r"^(T\d{3,})-[a-z0-9][a-z0-9-]*\.md$")
88
91
  PLAN_APPROVAL_SUBJECT = "plan: build plan approved"
@@ -110,7 +113,7 @@ LOOKAHEAD_EVIDENCE_RE = re.compile(r"^research/evidence-[a-z0-9][a-z0-9-]*\.md$"
110
113
  PROMOTION_RESIDUAL = ".gsd-path-promote-next-residual"
111
114
  CHECKPOINT_SCHEMA = "gsd-path/state-checkpoint/v1"
112
115
  CHECKPOINT_JOURNAL_NAME = "gsd-path-state-checkpoint.json"
113
- CHECKPOINT_KINDS = ("plan", "roadmap")
116
+ CHECKPOINT_KINDS = ("plan", "roadmap", "roadmap-reslice")
114
117
  SHIPMENT_SCHEMA = "gsd-path/shipment/v1"
115
118
  SHIPMENT_JOURNAL_NAME = "gsd-path-shipment.json"
116
119
  UNDO_TRANSACTION_SCHEMA = "gsd-path/undo-transaction/v2"
@@ -126,6 +129,8 @@ CROSS_PHASE_TRANSITIONS = {
126
129
  ("decide", "done", "plan", "active"),
127
130
  ("roadmap", "done", "define", "active"),
128
131
  ("plan", "done", "build", "active"),
132
+ ("build", "blocked", "define", "active"),
133
+ ("build", "blocked", "plan", "active"),
129
134
  ("build", "active", "ship", "active"),
130
135
  ("build", "done", "ship", "active"),
131
136
  ("ship", "active", "shipped", "done"),
@@ -166,99 +171,10 @@ class ApprovedTaskContract:
166
171
  files: tuple[str, ...]
167
172
 
168
173
 
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
- )
174
+ # Standalone transaction imports must reuse this state module and its types.
175
+ if __name__ == "__main__":
176
+ sys.modules.setdefault("pipeline_state", sys.modules[__name__])
177
+
262
178
 
263
179
  def _run_git(
264
180
  repo: Path,
@@ -693,6 +609,21 @@ def _next_skill(route: Mapping[str, object]) -> Optional[str]:
693
609
  return None
694
610
 
695
611
 
612
+ def _completion_status(repo: Path, state: Mapping[str, object], project_dir: str) -> dict:
613
+ if project_dir != ".project" or state.get("phase") != "shipped":
614
+ return {"status": "not-shipped"}
615
+ if __package__:
616
+ from . import integration
617
+ else:
618
+ import integration
619
+ try:
620
+ proof = integration.validate_integrated(
621
+ repo, str(state.get("milestone") or ""), refresh=False, historical=True)
622
+ except (integration.ArchiveError, OSError) as error:
623
+ return {"status": "unverified", "reason": str(error)}
624
+ return {"status": "verified", "proof": proof}
625
+
626
+
696
627
  def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
697
628
  """Report owned state, route, and git facts without advancing a phase."""
698
629
  resolved = _repo_root(repo)
@@ -726,9 +657,11 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
726
657
  "undo": None,
727
658
  "collect_artifact": None,
728
659
  }
660
+ completion = _completion_status(resolved, state, project_dir)
729
661
  return {
730
662
  "schema": STATUS_SCHEMA,
731
663
  "advance": False,
664
+ "completion": completion,
732
665
  "state": state,
733
666
  "route": route,
734
667
  "path": str(_track_root(resolved, project_dir) / "STATE.md"),
@@ -753,6 +686,28 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
753
686
  "lookahead": lookahead.exists() or lookahead.is_symlink(),
754
687
  "journals": journals,
755
688
  "next_skill": _next_skill(route if isinstance(route, dict) else {}),
689
+ "handoff": phase_handoff(state, route, _track_root(resolved, project_dir) / "STATE.md", completion),
690
+ }
691
+
692
+
693
+ def phase_handoff(state: Mapping[str, object], route: Mapping[str, object], path: Path,
694
+ completion: Mapping[str, object]) -> dict[str, str]:
695
+ """Present the authoritative route without granting continuation authority."""
696
+ action = route["action"]
697
+ if action == "run-phase":
698
+ next_action = f"Invoke $gsd-path to continue with {route['phase']}."
699
+ router_next = f"Continue with {route['phase']}; honor its input and approval gates."
700
+ else:
701
+ next_action = router_next = f"{action}: {route['reason']}"
702
+ outcome = f"{state['phase']}/{state['status']}"
703
+ if completion["status"] == "unverified":
704
+ outcome = f"Unverified: {outcome}"
705
+ return {
706
+ "outcome": outcome,
707
+ "review": str(path),
708
+ "next": next_action,
709
+ "phase_next": next_action,
710
+ "router_next": router_next,
756
711
  }
757
712
 
758
713
 
@@ -784,50 +739,11 @@ def _intent_lane(track: Path) -> Optional[str]:
784
739
 
785
740
 
786
741
  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
742
  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
743
  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
-
744
+ return roadmap.has_questions(text, milestone)
745
+ except roadmap.RoadmapError as error:
746
+ raise PipelineStateError(str(error)) from error
831
747
 
832
748
  def _valid_patch_findings(repo: Path) -> bool:
833
749
  validator = Path(__file__).resolve().with_name("check_handoffs.py")
@@ -1106,6 +1022,14 @@ def route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
1106
1022
  """Route ordinary phase work only when its pending discussion owner can enter."""
1107
1023
  result = _route_state(repo, project_dir)
1108
1024
  route = result["route"]
1025
+ if project_dir == ".project" and route["action"] == "run-phase":
1026
+ recovery = _build_recovery().context(_repo_root(repo))
1027
+ if recovery and recovery["active"]:
1028
+ result["recovery"] = recovery
1029
+ if route.get("phase") == "define":
1030
+ route["mode"] = "corrections"
1031
+ elif route.get("phase") == "plan":
1032
+ route["mode"] = "build-repair"
1109
1033
  if route["action"] == "run-phase" and result["state"]["archive"] is None:
1110
1034
  reason = _pending_discussion_block(_repo_root(repo), route.get("phase"))
1111
1035
  if reason:
@@ -1159,7 +1083,11 @@ def _route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
1159
1083
  return result
1160
1084
  checkpoint_journal = _git_path(resolved, CHECKPOINT_JOURNAL_NAME)
1161
1085
  if checkpoint_journal.exists() or checkpoint_journal.is_symlink():
1162
- transaction = _approval_journal(
1086
+ if __package__:
1087
+ from . import state_checkpoint
1088
+ else:
1089
+ import state_checkpoint
1090
+ transaction = state_checkpoint._approval_journal(
1163
1091
  resolved,
1164
1092
  _read_json(checkpoint_journal),
1165
1093
  )
@@ -1736,6 +1664,16 @@ def transition_state(
1736
1664
  event,
1737
1665
  project_dir,
1738
1666
  )
1667
+ recovery_context = _build_recovery().context(resolved, text) if project_dir == ".project" else None
1668
+ if recovery_context and recovery_context["active"]:
1669
+ if (state.milestone, state.branch, state.archive) != (after.milestone, after.branch, after.archive):
1670
+ raise PipelineStateError("build recovery must preserve milestone identity")
1671
+ if state.phase == "build" and after.phase in {"define", "plan"}:
1672
+ recovery = _build_recovery().begin(resolved, state, after, event)
1673
+ rendered = _append_event(
1674
+ rendered, after.phase,
1675
+ _build_recovery().MARKER + json.dumps(recovery, sort_keys=True),
1676
+ )
1739
1677
  if after.status != "blocked":
1740
1678
  reason = _pending_discussion_block(
1741
1679
  resolved, after.phase if after.status == "active" else None
@@ -1767,6 +1705,14 @@ def transition_state(
1767
1705
  }
1768
1706
 
1769
1707
 
1708
+ def _build_recovery():
1709
+ if __package__:
1710
+ from scripts import build_recovery
1711
+ else:
1712
+ import build_recovery
1713
+ return build_recovery
1714
+
1715
+
1770
1716
  def configure_integration(
1771
1717
  repo: Path,
1772
1718
  scope: str,
@@ -1786,7 +1732,9 @@ def configure_integration(
1786
1732
  project = _track_root(resolved, project_dir)
1787
1733
  with _state_lock(project):
1788
1734
  state, text, path = load_state(resolved, project_dir)
1789
- if state.phase in {"build", "ship", "shipped"}:
1735
+ if state.phase in {"build", "ship", "shipped"} or (
1736
+ project_dir == ".project" and _build_recovery().context(resolved, text)
1737
+ ):
1790
1738
  raise PipelineStateError("integration mode is locked when build starts")
1791
1739
  if scope == "default":
1792
1740
  integration = (
@@ -2022,49 +1970,18 @@ def _render_transition(
2022
1970
 
2023
1971
 
2024
1972
  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
-
1973
+ try:
1974
+ return roadmap.strict_sections(text)
1975
+ except roadmap.RoadmapError as error:
1976
+ raise PipelineStateError(str(error)) from error
2041
1977
 
2042
1978
  def _replace_roadmap_field(
2043
- lines: list[str],
2044
- start: int,
2045
- end: int,
2046
- field: str,
2047
- expected: set[str],
2048
- value: str,
1979
+ lines: list[str], start: int, end: int, field: str, expected: set[str], value: str,
2049
1980
  ) -> 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
-
1981
+ try:
1982
+ return roadmap.replace_field(lines, start, end, field, expected, value)
1983
+ except roadmap.RoadmapError as error:
1984
+ raise PipelineStateError(str(error)) from error
2068
1985
 
2069
1986
  def _git_path(repo: Path, name: str) -> Path:
2070
1987
  value = _run_git(repo, "rev-parse", "--git-path", name).stdout.strip()
@@ -2163,7 +2080,7 @@ def _specified_fields(arguments: argparse.Namespace, prefix: str) -> dict[str, O
2163
2080
  def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
2164
2081
  parser = argparse.ArgumentParser(description=__doc__)
2165
2082
  subparsers = parser.add_subparsers(dest="command", required=True)
2166
- for command in ("validate", "route", "status"):
2083
+ for command in ("validate", "route", "status", "prepare-build-recovery"):
2167
2084
  subparser = subparsers.add_parser(command)
2168
2085
  subparser.add_argument("--repo", required=True, type=Path)
2169
2086
  subparser.add_argument("--project-dir", default=".project")
@@ -2204,6 +2121,16 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
2204
2121
 
2205
2122
  def main(argv: Optional[Sequence[str]] = None) -> int:
2206
2123
  args = parse_args(argv)
2124
+ if args.command in {"approve", "resume-checkpoint"}:
2125
+ if __package__:
2126
+ from . import state_checkpoint
2127
+ else:
2128
+ import state_checkpoint
2129
+ elif args.command == "promote-next":
2130
+ if __package__:
2131
+ from . import state_promote
2132
+ else:
2133
+ import state_promote
2207
2134
  try:
2208
2135
  if args.command == "validate":
2209
2136
  result = validate_state(args.repo, args.project_dir)
@@ -2211,6 +2138,10 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2211
2138
  result = route_state(args.repo, args.project_dir)
2212
2139
  elif args.command == "status":
2213
2140
  result = status_state(args.repo, args.project_dir)
2141
+ elif args.command == "prepare-build-recovery":
2142
+ if args.project_dir != ".project":
2143
+ raise PipelineStateError("build recovery requires the active track")
2144
+ result = _build_recovery().prepare(args.repo)
2214
2145
  elif args.command == "transition":
2215
2146
  result = transition_state(
2216
2147
  args.repo,
@@ -2224,7 +2155,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2224
2155
  raise PipelineStateError(
2225
2156
  "--expected-head is not accepted with --defer-checkpoint or --patch"
2226
2157
  )
2227
- result = defer_approval(
2158
+ result = state_checkpoint.defer_approval(
2228
2159
  args.repo,
2229
2160
  args.kind,
2230
2161
  args.project_dir,
@@ -2236,7 +2167,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2236
2167
  raise PipelineStateError(
2237
2168
  "approve requires --expected-head unless --defer-checkpoint or --patch"
2238
2169
  )
2239
- result = checkpoint_approval(
2170
+ result = state_checkpoint.checkpoint_approval(
2240
2171
  args.repo,
2241
2172
  args.kind,
2242
2173
  args.expected_head,
@@ -2244,7 +2175,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2244
2175
  args.milestone,
2245
2176
  )
2246
2177
  elif args.command == "resume-checkpoint":
2247
- result = resume_checkpoint(args.repo)
2178
+ result = state_checkpoint.resume_checkpoint(args.repo)
2248
2179
  elif args.command == "promote-next":
2249
2180
  if args.integrate is not None and (
2250
2181
  args.base is not None or args.landing is not None
@@ -2262,7 +2193,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
2262
2193
  raise PipelineStateError(
2263
2194
  "promote-next requires --base or legacy --integrate"
2264
2195
  )
2265
- result = promote_next(
2196
+ result = state_promote.promote_next(
2266
2197
  args.repo,
2267
2198
  args.milestone,
2268
2199
  args.branch,
@@ -17,6 +17,9 @@ import os
17
17
  import re
18
18
  import shutil
19
19
  import sys
20
+
21
+ # Runtime helpers must not modify their immutable installation.
22
+ sys.dont_write_bytecode = True
20
23
  import tempfile
21
24
  from pathlib import Path, PurePosixPath
22
25
  from typing import Optional, Sequence
@@ -27,18 +30,20 @@ def _load_pipeline_modules():
27
30
  import isolation
28
31
  import pipeline_git
29
32
  import pipeline_state
30
- return archive_milestone, isolation, pipeline_git, pipeline_state
33
+ import state_checkpoint
34
+ return archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
31
35
  except ModuleNotFoundError as error:
32
36
  if error.name not in {
33
37
  "archive_milestone",
34
38
  "isolation",
35
39
  "pipeline_git",
36
40
  "pipeline_state",
41
+ "state_checkpoint",
37
42
  }:
38
43
  raise
39
44
  try:
40
- from scripts import archive_milestone, isolation, pipeline_git, pipeline_state
41
- return archive_milestone, isolation, pipeline_git, pipeline_state
45
+ from scripts import archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
46
+ return archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
42
47
  except ModuleNotFoundError as error:
43
48
  if error.name not in {
44
49
  "scripts",
@@ -46,6 +51,7 @@ def _load_pipeline_modules():
46
51
  "scripts.isolation",
47
52
  "scripts.pipeline_git",
48
53
  "scripts.pipeline_state",
54
+ "scripts.state_checkpoint",
49
55
  }:
50
56
  raise
51
57
  shared = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
@@ -54,16 +60,17 @@ def _load_pipeline_modules():
54
60
  import isolation
55
61
  import pipeline_git
56
62
  import pipeline_state
57
- return archive_milestone, isolation, pipeline_git, pipeline_state
63
+ import state_checkpoint
64
+ return archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
58
65
 
59
66
 
60
- archive_milestone, isolation, pipeline_git, pipeline_state = _load_pipeline_modules()
67
+ archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint = _load_pipeline_modules()
61
68
  ArchiveError = archive_milestone.ArchiveError
62
69
  IsolationError = isolation.IsolationError
63
70
  PLAN_APPROVAL_SUBJECT = pipeline_state.PLAN_APPROVAL_SUBJECT
64
71
  PipelineStateError = pipeline_state.PipelineStateError
65
- _activate_roadmap_milestone = pipeline_state._activate_roadmap_milestone
66
- _approval_details = pipeline_state._approval_details
72
+ _activate_roadmap_milestone = state_checkpoint._activate_roadmap_milestone
73
+ _approval_details = state_checkpoint._approval_details
67
74
  _commit_subject_body = pipeline_state._commit_subject_body
68
75
  _optional_rev = pipeline_state._optional_rev
69
76
  _render_transition = pipeline_state._render_transition