@opengsd/gsd-path 1.4.0 → 1.6.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 (476) hide show
  1. package/CHANGELOG.md +460 -341
  2. package/DOCS.md +16 -5
  3. package/FULL.md +67 -6
  4. package/HOOKS.md +158 -10
  5. package/MIGRATE.md +12 -0
  6. package/QUICK.md +4 -2
  7. package/README.md +136 -116
  8. package/RUNTIME.md +24 -6
  9. package/UPDATE.md +39 -3
  10. package/WORKFLOW.md +80 -4
  11. package/package.json +5 -2
  12. package/platforms/shared-agents/dispatch.md +13 -0
  13. package/scripts/_common.py +256 -2
  14. package/scripts/archive_milestone.py +14 -13
  15. package/scripts/build_recovery.py +155 -58
  16. package/scripts/build_state.py +274 -8
  17. package/scripts/check_docs_audit.py +77 -4
  18. package/scripts/check_handoffs.py +635 -57
  19. package/scripts/check_task_briefs.py +293 -32
  20. package/scripts/detect_project.py +260 -20
  21. package/scripts/discussion_records.py +9 -1
  22. package/scripts/discussion_validate.py +93 -35
  23. package/scripts/dispatch_driver.py +549 -53
  24. package/scripts/git_guard.py +27 -8
  25. package/scripts/guard_hook.py +2630 -210
  26. package/scripts/install.mjs +99 -11
  27. package/scripts/install.py +231 -46
  28. package/scripts/integration.py +244 -65
  29. package/scripts/isolation.py +539 -70
  30. package/scripts/loop_run.py +16 -4
  31. package/scripts/members.py +77 -32
  32. package/scripts/migrate_core.py +2 -0
  33. package/scripts/model_policy.py +5 -1
  34. package/scripts/path_config.py +3 -3
  35. package/scripts/pipeline_diagnose.py +17 -2
  36. package/scripts/pipeline_git.py +131 -42
  37. package/scripts/pipeline_state.py +139 -39
  38. package/scripts/pipeline_undo.py +118 -16
  39. package/scripts/promote_lookahead.py +3 -3
  40. package/scripts/review_findings.py +180 -44
  41. package/scripts/roadmap.py +9 -1
  42. package/scripts/runtime_store.py +21 -2
  43. package/scripts/skill-resources.json +9 -2
  44. package/scripts/state_checkpoint.py +39 -36
  45. package/scripts/state_promote.py +15 -4
  46. package/scripts/status_runtime.py +22 -4
  47. package/scripts/task_context.py +14 -3
  48. package/scripts/wizard.mjs +1 -0
  49. package/scripts/workflow_run.py +14 -4
  50. package/scripts/worktree_paths.py +54 -2
  51. package/skills/gsd-path/DEFINE.md +34 -5
  52. package/skills/gsd-path/PLAN.md +14 -3
  53. package/skills/gsd-path/RESEARCH.md +11 -0
  54. package/skills/gsd-path/ROADMAP.md +16 -6
  55. package/skills/gsd-path/SHIP.md +32 -5
  56. package/skills/gsd-path/SKILL.md +52 -24
  57. package/skills/gsd-path/references/build-native.md +112 -10
  58. package/skills/gsd-path/references/build-recovery.md +13 -0
  59. package/skills/gsd-path/references/coder.md +7 -3
  60. package/skills/gsd-path/references/dispatch.md +13 -0
  61. package/skills/gsd-path/references/docs-auditor.md +5 -0
  62. package/skills/gsd-path/references/operating-rules.md +11 -3
  63. package/skills/gsd-path/references/planner.md +26 -4
  64. package/skills/gsd-path/references/reviewer-final.md +20 -2
  65. package/skills/gsd-path/references/reviewer-wave.md +56 -12
  66. package/skills/gsd-path/references/reviewer.md +3 -1
  67. package/skills/gsd-path/references/runtime-selection.md +9 -0
  68. package/skills/gsd-path/references/spec-probes.md +150 -0
  69. package/skills/gsd-path/scripts/_common.py +256 -2
  70. package/skills/gsd-path/scripts/archive_milestone.py +14 -13
  71. package/skills/gsd-path/scripts/build_recovery.py +155 -58
  72. package/skills/gsd-path/scripts/build_state.py +274 -8
  73. package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
  74. package/skills/gsd-path/scripts/check_handoffs.py +635 -57
  75. package/skills/gsd-path/scripts/check_task_briefs.py +293 -32
  76. package/skills/gsd-path/scripts/detect_project.py +260 -20
  77. package/skills/gsd-path/scripts/discussion_records.py +9 -1
  78. package/skills/gsd-path/scripts/discussion_validate.py +93 -35
  79. package/skills/gsd-path/scripts/dispatch_driver.py +549 -53
  80. package/skills/gsd-path/scripts/git_guard.py +27 -8
  81. package/skills/gsd-path/scripts/integration.py +244 -65
  82. package/skills/gsd-path/scripts/isolation.py +539 -70
  83. package/skills/gsd-path/scripts/loop_run.py +16 -4
  84. package/skills/gsd-path/scripts/members.py +77 -32
  85. package/skills/gsd-path/scripts/model_policy.py +5 -1
  86. package/skills/gsd-path/scripts/path_config.py +3 -3
  87. package/skills/gsd-path/scripts/pipeline_git.py +131 -42
  88. package/skills/gsd-path/scripts/pipeline_state.py +139 -39
  89. package/skills/gsd-path/scripts/promote_lookahead.py +3 -3
  90. package/skills/gsd-path/scripts/review_findings.py +180 -44
  91. package/skills/gsd-path/scripts/roadmap.py +9 -1
  92. package/skills/gsd-path/scripts/state_checkpoint.py +39 -36
  93. package/skills/gsd-path/scripts/state_promote.py +15 -4
  94. package/skills/gsd-path/scripts/status_runtime.py +22 -4
  95. package/skills/gsd-path/scripts/task_context.py +14 -3
  96. package/skills/gsd-path/scripts/workflow_run.py +14 -4
  97. package/skills/gsd-path/scripts/worktree_paths.py +54 -2
  98. package/skills/gsd-path/templates/docs-audit.md +5 -1
  99. package/skills/gsd-path/templates/final-review.md +11 -2
  100. package/skills/gsd-path/templates/intent.md +30 -0
  101. package/skills/gsd-path/templates/patch-findings.md +3 -3
  102. package/skills/gsd-path/templates/plan.md +17 -2
  103. package/skills/gsd-path/templates/research-handoff.md +14 -3
  104. package/skills/gsd-path/templates/state.md +2 -1
  105. package/skills/gsd-path/templates/task.md +1 -0
  106. package/skills/gsd-path/templates/wave-review.md +28 -9
  107. package/skills/gsd-path-build/references/build-native.md +112 -10
  108. package/skills/gsd-path-build/references/build-recovery.md +13 -0
  109. package/skills/gsd-path-build/references/coder.md +7 -3
  110. package/skills/gsd-path-build/references/dispatch.md +13 -0
  111. package/skills/gsd-path-build/references/operating-rules.md +11 -3
  112. package/skills/gsd-path-build/references/reviewer-final.md +20 -2
  113. package/skills/gsd-path-build/references/reviewer-wave.md +56 -12
  114. package/skills/gsd-path-build/references/reviewer.md +3 -1
  115. package/skills/gsd-path-build/references/runtime-selection.md +9 -0
  116. package/skills/gsd-path-build/references/spec-probes.md +150 -0
  117. package/skills/gsd-path-build/scripts/_common.py +256 -2
  118. package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
  119. package/skills/gsd-path-build/scripts/build_recovery.py +155 -58
  120. package/skills/gsd-path-build/scripts/build_state.py +274 -8
  121. package/skills/gsd-path-build/scripts/check_handoffs.py +635 -57
  122. package/skills/gsd-path-build/scripts/check_task_briefs.py +293 -32
  123. package/skills/gsd-path-build/scripts/detect_project.py +260 -20
  124. package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
  125. package/skills/gsd-path-build/scripts/discussion_validate.py +93 -35
  126. package/skills/gsd-path-build/scripts/dispatch_driver.py +549 -53
  127. package/skills/gsd-path-build/scripts/integration.py +244 -65
  128. package/skills/gsd-path-build/scripts/isolation.py +539 -70
  129. package/skills/gsd-path-build/scripts/loop_run.py +16 -4
  130. package/skills/gsd-path-build/scripts/members.py +77 -32
  131. package/skills/gsd-path-build/scripts/model_policy.py +5 -1
  132. package/skills/gsd-path-build/scripts/path_config.py +3 -3
  133. package/skills/gsd-path-build/scripts/pipeline_git.py +131 -42
  134. package/skills/gsd-path-build/scripts/pipeline_state.py +139 -39
  135. package/skills/gsd-path-build/scripts/promote_lookahead.py +3 -3
  136. package/skills/gsd-path-build/scripts/review_findings.py +180 -44
  137. package/skills/gsd-path-build/scripts/roadmap.py +9 -1
  138. package/skills/gsd-path-build/scripts/state_checkpoint.py +39 -36
  139. package/skills/gsd-path-build/scripts/state_promote.py +15 -4
  140. package/skills/gsd-path-build/scripts/task_context.py +14 -3
  141. package/skills/gsd-path-build/scripts/workflow_run.py +14 -4
  142. package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
  143. package/skills/gsd-path-build/templates/task.md +1 -0
  144. package/skills/gsd-path-build/templates/wave-review.md +28 -9
  145. package/skills/gsd-path-decide/references/dispatch.md +13 -0
  146. package/skills/gsd-path-decide/references/operating-rules.md +11 -3
  147. package/skills/gsd-path-decide/references/runtime-selection.md +9 -0
  148. package/skills/gsd-path-decide/scripts/_common.py +256 -2
  149. package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
  150. package/skills/gsd-path-decide/scripts/build_recovery.py +155 -58
  151. package/skills/gsd-path-decide/scripts/check_handoffs.py +635 -57
  152. package/skills/gsd-path-decide/scripts/check_task_briefs.py +293 -32
  153. package/skills/gsd-path-decide/scripts/detect_project.py +260 -20
  154. package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
  155. package/skills/gsd-path-decide/scripts/discussion_validate.py +93 -35
  156. package/skills/gsd-path-decide/scripts/integration.py +244 -65
  157. package/skills/gsd-path-decide/scripts/isolation.py +539 -70
  158. package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
  159. package/skills/gsd-path-decide/scripts/members.py +77 -32
  160. package/skills/gsd-path-decide/scripts/model_policy.py +5 -1
  161. package/skills/gsd-path-decide/scripts/path_config.py +3 -3
  162. package/skills/gsd-path-decide/scripts/pipeline_git.py +131 -42
  163. package/skills/gsd-path-decide/scripts/pipeline_state.py +139 -39
  164. package/skills/gsd-path-decide/scripts/promote_lookahead.py +3 -3
  165. package/skills/gsd-path-decide/scripts/roadmap.py +9 -1
  166. package/skills/gsd-path-decide/scripts/state_checkpoint.py +39 -36
  167. package/skills/gsd-path-decide/scripts/state_promote.py +15 -4
  168. package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
  169. package/skills/gsd-path-define/SKILL.md +34 -5
  170. package/skills/gsd-path-define/references/build-recovery.md +13 -0
  171. package/skills/gsd-path-define/references/operating-rules.md +11 -3
  172. package/skills/gsd-path-define/references/runtime-selection.md +9 -0
  173. package/skills/gsd-path-define/references/spec-probes.md +150 -0
  174. package/skills/gsd-path-define/scripts/_common.py +256 -2
  175. package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
  176. package/skills/gsd-path-define/scripts/build_recovery.py +155 -58
  177. package/skills/gsd-path-define/scripts/check_handoffs.py +635 -57
  178. package/skills/gsd-path-define/scripts/check_task_briefs.py +293 -32
  179. package/skills/gsd-path-define/scripts/detect_project.py +260 -20
  180. package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
  181. package/skills/gsd-path-define/scripts/discussion_validate.py +93 -35
  182. package/skills/gsd-path-define/scripts/integration.py +244 -65
  183. package/skills/gsd-path-define/scripts/isolation.py +539 -70
  184. package/skills/gsd-path-define/scripts/loop_run.py +16 -4
  185. package/skills/gsd-path-define/scripts/members.py +77 -32
  186. package/skills/gsd-path-define/scripts/model_policy.py +5 -1
  187. package/skills/gsd-path-define/scripts/path_config.py +3 -3
  188. package/skills/gsd-path-define/scripts/pipeline_git.py +131 -42
  189. package/skills/gsd-path-define/scripts/pipeline_state.py +139 -39
  190. package/skills/gsd-path-define/scripts/promote_lookahead.py +3 -3
  191. package/skills/gsd-path-define/scripts/roadmap.py +9 -1
  192. package/skills/gsd-path-define/scripts/state_checkpoint.py +39 -36
  193. package/skills/gsd-path-define/scripts/state_promote.py +15 -4
  194. package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
  195. package/skills/gsd-path-define/templates/intent.md +30 -0
  196. package/skills/gsd-path-define/templates/state.md +2 -1
  197. package/skills/gsd-path-discuss/references/operating-rules.md +11 -3
  198. package/skills/gsd-path-discuss/references/runtime-selection.md +9 -0
  199. package/skills/gsd-path-discuss/scripts/_common.py +256 -2
  200. package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
  201. package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
  202. package/skills/gsd-path-discuss/scripts/model_policy.py +5 -1
  203. package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
  204. package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
  205. package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
  206. package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
  207. package/skills/gsd-path-docs-audit/references/operating-rules.md +11 -3
  208. package/skills/gsd-path-docs-audit/references/runtime-selection.md +9 -0
  209. package/skills/gsd-path-docs-audit/scripts/_common.py +256 -2
  210. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
  211. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +155 -58
  212. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
  213. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +635 -57
  214. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +293 -32
  215. package/skills/gsd-path-docs-audit/scripts/detect_project.py +260 -20
  216. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
  217. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +93 -35
  218. package/skills/gsd-path-docs-audit/scripts/integration.py +244 -65
  219. package/skills/gsd-path-docs-audit/scripts/isolation.py +539 -70
  220. package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
  221. package/skills/gsd-path-docs-audit/scripts/members.py +77 -32
  222. package/skills/gsd-path-docs-audit/scripts/model_policy.py +5 -1
  223. package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
  224. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +131 -42
  225. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +139 -39
  226. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +3 -3
  227. package/skills/gsd-path-docs-audit/scripts/roadmap.py +9 -1
  228. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +39 -36
  229. package/skills/gsd-path-docs-audit/scripts/state_promote.py +15 -4
  230. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
  231. package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
  232. package/skills/gsd-path-forensics/references/operating-rules.md +11 -3
  233. package/skills/gsd-path-forensics/references/runtime-selection.md +9 -0
  234. package/skills/gsd-path-forensics/scripts/_common.py +256 -2
  235. package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
  236. package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
  237. package/skills/gsd-path-forensics/scripts/model_policy.py +5 -1
  238. package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
  239. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
  240. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +118 -16
  241. package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
  242. package/skills/gsd-path-inspect/references/dispatch.md +13 -0
  243. package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
  244. package/skills/gsd-path-inspect/references/operating-rules.md +11 -3
  245. package/skills/gsd-path-inspect/references/runtime-selection.md +9 -0
  246. package/skills/gsd-path-inspect/scripts/_common.py +256 -2
  247. package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
  248. package/skills/gsd-path-inspect/scripts/build_recovery.py +155 -58
  249. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
  250. package/skills/gsd-path-inspect/scripts/check_handoffs.py +635 -57
  251. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +293 -32
  252. package/skills/gsd-path-inspect/scripts/detect_project.py +260 -20
  253. package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
  254. package/skills/gsd-path-inspect/scripts/discussion_validate.py +93 -35
  255. package/skills/gsd-path-inspect/scripts/integration.py +244 -65
  256. package/skills/gsd-path-inspect/scripts/isolation.py +539 -70
  257. package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
  258. package/skills/gsd-path-inspect/scripts/members.py +77 -32
  259. package/skills/gsd-path-inspect/scripts/model_policy.py +5 -1
  260. package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
  261. package/skills/gsd-path-inspect/scripts/pipeline_git.py +131 -42
  262. package/skills/gsd-path-inspect/scripts/pipeline_state.py +139 -39
  263. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +3 -3
  264. package/skills/gsd-path-inspect/scripts/roadmap.py +9 -1
  265. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +39 -36
  266. package/skills/gsd-path-inspect/scripts/state_promote.py +15 -4
  267. package/skills/gsd-path-inspect/scripts/workflow_run.py +14 -4
  268. package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
  269. package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
  270. package/skills/gsd-path-inspect/templates/state.md +2 -1
  271. package/skills/gsd-path-loop/references/operating-rules.md +11 -3
  272. package/skills/gsd-path-loop/references/runtime-selection.md +9 -0
  273. package/skills/gsd-path-loop/scripts/_common.py +256 -2
  274. package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
  275. package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
  276. package/skills/gsd-path-loop/scripts/model_policy.py +5 -1
  277. package/skills/gsd-path-loop/scripts/path_config.py +3 -3
  278. package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
  279. package/skills/gsd-path-migrate/SKILL.md +8 -0
  280. package/skills/gsd-path-migrate/references/operating-rules.md +11 -3
  281. package/skills/gsd-path-migrate/references/runtime-selection.md +9 -0
  282. package/skills/gsd-path-migrate/scripts/_common.py +256 -2
  283. package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
  284. package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
  285. package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -0
  286. package/skills/gsd-path-migrate/scripts/model_policy.py +5 -1
  287. package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
  288. package/skills/gsd-path-plan/SKILL.md +14 -3
  289. package/skills/gsd-path-plan/references/build-recovery.md +13 -0
  290. package/skills/gsd-path-plan/references/dispatch.md +13 -0
  291. package/skills/gsd-path-plan/references/operating-rules.md +11 -3
  292. package/skills/gsd-path-plan/references/planner.md +26 -4
  293. package/skills/gsd-path-plan/references/runtime-selection.md +9 -0
  294. package/skills/gsd-path-plan/references/spec-probes.md +150 -0
  295. package/skills/gsd-path-plan/scripts/_common.py +256 -2
  296. package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
  297. package/skills/gsd-path-plan/scripts/build_recovery.py +155 -58
  298. package/skills/gsd-path-plan/scripts/check_handoffs.py +635 -57
  299. package/skills/gsd-path-plan/scripts/check_task_briefs.py +293 -32
  300. package/skills/gsd-path-plan/scripts/detect_project.py +260 -20
  301. package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
  302. package/skills/gsd-path-plan/scripts/discussion_validate.py +93 -35
  303. package/skills/gsd-path-plan/scripts/integration.py +244 -65
  304. package/skills/gsd-path-plan/scripts/isolation.py +539 -70
  305. package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
  306. package/skills/gsd-path-plan/scripts/members.py +77 -32
  307. package/skills/gsd-path-plan/scripts/model_policy.py +5 -1
  308. package/skills/gsd-path-plan/scripts/path_config.py +3 -3
  309. package/skills/gsd-path-plan/scripts/pipeline_git.py +131 -42
  310. package/skills/gsd-path-plan/scripts/pipeline_state.py +139 -39
  311. package/skills/gsd-path-plan/scripts/promote_lookahead.py +3 -3
  312. package/skills/gsd-path-plan/scripts/roadmap.py +9 -1
  313. package/skills/gsd-path-plan/scripts/state_checkpoint.py +39 -36
  314. package/skills/gsd-path-plan/scripts/state_promote.py +15 -4
  315. package/skills/gsd-path-plan/scripts/workflow_run.py +14 -4
  316. package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
  317. package/skills/gsd-path-plan/templates/patch-findings.md +3 -3
  318. package/skills/gsd-path-plan/templates/plan.md +17 -2
  319. package/skills/gsd-path-plan/templates/task.md +1 -0
  320. package/skills/gsd-path-research/SKILL.md +11 -0
  321. package/skills/gsd-path-research/references/dispatch.md +13 -0
  322. package/skills/gsd-path-research/references/operating-rules.md +11 -3
  323. package/skills/gsd-path-research/references/runtime-selection.md +9 -0
  324. package/skills/gsd-path-research/scripts/_common.py +256 -2
  325. package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
  326. package/skills/gsd-path-research/scripts/build_recovery.py +155 -58
  327. package/skills/gsd-path-research/scripts/check_handoffs.py +635 -57
  328. package/skills/gsd-path-research/scripts/check_task_briefs.py +293 -32
  329. package/skills/gsd-path-research/scripts/detect_project.py +260 -20
  330. package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
  331. package/skills/gsd-path-research/scripts/discussion_validate.py +93 -35
  332. package/skills/gsd-path-research/scripts/integration.py +244 -65
  333. package/skills/gsd-path-research/scripts/isolation.py +539 -70
  334. package/skills/gsd-path-research/scripts/loop_run.py +16 -4
  335. package/skills/gsd-path-research/scripts/members.py +77 -32
  336. package/skills/gsd-path-research/scripts/model_policy.py +5 -1
  337. package/skills/gsd-path-research/scripts/path_config.py +3 -3
  338. package/skills/gsd-path-research/scripts/pipeline_git.py +131 -42
  339. package/skills/gsd-path-research/scripts/pipeline_state.py +139 -39
  340. package/skills/gsd-path-research/scripts/promote_lookahead.py +3 -3
  341. package/skills/gsd-path-research/scripts/roadmap.py +9 -1
  342. package/skills/gsd-path-research/scripts/state_checkpoint.py +39 -36
  343. package/skills/gsd-path-research/scripts/state_promote.py +15 -4
  344. package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
  345. package/skills/gsd-path-research/templates/research-handoff.md +14 -3
  346. package/skills/gsd-path-roadmap/SKILL.md +16 -6
  347. package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
  348. package/skills/gsd-path-roadmap/references/operating-rules.md +11 -3
  349. package/skills/gsd-path-roadmap/references/runtime-selection.md +9 -0
  350. package/skills/gsd-path-roadmap/scripts/_common.py +256 -2
  351. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
  352. package/skills/gsd-path-roadmap/scripts/build_recovery.py +155 -58
  353. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +635 -57
  354. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +293 -32
  355. package/skills/gsd-path-roadmap/scripts/detect_project.py +260 -20
  356. package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
  357. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +93 -35
  358. package/skills/gsd-path-roadmap/scripts/integration.py +244 -65
  359. package/skills/gsd-path-roadmap/scripts/isolation.py +539 -70
  360. package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
  361. package/skills/gsd-path-roadmap/scripts/members.py +77 -32
  362. package/skills/gsd-path-roadmap/scripts/model_policy.py +5 -1
  363. package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
  364. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +131 -42
  365. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +139 -39
  366. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +3 -3
  367. package/skills/gsd-path-roadmap/scripts/roadmap.py +9 -1
  368. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +39 -36
  369. package/skills/gsd-path-roadmap/scripts/state_promote.py +15 -4
  370. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
  371. package/skills/gsd-path-ship/SKILL.md +32 -5
  372. package/skills/gsd-path-ship/references/dispatch.md +13 -0
  373. package/skills/gsd-path-ship/references/operating-rules.md +11 -3
  374. package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
  375. package/skills/gsd-path-ship/references/reviewer-wave.md +56 -12
  376. package/skills/gsd-path-ship/references/reviewer.md +3 -1
  377. package/skills/gsd-path-ship/references/runtime-selection.md +9 -0
  378. package/skills/gsd-path-ship/references/spec-probes.md +150 -0
  379. package/skills/gsd-path-ship/scripts/_common.py +256 -2
  380. package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
  381. package/skills/gsd-path-ship/scripts/build_recovery.py +155 -58
  382. package/skills/gsd-path-ship/scripts/build_state.py +274 -8
  383. package/skills/gsd-path-ship/scripts/check_handoffs.py +635 -57
  384. package/skills/gsd-path-ship/scripts/check_task_briefs.py +293 -32
  385. package/skills/gsd-path-ship/scripts/detect_project.py +260 -20
  386. package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
  387. package/skills/gsd-path-ship/scripts/discussion_validate.py +93 -35
  388. package/skills/gsd-path-ship/scripts/integration.py +244 -65
  389. package/skills/gsd-path-ship/scripts/isolation.py +539 -70
  390. package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
  391. package/skills/gsd-path-ship/scripts/members.py +77 -32
  392. package/skills/gsd-path-ship/scripts/model_policy.py +5 -1
  393. package/skills/gsd-path-ship/scripts/path_config.py +3 -3
  394. package/skills/gsd-path-ship/scripts/pipeline_git.py +131 -42
  395. package/skills/gsd-path-ship/scripts/pipeline_state.py +139 -39
  396. package/skills/gsd-path-ship/scripts/promote_lookahead.py +3 -3
  397. package/skills/gsd-path-ship/scripts/roadmap.py +9 -1
  398. package/skills/gsd-path-ship/scripts/state_checkpoint.py +39 -36
  399. package/skills/gsd-path-ship/scripts/state_promote.py +15 -4
  400. package/skills/gsd-path-ship/scripts/workflow_run.py +14 -4
  401. package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
  402. package/skills/gsd-path-ship/templates/final-review.md +11 -2
  403. package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
  404. package/skills/gsd-path-ship/templates/wave-review.md +28 -9
  405. package/skills/gsd-path-undo/references/operating-rules.md +11 -3
  406. package/skills/gsd-path-undo/references/runtime-selection.md +9 -0
  407. package/skills/gsd-path-undo/scripts/_common.py +256 -2
  408. package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
  409. package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
  410. package/skills/gsd-path-undo/scripts/model_policy.py +5 -1
  411. package/skills/gsd-path-undo/scripts/path_config.py +3 -3
  412. package/skills/gsd-path-undo/scripts/pipeline_undo.py +118 -16
  413. package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
  414. package/skills/path/DEFINE.md +34 -5
  415. package/skills/path/PLAN.md +14 -3
  416. package/skills/path/RESEARCH.md +11 -0
  417. package/skills/path/ROADMAP.md +16 -6
  418. package/skills/path/SHIP.md +32 -5
  419. package/skills/path/SKILL.md +52 -24
  420. package/skills/path/references/build-native.md +112 -10
  421. package/skills/path/references/build-recovery.md +13 -0
  422. package/skills/path/references/coder.md +7 -3
  423. package/skills/path/references/dispatch.md +13 -0
  424. package/skills/path/references/docs-auditor.md +5 -0
  425. package/skills/path/references/operating-rules.md +11 -3
  426. package/skills/path/references/planner.md +26 -4
  427. package/skills/path/references/reviewer-final.md +20 -2
  428. package/skills/path/references/reviewer-wave.md +56 -12
  429. package/skills/path/references/reviewer.md +3 -1
  430. package/skills/path/references/runtime-selection.md +9 -0
  431. package/skills/path/references/spec-probes.md +150 -0
  432. package/skills/path/scripts/_common.py +256 -2
  433. package/skills/path/scripts/archive_milestone.py +14 -13
  434. package/skills/path/scripts/build_recovery.py +155 -58
  435. package/skills/path/scripts/build_state.py +274 -8
  436. package/skills/path/scripts/check_docs_audit.py +77 -4
  437. package/skills/path/scripts/check_handoffs.py +635 -57
  438. package/skills/path/scripts/check_task_briefs.py +293 -32
  439. package/skills/path/scripts/detect_project.py +260 -20
  440. package/skills/path/scripts/discussion_records.py +9 -1
  441. package/skills/path/scripts/discussion_validate.py +93 -35
  442. package/skills/path/scripts/dispatch_driver.py +549 -53
  443. package/skills/path/scripts/git_guard.py +27 -8
  444. package/skills/path/scripts/integration.py +244 -65
  445. package/skills/path/scripts/isolation.py +539 -70
  446. package/skills/path/scripts/loop_run.py +16 -4
  447. package/skills/path/scripts/members.py +77 -32
  448. package/skills/path/scripts/model_policy.py +5 -1
  449. package/skills/path/scripts/path_config.py +3 -3
  450. package/skills/path/scripts/pipeline_git.py +131 -42
  451. package/skills/path/scripts/pipeline_state.py +139 -39
  452. package/skills/path/scripts/promote_lookahead.py +3 -3
  453. package/skills/path/scripts/review_findings.py +180 -44
  454. package/skills/path/scripts/roadmap.py +9 -1
  455. package/skills/path/scripts/state_checkpoint.py +39 -36
  456. package/skills/path/scripts/state_promote.py +15 -4
  457. package/skills/path/scripts/status_runtime.py +22 -4
  458. package/skills/path/scripts/task_context.py +14 -3
  459. package/skills/path/scripts/workflow_run.py +14 -4
  460. package/skills/path/scripts/worktree_paths.py +54 -2
  461. package/skills/path/templates/docs-audit.md +5 -1
  462. package/skills/path/templates/final-review.md +11 -2
  463. package/skills/path/templates/intent.md +30 -0
  464. package/skills/path/templates/patch-findings.md +3 -3
  465. package/skills/path/templates/plan.md +17 -2
  466. package/skills/path/templates/research-handoff.md +14 -3
  467. package/skills/path/templates/state.md +2 -1
  468. package/skills/path/templates/task.md +1 -0
  469. package/skills/path/templates/wave-review.md +28 -9
  470. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  471. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  472. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  473. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  474. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  475. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  476. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
