@opengsd/gsd-path 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. package/AGENTS.md +33 -13
  2. package/CHANGELOG.md +68 -0
  3. package/DOCS.md +75 -6
  4. package/FULL.md +12 -15
  5. package/HOOKS.md +18 -9
  6. package/QUICK.md +8 -6
  7. package/README.md +218 -14
  8. package/RUNTIME.md +16 -5
  9. package/UPDATE.md +30 -11
  10. package/WORKFLOW.md +35 -16
  11. package/package.json +23 -1
  12. package/platforms/claude/dispatch.md +4 -4
  13. package/platforms/copilot/dispatch.md +4 -4
  14. package/platforms/cursor/dispatch.md +5 -10
  15. package/platforms/grok/dispatch.md +4 -6
  16. package/platforms/kimi/dispatch.md +4 -4
  17. package/platforms/kiro/dispatch.md +4 -6
  18. package/platforms/opencode/dispatch.md +4 -4
  19. package/platforms/qwen/dispatch.md +4 -4
  20. package/platforms/shared-agents/dispatch.md +12 -19
  21. package/scripts/_common.py +5 -0
  22. package/scripts/archive_milestone.py +30 -124
  23. package/scripts/bootstrap_repository.py +33 -4
  24. package/scripts/build_recovery.py +292 -0
  25. package/scripts/build_state.py +2 -0
  26. package/scripts/check_docs_audit.py +7 -3
  27. package/scripts/check_handoffs.py +7 -1
  28. package/scripts/check_task_briefs.py +3 -0
  29. package/scripts/detect_project.py +22 -3
  30. package/scripts/discussion_records.py +3 -0
  31. package/scripts/discussion_validate.py +8 -3
  32. package/scripts/dispatch_driver.py +233 -22
  33. package/scripts/git_guard.py +14 -5
  34. package/scripts/guard_hook.py +11 -1
  35. package/scripts/install.mjs +54 -1448
  36. package/scripts/install.py +155 -188
  37. package/scripts/integration.py +54 -28
  38. package/scripts/isolation.py +24 -6
  39. package/scripts/jev_review.py +138 -0
  40. package/scripts/lean_verification.py +3 -1
  41. package/scripts/loop_run.py +2 -0
  42. package/scripts/model_policy.py +279 -0
  43. package/scripts/path_config.py +248 -0
  44. package/scripts/pipeline_diagnose.py +15 -3
  45. package/scripts/pipeline_git.py +3 -0
  46. package/scripts/pipeline_state.py +117 -186
  47. package/scripts/pipeline_undo.py +14 -7
  48. package/scripts/promote_lookahead.py +33 -162
  49. package/scripts/review_panel.py +11 -0
  50. package/scripts/roadmap.py +326 -0
  51. package/scripts/runtime_store.py +278 -0
  52. package/scripts/skill-resources.json +182 -4
  53. package/scripts/state_checkpoint.py +114 -72
  54. package/scripts/state_promote.py +47 -44
  55. package/scripts/status_runtime.py +92 -6
  56. package/scripts/task_context.py +73 -0
  57. package/scripts/token_budget.py +40 -1
  58. package/scripts/workflow_run.py +128 -8
  59. package/scripts/worktree_paths.py +94 -0
  60. package/skills/gsd-path/BUILD.md +54 -575
  61. package/skills/gsd-path/DECIDE.md +4 -6
  62. package/skills/gsd-path/DEFINE.md +23 -21
  63. package/skills/gsd-path/DOCS-AUDIT.md +2 -0
  64. package/skills/gsd-path/INSPECT.md +32 -8
  65. package/skills/gsd-path/PLAN.md +29 -19
  66. package/skills/gsd-path/RESEARCH.md +5 -6
  67. package/skills/gsd-path/ROADMAP.md +24 -58
  68. package/skills/gsd-path/SHIP.md +29 -17
  69. package/skills/gsd-path/SKILL.md +46 -22
  70. package/skills/gsd-path/references/build-abandon.md +33 -0
  71. package/skills/gsd-path/references/build-native.md +502 -0
  72. package/skills/gsd-path/references/build-recovery.md +78 -0
  73. package/skills/gsd-path/references/coder.md +8 -3
  74. package/skills/gsd-path/references/config.md +57 -0
  75. package/skills/gsd-path/references/dispatch.md +12 -19
  76. package/skills/gsd-path/references/docs-auditor.md +14 -0
  77. package/skills/gsd-path/references/jev-review.md +82 -0
  78. package/skills/gsd-path/references/model-policy.md +139 -0
  79. package/skills/gsd-path/references/reviewer-final.md +21 -0
  80. package/skills/gsd-path/references/reviewer-panel.md +17 -0
  81. package/skills/gsd-path/references/reviewer-skeptic.md +20 -0
  82. package/skills/gsd-path/references/reviewer-wave.md +89 -0
  83. package/skills/gsd-path/references/reviewer.md +12 -148
  84. package/skills/gsd-path/references/runtime-selection.md +25 -0
  85. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  86. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  87. package/skills/gsd-path/scripts/_common.py +5 -0
  88. package/skills/gsd-path/scripts/archive_milestone.py +30 -124
  89. package/skills/gsd-path/scripts/bootstrap_repository.py +33 -4
  90. package/skills/gsd-path/scripts/build_recovery.py +292 -0
  91. package/skills/gsd-path/scripts/build_state.py +2 -0
  92. package/skills/gsd-path/scripts/check_docs_audit.py +7 -3
  93. package/skills/gsd-path/scripts/check_handoffs.py +7 -1
  94. package/skills/gsd-path/scripts/check_task_briefs.py +3 -0
  95. package/skills/gsd-path/scripts/detect_project.py +22 -3
  96. package/skills/gsd-path/scripts/discussion_records.py +3 -0
  97. package/skills/gsd-path/scripts/discussion_validate.py +8 -3
  98. package/skills/gsd-path/scripts/dispatch_driver.py +233 -22
  99. package/skills/gsd-path/scripts/git_guard.py +768 -0
  100. package/skills/gsd-path/scripts/integration.py +54 -28
  101. package/skills/gsd-path/scripts/isolation.py +24 -6
  102. package/skills/gsd-path/scripts/jev_review.py +138 -0
  103. package/skills/gsd-path/scripts/lean_verification.py +3 -1
  104. package/skills/gsd-path/scripts/loop_run.py +2 -0
  105. package/skills/gsd-path/scripts/model_policy.py +279 -0
  106. package/skills/gsd-path/scripts/path_config.py +248 -0
  107. package/skills/gsd-path/scripts/pipeline_git.py +3 -0
  108. package/skills/gsd-path/scripts/pipeline_state.py +117 -186
  109. package/skills/gsd-path/scripts/promote_lookahead.py +33 -162
  110. package/skills/gsd-path/scripts/review_panel.py +11 -0
  111. package/skills/gsd-path/scripts/roadmap.py +326 -0
  112. package/skills/gsd-path/scripts/state_checkpoint.py +114 -72
  113. package/skills/gsd-path/scripts/state_promote.py +47 -44
  114. package/skills/gsd-path/scripts/status_runtime.py +208 -0
  115. package/skills/gsd-path/scripts/task_context.py +73 -0
  116. package/skills/gsd-path/scripts/token_budget.py +40 -1
  117. package/skills/gsd-path/scripts/workflow_run.py +128 -8
  118. package/skills/gsd-path/scripts/worktree_paths.py +94 -0
  119. package/skills/gsd-path/templates/skeptic.md +1 -1
  120. package/skills/gsd-path/templates/task.md +2 -0
  121. package/skills/gsd-path/templates/wave-panel.md +1 -1
  122. package/skills/gsd-path/templates/wave-review.md +1 -1
  123. package/skills/gsd-path-build/SKILL.md +54 -575
  124. package/skills/gsd-path-build/references/build-abandon.md +33 -0
  125. package/skills/gsd-path-build/references/build-native.md +502 -0
  126. package/skills/gsd-path-build/references/build-recovery.md +78 -0
  127. package/skills/gsd-path-build/references/coder.md +8 -3
  128. package/skills/gsd-path-build/references/dispatch.md +12 -19
  129. package/skills/gsd-path-build/references/jev-review.md +82 -0
  130. package/skills/gsd-path-build/references/model-policy.md +139 -0
  131. package/skills/gsd-path-build/references/reviewer-final.md +21 -0
  132. package/skills/gsd-path-build/references/reviewer-panel.md +17 -0
  133. package/skills/gsd-path-build/references/reviewer-skeptic.md +20 -0
  134. package/skills/gsd-path-build/references/reviewer-wave.md +89 -0
  135. package/skills/gsd-path-build/references/reviewer.md +12 -148
  136. package/skills/gsd-path-build/references/runtime-selection.md +25 -0
  137. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  138. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  139. package/skills/gsd-path-build/scripts/_common.py +5 -0
  140. package/skills/gsd-path-build/scripts/archive_milestone.py +30 -124
  141. package/skills/gsd-path-build/scripts/build_recovery.py +292 -0
  142. package/skills/gsd-path-build/scripts/build_state.py +2 -0
  143. package/skills/gsd-path-build/scripts/check_handoffs.py +7 -1
  144. package/skills/gsd-path-build/scripts/check_task_briefs.py +3 -0
  145. package/skills/gsd-path-build/scripts/detect_project.py +1536 -0
  146. package/skills/gsd-path-build/scripts/discussion_records.py +3 -0
  147. package/skills/gsd-path-build/scripts/discussion_validate.py +8 -3
  148. package/skills/gsd-path-build/scripts/dispatch_driver.py +233 -22
  149. package/skills/gsd-path-build/scripts/integration.py +54 -28
  150. package/skills/gsd-path-build/scripts/isolation.py +24 -6
  151. package/skills/gsd-path-build/scripts/jev_review.py +138 -0
  152. package/skills/gsd-path-build/scripts/loop_run.py +2 -0
  153. package/skills/gsd-path-build/scripts/model_policy.py +279 -0
  154. package/skills/gsd-path-build/scripts/path_config.py +248 -0
  155. package/skills/gsd-path-build/scripts/pipeline_git.py +3 -0
  156. package/skills/gsd-path-build/scripts/pipeline_state.py +117 -186
  157. package/skills/gsd-path-build/scripts/promote_lookahead.py +286 -0
  158. package/skills/gsd-path-build/scripts/review_panel.py +11 -0
  159. package/skills/gsd-path-build/scripts/roadmap.py +326 -0
  160. package/skills/gsd-path-build/scripts/state_checkpoint.py +114 -72
  161. package/skills/gsd-path-build/scripts/state_promote.py +47 -44
  162. package/skills/gsd-path-build/scripts/task_context.py +73 -0
  163. package/skills/gsd-path-build/scripts/token_budget.py +40 -1
  164. package/skills/gsd-path-build/scripts/workflow_run.py +128 -8
  165. package/skills/gsd-path-build/scripts/worktree_paths.py +94 -0
  166. package/skills/gsd-path-build/templates/skeptic.md +1 -1
  167. package/skills/gsd-path-build/templates/task.md +2 -0
  168. package/skills/gsd-path-build/templates/wave-panel.md +1 -1
  169. package/skills/gsd-path-build/templates/wave-review.md +1 -1
  170. package/skills/gsd-path-decide/SKILL.md +4 -6
  171. package/skills/gsd-path-decide/references/dispatch.md +12 -19
  172. package/skills/gsd-path-decide/references/model-policy.md +139 -0
  173. package/skills/gsd-path-decide/references/runtime-selection.md +25 -0
  174. package/skills/gsd-path-decide/scripts/_common.py +5 -0
  175. package/skills/gsd-path-decide/scripts/archive_milestone.py +2171 -0
  176. package/skills/gsd-path-decide/scripts/build_recovery.py +292 -0
  177. package/skills/gsd-path-decide/scripts/check_handoffs.py +7 -1
  178. package/skills/gsd-path-decide/scripts/check_task_briefs.py +3 -0
  179. package/skills/gsd-path-decide/scripts/detect_project.py +1536 -0
  180. package/skills/gsd-path-decide/scripts/discussion_records.py +3 -0
  181. package/skills/gsd-path-decide/scripts/discussion_validate.py +1326 -0
  182. package/skills/gsd-path-decide/scripts/integration.py +1459 -0
  183. package/skills/gsd-path-decide/scripts/isolation.py +24 -6
  184. package/skills/gsd-path-decide/scripts/loop_run.py +839 -0
  185. package/skills/gsd-path-decide/scripts/model_policy.py +279 -0
  186. package/skills/gsd-path-decide/scripts/path_config.py +248 -0
  187. package/skills/gsd-path-decide/scripts/pipeline_git.py +3 -0
  188. package/skills/gsd-path-decide/scripts/pipeline_state.py +117 -186
  189. package/skills/gsd-path-decide/scripts/promote_lookahead.py +286 -0
  190. package/skills/gsd-path-decide/scripts/review_panel.py +564 -0
  191. package/skills/gsd-path-decide/scripts/roadmap.py +326 -0
  192. package/skills/gsd-path-decide/scripts/state_checkpoint.py +114 -72
  193. package/skills/gsd-path-decide/scripts/state_promote.py +47 -44
  194. package/skills/gsd-path-decide/scripts/worktree_paths.py +94 -0
  195. package/skills/gsd-path-define/SKILL.md +23 -21
  196. package/skills/gsd-path-define/references/build-recovery.md +78 -0
  197. package/skills/gsd-path-define/references/runtime-selection.md +25 -0
  198. package/skills/gsd-path-define/scripts/_common.py +5 -0
  199. package/skills/gsd-path-define/scripts/archive_milestone.py +2171 -0
  200. package/skills/gsd-path-define/scripts/build_recovery.py +292 -0
  201. package/skills/gsd-path-define/scripts/check_handoffs.py +7 -1
  202. package/skills/gsd-path-define/scripts/check_task_briefs.py +3 -0
  203. package/skills/gsd-path-define/scripts/detect_project.py +22 -3
  204. package/skills/gsd-path-define/scripts/discussion_records.py +3 -0
  205. package/skills/gsd-path-define/scripts/discussion_validate.py +1326 -0
  206. package/skills/gsd-path-define/scripts/integration.py +1459 -0
  207. package/skills/gsd-path-define/scripts/isolation.py +24 -6
  208. package/skills/gsd-path-define/scripts/loop_run.py +839 -0
  209. package/skills/gsd-path-define/scripts/model_policy.py +279 -0
  210. package/skills/gsd-path-define/scripts/path_config.py +248 -0
  211. package/skills/gsd-path-define/scripts/pipeline_git.py +3 -0
  212. package/skills/gsd-path-define/scripts/pipeline_state.py +117 -186
  213. package/skills/gsd-path-define/scripts/promote_lookahead.py +286 -0
  214. package/skills/gsd-path-define/scripts/review_panel.py +564 -0
  215. package/skills/gsd-path-define/scripts/roadmap.py +326 -0
  216. package/skills/gsd-path-define/scripts/state_checkpoint.py +114 -72
  217. package/skills/gsd-path-define/scripts/state_promote.py +47 -44
  218. package/skills/gsd-path-define/scripts/worktree_paths.py +94 -0
  219. package/skills/gsd-path-discuss/SKILL.md +2 -0
  220. package/skills/gsd-path-discuss/references/runtime-selection.md +25 -0
  221. package/skills/gsd-path-discuss/scripts/_common.py +5 -0
  222. package/skills/gsd-path-discuss/scripts/discussion_records.py +3 -0
  223. package/skills/gsd-path-discuss/scripts/loop_run.py +839 -0
  224. package/skills/gsd-path-discuss/scripts/model_policy.py +279 -0
  225. package/skills/gsd-path-discuss/scripts/path_config.py +248 -0
  226. package/skills/gsd-path-discuss/scripts/review_panel.py +564 -0
  227. package/skills/gsd-path-discuss/scripts/worktree_paths.py +94 -0
  228. package/skills/gsd-path-docs-audit/SKILL.md +2 -0
  229. package/skills/gsd-path-docs-audit/references/dispatch.md +12 -19
  230. package/skills/gsd-path-docs-audit/references/docs-auditor.md +14 -0
  231. package/skills/gsd-path-docs-audit/references/model-policy.md +139 -0
  232. package/skills/gsd-path-docs-audit/references/runtime-selection.md +25 -0
  233. package/skills/gsd-path-docs-audit/scripts/_common.py +5 -0
  234. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +2171 -0
  235. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +292 -0
  236. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +7 -3
  237. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +7 -1
  238. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +3 -0
  239. package/skills/gsd-path-docs-audit/scripts/detect_project.py +1536 -0
  240. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +3 -0
  241. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +1326 -0
  242. package/skills/gsd-path-docs-audit/scripts/integration.py +1459 -0
  243. package/skills/gsd-path-docs-audit/scripts/isolation.py +24 -6
  244. package/skills/gsd-path-docs-audit/scripts/loop_run.py +839 -0
  245. package/skills/gsd-path-docs-audit/scripts/model_policy.py +279 -0
  246. package/skills/gsd-path-docs-audit/scripts/path_config.py +248 -0
  247. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +3 -0
  248. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +117 -186
  249. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +286 -0
  250. package/skills/gsd-path-docs-audit/scripts/review_panel.py +564 -0
  251. package/skills/gsd-path-docs-audit/scripts/roadmap.py +326 -0
  252. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +114 -72
  253. package/skills/gsd-path-docs-audit/scripts/state_promote.py +47 -44
  254. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +94 -0
  255. package/skills/gsd-path-forensics/SKILL.md +9 -5
  256. package/skills/gsd-path-forensics/references/runtime-selection.md +25 -0
  257. package/skills/gsd-path-forensics/scripts/_common.py +5 -0
  258. package/skills/gsd-path-forensics/scripts/discussion_records.py +3 -0
  259. package/skills/gsd-path-forensics/scripts/loop_run.py +839 -0
  260. package/skills/gsd-path-forensics/scripts/model_policy.py +279 -0
  261. package/skills/gsd-path-forensics/scripts/path_config.py +248 -0
  262. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +15 -3
  263. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +14 -7
  264. package/skills/gsd-path-forensics/scripts/review_panel.py +564 -0
  265. package/skills/gsd-path-forensics/scripts/worktree_paths.py +94 -0
  266. package/skills/gsd-path-inspect/SKILL.md +32 -8
  267. package/skills/gsd-path-inspect/references/dispatch.md +12 -19
  268. package/skills/gsd-path-inspect/references/docs-auditor.md +14 -0
  269. package/skills/gsd-path-inspect/references/model-policy.md +139 -0
  270. package/skills/gsd-path-inspect/references/runtime-selection.md +25 -0
  271. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  272. package/skills/gsd-path-inspect/scripts/_common.py +5 -0
  273. package/skills/gsd-path-inspect/scripts/archive_milestone.py +2171 -0
  274. package/skills/gsd-path-inspect/scripts/build_recovery.py +292 -0
  275. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +7 -3
  276. package/skills/gsd-path-inspect/scripts/check_handoffs.py +7 -1
  277. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +3 -0
  278. package/skills/gsd-path-inspect/scripts/detect_project.py +22 -3
  279. package/skills/gsd-path-inspect/scripts/discussion_records.py +3 -0
  280. package/skills/gsd-path-inspect/scripts/discussion_validate.py +1326 -0
  281. package/skills/gsd-path-inspect/scripts/integration.py +1459 -0
  282. package/skills/gsd-path-inspect/scripts/isolation.py +24 -6
  283. package/skills/gsd-path-inspect/scripts/loop_run.py +839 -0
  284. package/skills/gsd-path-inspect/scripts/model_policy.py +279 -0
  285. package/skills/gsd-path-inspect/scripts/path_config.py +248 -0
  286. package/skills/gsd-path-inspect/scripts/pipeline_git.py +3 -0
  287. package/skills/gsd-path-inspect/scripts/pipeline_state.py +117 -186
  288. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +286 -0
  289. package/skills/gsd-path-inspect/scripts/review_panel.py +564 -0
  290. package/skills/gsd-path-inspect/scripts/roadmap.py +326 -0
  291. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +114 -72
  292. package/skills/gsd-path-inspect/scripts/state_promote.py +47 -44
  293. package/skills/gsd-path-inspect/scripts/workflow_run.py +237 -0
  294. package/skills/gsd-path-inspect/scripts/worktree_paths.py +94 -0
  295. package/skills/gsd-path-loop/SKILL.md +2 -0
  296. package/skills/gsd-path-loop/references/runtime-selection.md +25 -0
  297. package/skills/gsd-path-loop/scripts/_common.py +5 -0
  298. package/skills/gsd-path-loop/scripts/discussion_records.py +3 -0
  299. package/skills/gsd-path-loop/scripts/loop_run.py +2 -0
  300. package/skills/gsd-path-loop/scripts/model_policy.py +279 -0
  301. package/skills/gsd-path-loop/scripts/path_config.py +248 -0
  302. package/skills/gsd-path-loop/scripts/review_panel.py +564 -0
  303. package/skills/gsd-path-loop/scripts/worktree_paths.py +94 -0
  304. package/skills/gsd-path-migrate/SKILL.md +2 -0
  305. package/skills/gsd-path-migrate/references/runtime-selection.md +25 -0
  306. package/skills/gsd-path-migrate/scripts/_common.py +185 -0
  307. package/skills/gsd-path-migrate/scripts/discussion_records.py +3 -0
  308. package/skills/gsd-path-migrate/scripts/loop_run.py +839 -0
  309. package/skills/gsd-path-migrate/scripts/model_policy.py +279 -0
  310. package/skills/gsd-path-migrate/scripts/path_config.py +248 -0
  311. package/skills/gsd-path-migrate/scripts/review_panel.py +564 -0
  312. package/skills/gsd-path-plan/SKILL.md +29 -19
  313. package/skills/gsd-path-plan/references/build-recovery.md +78 -0
  314. package/skills/gsd-path-plan/references/dispatch.md +12 -19
  315. package/skills/gsd-path-plan/references/model-policy.md +139 -0
  316. package/skills/gsd-path-plan/references/runtime-selection.md +25 -0
  317. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  318. package/skills/gsd-path-plan/scripts/_common.py +5 -0
  319. package/skills/gsd-path-plan/scripts/archive_milestone.py +2171 -0
  320. package/skills/gsd-path-plan/scripts/build_recovery.py +292 -0
  321. package/skills/gsd-path-plan/scripts/check_handoffs.py +7 -1
  322. package/skills/gsd-path-plan/scripts/check_task_briefs.py +3 -0
  323. package/skills/gsd-path-plan/scripts/detect_project.py +1536 -0
  324. package/skills/gsd-path-plan/scripts/discussion_records.py +3 -0
  325. package/skills/gsd-path-plan/scripts/discussion_validate.py +1326 -0
  326. package/skills/gsd-path-plan/scripts/integration.py +1459 -0
  327. package/skills/gsd-path-plan/scripts/isolation.py +24 -6
  328. package/skills/gsd-path-plan/scripts/loop_run.py +839 -0
  329. package/skills/gsd-path-plan/scripts/model_policy.py +279 -0
  330. package/skills/gsd-path-plan/scripts/path_config.py +248 -0
  331. package/skills/gsd-path-plan/scripts/pipeline_git.py +3 -0
  332. package/skills/gsd-path-plan/scripts/pipeline_state.py +117 -186
  333. package/skills/gsd-path-plan/scripts/promote_lookahead.py +286 -0
  334. package/skills/gsd-path-plan/scripts/review_panel.py +11 -0
  335. package/skills/gsd-path-plan/scripts/roadmap.py +326 -0
  336. package/skills/gsd-path-plan/scripts/state_checkpoint.py +114 -72
  337. package/skills/gsd-path-plan/scripts/state_promote.py +47 -44
  338. package/skills/gsd-path-plan/scripts/workflow_run.py +128 -8
  339. package/skills/gsd-path-plan/scripts/worktree_paths.py +94 -0
  340. package/skills/gsd-path-plan/templates/task.md +2 -0
  341. package/skills/gsd-path-research/SKILL.md +5 -6
  342. package/skills/gsd-path-research/references/dispatch.md +12 -19
  343. package/skills/gsd-path-research/references/model-policy.md +139 -0
  344. package/skills/gsd-path-research/references/runtime-selection.md +25 -0
  345. package/skills/gsd-path-research/scripts/_common.py +5 -0
  346. package/skills/gsd-path-research/scripts/archive_milestone.py +2171 -0
  347. package/skills/gsd-path-research/scripts/build_recovery.py +292 -0
  348. package/skills/gsd-path-research/scripts/check_handoffs.py +7 -1
  349. package/skills/gsd-path-research/scripts/check_task_briefs.py +3 -0
  350. package/skills/gsd-path-research/scripts/detect_project.py +1536 -0
  351. package/skills/gsd-path-research/scripts/discussion_records.py +3 -0
  352. package/skills/gsd-path-research/scripts/discussion_validate.py +1326 -0
  353. package/skills/gsd-path-research/scripts/integration.py +1459 -0
  354. package/skills/gsd-path-research/scripts/isolation.py +24 -6
  355. package/skills/gsd-path-research/scripts/loop_run.py +839 -0
  356. package/skills/gsd-path-research/scripts/model_policy.py +279 -0
  357. package/skills/gsd-path-research/scripts/path_config.py +248 -0
  358. package/skills/gsd-path-research/scripts/pipeline_git.py +3 -0
  359. package/skills/gsd-path-research/scripts/pipeline_state.py +117 -186
  360. package/skills/gsd-path-research/scripts/promote_lookahead.py +286 -0
  361. package/skills/gsd-path-research/scripts/review_panel.py +564 -0
  362. package/skills/gsd-path-research/scripts/roadmap.py +326 -0
  363. package/skills/gsd-path-research/scripts/state_checkpoint.py +114 -72
  364. package/skills/gsd-path-research/scripts/state_promote.py +47 -44
  365. package/skills/gsd-path-research/scripts/worktree_paths.py +94 -0
  366. package/skills/gsd-path-roadmap/SKILL.md +24 -58
  367. package/skills/gsd-path-roadmap/references/dispatch.md +12 -19
  368. package/skills/gsd-path-roadmap/references/model-policy.md +139 -0
  369. package/skills/gsd-path-roadmap/references/runtime-selection.md +25 -0
  370. package/skills/gsd-path-roadmap/scripts/_common.py +5 -0
  371. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +30 -124
  372. package/skills/gsd-path-roadmap/scripts/build_recovery.py +292 -0
  373. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +7 -1
  374. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +3 -0
  375. package/skills/gsd-path-roadmap/scripts/detect_project.py +22 -3
  376. package/skills/gsd-path-roadmap/scripts/discussion_records.py +3 -0
  377. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +8 -3
  378. package/skills/gsd-path-roadmap/scripts/integration.py +54 -28
  379. package/skills/gsd-path-roadmap/scripts/isolation.py +24 -6
  380. package/skills/gsd-path-roadmap/scripts/loop_run.py +839 -0
  381. package/skills/gsd-path-roadmap/scripts/model_policy.py +279 -0
  382. package/skills/gsd-path-roadmap/scripts/path_config.py +248 -0
  383. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +3 -0
  384. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +117 -186
  385. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +33 -162
  386. package/skills/gsd-path-roadmap/scripts/review_panel.py +11 -0
  387. package/skills/gsd-path-roadmap/scripts/roadmap.py +326 -0
  388. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +114 -72
  389. package/skills/gsd-path-roadmap/scripts/state_promote.py +47 -44
  390. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +94 -0
  391. package/skills/gsd-path-ship/SKILL.md +29 -17
  392. package/skills/gsd-path-ship/references/dispatch.md +12 -19
  393. package/skills/gsd-path-ship/references/jev-review.md +82 -0
  394. package/skills/gsd-path-ship/references/model-policy.md +139 -0
  395. package/skills/gsd-path-ship/references/reviewer-final.md +21 -0
  396. package/skills/gsd-path-ship/references/reviewer-panel.md +17 -0
  397. package/skills/gsd-path-ship/references/reviewer-skeptic.md +20 -0
  398. package/skills/gsd-path-ship/references/reviewer-wave.md +89 -0
  399. package/skills/gsd-path-ship/references/reviewer.md +12 -148
  400. package/skills/gsd-path-ship/references/runtime-selection.md +25 -0
  401. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  402. package/skills/gsd-path-ship/scripts/_common.py +5 -0
  403. package/skills/gsd-path-ship/scripts/archive_milestone.py +30 -124
  404. package/skills/gsd-path-ship/scripts/build_recovery.py +292 -0
  405. package/skills/gsd-path-ship/scripts/build_state.py +2 -0
  406. package/skills/gsd-path-ship/scripts/check_handoffs.py +7 -1
  407. package/skills/gsd-path-ship/scripts/check_task_briefs.py +3 -0
  408. package/skills/gsd-path-ship/scripts/detect_project.py +1536 -0
  409. package/skills/gsd-path-ship/scripts/discussion_records.py +3 -0
  410. package/skills/gsd-path-ship/scripts/discussion_validate.py +8 -3
  411. package/skills/gsd-path-ship/scripts/integration.py +54 -28
  412. package/skills/gsd-path-ship/scripts/isolation.py +24 -6
  413. package/skills/gsd-path-ship/scripts/jev_review.py +138 -0
  414. package/skills/gsd-path-ship/scripts/lean_verification.py +3 -1
  415. package/skills/gsd-path-ship/scripts/loop_run.py +839 -0
  416. package/skills/gsd-path-ship/scripts/model_policy.py +279 -0
  417. package/skills/gsd-path-ship/scripts/path_config.py +248 -0
  418. package/skills/gsd-path-ship/scripts/pipeline_git.py +3 -0
  419. package/skills/gsd-path-ship/scripts/pipeline_state.py +117 -186
  420. package/skills/gsd-path-ship/scripts/promote_lookahead.py +286 -0
  421. package/skills/gsd-path-ship/scripts/review_panel.py +11 -0
  422. package/skills/gsd-path-ship/scripts/roadmap.py +326 -0
  423. package/skills/gsd-path-ship/scripts/state_checkpoint.py +114 -72
  424. package/skills/gsd-path-ship/scripts/state_promote.py +47 -44
  425. package/skills/gsd-path-ship/scripts/workflow_run.py +128 -8
  426. package/skills/gsd-path-ship/scripts/worktree_paths.py +94 -0
  427. package/skills/gsd-path-ship/templates/wave-review.md +1 -1
  428. package/skills/gsd-path-undo/SKILL.md +2 -0
  429. package/skills/gsd-path-undo/references/runtime-selection.md +25 -0
  430. package/skills/gsd-path-undo/scripts/_common.py +5 -0
  431. package/skills/gsd-path-undo/scripts/discussion_records.py +3 -0
  432. package/skills/gsd-path-undo/scripts/loop_run.py +839 -0
  433. package/skills/gsd-path-undo/scripts/model_policy.py +279 -0
  434. package/skills/gsd-path-undo/scripts/path_config.py +248 -0
  435. package/skills/gsd-path-undo/scripts/pipeline_undo.py +14 -7
  436. package/skills/gsd-path-undo/scripts/review_panel.py +564 -0
  437. package/skills/gsd-path-undo/scripts/worktree_paths.py +94 -0
  438. package/skills/path/BUILD.md +54 -575
  439. package/skills/path/DECIDE.md +4 -6
  440. package/skills/path/DEFINE.md +23 -21
  441. package/skills/path/DOCS-AUDIT.md +2 -0
  442. package/skills/path/INSPECT.md +32 -8
  443. package/skills/path/PLAN.md +29 -19
  444. package/skills/path/RESEARCH.md +5 -6
  445. package/skills/path/ROADMAP.md +24 -58
  446. package/skills/path/SHIP.md +29 -17
  447. package/skills/path/SKILL.md +46 -22
  448. package/skills/path/references/build-abandon.md +33 -0
  449. package/skills/path/references/build-native.md +502 -0
  450. package/skills/path/references/build-recovery.md +78 -0
  451. package/skills/path/references/coder.md +8 -3
  452. package/skills/path/references/config.md +57 -0
  453. package/skills/path/references/dispatch.md +12 -19
  454. package/skills/path/references/docs-auditor.md +14 -0
  455. package/skills/path/references/jev-review.md +82 -0
  456. package/skills/path/references/model-policy.md +139 -0
  457. package/skills/path/references/reviewer-final.md +21 -0
  458. package/skills/path/references/reviewer-panel.md +17 -0
  459. package/skills/path/references/reviewer-skeptic.md +20 -0
  460. package/skills/path/references/reviewer-wave.md +89 -0
  461. package/skills/path/references/reviewer.md +12 -148
  462. package/skills/path/references/runtime-selection.md +25 -0
  463. package/skills/path/scripts/_common.py +5 -0
  464. package/skills/path/scripts/archive_milestone.py +30 -124
  465. package/skills/path/scripts/bootstrap_repository.py +33 -4
  466. package/skills/path/scripts/build_recovery.py +292 -0
  467. package/skills/path/scripts/build_state.py +2 -0
  468. package/skills/path/scripts/check_docs_audit.py +7 -3
  469. package/skills/path/scripts/check_handoffs.py +7 -1
  470. package/skills/path/scripts/check_task_briefs.py +3 -0
  471. package/skills/path/scripts/detect_project.py +22 -3
  472. package/skills/path/scripts/discussion_records.py +3 -0
  473. package/skills/path/scripts/discussion_validate.py +8 -3
  474. package/skills/path/scripts/dispatch_driver.py +233 -22
  475. package/skills/path/scripts/git_guard.py +768 -0
  476. package/skills/path/scripts/integration.py +54 -28
  477. package/skills/path/scripts/isolation.py +24 -6
  478. package/skills/path/scripts/jev_review.py +138 -0
  479. package/skills/path/scripts/lean_verification.py +3 -1
  480. package/skills/path/scripts/loop_run.py +2 -0
  481. package/skills/path/scripts/model_policy.py +279 -0
  482. package/skills/path/scripts/path_config.py +248 -0
  483. package/skills/path/scripts/pipeline_git.py +3 -0
  484. package/skills/path/scripts/pipeline_state.py +117 -186
  485. package/skills/path/scripts/promote_lookahead.py +33 -162
  486. package/skills/path/scripts/review_panel.py +11 -0
  487. package/skills/path/scripts/roadmap.py +326 -0
  488. package/skills/path/scripts/state_checkpoint.py +114 -72
  489. package/skills/path/scripts/state_promote.py +47 -44
  490. package/skills/path/scripts/status_runtime.py +208 -0
  491. package/skills/path/scripts/task_context.py +73 -0
  492. package/skills/path/scripts/token_budget.py +40 -1
  493. package/skills/path/scripts/workflow_run.py +128 -8
  494. package/skills/path/scripts/worktree_paths.py +94 -0
  495. package/skills/path/templates/skeptic.md +1 -1
  496. package/skills/path/templates/task.md +2 -0
  497. package/skills/path/templates/wave-panel.md +1 -1
  498. package/skills/path/templates/wave-review.md +1 -1
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env python3
2
+ """Render a read-only coder intent view from the approved task and intent."""
3
+
4
+ import argparse
5
+ import hashlib
6
+ import re
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ try:
11
+ from scripts import check_handoffs as contracts
12
+ except ImportError:
13
+ import check_handoffs as contracts
14
+
15
+
16
+ def render(repo: Path, task: Path) -> str:
17
+ intent_path = repo.resolve() / '.project/intent/INTENT.md'
18
+ task = task.resolve()
19
+ intent = intent_path.read_bytes().decode('utf-8')
20
+ task_text = task.read_bytes().decode('utf-8')
21
+ owned = contracts._owned_criteria(task_text, task.stem)
22
+ criteria = contracts._success_criteria(intent)
23
+ unknown = set(owned) - set(criteria)
24
+ if unknown:
25
+ raise contracts.HandoffError('unknown owned criteria: ' + ', '.join(sorted(unknown)))
26
+ projected, mode = intent, 'full-intent'
27
+ sections = list(re.finditer(r'(?ms)^## Success criteria[ \t]*\n(?P<body>.*?)(?=^## |\Z)', intent))
28
+ if len(sections) == 1:
29
+ section = sections[0]
30
+ body = section['body']
31
+ items = list(re.finditer(r'(?m)^(\d+)\. .+\n?', body))
32
+ # Project only simple numbered prose. Preserve unfamiliar Markdown in full.
33
+ simple = (items and not body[:items[0].start()].strip()
34
+ and '```' not in body and '~~~' not in body and '<!--' not in body
35
+ and [f'SC{item[1]}' for item in items] == list(criteria))
36
+ chunks = [body[item.start():items[n + 1].start() if n + 1 < len(items) else len(body)]
37
+ for n, item in enumerate(items)]
38
+ simple = simple and all(not line.strip() or line[:1].isspace()
39
+ for chunk in chunks for line in chunk.splitlines()[1:])
40
+ if simple:
41
+ before, after = intent[:section.start('body')], intent[section.end('body'):]
42
+ # Corrections and task interfaces can explicitly refer to another SC.
43
+ required = set(owned) | set(re.findall(r'\bSC\d+\b', before + after + task_text))
44
+ selected = ''.join(chunk for item, chunk in zip(items, chunks) if f'SC{item[1]}' in required)
45
+ projected = before + '\n' + (selected or '- No criteria assigned.\n\n') + after
46
+ mode = 'owned-criteria'
47
+ return ('## Generated intent context\n\n'
48
+ f'Source: {intent_path}\n'
49
+ f'Intent SHA256: {hashlib.sha256(intent.encode()).hexdigest()}\n'
50
+ f'Task: {task}\n'
51
+ f'Task SHA256: {hashlib.sha256(task_text.encode()).hexdigest()}\n'
52
+ f'Mode: {mode}\n\n'
53
+ 'Use this view for intent. All non-criterion text is verbatim; selected criteria retain '
54
+ 'their original numbers. The source remains authoritative. Read it if a dependency '
55
+ 'or ambiguity requires omitted criteria.\n\n' + projected)
56
+
57
+
58
+ def main() -> int:
59
+ parser = argparse.ArgumentParser(description=__doc__)
60
+ parser.add_argument('--repo', type=Path, required=True)
61
+ parser.add_argument('--task', type=Path, required=True)
62
+ args = parser.parse_args()
63
+ try:
64
+ output = render(args.repo, args.task)
65
+ except (OSError, contracts.HandoffError) as error:
66
+ print(str(error), file=sys.stderr)
67
+ return 1
68
+ print(output, end='')
69
+ return 0
70
+
71
+
72
+ if __name__ == '__main__':
73
+ raise SystemExit(main())
@@ -69,6 +69,24 @@ def output_usage(path: Path) -> int:
69
69
  return sum(usages)
