@opengsd/gsd-path 1.4.0 → 1.5.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 (347) hide show
  1. package/CHANGELOG.md +325 -344
  2. package/DOCS.md +12 -2
  3. package/FULL.md +3 -2
  4. package/HOOKS.md +95 -8
  5. package/QUICK.md +1 -1
  6. package/README.md +78 -110
  7. package/RUNTIME.md +1 -1
  8. package/UPDATE.md +4 -3
  9. package/WORKFLOW.md +22 -1
  10. package/package.json +5 -2
  11. package/platforms/shared-agents/dispatch.md +13 -0
  12. package/scripts/_common.py +149 -1
  13. package/scripts/archive_milestone.py +14 -13
  14. package/scripts/build_recovery.py +96 -31
  15. package/scripts/build_state.py +79 -3
  16. package/scripts/check_docs_audit.py +77 -4
  17. package/scripts/check_handoffs.py +546 -30
  18. package/scripts/check_task_briefs.py +279 -23
  19. package/scripts/detect_project.py +243 -18
  20. package/scripts/discussion_validate.py +86 -29
  21. package/scripts/dispatch_driver.py +392 -22
  22. package/scripts/git_guard.py +3 -3
  23. package/scripts/guard_hook.py +1416 -165
  24. package/scripts/install.mjs +23 -8
  25. package/scripts/install.py +49 -9
  26. package/scripts/integration.py +146 -1
  27. package/scripts/isolation.py +392 -60
  28. package/scripts/loop_run.py +16 -4
  29. package/scripts/members.py +11 -9
  30. package/scripts/path_config.py +3 -3
  31. package/scripts/pipeline_git.py +63 -12
  32. package/scripts/pipeline_state.py +111 -33
  33. package/scripts/pipeline_undo.py +101 -8
  34. package/scripts/runtime_store.py +20 -2
  35. package/scripts/skill-resources.json +9 -2
  36. package/scripts/state_checkpoint.py +9 -27
  37. package/scripts/status_runtime.py +22 -4
  38. package/scripts/task_context.py +12 -3
  39. package/scripts/wizard.mjs +1 -0
  40. package/scripts/workflow_run.py +5 -2
  41. package/scripts/worktree_paths.py +54 -2
  42. package/skills/gsd-path/DEFINE.md +28 -3
  43. package/skills/gsd-path/PLAN.md +11 -3
  44. package/skills/gsd-path/RESEARCH.md +11 -0
  45. package/skills/gsd-path/SHIP.md +6 -1
  46. package/skills/gsd-path/references/build-native.md +16 -1
  47. package/skills/gsd-path/references/dispatch.md +13 -0
  48. package/skills/gsd-path/references/docs-auditor.md +5 -0
  49. package/skills/gsd-path/references/planner.md +14 -4
  50. package/skills/gsd-path/references/reviewer-final.md +20 -2
  51. package/skills/gsd-path/references/reviewer-wave.md +15 -4
  52. package/skills/gsd-path/references/reviewer.md +3 -1
  53. package/skills/gsd-path/references/spec-probes.md +150 -0
  54. package/skills/gsd-path/scripts/_common.py +149 -1
  55. package/skills/gsd-path/scripts/archive_milestone.py +14 -13
  56. package/skills/gsd-path/scripts/build_recovery.py +96 -31
  57. package/skills/gsd-path/scripts/build_state.py +79 -3
  58. package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
  59. package/skills/gsd-path/scripts/check_handoffs.py +546 -30
  60. package/skills/gsd-path/scripts/check_task_briefs.py +279 -23
  61. package/skills/gsd-path/scripts/detect_project.py +243 -18
  62. package/skills/gsd-path/scripts/discussion_validate.py +86 -29
  63. package/skills/gsd-path/scripts/dispatch_driver.py +392 -22
  64. package/skills/gsd-path/scripts/git_guard.py +3 -3
  65. package/skills/gsd-path/scripts/integration.py +146 -1
  66. package/skills/gsd-path/scripts/isolation.py +392 -60
  67. package/skills/gsd-path/scripts/loop_run.py +16 -4
  68. package/skills/gsd-path/scripts/members.py +11 -9
  69. package/skills/gsd-path/scripts/path_config.py +3 -3
  70. package/skills/gsd-path/scripts/pipeline_git.py +63 -12
  71. package/skills/gsd-path/scripts/pipeline_state.py +111 -33
  72. package/skills/gsd-path/scripts/state_checkpoint.py +9 -27
  73. package/skills/gsd-path/scripts/status_runtime.py +22 -4
  74. package/skills/gsd-path/scripts/task_context.py +12 -3
  75. package/skills/gsd-path/scripts/workflow_run.py +5 -2
  76. package/skills/gsd-path/scripts/worktree_paths.py +54 -2
  77. package/skills/gsd-path/templates/docs-audit.md +5 -1
  78. package/skills/gsd-path/templates/final-review.md +11 -2
  79. package/skills/gsd-path/templates/intent.md +30 -0
  80. package/skills/gsd-path/templates/patch-findings.md +3 -3
  81. package/skills/gsd-path/templates/plan.md +17 -2
  82. package/skills/gsd-path/templates/research-handoff.md +14 -3
  83. package/skills/gsd-path/templates/state.md +1 -1
  84. package/skills/gsd-path/templates/wave-review.md +16 -6
  85. package/skills/gsd-path-build/references/build-native.md +16 -1
  86. package/skills/gsd-path-build/references/dispatch.md +13 -0
  87. package/skills/gsd-path-build/references/reviewer-final.md +20 -2
  88. package/skills/gsd-path-build/references/reviewer-wave.md +15 -4
  89. package/skills/gsd-path-build/references/reviewer.md +3 -1
  90. package/skills/gsd-path-build/references/spec-probes.md +150 -0
  91. package/skills/gsd-path-build/scripts/_common.py +149 -1
  92. package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
  93. package/skills/gsd-path-build/scripts/build_recovery.py +96 -31
  94. package/skills/gsd-path-build/scripts/build_state.py +79 -3
  95. package/skills/gsd-path-build/scripts/check_handoffs.py +546 -30
  96. package/skills/gsd-path-build/scripts/check_task_briefs.py +279 -23
  97. package/skills/gsd-path-build/scripts/detect_project.py +243 -18
  98. package/skills/gsd-path-build/scripts/discussion_validate.py +86 -29
  99. package/skills/gsd-path-build/scripts/dispatch_driver.py +392 -22
  100. package/skills/gsd-path-build/scripts/integration.py +146 -1
  101. package/skills/gsd-path-build/scripts/isolation.py +392 -60
  102. package/skills/gsd-path-build/scripts/loop_run.py +16 -4
  103. package/skills/gsd-path-build/scripts/members.py +11 -9
  104. package/skills/gsd-path-build/scripts/path_config.py +3 -3
  105. package/skills/gsd-path-build/scripts/pipeline_git.py +63 -12
  106. package/skills/gsd-path-build/scripts/pipeline_state.py +111 -33
  107. package/skills/gsd-path-build/scripts/state_checkpoint.py +9 -27
  108. package/skills/gsd-path-build/scripts/task_context.py +12 -3
  109. package/skills/gsd-path-build/scripts/workflow_run.py +5 -2
  110. package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
  111. package/skills/gsd-path-build/templates/wave-review.md +16 -6
  112. package/skills/gsd-path-decide/references/dispatch.md +13 -0
  113. package/skills/gsd-path-decide/scripts/_common.py +149 -1
  114. package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
  115. package/skills/gsd-path-decide/scripts/build_recovery.py +96 -31
  116. package/skills/gsd-path-decide/scripts/check_handoffs.py +546 -30
  117. package/skills/gsd-path-decide/scripts/check_task_briefs.py +279 -23
  118. package/skills/gsd-path-decide/scripts/detect_project.py +243 -18
  119. package/skills/gsd-path-decide/scripts/discussion_validate.py +86 -29
  120. package/skills/gsd-path-decide/scripts/integration.py +146 -1
  121. package/skills/gsd-path-decide/scripts/isolation.py +392 -60
  122. package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
  123. package/skills/gsd-path-decide/scripts/members.py +11 -9
  124. package/skills/gsd-path-decide/scripts/path_config.py +3 -3
  125. package/skills/gsd-path-decide/scripts/pipeline_git.py +63 -12
  126. package/skills/gsd-path-decide/scripts/pipeline_state.py +111 -33
  127. package/skills/gsd-path-decide/scripts/state_checkpoint.py +9 -27
  128. package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
  129. package/skills/gsd-path-define/SKILL.md +28 -3
  130. package/skills/gsd-path-define/references/spec-probes.md +150 -0
  131. package/skills/gsd-path-define/scripts/_common.py +149 -1
  132. package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
  133. package/skills/gsd-path-define/scripts/build_recovery.py +96 -31
  134. package/skills/gsd-path-define/scripts/check_handoffs.py +546 -30
  135. package/skills/gsd-path-define/scripts/check_task_briefs.py +279 -23
  136. package/skills/gsd-path-define/scripts/detect_project.py +243 -18
  137. package/skills/gsd-path-define/scripts/discussion_validate.py +86 -29
  138. package/skills/gsd-path-define/scripts/integration.py +146 -1
  139. package/skills/gsd-path-define/scripts/isolation.py +392 -60
  140. package/skills/gsd-path-define/scripts/loop_run.py +16 -4
  141. package/skills/gsd-path-define/scripts/members.py +11 -9
  142. package/skills/gsd-path-define/scripts/path_config.py +3 -3
  143. package/skills/gsd-path-define/scripts/pipeline_git.py +63 -12
  144. package/skills/gsd-path-define/scripts/pipeline_state.py +111 -33
  145. package/skills/gsd-path-define/scripts/state_checkpoint.py +9 -27
  146. package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
  147. package/skills/gsd-path-define/templates/intent.md +30 -0
  148. package/skills/gsd-path-define/templates/state.md +1 -1
  149. package/skills/gsd-path-discuss/scripts/_common.py +149 -1
  150. package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
  151. package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
  152. package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
  153. package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
  154. package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
  155. package/skills/gsd-path-docs-audit/scripts/_common.py +149 -1
  156. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
  157. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +96 -31
  158. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
  159. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +546 -30
  160. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +279 -23
  161. package/skills/gsd-path-docs-audit/scripts/detect_project.py +243 -18
  162. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +86 -29
  163. package/skills/gsd-path-docs-audit/scripts/integration.py +146 -1
  164. package/skills/gsd-path-docs-audit/scripts/isolation.py +392 -60
  165. package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
  166. package/skills/gsd-path-docs-audit/scripts/members.py +11 -9
  167. package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
  168. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +63 -12
  169. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +111 -33
  170. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +9 -27
  171. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
  172. package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
  173. package/skills/gsd-path-forensics/scripts/_common.py +149 -1
  174. package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
  175. package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
  176. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +101 -8
  177. package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
  178. package/skills/gsd-path-inspect/references/dispatch.md +13 -0
  179. package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
  180. package/skills/gsd-path-inspect/scripts/_common.py +149 -1
  181. package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
  182. package/skills/gsd-path-inspect/scripts/build_recovery.py +96 -31
  183. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
  184. package/skills/gsd-path-inspect/scripts/check_handoffs.py +546 -30
  185. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +279 -23
  186. package/skills/gsd-path-inspect/scripts/detect_project.py +243 -18
  187. package/skills/gsd-path-inspect/scripts/discussion_validate.py +86 -29
  188. package/skills/gsd-path-inspect/scripts/integration.py +146 -1
  189. package/skills/gsd-path-inspect/scripts/isolation.py +392 -60
  190. package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
  191. package/skills/gsd-path-inspect/scripts/members.py +11 -9
  192. package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
  193. package/skills/gsd-path-inspect/scripts/pipeline_git.py +63 -12
  194. package/skills/gsd-path-inspect/scripts/pipeline_state.py +111 -33
  195. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +9 -27
  196. package/skills/gsd-path-inspect/scripts/workflow_run.py +5 -2
  197. package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
  198. package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
  199. package/skills/gsd-path-inspect/templates/state.md +1 -1
  200. package/skills/gsd-path-loop/scripts/_common.py +149 -1
  201. package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
  202. package/skills/gsd-path-loop/scripts/path_config.py +3 -3
  203. package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
  204. package/skills/gsd-path-migrate/scripts/_common.py +149 -1
  205. package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
  206. package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
  207. package/skills/gsd-path-plan/SKILL.md +11 -3
  208. package/skills/gsd-path-plan/references/dispatch.md +13 -0
  209. package/skills/gsd-path-plan/references/planner.md +14 -4
  210. package/skills/gsd-path-plan/references/spec-probes.md +150 -0
  211. package/skills/gsd-path-plan/scripts/_common.py +149 -1
  212. package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
  213. package/skills/gsd-path-plan/scripts/build_recovery.py +96 -31
  214. package/skills/gsd-path-plan/scripts/check_handoffs.py +546 -30
  215. package/skills/gsd-path-plan/scripts/check_task_briefs.py +279 -23
  216. package/skills/gsd-path-plan/scripts/detect_project.py +243 -18
  217. package/skills/gsd-path-plan/scripts/discussion_validate.py +86 -29
  218. package/skills/gsd-path-plan/scripts/integration.py +146 -1
  219. package/skills/gsd-path-plan/scripts/isolation.py +392 -60
  220. package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
  221. package/skills/gsd-path-plan/scripts/members.py +11 -9
  222. package/skills/gsd-path-plan/scripts/path_config.py +3 -3
  223. package/skills/gsd-path-plan/scripts/pipeline_git.py +63 -12
  224. package/skills/gsd-path-plan/scripts/pipeline_state.py +111 -33
  225. package/skills/gsd-path-plan/scripts/state_checkpoint.py +9 -27
  226. package/skills/gsd-path-plan/scripts/workflow_run.py +5 -2
  227. package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
  228. package/skills/gsd-path-plan/templates/patch-findings.md +3 -3
  229. package/skills/gsd-path-plan/templates/plan.md +17 -2
  230. package/skills/gsd-path-research/SKILL.md +11 -0
  231. package/skills/gsd-path-research/references/dispatch.md +13 -0
  232. package/skills/gsd-path-research/scripts/_common.py +149 -1
  233. package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
  234. package/skills/gsd-path-research/scripts/build_recovery.py +96 -31
  235. package/skills/gsd-path-research/scripts/check_handoffs.py +546 -30
  236. package/skills/gsd-path-research/scripts/check_task_briefs.py +279 -23
  237. package/skills/gsd-path-research/scripts/detect_project.py +243 -18
  238. package/skills/gsd-path-research/scripts/discussion_validate.py +86 -29
  239. package/skills/gsd-path-research/scripts/integration.py +146 -1
  240. package/skills/gsd-path-research/scripts/isolation.py +392 -60
  241. package/skills/gsd-path-research/scripts/loop_run.py +16 -4
  242. package/skills/gsd-path-research/scripts/members.py +11 -9
  243. package/skills/gsd-path-research/scripts/path_config.py +3 -3
  244. package/skills/gsd-path-research/scripts/pipeline_git.py +63 -12
  245. package/skills/gsd-path-research/scripts/pipeline_state.py +111 -33
  246. package/skills/gsd-path-research/scripts/state_checkpoint.py +9 -27
  247. package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
  248. package/skills/gsd-path-research/templates/research-handoff.md +14 -3
  249. package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
  250. package/skills/gsd-path-roadmap/scripts/_common.py +149 -1
  251. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
  252. package/skills/gsd-path-roadmap/scripts/build_recovery.py +96 -31
  253. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +546 -30
  254. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +279 -23
  255. package/skills/gsd-path-roadmap/scripts/detect_project.py +243 -18
  256. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +86 -29
  257. package/skills/gsd-path-roadmap/scripts/integration.py +146 -1
  258. package/skills/gsd-path-roadmap/scripts/isolation.py +392 -60
  259. package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
  260. package/skills/gsd-path-roadmap/scripts/members.py +11 -9
  261. package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
  262. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +63 -12
  263. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +111 -33
  264. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +9 -27
  265. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
  266. package/skills/gsd-path-ship/SKILL.md +6 -1
  267. package/skills/gsd-path-ship/references/dispatch.md +13 -0
  268. package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
  269. package/skills/gsd-path-ship/references/reviewer-wave.md +15 -4
  270. package/skills/gsd-path-ship/references/reviewer.md +3 -1
  271. package/skills/gsd-path-ship/references/spec-probes.md +150 -0
  272. package/skills/gsd-path-ship/scripts/_common.py +149 -1
  273. package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
  274. package/skills/gsd-path-ship/scripts/build_recovery.py +96 -31
  275. package/skills/gsd-path-ship/scripts/build_state.py +79 -3
  276. package/skills/gsd-path-ship/scripts/check_handoffs.py +546 -30
  277. package/skills/gsd-path-ship/scripts/check_task_briefs.py +279 -23
  278. package/skills/gsd-path-ship/scripts/detect_project.py +243 -18
  279. package/skills/gsd-path-ship/scripts/discussion_validate.py +86 -29
  280. package/skills/gsd-path-ship/scripts/integration.py +146 -1
  281. package/skills/gsd-path-ship/scripts/isolation.py +392 -60
  282. package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
  283. package/skills/gsd-path-ship/scripts/members.py +11 -9
  284. package/skills/gsd-path-ship/scripts/path_config.py +3 -3
  285. package/skills/gsd-path-ship/scripts/pipeline_git.py +63 -12
  286. package/skills/gsd-path-ship/scripts/pipeline_state.py +111 -33
  287. package/skills/gsd-path-ship/scripts/state_checkpoint.py +9 -27
  288. package/skills/gsd-path-ship/scripts/workflow_run.py +5 -2
  289. package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
  290. package/skills/gsd-path-ship/templates/final-review.md +11 -2
  291. package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
  292. package/skills/gsd-path-ship/templates/wave-review.md +16 -6
  293. package/skills/gsd-path-undo/scripts/_common.py +149 -1
  294. package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
  295. package/skills/gsd-path-undo/scripts/path_config.py +3 -3
  296. package/skills/gsd-path-undo/scripts/pipeline_undo.py +101 -8
  297. package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
  298. package/skills/path/DEFINE.md +28 -3
  299. package/skills/path/PLAN.md +11 -3
  300. package/skills/path/RESEARCH.md +11 -0
  301. package/skills/path/SHIP.md +6 -1
  302. package/skills/path/references/build-native.md +16 -1
  303. package/skills/path/references/dispatch.md +13 -0
  304. package/skills/path/references/docs-auditor.md +5 -0
  305. package/skills/path/references/planner.md +14 -4
  306. package/skills/path/references/reviewer-final.md +20 -2
  307. package/skills/path/references/reviewer-wave.md +15 -4
  308. package/skills/path/references/reviewer.md +3 -1
  309. package/skills/path/references/spec-probes.md +150 -0
  310. package/skills/path/scripts/_common.py +149 -1
  311. package/skills/path/scripts/archive_milestone.py +14 -13
  312. package/skills/path/scripts/build_recovery.py +96 -31
  313. package/skills/path/scripts/build_state.py +79 -3
  314. package/skills/path/scripts/check_docs_audit.py +77 -4
  315. package/skills/path/scripts/check_handoffs.py +546 -30
  316. package/skills/path/scripts/check_task_briefs.py +279 -23
  317. package/skills/path/scripts/detect_project.py +243 -18
  318. package/skills/path/scripts/discussion_validate.py +86 -29
  319. package/skills/path/scripts/dispatch_driver.py +392 -22
  320. package/skills/path/scripts/git_guard.py +3 -3
  321. package/skills/path/scripts/integration.py +146 -1
  322. package/skills/path/scripts/isolation.py +392 -60
  323. package/skills/path/scripts/loop_run.py +16 -4
  324. package/skills/path/scripts/members.py +11 -9
  325. package/skills/path/scripts/path_config.py +3 -3
  326. package/skills/path/scripts/pipeline_git.py +63 -12
  327. package/skills/path/scripts/pipeline_state.py +111 -33
  328. package/skills/path/scripts/state_checkpoint.py +9 -27
  329. package/skills/path/scripts/status_runtime.py +22 -4
  330. package/skills/path/scripts/task_context.py +12 -3
  331. package/skills/path/scripts/workflow_run.py +5 -2
  332. package/skills/path/scripts/worktree_paths.py +54 -2
  333. package/skills/path/templates/docs-audit.md +5 -1
  334. package/skills/path/templates/final-review.md +11 -2
  335. package/skills/path/templates/intent.md +30 -0
  336. package/skills/path/templates/patch-findings.md +3 -3
  337. package/skills/path/templates/plan.md +17 -2
  338. package/skills/path/templates/research-handoff.md +14 -3
  339. package/skills/path/templates/state.md +1 -1
  340. package/skills/path/templates/wave-review.md +16 -6
  341. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  342. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  343. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  344. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  345. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  346. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  347. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