@@ -91,7 +91,7 @@ STATE_FIELDS = (
91
91
  "integration_source",
92
92
  )
93
93
  LEGACY_STATE_FIELDS = STATE_FIELDS[:7]
94
- INTEGRATION_MODES = ("direct", "pull-request")
94
+ INTEGRATION_MODES = ("direct", "pull-request", "external-landing")
95
95
  INTEGRATION_SOURCES = ("default", "milestone")
96
96
  NULL = "null"
97
97
  SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
@@ -141,6 +141,8 @@ CROSS_PHASE_TRANSITIONS = {
141
141
  ("decide", "done", "plan", "active"),
142
142
  ("roadmap", "done", "define", "active"),
143
143
  ("plan", "done", "build", "active"),
144
+ ("plan", "active", "define", "active"),
145
+ ("plan", "blocked", "define", "active"),
144
146
  ("build", "blocked", "define", "active"),
145
147
  ("build", "blocked", "plan", "active"),
146
148
  ("build", "active", "ship", "active"),
@@ -171,9 +173,14 @@ class PipelineState:
171
173
  integration_default: str
172
174
  integration: str
173
175
  integration_source: str
176
+ default_branch: str = "main"
174
177
 
175
178
  def json(self) -> dict[str, Optional[str]]:
176
- return asdict(self)
179
+ # ponytail: default_branch stays out of this payload; guard_hook, install
180
+ # and the daemon probe accept only the closed STATE_FIELDS set.
181
+ payload = asdict(self)
182
+ del payload["default_branch"]
183
+ return payload
177
184
 
178
185
 
179
186
  @dataclass(frozen=True)
@@ -193,11 +200,24 @@ def _run_git(
193
200
  *arguments: str,
194
201
  check: bool = True,
195
202
  ) -> subprocess.CompletedProcess[str]:
203
+ command = _common.git_command(repo, *arguments)
196
204
  result = subprocess.run(
197
- ["git", "-C", str(repo), *arguments],
205
+ command,
198
206
  capture_output=True,
199
207
  encoding="utf-8", errors="replace",
200
208
  )
209
+ if (
210
+ check
211
+ and result.returncode != 0
212
+ and arguments
213
+ and arguments[0] == "commit"
214
+ and _common.git_index_lock_retryable(result.stderr)
215
+ ):
216
+ result = subprocess.run(
217
+ command,
218
+ capture_output=True,
219
+ encoding="utf-8", errors="replace",
220
+ )
201
221
  if check and result.returncode != 0:
202
222
  detail = result.stderr.strip() or result.stdout.strip()
203
223
  raise PipelineStateError(f"git {' '.join(arguments)} failed: {detail}")
@@ -275,7 +295,7 @@ def _bound_branch_number(value: str) -> Optional[int]:
275
295
  def _state_from_text(text: str, label: str = "STATE.md") -> PipelineState:
276
296
  values = _parse_frontmatter(text, label)
277
297
  missing = [field for field in LEGACY_STATE_FIELDS if field not in values]
278
- extra = sorted(set(values) - set(STATE_FIELDS))
298
+ extra = sorted(set(values) - set(STATE_FIELDS) - {"default_branch"})
279
299
  if missing:
280
300
  raise PipelineStateError(f"{label} is missing fields: {', '.join(missing)}")
281
301
  if extra:
@@ -307,6 +327,7 @@ def _state_from_text(text: str, label: str = "STATE.md") -> PipelineState:
307
327
  integration_default=integration_default,
308
328
  integration=integration,
309
329
  integration_source=integration_source,
330
+ default_branch=values.get("default_branch", "main"),
310
331
  )
