@opengsd/gsd-path 1.5.0 → 1.6.1

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 (363) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +169 -0
  3. package/DOCS.md +4 -3
  4. package/FULL.md +68 -7
  5. package/HOOKS.md +81 -4
  6. package/MIGRATE.md +12 -0
  7. package/QUICK.md +4 -2
  8. package/README.md +69 -16
  9. package/RUNTIME.md +23 -5
  10. package/UPDATE.md +35 -0
  11. package/WORKFLOW.md +66 -7
  12. package/package.json +1 -1
  13. package/scripts/_common.py +150 -1
  14. package/scripts/build_recovery.py +62 -30
  15. package/scripts/build_state.py +195 -5
  16. package/scripts/check_handoffs.py +92 -30
  17. package/scripts/check_task_briefs.py +27 -19
  18. package/scripts/detect_project.py +17 -2
  19. package/scripts/discussion_records.py +9 -1
  20. package/scripts/discussion_validate.py +7 -6
  21. package/scripts/dispatch_driver.py +174 -36
  22. package/scripts/git_guard.py +42 -7
  23. package/scripts/guard_hook.py +1216 -47
  24. package/scripts/install.mjs +76 -3
  25. package/scripts/install.py +182 -37
  26. package/scripts/integration.py +115 -68
  27. package/scripts/isolation.py +192 -23
  28. package/scripts/members.py +68 -25
  29. package/scripts/migrate_core.py +2 -0
  30. package/scripts/model_policy.py +13 -2
  31. package/scripts/pipeline_diagnose.py +17 -2
  32. package/scripts/pipeline_git.py +87 -35
  33. package/scripts/pipeline_state.py +31 -7
  34. package/scripts/pipeline_undo.py +17 -8
  35. package/scripts/promote_lookahead.py +3 -3
  36. package/scripts/review_findings.py +180 -44
  37. package/scripts/roadmap.py +9 -1
  38. package/scripts/runtime_store.py +1 -0
  39. package/scripts/state_checkpoint.py +30 -9
  40. package/scripts/state_promote.py +92 -5
  41. package/scripts/task_context.py +2 -0
  42. package/scripts/workflow_run.py +9 -2
  43. package/skills/gsd-path/DEFINE.md +6 -2
  44. package/skills/gsd-path/PLAN.md +6 -2
  45. package/skills/gsd-path/ROADMAP.md +16 -6
  46. package/skills/gsd-path/SHIP.md +38 -11
  47. package/skills/gsd-path/SKILL.md +52 -24
  48. package/skills/gsd-path/references/build-native.md +96 -9
  49. package/skills/gsd-path/references/build-recovery.md +13 -0
  50. package/skills/gsd-path/references/coder.md +7 -3
  51. package/skills/gsd-path/references/model-policy.md +3 -1
  52. package/skills/gsd-path/references/operating-rules.md +14 -5
  53. package/skills/gsd-path/references/planner.md +13 -1
  54. package/skills/gsd-path/references/reviewer-final.md +5 -5
  55. package/skills/gsd-path/references/reviewer-wave.md +46 -13
  56. package/skills/gsd-path/references/runtime-selection.md +10 -0
  57. package/skills/gsd-path/scripts/_common.py +150 -1
  58. package/skills/gsd-path/scripts/build_recovery.py +62 -30
  59. package/skills/gsd-path/scripts/build_state.py +195 -5
  60. package/skills/gsd-path/scripts/check_handoffs.py +92 -30
  61. package/skills/gsd-path/scripts/check_task_briefs.py +27 -19
  62. package/skills/gsd-path/scripts/detect_project.py +17 -2
  63. package/skills/gsd-path/scripts/discussion_records.py +9 -1
  64. package/skills/gsd-path/scripts/discussion_validate.py +7 -6
  65. package/skills/gsd-path/scripts/dispatch_driver.py +174 -36
  66. package/skills/gsd-path/scripts/git_guard.py +42 -7
  67. package/skills/gsd-path/scripts/integration.py +115 -68
  68. package/skills/gsd-path/scripts/isolation.py +192 -23
  69. package/skills/gsd-path/scripts/members.py +68 -25
  70. package/skills/gsd-path/scripts/model_policy.py +13 -2
  71. package/skills/gsd-path/scripts/pipeline_git.py +87 -35
  72. package/skills/gsd-path/scripts/pipeline_state.py +31 -7
  73. package/skills/gsd-path/scripts/promote_lookahead.py +3 -3
  74. package/skills/gsd-path/scripts/review_findings.py +180 -44
  75. package/skills/gsd-path/scripts/roadmap.py +9 -1
  76. package/skills/gsd-path/scripts/state_checkpoint.py +30 -9
  77. package/skills/gsd-path/scripts/state_promote.py +92 -5
  78. package/skills/gsd-path/scripts/task_context.py +2 -0
  79. package/skills/gsd-path/scripts/workflow_run.py +9 -2
  80. package/skills/gsd-path/templates/final-review.md +5 -5
  81. package/skills/gsd-path/templates/state.md +1 -0
  82. package/skills/gsd-path/templates/task.md +1 -0
  83. package/skills/gsd-path/templates/wave-review.md +18 -9
  84. package/skills/gsd-path-build/references/build-native.md +96 -9
  85. package/skills/gsd-path-build/references/build-recovery.md +13 -0
  86. package/skills/gsd-path-build/references/coder.md +7 -3
  87. package/skills/gsd-path-build/references/model-policy.md +3 -1
  88. package/skills/gsd-path-build/references/operating-rules.md +14 -5
  89. package/skills/gsd-path-build/references/reviewer-final.md +5 -5
  90. package/skills/gsd-path-build/references/reviewer-wave.md +46 -13
  91. package/skills/gsd-path-build/references/runtime-selection.md +10 -0
  92. package/skills/gsd-path-build/scripts/_common.py +150 -1
  93. package/skills/gsd-path-build/scripts/build_recovery.py +62 -30
  94. package/skills/gsd-path-build/scripts/build_state.py +195 -5
  95. package/skills/gsd-path-build/scripts/check_handoffs.py +92 -30
  96. package/skills/gsd-path-build/scripts/check_task_briefs.py +27 -19
  97. package/skills/gsd-path-build/scripts/detect_project.py +17 -2
  98. package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
  99. package/skills/gsd-path-build/scripts/discussion_validate.py +7 -6
  100. package/skills/gsd-path-build/scripts/dispatch_driver.py +174 -36
  101. package/skills/gsd-path-build/scripts/integration.py +115 -68
  102. package/skills/gsd-path-build/scripts/isolation.py +192 -23
  103. package/skills/gsd-path-build/scripts/members.py +68 -25
  104. package/skills/gsd-path-build/scripts/model_policy.py +13 -2
  105. package/skills/gsd-path-build/scripts/pipeline_git.py +87 -35
  106. package/skills/gsd-path-build/scripts/pipeline_state.py +31 -7
  107. package/skills/gsd-path-build/scripts/promote_lookahead.py +3 -3
  108. package/skills/gsd-path-build/scripts/review_findings.py +180 -44
  109. package/skills/gsd-path-build/scripts/roadmap.py +9 -1
  110. package/skills/gsd-path-build/scripts/state_checkpoint.py +30 -9
  111. package/skills/gsd-path-build/scripts/state_promote.py +92 -5
  112. package/skills/gsd-path-build/scripts/task_context.py +2 -0
  113. package/skills/gsd-path-build/scripts/workflow_run.py +9 -2
  114. package/skills/gsd-path-build/templates/task.md +1 -0
  115. package/skills/gsd-path-build/templates/wave-review.md +18 -9
  116. package/skills/gsd-path-decide/references/model-policy.md +3 -1
  117. package/skills/gsd-path-decide/references/operating-rules.md +14 -5
  118. package/skills/gsd-path-decide/references/runtime-selection.md +10 -0
  119. package/skills/gsd-path-decide/scripts/_common.py +150 -1
  120. package/skills/gsd-path-decide/scripts/build_recovery.py +62 -30
  121. package/skills/gsd-path-decide/scripts/check_handoffs.py +92 -30
  122. package/skills/gsd-path-decide/scripts/check_task_briefs.py +27 -19
  123. package/skills/gsd-path-decide/scripts/detect_project.py +17 -2
  124. package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
  125. package/skills/gsd-path-decide/scripts/discussion_validate.py +7 -6
  126. package/skills/gsd-path-decide/scripts/integration.py +115 -68
  127. package/skills/gsd-path-decide/scripts/isolation.py +192 -23
  128. package/skills/gsd-path-decide/scripts/members.py +68 -25
  129. package/skills/gsd-path-decide/scripts/model_policy.py +13 -2
  130. package/skills/gsd-path-decide/scripts/pipeline_git.py +87 -35
  131. package/skills/gsd-path-decide/scripts/pipeline_state.py +31 -7
  132. package/skills/gsd-path-decide/scripts/promote_lookahead.py +3 -3
  133. package/skills/gsd-path-decide/scripts/roadmap.py +9 -1
  134. package/skills/gsd-path-decide/scripts/state_checkpoint.py +30 -9
  135. package/skills/gsd-path-decide/scripts/state_promote.py +92 -5
  136. package/skills/gsd-path-define/SKILL.md +6 -2
  137. package/skills/gsd-path-define/references/build-recovery.md +13 -0
  138. package/skills/gsd-path-define/references/operating-rules.md +14 -5
  139. package/skills/gsd-path-define/references/runtime-selection.md +10 -0
  140. package/skills/gsd-path-define/scripts/_common.py +150 -1
  141. package/skills/gsd-path-define/scripts/build_recovery.py +62 -30
  142. package/skills/gsd-path-define/scripts/check_handoffs.py +92 -30
  143. package/skills/gsd-path-define/scripts/check_task_briefs.py +27 -19
  144. package/skills/gsd-path-define/scripts/detect_project.py +17 -2
  145. package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
  146. package/skills/gsd-path-define/scripts/discussion_validate.py +7 -6
  147. package/skills/gsd-path-define/scripts/integration.py +115 -68
  148. package/skills/gsd-path-define/scripts/isolation.py +192 -23
  149. package/skills/gsd-path-define/scripts/members.py +68 -25
  150. package/skills/gsd-path-define/scripts/model_policy.py +13 -2
  151. package/skills/gsd-path-define/scripts/pipeline_git.py +87 -35
  152. package/skills/gsd-path-define/scripts/pipeline_state.py +31 -7
  153. package/skills/gsd-path-define/scripts/promote_lookahead.py +3 -3
  154. package/skills/gsd-path-define/scripts/roadmap.py +9 -1
  155. package/skills/gsd-path-define/scripts/state_checkpoint.py +30 -9
  156. package/skills/gsd-path-define/scripts/state_promote.py +92 -5
  157. package/skills/gsd-path-define/templates/state.md +1 -0
  158. package/skills/gsd-path-discuss/references/operating-rules.md +14 -5
  159. package/skills/gsd-path-discuss/references/runtime-selection.md +10 -0
  160. package/skills/gsd-path-discuss/scripts/_common.py +150 -1
  161. package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
  162. package/skills/gsd-path-discuss/scripts/model_policy.py +13 -2
  163. package/skills/gsd-path-docs-audit/references/model-policy.md +3 -1
  164. package/skills/gsd-path-docs-audit/references/operating-rules.md +14 -5
  165. package/skills/gsd-path-docs-audit/references/runtime-selection.md +10 -0
  166. package/skills/gsd-path-docs-audit/scripts/_common.py +150 -1
  167. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +62 -30
  168. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +92 -30
  169. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +27 -19
  170. package/skills/gsd-path-docs-audit/scripts/detect_project.py +17 -2
  171. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
  172. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +7 -6
  173. package/skills/gsd-path-docs-audit/scripts/integration.py +115 -68
  174. package/skills/gsd-path-docs-audit/scripts/isolation.py +192 -23
  175. package/skills/gsd-path-docs-audit/scripts/members.py +68 -25
  176. package/skills/gsd-path-docs-audit/scripts/model_policy.py +13 -2
  177. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +87 -35
  178. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +31 -7
  179. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +3 -3
  180. package/skills/gsd-path-docs-audit/scripts/roadmap.py +9 -1
  181. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +30 -9
  182. package/skills/gsd-path-docs-audit/scripts/state_promote.py +92 -5
  183. package/skills/gsd-path-forensics/references/operating-rules.md +14 -5
  184. package/skills/gsd-path-forensics/references/runtime-selection.md +10 -0
  185. package/skills/gsd-path-forensics/scripts/_common.py +150 -1
  186. package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
  187. package/skills/gsd-path-forensics/scripts/model_policy.py +13 -2
  188. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
  189. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +17 -8
  190. package/skills/gsd-path-inspect/references/model-policy.md +3 -1
  191. package/skills/gsd-path-inspect/references/operating-rules.md +14 -5
  192. package/skills/gsd-path-inspect/references/runtime-selection.md +10 -0
  193. package/skills/gsd-path-inspect/scripts/_common.py +150 -1
  194. package/skills/gsd-path-inspect/scripts/build_recovery.py +62 -30
  195. package/skills/gsd-path-inspect/scripts/check_handoffs.py +92 -30
  196. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +27 -19
  197. package/skills/gsd-path-inspect/scripts/detect_project.py +17 -2
  198. package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
  199. package/skills/gsd-path-inspect/scripts/discussion_validate.py +7 -6
  200. package/skills/gsd-path-inspect/scripts/integration.py +115 -68
  201. package/skills/gsd-path-inspect/scripts/isolation.py +192 -23
  202. package/skills/gsd-path-inspect/scripts/members.py +68 -25
  203. package/skills/gsd-path-inspect/scripts/model_policy.py +13 -2
  204. package/skills/gsd-path-inspect/scripts/pipeline_git.py +87 -35
  205. package/skills/gsd-path-inspect/scripts/pipeline_state.py +31 -7
  206. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +3 -3
  207. package/skills/gsd-path-inspect/scripts/roadmap.py +9 -1
  208. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +30 -9
  209. package/skills/gsd-path-inspect/scripts/state_promote.py +92 -5
  210. package/skills/gsd-path-inspect/scripts/workflow_run.py +9 -2
  211. package/skills/gsd-path-inspect/templates/state.md +1 -0
  212. package/skills/gsd-path-loop/references/operating-rules.md +14 -5
  213. package/skills/gsd-path-loop/references/runtime-selection.md +10 -0
  214. package/skills/gsd-path-loop/scripts/_common.py +150 -1
  215. package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
  216. package/skills/gsd-path-loop/scripts/model_policy.py +13 -2
  217. package/skills/gsd-path-migrate/SKILL.md +8 -0
  218. package/skills/gsd-path-migrate/references/operating-rules.md +14 -5
  219. package/skills/gsd-path-migrate/references/runtime-selection.md +10 -0
  220. package/skills/gsd-path-migrate/scripts/_common.py +150 -1
  221. package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
  222. package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -0
  223. package/skills/gsd-path-migrate/scripts/model_policy.py +13 -2
  224. package/skills/gsd-path-plan/SKILL.md +6 -2
  225. package/skills/gsd-path-plan/references/build-recovery.md +13 -0
  226. package/skills/gsd-path-plan/references/model-policy.md +3 -1
  227. package/skills/gsd-path-plan/references/operating-rules.md +14 -5
  228. package/skills/gsd-path-plan/references/planner.md +13 -1
  229. package/skills/gsd-path-plan/references/runtime-selection.md +10 -0
  230. package/skills/gsd-path-plan/scripts/_common.py +150 -1
  231. package/skills/gsd-path-plan/scripts/build_recovery.py +62 -30
  232. package/skills/gsd-path-plan/scripts/check_handoffs.py +92 -30
  233. package/skills/gsd-path-plan/scripts/check_task_briefs.py +27 -19
  234. package/skills/gsd-path-plan/scripts/detect_project.py +17 -2
  235. package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
  236. package/skills/gsd-path-plan/scripts/discussion_validate.py +7 -6
  237. package/skills/gsd-path-plan/scripts/integration.py +115 -68
  238. package/skills/gsd-path-plan/scripts/isolation.py +192 -23
  239. package/skills/gsd-path-plan/scripts/members.py +68 -25
  240. package/skills/gsd-path-plan/scripts/model_policy.py +13 -2
  241. package/skills/gsd-path-plan/scripts/pipeline_git.py +87 -35
  242. package/skills/gsd-path-plan/scripts/pipeline_state.py +31 -7
  243. package/skills/gsd-path-plan/scripts/promote_lookahead.py +3 -3
  244. package/skills/gsd-path-plan/scripts/roadmap.py +9 -1
  245. package/skills/gsd-path-plan/scripts/state_checkpoint.py +30 -9
  246. package/skills/gsd-path-plan/scripts/state_promote.py +92 -5
  247. package/skills/gsd-path-plan/scripts/workflow_run.py +9 -2
  248. package/skills/gsd-path-plan/templates/task.md +1 -0
  249. package/skills/gsd-path-research/references/model-policy.md +3 -1
  250. package/skills/gsd-path-research/references/operating-rules.md +14 -5
  251. package/skills/gsd-path-research/references/runtime-selection.md +10 -0
  252. package/skills/gsd-path-research/scripts/_common.py +150 -1
  253. package/skills/gsd-path-research/scripts/build_recovery.py +62 -30
  254. package/skills/gsd-path-research/scripts/check_handoffs.py +92 -30
  255. package/skills/gsd-path-research/scripts/check_task_briefs.py +27 -19
  256. package/skills/gsd-path-research/scripts/detect_project.py +17 -2
  257. package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
  258. package/skills/gsd-path-research/scripts/discussion_validate.py +7 -6
  259. package/skills/gsd-path-research/scripts/integration.py +115 -68
  260. package/skills/gsd-path-research/scripts/isolation.py +192 -23
  261. package/skills/gsd-path-research/scripts/members.py +68 -25
  262. package/skills/gsd-path-research/scripts/model_policy.py +13 -2
  263. package/skills/gsd-path-research/scripts/pipeline_git.py +87 -35
  264. package/skills/gsd-path-research/scripts/pipeline_state.py +31 -7
  265. package/skills/gsd-path-research/scripts/promote_lookahead.py +3 -3
  266. package/skills/gsd-path-research/scripts/roadmap.py +9 -1
  267. package/skills/gsd-path-research/scripts/state_checkpoint.py +30 -9
  268. package/skills/gsd-path-research/scripts/state_promote.py +92 -5
  269. package/skills/gsd-path-roadmap/SKILL.md +16 -6
  270. package/skills/gsd-path-roadmap/references/model-policy.md +3 -1
  271. package/skills/gsd-path-roadmap/references/operating-rules.md +14 -5
  272. package/skills/gsd-path-roadmap/references/runtime-selection.md +10 -0
  273. package/skills/gsd-path-roadmap/scripts/_common.py +150 -1
  274. package/skills/gsd-path-roadmap/scripts/build_recovery.py +62 -30
  275. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +92 -30
  276. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +27 -19
  277. package/skills/gsd-path-roadmap/scripts/detect_project.py +17 -2
  278. package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
  279. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +7 -6
  280. package/skills/gsd-path-roadmap/scripts/integration.py +115 -68
  281. package/skills/gsd-path-roadmap/scripts/isolation.py +192 -23
  282. package/skills/gsd-path-roadmap/scripts/members.py +68 -25
  283. package/skills/gsd-path-roadmap/scripts/model_policy.py +13 -2
  284. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +87 -35
  285. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +31 -7
  286. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +3 -3
  287. package/skills/gsd-path-roadmap/scripts/roadmap.py +9 -1
  288. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +30 -9
  289. package/skills/gsd-path-roadmap/scripts/state_promote.py +92 -5
  290. package/skills/gsd-path-ship/SKILL.md +38 -11
  291. package/skills/gsd-path-ship/references/model-policy.md +3 -1
  292. package/skills/gsd-path-ship/references/operating-rules.md +14 -5
  293. package/skills/gsd-path-ship/references/reviewer-final.md +5 -5
  294. package/skills/gsd-path-ship/references/reviewer-wave.md +46 -13
  295. package/skills/gsd-path-ship/references/runtime-selection.md +10 -0
  296. package/skills/gsd-path-ship/scripts/_common.py +150 -1
  297. package/skills/gsd-path-ship/scripts/build_recovery.py +62 -30
  298. package/skills/gsd-path-ship/scripts/build_state.py +195 -5
  299. package/skills/gsd-path-ship/scripts/check_handoffs.py +92 -30
  300. package/skills/gsd-path-ship/scripts/check_task_briefs.py +27 -19
  301. package/skills/gsd-path-ship/scripts/detect_project.py +17 -2
  302. package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
  303. package/skills/gsd-path-ship/scripts/discussion_validate.py +7 -6
  304. package/skills/gsd-path-ship/scripts/integration.py +115 -68
  305. package/skills/gsd-path-ship/scripts/isolation.py +192 -23
  306. package/skills/gsd-path-ship/scripts/members.py +68 -25
  307. package/skills/gsd-path-ship/scripts/model_policy.py +13 -2
  308. package/skills/gsd-path-ship/scripts/pipeline_git.py +87 -35
  309. package/skills/gsd-path-ship/scripts/pipeline_state.py +31 -7
  310. package/skills/gsd-path-ship/scripts/promote_lookahead.py +3 -3
  311. package/skills/gsd-path-ship/scripts/roadmap.py +9 -1
  312. package/skills/gsd-path-ship/scripts/state_checkpoint.py +30 -9
  313. package/skills/gsd-path-ship/scripts/state_promote.py +92 -5
  314. package/skills/gsd-path-ship/scripts/workflow_run.py +9 -2
  315. package/skills/gsd-path-ship/templates/final-review.md +5 -5
  316. package/skills/gsd-path-ship/templates/wave-review.md +18 -9
  317. package/skills/gsd-path-undo/references/operating-rules.md +14 -5
  318. package/skills/gsd-path-undo/references/runtime-selection.md +10 -0
  319. package/skills/gsd-path-undo/scripts/_common.py +150 -1
  320. package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
  321. package/skills/gsd-path-undo/scripts/model_policy.py +13 -2
  322. package/skills/gsd-path-undo/scripts/pipeline_undo.py +17 -8
  323. package/skills/path/DEFINE.md +6 -2
  324. package/skills/path/PLAN.md +6 -2
  325. package/skills/path/ROADMAP.md +16 -6
  326. package/skills/path/SHIP.md +38 -11
  327. package/skills/path/SKILL.md +52 -24
  328. package/skills/path/references/build-native.md +96 -9
  329. package/skills/path/references/build-recovery.md +13 -0
  330. package/skills/path/references/coder.md +7 -3
  331. package/skills/path/references/model-policy.md +3 -1
  332. package/skills/path/references/operating-rules.md +14 -5
  333. package/skills/path/references/planner.md +13 -1
  334. package/skills/path/references/reviewer-final.md +5 -5
  335. package/skills/path/references/reviewer-wave.md +46 -13
  336. package/skills/path/references/runtime-selection.md +10 -0
  337. package/skills/path/scripts/_common.py +150 -1
  338. package/skills/path/scripts/build_recovery.py +62 -30
  339. package/skills/path/scripts/build_state.py +195 -5
  340. package/skills/path/scripts/check_handoffs.py +92 -30
  341. package/skills/path/scripts/check_task_briefs.py +27 -19
  342. package/skills/path/scripts/detect_project.py +17 -2
  343. package/skills/path/scripts/discussion_records.py +9 -1
  344. package/skills/path/scripts/discussion_validate.py +7 -6
  345. package/skills/path/scripts/dispatch_driver.py +174 -36
  346. package/skills/path/scripts/git_guard.py +42 -7
  347. package/skills/path/scripts/integration.py +115 -68
  348. package/skills/path/scripts/isolation.py +192 -23
  349. package/skills/path/scripts/members.py +68 -25
  350. package/skills/path/scripts/model_policy.py +13 -2
  351. package/skills/path/scripts/pipeline_git.py +87 -35
  352. package/skills/path/scripts/pipeline_state.py +31 -7
  353. package/skills/path/scripts/promote_lookahead.py +3 -3
  354. package/skills/path/scripts/review_findings.py +180 -44
  355. package/skills/path/scripts/roadmap.py +9 -1
  356. package/skills/path/scripts/state_checkpoint.py +30 -9
  357. package/skills/path/scripts/state_promote.py +92 -5
  358. package/skills/path/scripts/task_context.py +2 -0
  359. package/skills/path/scripts/workflow_run.py +9 -2
  360. package/skills/path/templates/final-review.md +5 -5
  361. package/skills/path/templates/state.md +1 -0
  362. package/skills/path/templates/task.md +1 -0
  363. package/skills/path/templates/wave-review.md +18 -9