70
70
 
71
71
 
72
+ def cumulative_counter(path: Path):
73
+ """One completed CLI invocation, with the thread identity needed for resume."""
74
+ identities, counters = set(), []
75
+ for line in path.read_text(encoding="utf-8").splitlines():
76
+ event = json.loads(line)
77
+ if "raw" in event:
78
+ event = json.loads(event["raw"])
79
+ if event.get("type") == "thread.started":
80
+ identities.add(event["thread_id"])
81
+ if event.get("type") == "turn.completed":
82
+ counters.append(event["usage"]["output_tokens"])
83
+ if len(identities) != 1 or len(counters) != 1:
84
+ raise ValueError("cumulative usage requires one identified, completed CLI invocation")
85
+ if type(counters[0]) is not int or counters[0] < 0:
86
+ raise ValueError("invalid cumulative output counter")
87
+ return identities.pop(), counters[0]
88
+
89
+
72
90
  def operate(args):
73
91
  ledger = args.ledger.absolute()
74
92
  if ledger.is_symlink():
@@ -92,9 +110,28 @@ def operate(args):
92
110
  if args.action == "record":
93
111
  source = str(args.events.resolve())
94
112
  observation = {"task": args.task, "output_tokens": output_usage(args.events)}
113
+ prior_events = getattr(args, "previous_events", None)
114
+ if prior_events is not None:
115
+ prior_source = str(prior_events.resolve())
116
+ prior = data["observations"].get(prior_source)
117
+ identity, total = cumulative_counter(args.events)
118
+ prior_identity, prior_total = cumulative_counter(prior_events)
119
+ if source == prior_source or identity != prior_identity or total < prior_total:
120
+ raise ValueError("cumulative resume has a different thread or a reset counter")
121
+ if prior is None or prior.get("reported_output_tokens", prior["output_tokens"]) != prior_total:
122
+ raise ValueError("previous cumulative invocation must be recorded unchanged first")
123
+ if any(key != source and row.get("previous_events") == prior_source
124
+ for key, row in data["observations"].items()):
125
+ raise ValueError("previous cumulative invocation already has a recorded successor")
126
+ observation.update(output_tokens=total - prior_total, reported_output_tokens=total,
127
+ previous_events=prior_source, session_id=identity)
95
128
  previous = data["observations"].get(source)