311
332
  _validate_state_values(state, label)
312
333
  return state
@@ -340,6 +361,10 @@ def _validate_state_values(state: PipelineState, label: str) -> None:
340
361
  raise PipelineStateError(
341
362
  f"{label} default-sourced integration must match integration_default"
342
363
  )
364
+ if not _common.valid_default_branch(state.default_branch):
365
+ raise PipelineStateError(
366
+ f"{label} has invalid default_branch: {state.default_branch}"
367
+ )
343
368
  if state.branch is not None and _bound_branch_number(state.branch) is None:
344
369
  raise PipelineStateError(f"{label} has invalid branch: {state.branch}")
345
370
  archive_match = ARCHIVE_RE.fullmatch(state.archive or "")
@@ -401,6 +426,7 @@ def validate_state(repo: Path, project_dir: str = ".project") -> dict[str, objec
401
426
  "status": "valid",
402
427
  "path": str(path),
403
428
  "state": state.json(),
429
+ "default_branch": state.default_branch,
404
430
  }
405
431
 
406
432
 
@@ -683,8 +709,10 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
683
709
  if branch
684
710
  else None
685
711
  )
712
+ # The key keeps its name for status consumers; the ref follows STATE.
713
+ default_branch = load_state(resolved, project_dir)[0].default_branch
686
714
  origin_main = (
687
- _optional_rev(resolved, "refs/remotes/origin/main") if has_git else None
715
+ _optional_rev(resolved, f"refs/remotes/origin/{default_branch}") if has_git else None
688
716
  )
