@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
@@ -4,6 +4,11 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ import sys
8
+
9
+ # Runtime helpers must not modify their immutable installation.
10
+ sys.dont_write_bytecode = True
11
+
7
12
  import hashlib
8
13
  import json
9
14
  import os
@@ -20,6 +25,43 @@ except ModuleNotFoundError as error: # pragma: no cover - package imports used
20
25
  from scripts.isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
21
26
 
22
27
 
28
+ if __package__:
29
+ from . import roadmap
30
+ else:
31
+ import roadmap
32
+
33
+ if __package__: # imported as scripts.state_checkpoint
34
+ from . import pipeline_state
35
+ from .pipeline_state import (
36
+ CHECKPOINT_JOURNAL_NAME,
37
+ CHECKPOINT_KINDS,
38
+ CHECKPOINT_SCHEMA,
39
+ PLAN_APPROVAL_SUBJECT,
40
+ PROMOTION_TRACKS,
41
+ SLUG_RE,
42
+ TASK_FILE_RE,
43
+ TASK_ID_RE,
44
+ ApprovedTaskContract,
45
+ PipelineState,
46
+ PipelineStateError,
47
+ )
48
+ else: # standalone script or sibling import
49
+ import pipeline_state
50
+ from pipeline_state import (
51
+ CHECKPOINT_JOURNAL_NAME,
52
+ CHECKPOINT_KINDS,
53
+ CHECKPOINT_SCHEMA,
54
+ PLAN_APPROVAL_SUBJECT,
55
+ PROMOTION_TRACKS,
56
+ SLUG_RE,
57
+ TASK_FILE_RE,
58
+ TASK_ID_RE,
59
+ ApprovedTaskContract,
60
+ PipelineState,
61
+ PipelineStateError,
62
+ )
63
+
64
+
23
65
  def _sha256(content: str) -> str:
24
66
  return hashlib.sha256(content.encode("utf-8")).hexdigest()
25
67
 
@@ -65,41 +107,29 @@ def _checkpoint_artifact_digest(project: Path, mutable_paths: set[str]) -> str:
65
107
  return digest.hexdigest()
66
108
 
67
109
 
68
- def _roadmap_status(lines: list[str], start: int, end: int) -> str:
69
- values = []
70
- for line in lines[start:end]:
71
- match = re.fullmatch(r"Status:\s*(\S+)\s*", line.rstrip("\r\n"))
72
- if match:
73
- values.append(match.group(1))
74
- if len(values) != 1:
75
- raise PipelineStateError("ROADMAP.md milestone must have one Status field")
76
- return values[0]
77
-
78
-
79
110
  def _activate_roadmap_milestone(text: str, milestone: str) -> str:
80
- sections = pipeline_state._roadmap_sections(text)
81
- if milestone not in sections:
82
- raise PipelineStateError(f"ROADMAP.md is missing selected milestone: {milestone}")
83
- lines = text.splitlines(keepends=True)
84
- active = [
85
- slug
86
- for slug, (_, start, end) in sections.items()
87
- if _roadmap_status(lines, start, end) == "active"
88
- ]
89
- if active:
90
- raise PipelineStateError(
91
- "ROADMAP.md already has an active milestone: " + ", ".join(active)
92
- )
93
- _, start, end = sections[milestone]
94
- pipeline_state._replace_roadmap_field(lines, start, end, "Status", {"pending"}, "active")
95
- return "".join(lines)
96
-
111
+ try:
112
+ return roadmap.activate_milestone(text, milestone)
113
+ except roadmap.RoadmapError as error:
114
+ raise PipelineStateError(str(error)) from error
97
115
 
98
116
  def _approval_details(
99
117
  kind: str,
100
118
  state: PipelineState,
101
119
  selected_milestone: Optional[str],
102
120
  ) -> tuple[dict[str, Optional[str]], str, str, str]:
121
+ if kind == "roadmap-reslice":
122
+ if state.status != "active" or state.archive is not None:
123
+ raise PipelineStateError("roadmap re-slice requires active, unarchived state")
124
+ if state.phase in {"inspect", "define"} and selected_milestone == state.milestone and state.milestone:
125
+ changes = {}
126
+ event = "program roadmap re-slice approved"
127
+ elif state.phase == "roadmap" and state.milestone is None and selected_milestone and SLUG_RE.fullmatch(selected_milestone):
128
+ changes = {"phase": "inspect", "milestone": selected_milestone}
129
+ event = "roadmap approved after abandoned milestone"
130
+ else:
131
+ raise PipelineStateError("roadmap re-slice must preserve the active milestone or select after abandon")
132
+ return changes, event, "roadmap: program roadmap approved", "Why: approved roadmap checkpoint"
103
133
  if kind == "plan":