129
+ if previous and previous != observation and any(
130
+ row.get("previous_events") == source for row in data["observations"].values()):
131
+ raise ValueError("a cumulative predecessor cannot change after its successor is recorded")
96
132
  if previous and (previous["task"] != args.task or
97
- previous["output_tokens"] > observation["output_tokens"]):
133
+ previous["output_tokens"] > observation["output_tokens"] or
134
+ previous.get("previous_events") != observation.get("previous_events")):
98
135
  raise ValueError("observation cannot change task or reduce recorded usage")
99
136
  data["observations"][source] = observation
100
137
  atomic_write(ledger, json.dumps(data, indent=2) + "\n")
@@ -131,6 +168,8 @@ def main(argv=None):
131
168
  command.add_argument("--task", required=True)
132
169
  if name == "record":
133
170
  command.add_argument("--events", type=Path, required=True)
171
+ command.add_argument("--previous-events", type=Path,
172
+ help="previous recorded invocation when this CLI reports cumulative resume counters")
134
173
  if name == "admit":
135
174
  command.add_argument("--require-hard-cap", action="store_true")
136
175
  try:
@@ -2,9 +2,12 @@
2
2
  """Run canonical workflow helpers with fixed arguments and fail-stop receipts."""
3
3
 
4
4
  import argparse