689
717
  pending, pending_error = _pending_answers(resolved)
690
718
  lookahead = resolved / ".project" / "next"
@@ -707,6 +735,7 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
707
735
  "advance": False,
708
736
  "completion": completion,
709
737
  "state": state,
738
+ "default_branch": default_branch,
710
739
  "route": route,
711
740
  "path": str(_track_root(resolved, project_dir) / "STATE.md"),
712
741
  "git": {
@@ -866,7 +895,12 @@ def _route_result(
866
895
  route["phase"] = phase
867
896
  if mode is not None:
868
897
  route["mode"] = mode
869
- return {"schema": ROUTE_SCHEMA, "state": state.json(), "route": route}
898
+ return {
899
+ "schema": ROUTE_SCHEMA,
900
+ "state": state.json(),
901
+ "default_branch": state.default_branch,
902
+ "route": route,
903
+ }
870
904
 
871
905
 
872
906
  def _legacy_bind_next_landing(repo: Path, state: PipelineState) -> str:
@@ -911,36 +945,13 @@ def _legacy_bind_next_landing(repo: Path, state: PipelineState) -> str:
911
945
  return landing
912
946
 
913
947
 
914
- def _bind_next_recovery(
948
+ def _bind_next_journal_recovery(
915
949
  repo: Path,
916
950
  state: PipelineState,
951
+ path: Path,
952
+ transaction: dict[str, object],
953
+ current: Optional[str],
917
954
  ) -> Optional[dict[str, object]]:
918
- journal_root = _git_path(repo, BIND_NEXT_JOURNAL_DIR)
919
- if not journal_root.exists() and not journal_root.is_symlink():
920
- return None
921
- if journal_root.is_symlink() or not journal_root.is_dir():
922
- raise PipelineStateError(f"bind-next journal root must be a real directory: {journal_root}")
923
-
924
- matches: list[tuple[Path, dict[str, object]]] = []
925
- for path in sorted(journal_root.glob("*.json")):
926
- transaction = _read_json(path)
927
- if transaction.get("schema") not in {
928
- LEGACY_BIND_NEXT_JOURNAL_SCHEMA,
929
- BIND_NEXT_JOURNAL_SCHEMA,
930
- }:
931
- raise PipelineStateError(f"bind-next journal has invalid schema: {path}")
932
- if transaction.get("repo") != str(repo):
933
- raise PipelineStateError(f"bind-next journal belongs to another worktree: {path}")
934
- if transaction.get("previous_branch") == state.branch:
935
- matches.append((path, transaction))
936
- if not matches:
937
- return None
938
- if len(matches) != 1:
939
- raise PipelineStateError("multiple bind-next journals claim the current STATE branch")
940
- if state.phase != "shipped" or state.status != "done":
941
- raise PipelineStateError("bind-next journal requires STATE shipped/done")
942
-
943
- path, transaction = matches[0]
944
955
  required = (
945
956
  "branch",
946
957
  "previous_branch",
@@ -1017,12 +1028,37 @@ def _bind_next_recovery(
1017
1028
  raise PipelineStateError("bind-next journal landing does not contain ship")
1018
1029
  if not _is_ancestor(repo, landing, base):
1019
1030
  raise PipelineStateError("bind-next journal landing is not an ancestor of base")
1020
- if transaction["remote_default"] != "origin/main":
1031
+ if transaction["remote_default"] != f"origin/{state.default_branch}":
1021
1032
  raise PipelineStateError("bind-next journal has invalid remote default")
1022
1033
  if stage not in {"prepared", "switched", "retired"}:
1023
1034
  raise PipelineStateError("bind-next journal has invalid stage")
1024
1035
 
1025
- current = _current_branch(repo)
1036
+ stale_retired = False
1037
+ if stage == "retired":
1038
+ target_ref = _run_git(
1039
+ repo,
1040
+ "show-ref",
1041
+ "--verify",
1042
+ "--quiet",
1043
+ f"refs/heads/{branch}",
1044
+ check=False,
1045
+ )
1046
+ if target_ref.returncode not in {0, 1}:
1047
+ detail = (target_ref.stderr or target_ref.stdout).strip()
1048
+ raise PipelineStateError(
1049
+ f"could not check bind-next target branch {branch}: {detail}"
1050
+ )
1051
+ target_exists = target_ref.returncode == 0
1052
+ stale_retired = current not in {previous, branch} or not target_exists
1053
+ if stale_retired:
1054
+ # If the completed target is gone while the previous branch is checked
1055
+ # out, still prove that branch has not moved away from the recorded ship.
1056
+ if current == previous:
1057
+ head = _run_git(repo, "rev-parse", "HEAD").stdout.strip()
1058
+ if head != ship:
1059
+ raise PipelineStateError("bind-next previous branch is not at journal ship")
1060
+ return None
1061
+
1026
1062
  if current not in {previous, branch}:
1027
1063
  raise PipelineStateError("bind-next journal does not own the current branch")
1028
1064
  if current == previous and stage != "prepared":
@@ -1057,6 +1093,52 @@ def _bind_next_recovery(
1057
1093
  return result
1058
1094
 
1059
1095
 
1096
+ def _bind_next_recovery(
1097
+ repo: Path,
1098
+ state: PipelineState,
1099
+ ) -> Optional[dict[str, object]]:
1100
+ journal_root = _git_path(repo, BIND_NEXT_JOURNAL_DIR)
1101
+ if not journal_root.exists() and not journal_root.is_symlink():
1102
+ return None
1103
+ if journal_root.is_symlink() or not journal_root.is_dir():
1104
+ raise PipelineStateError(f"bind-next journal root must be a real directory: {journal_root}")
1105
+
1106
+ matches: list[tuple[Path, dict[str, object]]] = []
1107
+ for path in sorted(journal_root.glob("*.json")):
1108
+ transaction = _read_json(path)
1109
+ if transaction.get("schema") not in {
1110
+ LEGACY_BIND_NEXT_JOURNAL_SCHEMA,
1111
+ BIND_NEXT_JOURNAL_SCHEMA,
1112
+ }:
1113
+ raise PipelineStateError(f"bind-next journal has invalid schema: {path}")
1114
+ if transaction.get("repo") != str(repo):
1115
+ raise PipelineStateError(f"bind-next journal belongs to another worktree: {path}")
1116
+ if transaction.get("previous_branch") == state.branch:
1117
+ matches.append((path, transaction))
1118
+ if not matches:
1119
+ return None
1120
+ if state.phase != "shipped" or state.status != "done":
1121
+ if len(matches) != 1:
1122
+ raise PipelineStateError("multiple bind-next journals claim the current STATE branch")
1123
+ raise PipelineStateError("bind-next journal requires STATE shipped/done")
1124
+
1125
+ current = _current_branch(repo)
1126
+ recoveries: list[dict[str, object]] = []
1127
+ for path, transaction in matches:
1128
+ recovery = _bind_next_journal_recovery(
1129
+ repo,
1130
+ state,
1131
+ path,
1132
+ transaction,
1133
+ current,
1134
+ )
1135
+ if recovery is not None:
1136
+ recoveries.append(recovery)
1137
+ if len(recoveries) > 1:
1138
+ raise PipelineStateError("multiple bind-next journals claim the current STATE branch")
1139
+ return recoveries[0] if recoveries else None
1140
+
1141
+
1060
1142
  def _pending_discussion_block(repo: Path, phase: Optional[str]) -> Optional[str]:
1061
1143
  pending, error = _pending_answers(repo)
1062
1144
  if error:
@@ -1077,7 +1159,7 @@ def route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
1077
1159
  result["recovery"] = recovery
1078
1160
  if route.get("phase") == "define":
1079
1161
  route["mode"] = "corrections"
1080
- elif route.get("phase") == "plan":
1162
+ elif route.get("phase") == "plan" and recovery.get("source", "build") == "build":
1081
1163
  route["mode"] = "build-repair"
1082
1164
  if route["action"] == "run-phase" and result["state"]["archive"] is None:
1083
1165
  reason = _pending_discussion_block(_repo_root(repo), route.get("phase"))
@@ -1668,6 +1750,8 @@ def _validate_transition(
1668
1750
  },
1669
1751
  ("define", "done", "plan", "active"): {"planning started"},
1670
1752
  ("decide", "done", "plan", "active"): {"planning started"},
1753
+ ("plan", "active", "define", "active"): {"plan intent corrections requested"},
1754
+ ("plan", "blocked", "define", "active"): {"plan intent corrections requested"},
1671
1755
  ("ship", "blocked", "plan", "active"): {"patch plan reopened"},
1672
1756
  ("ship", "active", "shipped", "done"): {
1673
1757
  "archive preflight passed; shipment recorded",
@@ -1693,7 +1777,10 @@ def transition_state(
1693
1777
  if unsupported:
1694
1778
  raise PipelineStateError(f"unsupported state fields: {', '.join(sorted(unsupported))}")
1695
1779
  if not changes:
1696
- raise PipelineStateError("transition requires at least one changed field")
1780
+ raise PipelineStateError(
1781
+ "transition requires at least one changed field; "
1782
+ "to record only a Log event, pass --set-status with the current status"
1783
+ )
1697
1784
  required_expected = {"phase", "status", "branch", "archive"} | set(changes)
1698
1785
  missing_expected = sorted(required_expected - set(expected))
1699
1786
  if missing_expected:
@@ -1720,9 +1807,10 @@ def transition_state(
1720
1807
  )
1721
1808
  if reason:
1722
1809
  raise PipelineStateError(reason)
1723
- if state.phase in {"research", "decide"} and (
1810
+ leaving_define = (state.phase, after.phase, after.status) == ("define", "define", "done")
1811
+ if leaving_define or (state.phase in {"research", "decide"} and (
1724
1812
  after.phase != state.phase or after.status == "done"
1725
- ):
1813
+ )):
1726
1814
  if __package__:
1727
1815
  from . import check_handoffs
1728
1816
  else:
@@ -1731,6 +1819,8 @@ def transition_state(
1731
1819
  except ImportError: # pragma: no cover - package imports used by tests
1732
1820
  from scripts import check_handoffs
1733
1821
  validator = {
1822
+ # Approved intent carries its spec-reach probe tables complete.
1823
+ "define": check_handoffs.validate_intent_probes,
1734
1824
  "research": check_handoffs.validate_research_artifacts,
1735
1825
  "decide": check_handoffs.validate_decide_artifacts,
1736
1826
  }[state.phase]
@@ -1747,6 +1837,16 @@ def transition_state(
1747
1837
  rendered, after.phase,
1748
1838
  _build_recovery().MARKER + json.dumps(recovery, sort_keys=True),
1749
1839
  )
1840
+ elif (
1841
+ state.phase == "plan"
1842
+ and state.status in {"active", "blocked"}
1843
+ and (after.phase, after.status) == ("define", "active")
1844
+ ):
1845
+ recovery = _build_recovery().begin(resolved, state, after, event)
1846
+ rendered = _append_event(
1847
+ rendered, after.phase,
1848
+ _build_recovery().MARKER + json.dumps(recovery, sort_keys=True),
1849
+ )
1750
1850
  _atomic_write(path, rendered)
1751
1851
  return {
1752
1852
  "schema": STATE_SCHEMA,
@@ -198,10 +198,10 @@ def select_fetched_base(
198
198
  use_lookahead: bool,
199
199
  ) -> dict:
200
200
  root = repo.resolve()
201
- if not re.fullmatch(r"origin/[A-Za-z0-9][A-Za-z0-9._/-]*", remote_default):
201
+ if not remote_default.startswith("origin/") or not _common.valid_default_branch(
202
+ remote_default.removeprefix("origin/")
203
+ ):
202
204
  raise LookaheadError("remote default must be an origin branch")
203
- if ".." in remote_default or "//" in remote_default:
204
- raise LookaheadError("remote default is invalid")
205
205
  resolved = subprocess.run(
206
206
  ["git", "-C", str(root), "rev-parse", "--verify", f"{remote_default}^{{commit}}"],
207
207
  capture_output=True,