104
134
  if selected_milestone is not None:
105
135
  raise PipelineStateError("plan approval does not accept a selected milestone")
@@ -126,6 +156,12 @@ def _approval_details(
126
156
  raise PipelineStateError(f"unsupported approval kind: {kind}")
127
157
 
128
158
 
159
+ def _reslice_roadmap(before: str, candidate: str, state: PipelineState, selected: str) -> str:
160
+ try:
161
+ return roadmap.reslice(before, candidate, state.phase, selected)
162
+ except roadmap.RoadmapError as error:
163
+ raise PipelineStateError(str(error)) from error
164
+
129
165
  def _checkpoint_request_fields(
130
166
  kind: str,
131
167
  project_dir: str,
@@ -175,6 +211,10 @@ def _approval_journal(repo: Path, journal: Mapping[str, object]) -> dict[str, ob
175
211
  "roadmap_before",
176
212
  "roadmap_after",
177
213
  }
214
+ if journal.get("kind") == "roadmap-reslice":
215
+ expected_keys.add("baseline_before")
216
+ if not isinstance(journal.get("baseline_before"), str):
217
+ raise PipelineStateError("checkpoint journal has an invalid re-slice baseline")
178
218
  if set(journal) != expected_keys:
179
219
  raise PipelineStateError("checkpoint journal has invalid fields")
180
220
  if journal.get("schema") != CHECKPOINT_SCHEMA or journal.get("repo") != str(repo):
@@ -253,12 +293,14 @@ def _approval_journal(repo: Path, journal: Mapping[str, object]) -> dict[str, ob
253
293
  or journal["state_after"] != rendered
254
294
  ):
255
295
  raise PipelineStateError("checkpoint journal approval contract is invalid")
256
- if str(journal["kind"]) == "roadmap":
296
+ if journal["kind"] in {"roadmap", "roadmap-reslice"}:
257
297
  if project_dir != ".project":
258
298
  raise PipelineStateError("roadmap approval is legal only on the active track")
259
299
  if journal["roadmap_path"] != ".project/ROADMAP.md":
260
300
  raise PipelineStateError("checkpoint journal has an invalid ROADMAP path")
261
- expected_roadmap = _activate_roadmap_milestone(
301
+ expected_roadmap = _reslice_roadmap(
302
+ str(journal["baseline_before"]), str(journal["roadmap_before"]), before, str(selected),
303
+ ) if journal["kind"] == "roadmap-reslice" else _activate_roadmap_milestone(
262
304
  str(journal["roadmap_before"]),
263
305
  str(selected),
264
306
  )
@@ -307,6 +349,12 @@ def _resume_checkpoint_locked(
307
349
  transaction = _approval_journal(repo, journal)
308
350
  state_path = _checkpoint_file(repo, str(transaction["state_path"]), "STATE.md")
309
351
  mutable = {state_path.relative_to(project).as_posix()}
352
+ baseline = project / "ROADMAP.before-reslice.md" if transaction["kind"] == "roadmap-reslice" else None
353
+ if baseline is not None:
354
+ mutable.add(baseline.name)
355
+ if baseline.exists() or baseline.is_symlink():
356
+ if pipeline_state._read_real_file(baseline, "re-slice baseline") != transaction["baseline_before"]:
357
+ raise PipelineStateError("re-slice baseline drifted during checkpoint recovery")
310
358
  roadmap_path: Optional[Path] = None
311
359
  if transaction["roadmap_path"] is not None:
312
360
  roadmap_path = _checkpoint_file(
@@ -354,6 +402,8 @@ def _resume_checkpoint_locked(
354
402
  raise PipelineStateError("completed checkpoint has the wrong ROADMAP.md")
355
403
 
356
404
  try:
405
+ if baseline is not None and baseline.exists():
406
+ baseline.unlink()
357
407
  committed = isolation_checkpoint(
358
408
  repo,
359
409
  expected_head,
@@ -362,6 +412,8 @@ def _resume_checkpoint_locked(
362
412
  [".project"],
363
413
  )
364
414
  except IsolationError as error:
415
+ if baseline is not None and pipeline_state._run_git(repo, "rev-parse", "HEAD").stdout.strip() == expected_head:
416
+ pipeline_state._atomic_write(baseline, str(transaction["baseline_before"]))
365
417
  raise PipelineStateError(f"approval checkpoint failed: {error}") from error
366
418
  if committed.get("commit") != pipeline_state._run_git(repo, "rev-parse", "HEAD").stdout.strip():
367
419
  raise PipelineStateError("approval checkpoint returned the wrong commit")
@@ -381,6 +433,8 @@ def _resume_checkpoint_locked(
381
433
  def _validate_plan_briefs(repo: Path, kind: str, project_dir: str) -> None:
382
434
  if kind != "plan":
383
435
  return
436
+ if project_dir == ".project":
437
+ pipeline_state._build_recovery().validate_plan(repo)
384
438
  head = pipeline_state._run_git(repo, "rev-parse", "--verify", "HEAD", check=False)
385
439
  if head.returncode != 0:
386
440
  # Pre-Git approval defers base-dependent checks to build.
@@ -476,6 +530,8 @@ def checkpoint_approval(
476
530
  state, state_before, state_path = pipeline_state.load_state(resolved, project_dir)
477
531
  changes, event, subject, body = _approval_details(kind, state, selected_milestone)
478
532
  _validate_plan_briefs(resolved, kind, project_dir)
533
+ if kind == "plan" and project_dir == ".project":
534
+ pipeline_state._build_recovery().restore_unchanged_reviews(resolved)
479
535
  expected = {
480
536
  "phase": state.phase,
481
537
  "status": state.status,
@@ -497,13 +553,18 @@ def checkpoint_approval(
497
553
  roadmap_path: Optional[Path] = None
498
554
  roadmap_before: Optional[str] = None
499
555
  roadmap_after: Optional[str] = None
500
- if kind == "roadmap":
556
+ baseline_before = None
557
+ if kind in {"roadmap", "roadmap-reslice"}:
501
558
  if project_dir != ".project":
502
559
  raise PipelineStateError("roadmap approval is legal only on the active track")
503
560
  assert selected_milestone is not None
504
561
  roadmap_path = project / "ROADMAP.md"
505
562
  roadmap_before = pipeline_state._read_real_file(roadmap_path, "ROADMAP.md")
506
- roadmap_after = _activate_roadmap_milestone(
563
+ if kind == "roadmap-reslice":
564
+ baseline_before = pipeline_state._read_real_file(project / "ROADMAP.before-reslice.md", "re-slice baseline")
565
+ roadmap_after = _reslice_roadmap(
566
+ baseline_before, roadmap_before, state, selected_milestone,
567
+ ) if kind == "roadmap-reslice" else _activate_roadmap_milestone(
507
568
  roadmap_before,
508
569
  selected_milestone,
509
570
  )
@@ -512,6 +573,8 @@ def checkpoint_approval(
512
573
  mutable = {state_relative}
513
574
  if roadmap_path is not None:
514
575
  mutable.add(roadmap_path.relative_to(project).as_posix())
576
+ if baseline_before is not None:
577
+ mutable.add("ROADMAP.before-reslice.md")
515
578
  journal: dict[str, object] = {
516
579
  "schema": CHECKPOINT_SCHEMA,
517
580
  "repo": str(resolved),
@@ -528,6 +591,8 @@ def checkpoint_approval(
528
591
  "roadmap_before": roadmap_before,
529
592
  "roadmap_after": roadmap_after,
530
593
  }
594
+ if baseline_before is not None:
595
+ journal["baseline_before"] = baseline_before
531
596
  pipeline_state._write_json(journal_path, journal)
532
597
  return _resume_checkpoint_locked(resolved, project, journal_path, journal)
533
598
 
@@ -576,6 +641,10 @@ def defer_approval(
576
641
  with pipeline_state._state_lock(project):
577
642
  state, state_before, state_path = pipeline_state.load_state(resolved, project_dir)
578
643
  changes, event, _, _ = _approval_details(kind, state, selected_milestone)
644
+ if project_dir == ".project":
645
+ recovery = pipeline_state._build_recovery().context(resolved, state_before)
646
+ if recovery and recovery["active"]:
647
+ raise PipelineStateError("build recovery requires a plan checkpoint")
579
648
  _validate_plan_briefs(resolved, kind, project_dir)
580
649
  if patch:
581
650
  event = "patch plan approved"
@@ -595,17 +664,25 @@ def defer_approval(
595
664
  project_dir,
596
665
  approval_kind=kind,
597
666
  )
598
- if kind == "roadmap":
667
+ baseline = None
668
+ if kind in {"roadmap", "roadmap-reslice"}:
599
669
  if project_dir != ".project":
600
670
  raise PipelineStateError("roadmap approval is legal only on the active track")
601
671
  assert selected_milestone is not None
602
672
  roadmap_path = project / "ROADMAP.md"
603
- roadmap_after = _activate_roadmap_milestone(
604
- pipeline_state._read_real_file(roadmap_path, "ROADMAP.md"),
605
- selected_milestone,
606
- )
673
+ roadmap_before = pipeline_state._read_real_file(roadmap_path, "ROADMAP.md")
674
+ if kind == "roadmap-reslice":
675
+ baseline = project / "ROADMAP.before-reslice.md"
676
+ roadmap_after = _reslice_roadmap(
677
+ pipeline_state._read_real_file(baseline, "re-slice baseline"),
678
+ roadmap_before, state, selected_milestone,
679
+ )
680
+ else:
681
+ roadmap_after = _activate_roadmap_milestone(roadmap_before, selected_milestone)
607
682
  pipeline_state._atomic_write(roadmap_path, roadmap_after)
608
683
  pipeline_state._atomic_write(state_path, state_after)
684
+ if baseline is not None:
685
+ baseline.unlink()
609
686
  return {
610
687
  "schema": CHECKPOINT_SCHEMA,
611
688
  "status": "approved",
@@ -1002,38 +1079,3 @@ def _classify_plan_drift(
1002
1079
  "contract_paths": sorted(contract_paths),
1003
1080
  "reason": "; ".join(reasons) if reasons else "approval contracts and declared paths are unchanged",
1004
1081
  }
1005
-
1006
-
1007
- # pipeline_state imports this module, so the parent is resolved after the
1008
- # definitions above. Parent functions are looked up on the module at call time
1009
- # so patches applied to pipeline_state stay visible here.
1010
- if __package__: # imported as scripts.state_checkpoint
1011
- from . import pipeline_state
1012
- from .pipeline_state import (
1013
- CHECKPOINT_JOURNAL_NAME,
1014
- CHECKPOINT_KINDS,
1015
- CHECKPOINT_SCHEMA,
1016
- PLAN_APPROVAL_SUBJECT,
1017
- PROMOTION_TRACKS,
1018
- SLUG_RE,
1019
- TASK_FILE_RE,
1020
- TASK_ID_RE,
1021
- ApprovedTaskContract,
1022
- PipelineState,
1023
- PipelineStateError,
1024
- )
1025
- else: # standalone script or sibling import
1026
- import pipeline_state
1027
- from pipeline_state import (
1028
- CHECKPOINT_JOURNAL_NAME,
1029
- CHECKPOINT_KINDS,
1030
- CHECKPOINT_SCHEMA,
1031
- PLAN_APPROVAL_SUBJECT,
1032
- PROMOTION_TRACKS,
1033
- SLUG_RE,
1034
- TASK_FILE_RE,
1035
- TASK_ID_RE,
1036
- ApprovedTaskContract,
1037
- PipelineState,
1038
- PipelineStateError,
1039
- )
@@ -4,6 +4,11 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ import sys
8
+
9
+ # Runtime helpers must not modify their immutable installation.
10
+ sys.dont_write_bytecode = True
11
+
7
12
  import json
8
13
  import re
9
14
  import shutil
@@ -11,6 +16,31 @@ from pathlib import Path, PurePosixPath
11
16
  from typing import Mapping, Optional
12
17
 
13
18
 
19
+ if __package__: # imported as scripts.state_promote
20
+ from . import pipeline_state, state_checkpoint
21
+ from .pipeline_state import (
22
+ NULL,
23
+ PROMOTION_RESIDUAL,
24
+ PROMOTION_SCHEMA,
25
+ PROMOTION_TRACKS,
26
+ SLUG_RE,
27
+ PipelineState,
28
+ PipelineStateError,
29
+ )
30
+ else: # standalone script or sibling import
31
+ import pipeline_state
32
+ import state_checkpoint
33
+ from pipeline_state import (
34
+ NULL,
35
+ PROMOTION_RESIDUAL,
36
+ PROMOTION_SCHEMA,
37
+ PROMOTION_TRACKS,
38
+ SLUG_RE,
39
+ PipelineState,
40
+ PipelineStateError,
41
+ )
42
+
43
+
14
44
  def _render_roadmap(
15
45
  text: str,
16
46
  previous_milestone: str,
@@ -243,9 +273,9 @@ def _completed_promotion(
243
273
  if _head_with_exact_message(repo, subject, fields) != head:
244
274
  raise PipelineStateError("completed promotion has the wrong commit message")
245
275
 
246
- active_text = pipeline_state._git_text_at(repo, base, ".project/STATE.md")
247
- next_text = pipeline_state._git_text_at(repo, base, ".project/next/STATE.md")
248
- roadmap_text = pipeline_state._git_text_at(repo, base, ".project/ROADMAP.md")
276
+ active_text = state_checkpoint._git_text_at(repo, base, ".project/STATE.md")
277
+ next_text = state_checkpoint._git_text_at(repo, base, ".project/next/STATE.md")
278
+ roadmap_text = state_checkpoint._git_text_at(repo, base, ".project/ROADMAP.md")
249
279
  if active_text is None or next_text is None or roadmap_text is None:
250
280
  raise PipelineStateError("promotion parent is missing required metadata")
251
281
  active_state = pipeline_state._state_from_text(active_text, "promotion parent STATE.md")
@@ -265,7 +295,7 @@ def _completed_promotion(
265
295
  )
266
296
 
267
297
  _promotion_tree_mapping(repo, base, head)
268
- drift = pipeline_state._classify_plan_drift(repo, next_state, base, landing)
298
+ drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
269
299
  expected_roadmap = _render_roadmap(
270
300
  roadmap_text,
271
301
  active_state.milestone,
@@ -273,11 +303,11 @@ def _completed_promotion(
273
303
  branch,
274
304
  landing,
275
305
  )
276
- current_roadmap = pipeline_state._git_text_at(repo, head, ".project/ROADMAP.md")
306
+ current_roadmap = state_checkpoint._git_text_at(repo, head, ".project/ROADMAP.md")
277
307
  if current_roadmap != expected_roadmap:
278
308
  raise PipelineStateError("completed promotion has invalid ROADMAP.md")
279
309
 
280
- current_state = pipeline_state._git_text_at(repo, head, ".project/STATE.md")
310
+ current_state = state_checkpoint._git_text_at(repo, head, ".project/STATE.md")
281
311
  if current_state is None:
282
312
  raise PipelineStateError("completed promotion has no STATE.md")
283
313
  event = re.escape(_promotion_event(drift, branch, landing, base))
@@ -438,10 +468,10 @@ def _prepare_promotion(
438
468
  if source.exists() or source.is_symlink():
439
469
  if destination.exists() or destination.is_symlink():
440
470
  raise PipelineStateError(f"promotion destination already exists: {destination}")
441
- tracks[name] = pipeline_state._tree_digest(source)
471
+ tracks[name] = state_checkpoint._tree_digest(source)
442
472
  if not tracks:
443
473
  raise PipelineStateError("lookahead track has no promotable artifacts")
444
- drift = pipeline_state._classify_plan_drift(repo, next_state, base, landing)
474
+ drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
445
475
  roadmap_path = project / "ROADMAP.md"
446
476
  roadmap_text = pipeline_state._read_real_file(roadmap_path, "ROADMAP.md")
447
477
  target_state = _promotion_state(
@@ -464,10 +494,10 @@ def _prepare_promotion(
464
494
  "landing": landing,
465
495
  "base": base,
466
496
  "tracks": tracks,
467
- "residual_sha256": pipeline_state._tree_digest(next_root, tuple(tracks)),
468
- "next_state_sha256": pipeline_state._sha256(next_text),
469
- "active_state_sha256": pipeline_state._sha256(active_text),
470
- "roadmap_sha256": pipeline_state._sha256(roadmap_text),
497
+ "residual_sha256": state_checkpoint._tree_digest(next_root, tuple(tracks)),
498
+ "next_state_sha256": state_checkpoint._sha256(next_text),
499
+ "active_state_sha256": state_checkpoint._sha256(active_text),
500
+ "roadmap_sha256": state_checkpoint._sha256(roadmap_text),
471
501
  "target_state": target_state,
472
502
  "target_roadmap": target_roadmap,
473
503
  "drift": drift,
@@ -521,7 +551,7 @@ def _resume_track_moves(project: Path, journal: dict[str, object], path: Path) -
521
551
  if not source_exists and not destination_exists:
522
552
  raise PipelineStateError(f"promotion lost both source and destination: {name}")
523
553
  candidate = source if source_exists else destination
524
- if pipeline_state._tree_digest(candidate) != expected_digest:
554
+ if state_checkpoint._tree_digest(candidate) != expected_digest:
525
555
  raise PipelineStateError(f"promotion track drifted: {name}")
526
556
  if source_exists:
527
557
  source.rename(destination)
@@ -542,7 +572,7 @@ def _resume_metadata(project: Path, journal: dict[str, object], path: Path) -> N
542
572
  raise PipelineStateError("promotion journal has invalid metadata")
543
573
  if current == desired:
544
574
  continue
545
- if pipeline_state._sha256(current) != expected_original:
575
+ if state_checkpoint._sha256(current) != expected_original:
546
576
  raise PipelineStateError(f"promotion metadata drifted: {target}")
547
577
  pipeline_state._atomic_write(target, desired)
548
578
  journal["stage"] = f"updated:{target.name}"
@@ -560,9 +590,9 @@ def _resume_next_removal(
560
590
  if residual.exists() or residual.is_symlink():
561
591
  raise PipelineStateError("promotion has both next track and residual staging")
562
592
  next_text = pipeline_state._read_real_file(next_root / "STATE.md", "next/STATE.md")
563
- if pipeline_state._sha256(next_text) != journal.get("next_state_sha256"):
593
+ if state_checkpoint._sha256(next_text) != journal.get("next_state_sha256"):
564
594
  raise PipelineStateError("lookahead STATE drifted during promotion")
565
- if pipeline_state._tree_digest(next_root) != journal.get("residual_sha256"):
595
+ if state_checkpoint._tree_digest(next_root) != journal.get("residual_sha256"):
566
596
  raise PipelineStateError("lookahead residual drifted during promotion")
567
597
  next_root.rename(residual)
568
598
  journal["stage"] = "next-staged"
@@ -574,7 +604,7 @@ def _resume_next_removal(
574
604
  raise PipelineStateError("promotion lost next track and residual staging")
575
605
  if residual.is_symlink() or not residual.is_dir():
576
606
  raise PipelineStateError(f"promotion residual must be a real directory: {residual}")
577
- if pipeline_state._tree_digest(residual) != journal.get("residual_sha256"):
607
+ if state_checkpoint._tree_digest(residual) != journal.get("residual_sha256"):
578
608
  raise PipelineStateError("staged lookahead residual drifted during promotion")
579
609
 
580
610
 
@@ -714,30 +744,3 @@ def promote_next(
714
744
  "commit": commit,
715
745
  "drift": journal["drift"],
716
746
  }
717
-
718
-
719
- # pipeline_state imports this module, so the parent is resolved after the
720
- # definitions above. Parent functions are looked up on the module at call time
721
- # so patches applied to pipeline_state stay visible here.
722
- if __package__: # imported as scripts.state_promote
723
- from . import pipeline_state
724
- from .pipeline_state import (
725
- NULL,
726
- PROMOTION_RESIDUAL,
727
- PROMOTION_SCHEMA,
728
- PROMOTION_TRACKS,
729
- SLUG_RE,
730
- PipelineState,
731
- PipelineStateError,
732
- )
733
- else: # standalone script or sibling import
734
- import pipeline_state
735
- from pipeline_state import (
736
- NULL,
737
- PROMOTION_RESIDUAL,
738
- PROMOTION_SCHEMA,
739
- PROMOTION_TRACKS,
740
- SLUG_RE,
741
- PipelineState,
742
- PipelineStateError,
743
- )