5
+ import hashlib
5
6
  import json
7
+ import os
6
8
  import subprocess
7
9
  import sys
10
+ import tempfile
8
11
  from pathlib import Path
9
12
 
10
13
  try:
@@ -16,14 +19,20 @@ except ImportError: # bundled copy inside a skill's scripts directory
16
19
  class StepFailed(RuntimeError):
17
20
  pass
18
21
 
22
+ INSPECTION_SPECS = (("inspect_codebase", "codebase-mapper", "codebase", "evidence-codebase.md"),
23
+ ("inspect_docs", "docs-auditor", "docs-audit", "DOCS-AUDIT.md"))
24
+
19
25
 
20
26
  def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str = None,
21
- task_id: str = None, round_size: int = None) -> dict:
27
+ task_id: str = None, round_size: int = None, inspection: Path = None,
28
+ mapper_reviewed: bool = False) -> dict:
22
29
  steps = []
30
+ outputs = {}
23
31
  scripts = Path(__file__).resolve().parent
32
+ helpers = scripts
24
33
 
25
- def step(script, *arguments):
26
- command = [sys.executable, "-B", str(scripts / script), *arguments]
34
+ def step(script, *arguments, raw=False):
35
+ command = [sys.executable, "-B", str(helpers / script), *arguments]
27
36
  completed = subprocess.run(command, cwd=repo, capture_output=True, text=True)