@@ -53,6 +53,9 @@ COMMENT_PATTERN = re.compile(r"<!--.*?-->", re.DOTALL)
53
53
  BACKTICK_PATTERN = re.compile(r"`([^`\n]+)`")
54
54
  PATH_TOKEN_PATTERN = re.compile(r"[A-Za-z0-9._~/-]+")
55
55
  VERIFY_BLOCK_PATTERN = re.compile(r"```bash[ \t]*\n(?P<block>.*?)```", re.DOTALL)
56
+ TEXT_TOOL_COMMANDS = frozenset({"awk", "egrep", "fgrep", "gawk", "grep", "gsed", "rg", "sed"})
57
+ REGEX_PATTERN_CHARS = frozenset("|*+?[]()^$.\\")
58
+ PIPELINE_WORKSPACE_DIRS = ("review", "discuss", "build", "plan")
56
59
 
57
60
 
58
61
  class BriefError(RuntimeError):
@@ -73,10 +76,20 @@ def _base_exists(repo: Path, base: str, path: str) -> bool:
73
76
  return _run_git(repo, "cat-file", "-e", f"{base}:{path}").returncode == 0
74
77
 
75
78
 
79
+ def _project_track(task: Path, repo: Path) -> Optional[str]:
80
+ try:
81
+ track = task.parent.parent.relative_to(repo).as_posix()
82
+ except ValueError:
83
+ return None
84
+ if track not in {".project", ".project/next"}:
85
+ return None
86
+ return track
87
+
88
+
76
89
  def _supplied_contract(repo: Path, task: Path, token: str) -> bool:
77
90
  """Plan approval checkpoints these supplied inputs after the brief gate."""
78
- track = task.parent.parent.relative_to(repo).as_posix()
79
- if track not in {".project", ".project/next"}:
91
+ track = _project_track(task, repo)
92
+ if track is None:
80
93
  return False
81
94
  if token not in {
82
95
  f"{track}/intent/INTENT.md",
@@ -87,6 +100,18 @@ def _supplied_contract(repo: Path, task: Path, token: str) -> bool:
87
100
  return path.is_file() and path.resolve() == repo.resolve() / token
88
101
 
89
102
 
103
+ def _pipeline_workspace_file(repo: Path, task: Path, token: str) -> bool:
104
+ """Pipeline-owned paths may exist only in the working tree before checkpoint."""
105
+ track = _project_track(task, repo)
106
+ if track is None:
107
+ return False
108
+ prefixes = tuple(f"{track}/{name}/" for name in PIPELINE_WORKSPACE_DIRS)
109
+ if not any(token.startswith(prefix) for prefix in prefixes):
110
+ return False
111
+ path = repo / token
112
+ return path.is_file() and path.resolve() == repo.resolve() / token
113
+
114
+
90
115
  _strip_yaml_comment = _common.strip_yaml_comment
91
116
  _unquote = _common.unquote
92
117
 
@@ -151,7 +176,7 @@ def _clean(body: str) -> str:
151
176
  return COMMENT_PATTERN.sub("", body).strip()
152
177
 
153
178
 
154
- def _looks_like_path(token: str) -> bool:
179
+ def _slash_token_shape(token: str) -> bool:
155
180
  return (
156
181
  "/" in token
157
182
  and PATH_TOKEN_PATTERN.fullmatch(token) is not None
@@ -162,26 +187,91 @@ def _looks_like_path(token: str) -> bool:
162
187
  )
163
188
 
164
189
 
190
+ def _last_segment_has_extension(token: str) -> bool:
191
+ name = PurePosixPath(token).name
192
+ return "." in name and not name.startswith(".")
193
+
194
+
195
+ def _looks_like_path(
196
+ token: str,
197
+ *,
198
+ repo: Path,
199
+ git_root: Path,
200
+ base: str,
201
+ task: Path,
202
+ ) -> bool:
203
+ if not _slash_token_shape(token):
204
+ return False
205
+ if _last_segment_has_extension(token):
206
+ return True
207
+ if _base_exists(git_root, base, token):
208
+ return True
209
+ if _pipeline_workspace_file(repo, task, token):
210
+ return True
211
+ return False
212
+
213
+
214
+ def _looks_like_regex_pattern(token: str) -> bool:
215
+ return any(character in token for character in REGEX_PATTERN_CHARS)
216
+
217
+
218
+ def _text_tool_command(command: str) -> bool:
219
+ return Path(command).name.casefold() in TEXT_TOOL_COMMANDS
220
+
221
+
165
222
  def _normalize(path: str) -> str:
166
223
  return str(PurePosixPath(path))
167
224
 
168
225
 
169
- def _prose_tokens(body: str) -> List[str]:
226
+ def _prose_tokens(
227
+ body: str,
228
+ *,
229
+ repo: Path,
230
+ git_root: Path,
231
+ base: str,
232
+ task: Path,
233
+ ) -> List[str]:
170
234
  cleaned = COMMENT_PATTERN.sub("", body)
171
- return [
172
- _normalize(match.group(1).strip())
173
- for match in BACKTICK_PATTERN.finditer(cleaned)
174
- if _looks_like_path(match.group(1).strip())
175
- ]
235
+ tokens: List[str] = []
236
+ for match in BACKTICK_PATTERN.finditer(cleaned):
237
+ candidate = match.group(1).strip()
238
+ if _looks_like_path(
239
+ candidate, repo=repo, git_root=git_root, base=base, task=task
240
+ ):
241
+ tokens.append(_normalize(candidate))
242
+ return tokens
176
243
 
177
244
 
178
- def _verify_tokens(block: str) -> List[str]:
179
- tokens = []
245
+ def _verify_tokens(
246
+ block: str,
247
+ *,
248
+ repo: Path,
249
+ git_root: Path,
250
+ base: str,
251
+ task: Path,
252
+ ) -> List[str]:
253
+ tokens: List[str] = []
180
254
  for line in block.splitlines():
181
255
  parts = line.split()
182
- for token in parts[1:]:
183
- token = token.strip("\"'")
184
- if _looks_like_path(token):
256
+ if len(parts) < 2:
257
+ continue
258
+ command = parts[0]
259
+ extended_grep = False
260
+ index = 1
261
+ while index < len(parts) and parts[index].startswith("-") and "=" not in parts[index]:
262
+ flag = parts[index]
263
+ if flag in {"-E", "-G"} or flag.startswith("-E"):
264
+ extended_grep = True
265
+ index += 1
266
+ text_tool = _text_tool_command(command)
267
+ for raw in parts[index:]:
268
+ quoted = raw.startswith(("'", '"'))
269
+ token = raw.strip("\"'")
270
+ if text_tool and quoted:
271
+ continue
272
+ if text_tool and command.casefold() == "grep" and extended_grep and _looks_like_regex_pattern(token):
273
+ continue
274
+ if _looks_like_path(token, repo=repo, git_root=git_root, base=base, task=task):
185
275
  tokens.append(_normalize(token))
186
276
  return tokens
187
277
 
@@ -298,12 +388,15 @@ def _lint_task(
298
388
  body = sections.get(name)
299
389
  if body is None or not _clean(body):
300
390
  continue
301
- for token in _prose_tokens(body):
391
+ for token in _prose_tokens(
392
+ body, repo=repo, git_root=git_root, base=base, task=path
393
+ ):
302
394
  checked += 1
303
395
  if (
304
396
  token not in declared
305
397
  and token not in supplied
306
398
  and not _supplied_contract(repo, path, token)
399
+ and not _pipeline_workspace_file(repo, path, token)
307
400
  and not _base_exists(git_root, base, token)
308
401
  ):
309
402
  problems.append(f"## {name} names a path missing at the layer base: {token}")
@@ -314,9 +407,20 @@ def _lint_task(
314
407
  if block is None or not block.group("block").strip():
315
408
  problems.append("## Verify must contain a non-empty fenced bash block")
316
409
  else:
317
- for token in _verify_tokens(block.group("block")):
410
+ for token in _verify_tokens(
411
+ block.group("block"),
412
+ repo=repo,
413
+ git_root=git_root,
414
+ base=base,
415
+ task=path,
416
+ ):
318
417
  checked += 1
319
- if token not in declared and token not in supplied and not _base_exists(git_root, base, token):
418
+ if (
419
+ token not in declared
420
+ and token not in supplied
421
+ and not _pipeline_workspace_file(repo, path, token)
422
+ and not _base_exists(git_root, base, token)
423
+ ):
320
424
  problems.append(f"## Verify names a path missing at the layer base: {token}")
321
425
 
322
426
  contract = None
@@ -337,9 +441,9 @@ def validate_task_briefs(
337
441
  ) -> Dict[str, object]:
338
442
  """Lint task briefs using the caller's validation bases.
339
443
 
340
- Dispatch uses the layer base without overrides. Plan approval supplies
341
- transitive dependency files for pending tasks and resolved historical bases
342
- for landed tasks, whose immutable briefs must survive later file changes.
444
+ Plain lint uses the layer base without overrides. Plan approval and dispatch
445
+ supply transitive dependency files for unlanded tasks and resolved historical
446
+ bases for landed tasks, whose immutable briefs must survive later file changes.
343
447
  The caller validates the task graph and landed metadata before supplying
344
448
  these mappings; landed tasks receive no dependency-file allowance.
345
449
  """
@@ -381,6 +485,136 @@ def validate_task_briefs(
381
485
  return {"base": resolved_base, "checked": checked, "tasks": len(task_files)}
382
486
 
383
487
 
488
+ def _resolve_landed_task_base(
489
+ task_id: str,
490
+ recorded_base: str,
491
+ recorded_member_base: object,
492
+ coordinator_repo: Path,
493
+ member_repo: Optional[Path],
494
+ ) -> str:
495
+ """Resolve a landed task's historical base in the repository it names."""
496
+ if __package__:
497
+ from .isolation import IsolationError, require_commit, require_full_sha
498
+ else:
499
+ try:
500
+ from isolation import IsolationError, require_commit, require_full_sha
501
+ except ModuleNotFoundError as error:
502
+ if error.name != "isolation":
503
+ raise
504
+ from scripts.isolation import IsolationError, require_commit, require_full_sha
505
+
506
+ recorded_full = require_full_sha(recorded_base)
507
+ if member_repo is None:
508
+ try:
509
+ return require_commit(coordinator_repo, recorded_full)
510
+ except IsolationError as error:
511
+ raise BriefError(
512
+ f"{task_id} landed task has invalid historical base: {error}"
513
+ ) from error
514
+
515
+ legacy_member_base = (
516
+ recorded_member_base is None
517
+ or (isinstance(recorded_member_base, str)
518
+ and recorded_member_base.strip().casefold() in {"", "null", "~"})
519
+ or (isinstance(recorded_member_base, list) and not recorded_member_base)
520
+ )
521
+ try:
522
+ if not legacy_member_base:
523
+ if not isinstance(recorded_member_base, str):
524
+ raise IsolationError(
525
+ f"member_base must be a full 40-character SHA: {recorded_member_base}"
526
+ )
527
+ member_full = require_full_sha(recorded_member_base)
528
+ return require_commit(member_repo, member_full)
529
+ try:
530
+ return require_commit(coordinator_repo, recorded_full)
531
+ except IsolationError:
532
+ return require_commit(member_repo, recorded_full)
533
+ except IsolationError as error:
534
+ raise BriefError(
535
+ f"{task_id} landed task has invalid historical base: {error}"
536
+ ) from error
537
+
538
+ def plan_validation_bases(
539
+ root: Path, project_dir: str, member_base=None, *, initial: bool = True,
540
+ ) -> Tuple[Dict[str, str], Dict[str, Set[str]], Dict[str, str]]:
541
+ """Share dependency files and landed historical bases across approval and dispatch.
542
+
543
+ Approval requires unlanded tasks to start clean. Dispatch may run beside
544
+ in-flight tasks, while retaining the same graph and path checks.
545
+ """
546
+ if __package__:
547
+ from . import check_handoffs
548
+ from .isolation import IsolationError
549
+ else:
550
+ try:
551
+ import check_handoffs
552
+ from isolation import IsolationError
553
+ except ModuleNotFoundError as error:
554
+ if error.name not in {"check_handoffs", "isolation"}:
555
+ raise
556
+ from scripts import check_handoffs
557
+ from scripts.isolation import IsolationError
558
+ if member_base is None:
559
+ member_base = _member_bases(root)
560
+ try:
561
+ tasks, dependency_files = check_handoffs.plan_brief_inputs(
562
+ root, project_dir, initial=initial
563
+ )
564
+ landed_bases: Dict[str, str] = {}
565
+ for task_id, text in tasks.items():
566
+ if check_handoffs._task_scalar(text, task_id, "status") != "done":
567
+ continue
568
+ agent = check_handoffs._task_scalar(text, task_id, "agent")
569
+ if agent in {"", "null"}:
570
+ raise BriefError(f"{task_id} landed task has no recorded agent")
571
+ fields = check_handoffs._strict_frontmatter(text, task_id)
572
+ member = fields.get("repo")
573
+ base_repo = root
574
+ if member is not None:
575
+ located = member_base(member) if isinstance(member, str) and member else None
576
+ if located is None:
577
+ raise BriefError(f"repo: names no member in MEMBERS.md: {member}")
578
+ base_repo = located[0]
579
+ recorded_base = check_handoffs._task_scalar(text, task_id, "base")
580
+ try:
581
+ landed_bases[task_id] = _resolve_landed_task_base(
582
+ task_id,
583
+ recorded_base,
584
+ fields.get("member_base") if member is not None else None,
585
+ root,
586
+ base_repo if member is not None else None,
587
+ )
588
+ except IsolationError as error:
589
+ raise BriefError(f"{task_id} landed task has invalid historical base: {error}") from error
590
+ dependency_files[task_id] = set()
591
+ except check_handoffs.HandoffError as error:
592
+ raise BriefError(str(error)) from error
593
+ return tasks, dependency_files, landed_bases
594
+
595
+
596
+ def validate_plan_task_briefs(
597
+ root: Path,
598
+ base: str,
599
+ project_dir: str = ".project",
600
+ tasks_dir: Optional[str] = None,
601
+ ) -> Dict[str, object]:
602
+ """Dispatch lint with dependency files and landed historical bases."""
603
+ member_base = _member_bases(root)
604
+ _, dependency_files, landed_bases = plan_validation_bases(
605
+ root, project_dir, member_base, initial=False
606
+ )
607
+ resolved_tasks_dir = tasks_dir or f"{project_dir}/tasks"
608
+ return validate_task_briefs(
609
+ root,
610
+ base,
611
+ resolved_tasks_dir,
612
+ dependency_files=dependency_files,
613
+ landed_bases=landed_bases,
614
+ member_base=member_base,
615
+ )
616
+
617
+
384
618
  def _tasks_dir(value: str) -> str:
385
619
  """Argparse type for --tasks-dir: a relative POSIX-style path."""
386
620
 
@@ -411,15 +645,37 @@ def parser() -> argparse.ArgumentParser:
411
645
  help="relative POSIX-style directory under --repo holding the task files "
412
646
  "(default: .project/tasks)",
413
647
  )
648
+ argument_parser.add_argument(
649
+ "--project-dir",
650
+ default=None,
651
+ help="apply plan dependency files and landed-task bases for this track "
652
+ "(inferred from --tasks-dir when its sibling plan/PLAN.md exists)",
653
+ )
414
654
  return argument_parser
415
655
 
416
656
 
417
657
  def main(argv: Optional[Sequence[str]] = None) -> int:
418
658
  arguments = parser().parse_args(argv)
419
659
  try:
420
- result = validate_task_briefs(
421
- arguments.repo.resolve(), arguments.base, arguments.tasks_dir
422
- )
660
+ root = arguments.repo.resolve()
661
+ project_dir = arguments.project_dir
662
+ if project_dir is None:
663
+ tasks_path = PurePosixPath(arguments.tasks_dir)
664
+ if tasks_path.name == "tasks" and len(tasks_path.parts) > 1:
665
+ track = tasks_path.parent.as_posix()
666
+ if (root / track / "plan/PLAN.md").is_file():
667
+ project_dir = track
668
+ if project_dir is not None:
669
+ result = validate_plan_task_briefs(
670
+ root,
671
+ arguments.base,
672
+ project_dir,
673
+ None if arguments.tasks_dir == DEFAULT_TASKS_DIR else arguments.tasks_dir,
674
+ )
675
+ else:
676
+ result = validate_task_briefs(
677
+ root, arguments.base, arguments.tasks_dir
678
+ )
423
679
  except BriefError as error:
424
680
  print(f"task brief validation failed: {error}", file=sys.stderr)
425
681
  return 1