@@ -2,8 +2,9 @@
2
2
  # gsd-path project runtime
3
3
  """Deterministic GSD Path branch names and pipeline commit messages.
4
4
 
5
- Bound work lives on `gsd-path/M00N` for that milestone. The required remote
6
- default `main` stays a separate trunk. Ship merges the bound branch onto main;
5
+ Bound work lives on `gsd-path/M00N` for that milestone. The remote default
6
+ that STATE.md records (`main` when unrecorded) stays a separate trunk. Ship
7
+ merges the bound branch onto it;
7
8
  the next milestone binds a new unused `gsd-path/M00N` and retires the
8
9
  integrated previous branch, locally and on origin.
9
10
  """
@@ -98,7 +99,8 @@ def ship_subject(archive_name: str) -> str:
98
99
 
99
100
 
100
101
  def integrate_subject(archive_name: str, default_branch: str) -> str:
101
- if not default_branch or default_branch.startswith("origin/"):
102
+ # The bare name, under the rule that records it; `origin/trunk` is a legal bare name.
103
+ if not _common.valid_default_branch(default_branch):
102
104
  raise PipelineGitError(f"default branch is invalid: {default_branch}")
103
105
  number = milestone_number(archive_name)
104
106
  return (
@@ -363,7 +365,7 @@ def _remote_branch_exists(repo: Path, branch: str) -> bool:
363
365
  return _remote_ref_sha(repo, f"refs/heads/{branch}") is not None
364
366
 
365
367
 
366
- def _pull_request_tag_fields(repo: Path, ref: str) -> dict[str, str]:
368
+ def _milestone_tag_fields(repo: Path, ref: str) -> dict[str, str]:
367
369
  tag_type = _run_git(repo, "cat-file", "-t", ref, check=False)
368
370
  if tag_type.returncode != 0 or tag_type.stdout.strip() != "tag":
369
371
  return {}
@@ -373,7 +375,7 @@ def _pull_request_tag_fields(repo: Path, ref: str) -> dict[str, str]:
373
375
  match = re.fullmatch(r"(Mode|Pull-Request|Ship|Landing): (.+)", line)
374
376
  if match:
375
377
  if match.group(1) in fields:
376
- raise PipelineGitError("pull-request milestone tag repeats metadata")
378
+ raise PipelineGitError("milestone tag repeats metadata")
377
379
  fields[match.group(1)] = match.group(2)
378
380
  return fields
379
381
 
@@ -404,7 +406,15 @@ def _validated_shipped_state(repo: Path) -> dict[str, object]:
404
406
  return state
405
407
 
406
408
 
407
- def _require_pull_request_integration_proof(
409
+ # Metadata a published milestone tag must carry, per integration mode, before
410
+ # bind-next accepts a previous bound branch that the forge deleted on merge.
411
+ TAG_PROOF_FIELDS = {
412
+ "pull-request": {"Mode", "Pull-Request", "Ship", "Landing"},
413
+ "external-landing": {"Mode", "Ship", "Landing"},
414
+ }
415
+
416
+
417
+ def _require_tag_integration_proof(
408
418
  repo: Path,
409
419
  ship: str,
410
420
  base: str,
@@ -415,8 +425,11 @@ def _require_pull_request_integration_proof(
415
425
  raise PipelineGitError("bind-next requires shipped/done state")
416
426
  if state.get("branch") != previous_branch:
417
427
  raise PipelineGitError("shipped state does not name the previous branch")
418
- if state.get("integration") != "pull-request":
419
- raise PipelineGitError("shipped integration mode is not pull-request")
428
+ mode = state.get("integration")
429
+ if mode not in TAG_PROOF_FIELDS:
430
+ raise PipelineGitError(
431
+ "shipped integration mode is not pull-request or external-landing"
432
+ )
420
433
  archive = state.get("archive")
421
434
  if not isinstance(archive, str):
422
435
  raise PipelineGitError("shipped state does not name an archive")
@@ -427,24 +440,23 @@ def _require_pull_request_integration_proof(
427
440
  ):
428
441
  raise PipelineGitError("shipped archive does not match the previous branch")
429
442
  ref = f"refs/tags/milestone/{match.group(1)}"
430
- fields = _pull_request_tag_fields(repo, ref)
431
- if set(fields) != {"Mode", "Pull-Request", "Ship", "Landing"}:
432
- raise PipelineGitError("pull-request integration proof is incomplete")
433
- if fields["Mode"] != "pull-request" or fields["Ship"] != ship:
434
- raise PipelineGitError("pull-request integration proof does not match shipped state")
435
- pull_request = fields["Pull-Request"]
436
- if re.fullmatch(
443
+ fields = _milestone_tag_fields(repo, ref)
444
+ if set(fields) != TAG_PROOF_FIELDS[mode]:
445
+ raise PipelineGitError(f"{mode} integration proof is incomplete")
446
+ if fields["Mode"] != mode or fields["Ship"] != ship:
447
+ raise PipelineGitError(f"{mode} integration proof does not match shipped state")
448
+ if mode == "pull-request" and re.fullmatch(
437
449
  r"https://github\.com/[^/]+/[^/]+/pull/[1-9][0-9]*",
438
- pull_request,
450
+ fields["Pull-Request"],
439
451
  ) is None:
440
452
  raise PipelineGitError("pull-request integration proof has an invalid PR URL")
441
453
  landing = fields["Landing"]
442
454
  if re.fullmatch(r"[0-9a-f]{40}", landing) is None:
443
- raise PipelineGitError("pull-request integration proof has an invalid landing")
455
+ raise PipelineGitError(f"{mode} integration proof has an invalid landing")
444
456
  local_object = _run_git(repo, "rev-parse", ref).stdout.strip()
445
457
  local_target = _run_git(repo, "rev-parse", f"{ref}^{{commit}}").stdout.strip()
446
458
  if local_target != landing:
447
- raise PipelineGitError("pull-request integration tag does not point at landing")
459
+ raise PipelineGitError(f"{mode} integration tag does not point at landing")
448
460
  remote = _run_git(
449
461
  repo,
450
462
  "ls-remote",
@@ -456,14 +468,14 @@ def _require_pull_request_integration_proof(
456
468
  check=False,
457
469
  )
458
470
  if remote.returncode != 0:
459
- raise PipelineGitError("pull-request integration tag is not published")
471
+ raise PipelineGitError(f"{mode} integration tag is not published")
460
472
  rows = dict(
461
473
  line.split("\t", 1)[::-1]
462
474
  for line in remote.stdout.splitlines()
463
475
  if "\t" in line
464
476
  )
465
477
  if rows != {ref: local_object, f"{ref}^{{}}": landing}:
466
- raise PipelineGitError("published pull-request integration tag differs")
478
+ raise PipelineGitError(f"published {mode} integration tag differs")
467
479
  parents = _run_git(
468
480
  repo,
469
481
  "rev-list",
@@ -472,12 +484,17 @@ def _require_pull_request_integration_proof(
472
484
  "1",
473
485
  landing,
474
486
  ).stdout.split()
475
- if len(parents) != 3 or parents[2] != ship:
476
- raise PipelineGitError("pull-request integration proof has invalid merge topology")
487
+ rebased = (
488
+ mode == "pull-request"
489
+ and len(parents) == 2
490
+ and _common.rebase_landing_problem(repo, ship, landing) is None
491
+ )
492
+ if not rebased and (len(parents) != 3 or parents[2] != ship):
493
+ raise PipelineGitError(f"{mode} integration proof has invalid merge topology")
477
494
  first_parent = _run_git(repo, "rev-list", "--first-parent", base).stdout.splitlines()
478
495
  if landing not in first_parent:
479
496
  raise PipelineGitError(
480
- "pull-request integration landing is not on main first-parent history"
497
+ f"{mode} integration landing is not on the default branch first-parent history"
481
498
  )
482
499
  return landing
483
500
 
@@ -533,6 +550,34 @@ def _write_bind_next_journal(path: Path, value: dict[str, object]) -> None:
533
550
  temporary.unlink()
534
551
 
535
552
 
553
+ def _require_state_remote_default(repo: Path, remote_default: str) -> str:
554
+ """Return the default branch STATE.md records; `remote_default` must name it.
555
+
556
+ No STATE.md yet (bind-initial before initialize) or no field means main.
557
+ An unreadable STATE.md also means main, as before the field existed: the
558
+ callers that need a valid state check it themselves.
559
+ """
560
+ if __package__:
561
+ from . import pipeline_state
562
+ else:
563
+ try:
564
+ import pipeline_state
565
+ except ImportError: # pragma: no cover - package import used by tests
566
+ from scripts import pipeline_state
567
+
568
+ default_name, unreadable = "main", ""
569
+ if (repo / ".project" / "STATE.md").exists():
570
+ try:
571
+ default_name = pipeline_state.load_state(repo)[0].default_branch
572
+ except (OSError, pipeline_state.PipelineStateError) as error:
573
+ unreadable = f" (STATE.md is unreadable: {error})"
574
+ if remote_default != f"origin/{default_name}":
575
+ raise PipelineGitError(
576
+ f"remote default must be origin/{default_name}, got {remote_default}{unreadable}"
577
+ )
578
+ return default_name
579
+
580
+
536
581
  def _initial_binding_snapshot(repo: Path) -> Optional[tuple]:
537
582
  """Admit only clean work or the validated, untracked initializer state."""
538
583
  dirty = _run_git(repo, "status", "--porcelain=v1", "-z", "--untracked-files=all").stdout
@@ -579,8 +624,7 @@ def bind_initial_milestone_branch(
579
624
  resolved = _require_worktree_root(repo)
580
625
  if not is_bound_branch(branch):
581
626
  raise PipelineGitError(f"invalid bound branch: {branch}")
582
- if remote_default != "origin/main":
583
- raise PipelineGitError(f"remote default must be origin/main, got {remote_default}")
627
+ default_name = _require_state_remote_default(resolved, remote_default)
584
628
 
585
629
  default_sha = _run_git(
586
630
  resolved,
@@ -600,7 +644,7 @@ def bind_initial_milestone_branch(
600
644
  raise PipelineGitError(
601
645
  f"validated base is stale: {base_sha} != {remote_default} {default_sha}"
602
646
  )
603
- remote_sha = _remote_ref_sha(resolved, "refs/heads/main")
647
+ remote_sha = _remote_ref_sha(resolved, f"refs/heads/{default_name}")
604
648
  if remote_sha != default_sha:
605
649
  raise PipelineGitError(
606
650
  f"fetched {remote_default} is stale relative to origin"
@@ -655,6 +699,7 @@ def retire_previous_branch(
655
699
  expected_sha: str,
656
700
  *,
657
701
  allow_remote_absent: bool = False,
702
+ rebased: bool = False,
658
703
  ) -> None:
659
704
  """Delete an integrated previous bound branch, locally and on origin.
660
705
 
@@ -702,7 +747,8 @@ def retire_previous_branch(
702
747
  if _ref_exists(repo, tracking_ref):
703
748
  _run_git(repo, "update-ref", "-d", tracking_ref)
704
749
  if _ref_exists(repo, local_ref):
705
- _run_git(repo, "branch", "-d", previous_branch)
750
+ # A rebased ship is not an ancestor of HEAD, so -d would refuse it.
751
+ _run_git(repo, "branch", "-D" if rebased else "-d", previous_branch)
706
752
 
707
753
 
708
754
  def _retire_members(repo: Path, ship_sha: str) -> None:
@@ -742,8 +788,7 @@ def bind_next_milestone_branch(
742
788
  raise PipelineGitError(f"invalid previous bound branch: {previous_branch}")
743
789
  if milestone_number(branch) <= milestone_number(previous_branch):
744
790
  raise PipelineGitError(f"next branch {branch} must follow {previous_branch}")
745
- if remote_default != "origin/main":
746
- raise PipelineGitError(f"remote default must be origin/main, got {remote_default}")
791
+ default_name = _require_state_remote_default(repo, remote_default)
747
792
 
748
793
  default_sha = _run_git(
749
794
  repo,
@@ -763,7 +808,7 @@ def bind_next_milestone_branch(
763
808
  raise PipelineGitError(
764
809
  f"validated base is stale: {base_sha} != {remote_default} {default_sha}"
765
810
  )
766
- live_default_sha = _remote_ref_sha(repo, "refs/heads/main")
811
+ live_default_sha = _remote_ref_sha(repo, f"refs/heads/{default_name}")
767
812
  if live_default_sha != default_sha:
768
813
  raise PipelineGitError(f"fetched {remote_default} is stale relative to origin")
769
814
  ship_sha = _run_git(
@@ -802,9 +847,15 @@ def bind_next_milestone_branch(
802
847
  landing_sha,
803
848
  check=False,
804
849
  )
805
- if integrated.returncode == 1:
850
+ # A forge rebase merge lands copies of the ship commits (#418); the
851
+ # pull-request milestone tag must then prove the landing.
852
+ rebased = (
853
+ integrated.returncode == 1
854
+ and _common.rebase_landing_problem(repo, ship_sha, landing_sha) is None
855
+ )
856
+ if integrated.returncode == 1 and not rebased:
806
857
  raise PipelineGitError("milestone landing does not contain the ship commit")
807
- if integrated.returncode != 0:
858
+ if integrated.returncode not in (0, 1):
808
859
  detail = integrated.stderr.strip() or integrated.stdout.strip()
809
860
  raise PipelineGitError(f"could not verify milestone landing: {detail}")
810
861
  landing_integrated = _run_git(
@@ -820,8 +871,8 @@ def bind_next_milestone_branch(
820
871
  if landing_integrated.returncode != 0:
821
872
  detail = landing_integrated.stderr.strip() or landing_integrated.stdout.strip()
822
873
  raise PipelineGitError(f"could not verify integrated branch: {detail}")
823
- if allow_remote_absent:
824
- proven_landing = _require_pull_request_integration_proof(
874
+ if allow_remote_absent or rebased:
875
+ proven_landing = _require_tag_integration_proof(
825
876
  repo,
826
877
  ship_sha,
827
878
  base_sha,
@@ -829,7 +880,7 @@ def bind_next_milestone_branch(
829
880
  )
830
881
  if proven_landing != landing_sha:
831
882
  raise PipelineGitError(
832
- "validated landing does not match pull-request integration proof"
883
+ "validated landing does not match the milestone tag integration proof"
833
884
  )
834
885
 
835
886
  symbolic_branch = _run_git(
@@ -956,6 +1007,7 @@ def bind_next_milestone_branch(
956
1007
  allow_remote_absent=(
957
1008
  allow_remote_absent or journal["stage"] in {"switched", "retired"}
958
1009
  ),
1010
+ rebased=rebased,
959
1011
  )
960
1012
  _retire_members(repo, ship_sha)
961
1013
  journal["stage"] = "retired"
@@ -173,9 +173,14 @@ class PipelineState:
173
173
  integration_default: str
174
174
  integration: str
175
175
  integration_source: str
176
+ default_branch: str = "main"
176
177
 
177
178
  def json(self) -> dict[str, Optional[str]]:
178
- 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
179
184
 
180
185
 
181
186
  @dataclass(frozen=True)
@@ -290,7 +295,7 @@ def _bound_branch_number(value: str) -> Optional[int]:
290
295
  def _state_from_text(text: str, label: str = "STATE.md") -> PipelineState:
291
296
  values = _parse_frontmatter(text, label)
292
297
  missing = [field for field in LEGACY_STATE_FIELDS if field not in values]
293
- extra = sorted(set(values) - set(STATE_FIELDS))
298
+ extra = sorted(set(values) - set(STATE_FIELDS) - {"default_branch"})
294
299
  if missing:
295
300
  raise PipelineStateError(f"{label} is missing fields: {', '.join(missing)}")
296
301
  if extra:
@@ -322,6 +327,7 @@ def _state_from_text(text: str, label: str = "STATE.md") -> PipelineState:
322
327
  integration_default=integration_default,
323
328
  integration=integration,
324
329
  integration_source=integration_source,
330
+ default_branch=values.get("default_branch", "main"),
325
331
  )
326
332
  _validate_state_values(state, label)
327
333
  return state
@@ -355,6 +361,10 @@ def _validate_state_values(state: PipelineState, label: str) -> None:
355
361
  raise PipelineStateError(
356
362
  f"{label} default-sourced integration must match integration_default"
357
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
+ )
358
368
  if state.branch is not None and _bound_branch_number(state.branch) is None:
359
369
  raise PipelineStateError(f"{label} has invalid branch: {state.branch}")
360
370
  archive_match = ARCHIVE_RE.fullmatch(state.archive or "")
@@ -416,6 +426,7 @@ def validate_state(repo: Path, project_dir: str = ".project") -> dict[str, objec
416
426
  "status": "valid",
417
427
  "path": str(path),
418
428
  "state": state.json(),
429
+ "default_branch": state.default_branch,
419
430
  }
420
431
 
421
432
 
@@ -698,8 +709,10 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
698
709
  if branch
699
710
  else None
700
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
701
714
  origin_main = (
702
- _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
703
716
  )
704
717
  pending, pending_error = _pending_answers(resolved)
705
718
  lookahead = resolved / ".project" / "next"
@@ -722,6 +735,7 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
722
735
  "advance": False,
723
736
  "completion": completion,
724
737
  "state": state,
738
+ "default_branch": default_branch,
725
739
  "route": route,
726
740
  "path": str(_track_root(resolved, project_dir) / "STATE.md"),
727
741
  "git": {
@@ -881,7 +895,12 @@ def _route_result(
881
895
  route["phase"] = phase
882
896
  if mode is not None:
883
897
  route["mode"] = mode
884
- 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
+ }
885
904
 
886
905
 
887
906
  def _legacy_bind_next_landing(repo: Path, state: PipelineState) -> str:
@@ -1005,11 +1024,13 @@ def _bind_next_journal_recovery(
1005
1024
  )
1006
1025
  if resolved_landing.returncode != 0 or resolved_landing.stdout.strip() != landing:
1007
1026
  raise PipelineStateError("bind-next journal landing is not an existing full SHA")
1008
- if not _is_ancestor(repo, ship, landing):
1027
+ if not _is_ancestor(repo, ship, landing) and _common.rebase_landing_problem(
1028
+ repo, ship, landing
1029
+ ) is not None:
1009
1030
  raise PipelineStateError("bind-next journal landing does not contain ship")
1010
1031
  if not _is_ancestor(repo, landing, base):
1011
1032
  raise PipelineStateError("bind-next journal landing is not an ancestor of base")
1012
- if transaction["remote_default"] != "origin/main":
1033
+ if transaction["remote_default"] != f"origin/{state.default_branch}":
1013
1034
  raise PipelineStateError("bind-next journal has invalid remote default")
1014
1035
  if stage not in {"prepared", "switched", "retired"}:
1015
1036
  raise PipelineStateError("bind-next journal has invalid stage")
@@ -1758,7 +1779,10 @@ def transition_state(
1758
1779
  if unsupported:
1759
1780
  raise PipelineStateError(f"unsupported state fields: {', '.join(sorted(unsupported))}")
1760
1781
  if not changes:
1761
- raise PipelineStateError("transition requires at least one changed field")
1782
+ raise PipelineStateError(
1783
+ "transition requires at least one changed field; "
1784
+ "to record only a Log event, pass --set-status with the current status"
1785
+ )
1762
1786
  required_expected = {"phase", "status", "branch", "archive"} | set(changes)
1763
1787
  missing_expected = sorted(required_expected - set(expected))
1764
1788
  if missing_expected:
@@ -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,