28
37
  receipt = {"script": script, "command": command, "exit_code": completed.returncode,
29
38
  "stdout": completed.stdout, "stderr": completed.stderr}
@@ -32,6 +41,8 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
32
41
  sys.stderr.write(completed.stderr)
33
42
  if completed.returncode:
34
43
  raise StepFailed(script)
44
+ if raw:
45
+ return completed.stdout
35
46
  try:
36
47
  receipt["result"] = json.loads(completed.stdout)
37
48
  except json.JSONDecodeError as error:
@@ -40,8 +51,114 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
40
51
 
41
52
  common = ["--repo", str(repo), "--project-dir", project_dir]
42
53
  try:
54
+ if os.path.lexists(repo / ".gsd-path/runtime.json"):
55
+ resolved = subprocess.run(
56
+ [sys.executable, "-B", str(repo / ".gsd-path/status_runtime.py"),
57
+ "--repo", str(repo), "--runtime-path"],
58
+ cwd=repo, capture_output=True, text=True)
59
+ if resolved.returncode:
60
+ sys.stderr.write(resolved.stderr)
61
+ raise StepFailed(resolved.stderr.strip())
62
+ helpers = Path(resolved.stdout.strip())
43
63
  if action == "route":
44
64
  step("pipeline_state.py", "route", *common)
65
+ elif action == "prepare-inspect":
66
+ state = step("pipeline_state.py", "validate", *common)["state"]
67
+ if project_dir != ".project" or state["phase"] != "inspect" or state["status"] != "active":
68
+ raise StepFailed("initial inspection requires the active inspect track")
69
+ specs = INSPECTION_SPECS
70
+ if any((repo / project_dir / "research" / spec[3]).exists() or
71
+ (repo / project_dir / "research" / spec[3]).is_symlink() for spec in specs):
72
+ raise StepFailed("prior inspection evidence requires the re-inspection contract")
73
+ branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
74
+ capture_output=True, text=True, check=True).stdout.strip()
75
+ if branch != state["branch"]:
76
+ raise StepFailed("current branch differs from the recorded inspection branch")
77
+ pending = step("discussion_records.py", "pending", "--repo", str(repo))
78
+ if pending["pending"]:
79
+ raise StepFailed("pending discussion requires its owner disposition")
80
+ inventory = step("check_docs_audit.py", "--repo", str(repo), "--emit-inventory", raw=True)
81
+ resources = scripts.parent
82
+ if not (resources / "references").is_dir():
83
+ resources = resources / "skills/gsd-path"
84
+ for _, role, template, _ in specs:
85
+ for path in (resources / "references" / f"{role}.md", resources / "templates" / f"{template}.md"):
86
+ if not path.is_file():
87
+ raise StepFailed(f"missing inspection resource: {path}")
88
+ staging = Path(tempfile.mkdtemp(prefix="gsd-path-inspect-"))
89
+ inventory_file = staging / "inventory.txt"
90
+ inventory_file.write_text(inventory, encoding="utf-8")
91
+ assignments = []
92
+ for task_name, role, template, filename in specs:
93
+ isolated = step("isolation.py", "isolate-verify", "--repo", str(repo),
94
+ "--base", expected_head, "--name", task_name.replace("_", "-"))
95
+ role_path = resources / "references" / f"{role}.md"
96
+ template_path = resources / "templates" / f"{template}.md"
97
+ output = f"{project_dir}/research/{filename}"
98
+ brief_file = staging / f"{task_name}.md"
99
+ brief = (f"Logical task: {task_name}\nRead and follow role: {role_path}\n"
100
+ f"Template: {template_path}\nRepository and command cwd: {isolated['worktree']}\n"
101
+ f"Recorded baseline and Audited HEAD: {isolated['base']}\n"
102
+ f"Write only: {Path(isolated['worktree']) / output}\n"
103
+ "Use only this supplied sidecar for project commands; do not create worktrees.\n"
104
+ "The parent owns gates, collection, retirement, and phase state.\n"
105
+ "Exclude .git, node_modules, .project/archive, and installed GSD Path and path skill bundles.\n")
106
+ if task_name == "inspect_docs":
107
+ brief += ("Alignment mode: false. No prior audit or changed set.\n"
108
+ "Frozen inventory follows; use it exactly, without rediscovery:\n" + inventory)
109
+ brief_file.write_text(brief, encoding="utf-8")
110
+ assignments.append({**isolated, "task_name": task_name, "role": str(role_path),
111
+ "template": str(template_path), "output": output,
112
+ "brief_file": str(brief_file)})
113
+ receipt_file = staging / "inspection.json"
114
+ outputs["inspection"] = {"repo": str(repo), "base": expected_head,
115
+ "inventory_file": str(inventory_file),
116
+ "inventory_sha256": hashlib.sha256(inventory_file.read_bytes()).hexdigest(),
117
+ "assignments": assignments, "receipt_file": str(receipt_file)}
118
+ _common.atomic_write(receipt_file, json.dumps(outputs["inspection"], sort_keys=True) + "\n")
119
+ elif action == "finish-inspect":
120
+ if not mapper_reviewed or inspection is None or project_dir != ".project":
121
+ raise StepFailed("finish-inspect requires the prepared active track and mapper review")
122
+ prepared = json.loads(inspection.read_text(encoding="utf-8"))
123
+ if prepared["repo"] != str(repo) or prepared["base"] != expected_head:
124
+ raise StepFailed("inspection receipt does not match repository and expected HEAD")
125
+ assignments = {a["task_name"]: a for a in prepared["assignments"]}
126
+ if len(prepared["assignments"]) != len(INSPECTION_SPECS) or set(assignments) != {s[0] for s in INSPECTION_SPECS}:
127
+ raise StepFailed("inspection receipt must name both original assignments")
128
+ for task_name, _, _, filename in INSPECTION_SPECS:
129
+ assignment = assignments[task_name]
130
+ if assignment["base"] != expected_head or assignment["output"] != f".project/research/{filename}":
131
+ raise StepFailed("inspection assignment changed its baseline or output")
132
+ inventory_file = Path(prepared["inventory_file"])
133
+ if hashlib.sha256(inventory_file.read_bytes()).hexdigest() != prepared["inventory_sha256"]:
134
+ raise StepFailed("frozen inspection inventory changed")
135
+ state = step("pipeline_state.py", "validate", *common)["state"]
136
+ if state["phase"] != "inspect" or state["status"] != "active":
137
+ raise StepFailed("inspection completion requires inspect/active")
138
+ branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
139
+ capture_output=True, text=True, check=True).stdout.strip()
140
+ if state["branch"] != branch:
141
+ raise StepFailed("current branch differs from the recorded inspection branch")
142
+ pending = step("discussion_records.py", "pending", "--repo", str(repo))
143
+ if pending["pending"]:
144
+ raise StepFailed("pending discussion requires its owner disposition")
145
+ docs = assignments["inspect_docs"]
146
+ step("check_docs_audit.py", "--repo", docs["worktree"], "--audit", docs["output"],
147
+ "--inventory", str(inventory_file))
148
+ if f"Audited HEAD: {expected_head}" not in (Path(docs["worktree"]) / docs["output"]).read_text().splitlines():
149
+ raise StepFailed("audit does not name the supplied inspection baseline")
150
+ for task_name, _, _, _ in INSPECTION_SPECS:
151
+ assignment = assignments[task_name]
152
+ step("isolation.py", "collect-artifact", "--repo", str(repo),
153
+ "--source", assignment["worktree"], "--base", expected_head,
154
+ "--branch", assignment["branch"], "--source-path", assignment["output"],
155
+ "--destination-path", assignment["output"])
156
+ step("isolation.py", "retire", "--repo", str(repo), "--worktree", assignment["worktree"],
157
+ "--branch", assignment["branch"])
158
+ expected = [part for key, value in state.items()
159
+ for part in (f"--expect-{key}", "null" if value is None else str(value))]
160
+ step("pipeline_state.py", "transition", *common, *expected,
161
+ "--set-phase", "inspect", "--set-status", "done", "--event", "inspection artifacts passed")
45
162
  elif action == "lint-round":
46
163
  head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
47
164
  cwd=repo, capture_output=True, text=True, check=True).stdout.strip()
@@ -87,28 +204,31 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
87
204
  if action == "approve-plan":
88
205
  step("pipeline_state.py", "approve", *common, "--kind", "plan",
89
206
  "--expected-head", expected_head)
90
- except (StepFailed, OSError, subprocess.CalledProcessError) as error:
207
+ except (StepFailed, OSError, subprocess.CalledProcessError, ValueError, KeyError, TypeError) as error:
91
208
  return {"status": "blocked", "reason": str(error), "steps": steps,
92
209
  "next": "$gsd-path-forensics"}
93
- return {"status": "complete", "steps": steps}
210
+ return {"status": "complete", "steps": steps, **outputs}
94
211
 
95
212
 
96
213
  def main(argv=None):
97
214
  parser = argparse.ArgumentParser(description=__doc__)
98
- parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final"))
215
+ parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"))
99
216
  parser.add_argument("--repo", type=Path, required=True)
100
217
  parser.add_argument("--project-dir", choices=(".project", ".project/next"), default=".project")
101
218
  parser.add_argument("--expected-head")
102
219
  parser.add_argument("--task-id")
103
220
  parser.add_argument("--round-size", type=int)
221
+ parser.add_argument("--inspection", type=Path)
222
+ parser.add_argument("--mapper-reviewed", action="store_true")
104
223
  arguments = parser.parse_args(argv)
105
- if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final"} and not arguments.expected_head:
224
+ if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"} and not arguments.expected_head:
106
225
  parser.error(f"{arguments.action} requires --expected-head")
107
226
  if arguments.action == "prepare-task" and (not arguments.task_id or arguments.round_size is None):
108
227
  parser.error("prepare-task requires --task-id and --round-size")
109
228
  result = run_workflow(arguments.repo.resolve(), arguments.action,
110
229
  arguments.project_dir, arguments.expected_head,
111
- arguments.task_id, arguments.round_size)
230
+ arguments.task_id, arguments.round_size, arguments.inspection,
231
+ arguments.mapper_reviewed)
112
232
  print(json.dumps(result, sort_keys=True))
113
233
  return 0 if result["status"] == "complete" else 1
114
234
 
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python3
2
+ # gsd-path project runtime
3
+ """Placement shared by task isolation, verification, and integration."""
4
+
5
+ import sys
6
+
7
+ # Runtime helpers must not modify their immutable installation.
8
+ sys.dont_write_bytecode = True
9
+
10
+ import hashlib
11
+ import json
12
+ import os
13
+ import tempfile
14
+ from pathlib import Path
15
+
16
+ try:
17
+ import _common
18
+ except ImportError:
19
+ from scripts import _common
20
+
21
+
22
+ def _git(primary: Path, *args: str) -> str:
23
+ result = _common.run_git(primary, *args)
24
+ if result.returncode:
25
+ raise ValueError(result.stderr.strip() or "cannot inspect worktree placement")
26
+ return result.stdout.rstrip("\n")
27
+
28
+
29
+ def _identity(path: Path) -> str:
30
+ return hashlib.sha256(os.fsencode(path)).hexdigest()
31
+
32
+
33
+ def _workspace(primary: Path, pin: bool) -> Path:
34
+ common = Path(_git(primary, "rev-parse", "--git-common-dir"))
35
+ common = (primary / common).resolve()
36
+ identity = _identity(primary)
37
+ receipt = common / "gsd-path" / "workspaces" / f"{identity}.json"
38
+ try:
39
+ data = json.loads(receipt.read_text(encoding="utf-8"))
40
+ except FileNotFoundError:
41
+ pass
42
+ else:
43
+ if (not isinstance(data, dict) or data.get("primary") != str(primary)
44
+ or not isinstance(data.get("root"), str)
45
+ or not Path(data["root"]).is_absolute()):
46
+ raise ValueError(f"invalid worktree placement receipt: {receipt}")
47
+ return Path(data["root"])
48
+
49
+ root = Path(os.environ.get("GSD_PATH_WORKTREE_ROOT") or Path.home() / ".gsd-path" / "projects").expanduser()
50
+ if not root.is_absolute():
51
+ raise ValueError("GSD_PATH_WORKTREE_ROOT must be absolute")
52
+ root = root.resolve()
53
+ parent = root
54
+ while not parent.exists():
55
+ parent = parent.parent
56
+ ancestor = _common.run_git(parent, "rev-parse", "--git-common-dir")
57
+ same_repository = (
58
+ ancestor.returncode == 0
59
+ and (parent / ancestor.stdout.strip()).resolve() == common
60
+ )
61
+ if root.is_relative_to(primary) or same_repository:
62
+ raise ValueError(f"managed worktree root must be outside this repository's worktrees: {root}")
63
+ workspace = root / _identity(common) / identity
64
+ if pin:
65
+ receipt.parent.mkdir(parents=True, exist_ok=True)
66
+ fd, temporary = tempfile.mkstemp(dir=receipt.parent)
67
+ try:
68
+ with os.fdopen(fd, "w", encoding="utf-8") as handle:
69
+ json.dump({"primary": str(primary), "root": str(workspace)}, handle)
70
+ try:
71
+ os.link(temporary, receipt)
72
+ except FileExistsError:
73
+ return _workspace(primary, False)
74
+ finally:
75
+ os.unlink(temporary)
76
+ return workspace
77
+
78
+
79
+ def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) -> Path:
80
+ primary = primary.resolve()
81
+ if kind not in {"task", "verify", "integrate"} or not name or Path(name).name != name or name in {".", ".."}:
82
+ raise ValueError("invalid managed worktree kind or name")
83
+ legacy = (primary.parent / f".{primary.name}-gsd-path-integrate-{name}"
84
+ if kind == "integrate" else primary.parent / f"{primary.name}.gsd-path" / kind / name)
85
+ branch = f"refs/heads/gsd-path-{kind}/{name}"
86
+ records = _git(primary, "worktree", "list", "--porcelain", "-z").split("\0\0")
87
+ for record in records:
88
+ fields = record.split("\0")
89
+ if f"worktree {legacy}" in fields and f"branch {branch}" in fields:
90
+ return legacy
91
+ # Keep collision checks and missing-directory recovery at the old location.
92
+ if os.path.lexists(legacy):
93
+ return legacy
94
+ return _workspace(primary, pin) / kind / name