@opengsd/gsd-path 1.3.0 → 1.4.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 (434) hide show
  1. package/AGENTS.md +2 -207
  2. package/CHANGELOG.md +294 -0
  3. package/DOCS.md +19 -10
  4. package/FULL.md +9 -3
  5. package/GUIDE.md +1 -1
  6. package/HOOKS.md +9 -6
  7. package/QUICK.md +4 -1
  8. package/README.md +63 -11
  9. package/RUNTIME.md +1 -1
  10. package/UPDATE.md +61 -12
  11. package/WORKFLOW.md +22 -6
  12. package/package.json +9 -8
  13. package/scripts/_common.py +472 -19
  14. package/scripts/archive_milestone.py +146 -73
  15. package/scripts/bootstrap_repository.py +8 -5
  16. package/scripts/build_recovery.py +4 -1
  17. package/scripts/build_state.py +66 -23
  18. package/scripts/check_docs_audit.py +14 -3
  19. package/scripts/check_handoffs.py +116 -20
  20. package/scripts/check_task_briefs.py +60 -8
  21. package/scripts/check_update.py +2 -2
  22. package/scripts/core_hook_gate.py +10 -1
  23. package/scripts/core_hook_settings.py +11 -4
  24. package/scripts/detect_project.py +345 -15
  25. package/scripts/discussion_records.py +19 -13
  26. package/scripts/discussion_validate.py +66 -21
  27. package/scripts/dispatch_driver.py +111 -26
  28. package/scripts/git_guard.py +116 -29
  29. package/scripts/guard_hook.py +151 -29
  30. package/scripts/install.mjs +55 -39
  31. package/scripts/install.py +564 -41
  32. package/scripts/integration.py +434 -24
  33. package/scripts/isolation.py +1077 -28
  34. package/scripts/lean_verification.py +99 -19
  35. package/scripts/loop_run.py +20 -30
  36. package/scripts/members.py +704 -0
  37. package/scripts/migrate_core.py +2 -2
  38. package/scripts/path_config.py +2 -2
  39. package/scripts/pipeline_diagnose.py +82 -31
  40. package/scripts/pipeline_git.py +61 -22
  41. package/scripts/pipeline_state.py +176 -54
  42. package/scripts/pipeline_undo.py +117 -22
  43. package/scripts/promote_lookahead.py +1 -1
  44. package/scripts/review_panel.py +1 -1
  45. package/scripts/runtime_store.py +49 -11
  46. package/scripts/skill-resources.json +28 -3
  47. package/scripts/state_checkpoint.py +140 -31
  48. package/scripts/state_promote.py +2 -0
  49. package/scripts/status_runtime.py +36 -6
  50. package/scripts/sync_skill_resources.py +8 -7
  51. package/scripts/token_budget.py +12 -8
  52. package/scripts/workflow_run.py +103 -29
  53. package/scripts/worktree_paths.py +18 -8
  54. package/skills/gsd-path/BUILD.md +7 -1
  55. package/skills/gsd-path/DECIDE.md +11 -4
  56. package/skills/gsd-path/DEFINE.md +8 -1
  57. package/skills/gsd-path/DOCS-AUDIT.md +6 -4
  58. package/skills/gsd-path/INSPECT.md +5 -4
  59. package/skills/gsd-path/PLAN.md +7 -1
  60. package/skills/gsd-path/RESEARCH.md +2 -1
  61. package/skills/gsd-path/ROADMAP.md +2 -1
  62. package/skills/gsd-path/SHIP.md +27 -10
  63. package/skills/gsd-path/SKILL.md +45 -1
  64. package/skills/gsd-path/references/build-native.md +47 -14
  65. package/skills/gsd-path/references/codebase-mapper.md +2 -1
  66. package/skills/gsd-path/references/docs-auditor.md +2 -1
  67. package/skills/gsd-path/references/operating-rules.md +214 -0
  68. package/skills/gsd-path/references/planner.md +8 -0
  69. package/skills/gsd-path/references/reviewer-wave.md +3 -1
  70. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  71. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  72. package/skills/gsd-path/scripts/_common.py +472 -19
  73. package/skills/gsd-path/scripts/archive_milestone.py +146 -73
  74. package/skills/gsd-path/scripts/bootstrap_repository.py +8 -5
  75. package/skills/gsd-path/scripts/build_recovery.py +4 -1
  76. package/skills/gsd-path/scripts/build_state.py +66 -23
  77. package/skills/gsd-path/scripts/check_docs_audit.py +14 -3
  78. package/skills/gsd-path/scripts/check_handoffs.py +116 -20
  79. package/skills/gsd-path/scripts/check_task_briefs.py +60 -8
  80. package/skills/gsd-path/scripts/check_update.py +2 -2
  81. package/skills/gsd-path/scripts/detect_project.py +345 -15
  82. package/skills/gsd-path/scripts/discussion_records.py +19 -13
  83. package/skills/gsd-path/scripts/discussion_validate.py +66 -21
  84. package/skills/gsd-path/scripts/dispatch_driver.py +111 -26
  85. package/skills/gsd-path/scripts/git_guard.py +116 -29
  86. package/skills/gsd-path/scripts/integration.py +434 -24
  87. package/skills/gsd-path/scripts/isolation.py +1077 -28
  88. package/skills/gsd-path/scripts/lean_verification.py +99 -19
  89. package/skills/gsd-path/scripts/loop_run.py +20 -30
  90. package/skills/gsd-path/scripts/members.py +704 -0
  91. package/skills/gsd-path/scripts/path_config.py +2 -2
  92. package/skills/gsd-path/scripts/pipeline_git.py +61 -22
  93. package/skills/gsd-path/scripts/pipeline_state.py +176 -54
  94. package/skills/gsd-path/scripts/promote_lookahead.py +1 -1
  95. package/skills/gsd-path/scripts/review_panel.py +1 -1
  96. package/skills/gsd-path/scripts/state_checkpoint.py +140 -31
  97. package/skills/gsd-path/scripts/state_promote.py +2 -0
  98. package/skills/gsd-path/scripts/status_runtime.py +36 -6
  99. package/skills/gsd-path/scripts/token_budget.py +12 -8
  100. package/skills/gsd-path/scripts/workflow_run.py +103 -29
  101. package/skills/gsd-path/scripts/worktree_paths.py +18 -8
  102. package/skills/gsd-path/templates/codebase.md +1 -1
  103. package/skills/gsd-path/templates/docs-audit.md +1 -1
  104. package/skills/gsd-path/templates/final-review.md +5 -2
  105. package/skills/gsd-path/templates/gap-review.md +2 -1
  106. package/skills/gsd-path/templates/task.md +1 -0
  107. package/skills/gsd-path/templates/wave-review.md +3 -1
  108. package/skills/gsd-path-build/SKILL.md +7 -1
  109. package/skills/gsd-path-build/references/build-native.md +47 -14
  110. package/skills/gsd-path-build/references/operating-rules.md +214 -0
  111. package/skills/gsd-path-build/references/reviewer-wave.md +3 -1
  112. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  113. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  114. package/skills/gsd-path-build/scripts/_common.py +472 -19
  115. package/skills/gsd-path-build/scripts/archive_milestone.py +146 -73
  116. package/skills/gsd-path-build/scripts/build_recovery.py +4 -1
  117. package/skills/gsd-path-build/scripts/build_state.py +66 -23
  118. package/skills/gsd-path-build/scripts/check_handoffs.py +116 -20
  119. package/skills/gsd-path-build/scripts/check_task_briefs.py +60 -8
  120. package/skills/gsd-path-build/scripts/detect_project.py +345 -15
  121. package/skills/gsd-path-build/scripts/discussion_records.py +19 -13
  122. package/skills/gsd-path-build/scripts/discussion_validate.py +66 -21
  123. package/skills/gsd-path-build/scripts/dispatch_driver.py +111 -26
  124. package/skills/gsd-path-build/scripts/integration.py +434 -24
  125. package/skills/gsd-path-build/scripts/isolation.py +1077 -28
  126. package/skills/gsd-path-build/scripts/loop_run.py +20 -30
  127. package/skills/gsd-path-build/scripts/members.py +704 -0
  128. package/skills/gsd-path-build/scripts/path_config.py +2 -2
  129. package/skills/gsd-path-build/scripts/pipeline_git.py +61 -22
  130. package/skills/gsd-path-build/scripts/pipeline_state.py +176 -54
  131. package/skills/gsd-path-build/scripts/promote_lookahead.py +1 -1
  132. package/skills/gsd-path-build/scripts/review_panel.py +1 -1
  133. package/skills/gsd-path-build/scripts/state_checkpoint.py +140 -31
  134. package/skills/gsd-path-build/scripts/state_promote.py +2 -0
  135. package/skills/gsd-path-build/scripts/token_budget.py +12 -8
  136. package/skills/gsd-path-build/scripts/workflow_run.py +103 -29
  137. package/skills/gsd-path-build/scripts/worktree_paths.py +18 -8
  138. package/skills/gsd-path-build/templates/task.md +1 -0
  139. package/skills/gsd-path-build/templates/wave-review.md +3 -1
  140. package/skills/gsd-path-decide/SKILL.md +11 -4
  141. package/skills/gsd-path-decide/references/operating-rules.md +214 -0
  142. package/skills/gsd-path-decide/scripts/_common.py +472 -19
  143. package/skills/gsd-path-decide/scripts/archive_milestone.py +146 -73
  144. package/skills/gsd-path-decide/scripts/build_recovery.py +4 -1
  145. package/skills/gsd-path-decide/scripts/check_handoffs.py +116 -20
  146. package/skills/gsd-path-decide/scripts/check_task_briefs.py +60 -8
  147. package/skills/gsd-path-decide/scripts/detect_project.py +345 -15
  148. package/skills/gsd-path-decide/scripts/discussion_records.py +19 -13
  149. package/skills/gsd-path-decide/scripts/discussion_validate.py +66 -21
  150. package/skills/gsd-path-decide/scripts/integration.py +434 -24
  151. package/skills/gsd-path-decide/scripts/isolation.py +1077 -28
  152. package/skills/gsd-path-decide/scripts/loop_run.py +20 -30
  153. package/skills/gsd-path-decide/scripts/members.py +704 -0
  154. package/skills/gsd-path-decide/scripts/path_config.py +2 -2
  155. package/skills/gsd-path-decide/scripts/pipeline_git.py +61 -22
  156. package/skills/gsd-path-decide/scripts/pipeline_state.py +176 -54
  157. package/skills/gsd-path-decide/scripts/promote_lookahead.py +1 -1
  158. package/skills/gsd-path-decide/scripts/review_panel.py +1 -1
  159. package/skills/gsd-path-decide/scripts/state_checkpoint.py +140 -31
  160. package/skills/gsd-path-decide/scripts/state_promote.py +2 -0
  161. package/skills/gsd-path-decide/scripts/worktree_paths.py +18 -8
  162. package/skills/gsd-path-define/SKILL.md +8 -1
  163. package/skills/gsd-path-define/references/operating-rules.md +214 -0
  164. package/skills/gsd-path-define/scripts/_common.py +472 -19
  165. package/skills/gsd-path-define/scripts/archive_milestone.py +146 -73
  166. package/skills/gsd-path-define/scripts/build_recovery.py +4 -1
  167. package/skills/gsd-path-define/scripts/check_handoffs.py +116 -20
  168. package/skills/gsd-path-define/scripts/check_task_briefs.py +60 -8
  169. package/skills/gsd-path-define/scripts/detect_project.py +345 -15
  170. package/skills/gsd-path-define/scripts/discussion_records.py +19 -13
  171. package/skills/gsd-path-define/scripts/discussion_validate.py +66 -21
  172. package/skills/gsd-path-define/scripts/integration.py +434 -24
  173. package/skills/gsd-path-define/scripts/isolation.py +1077 -28
  174. package/skills/gsd-path-define/scripts/loop_run.py +20 -30
  175. package/skills/gsd-path-define/scripts/members.py +704 -0
  176. package/skills/gsd-path-define/scripts/path_config.py +2 -2
  177. package/skills/gsd-path-define/scripts/pipeline_git.py +61 -22
  178. package/skills/gsd-path-define/scripts/pipeline_state.py +176 -54
  179. package/skills/gsd-path-define/scripts/promote_lookahead.py +1 -1
  180. package/skills/gsd-path-define/scripts/review_panel.py +1 -1
  181. package/skills/gsd-path-define/scripts/state_checkpoint.py +140 -31
  182. package/skills/gsd-path-define/scripts/state_promote.py +2 -0
  183. package/skills/gsd-path-define/scripts/worktree_paths.py +18 -8
  184. package/skills/gsd-path-discuss/SKILL.md +2 -1
  185. package/skills/gsd-path-discuss/references/operating-rules.md +214 -0
  186. package/skills/gsd-path-discuss/scripts/_common.py +472 -19
  187. package/skills/gsd-path-discuss/scripts/discussion_records.py +19 -13
  188. package/skills/gsd-path-discuss/scripts/loop_run.py +20 -30
  189. package/skills/gsd-path-discuss/scripts/path_config.py +2 -2
  190. package/skills/gsd-path-discuss/scripts/review_panel.py +1 -1
  191. package/skills/gsd-path-discuss/scripts/worktree_paths.py +18 -8
  192. package/skills/gsd-path-docs-audit/SKILL.md +6 -4
  193. package/skills/gsd-path-docs-audit/references/docs-auditor.md +2 -1
  194. package/skills/gsd-path-docs-audit/references/operating-rules.md +214 -0
  195. package/skills/gsd-path-docs-audit/scripts/_common.py +472 -19
  196. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +146 -73
  197. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +4 -1
  198. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +14 -3
  199. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +116 -20
  200. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +60 -8
  201. package/skills/gsd-path-docs-audit/scripts/detect_project.py +345 -15
  202. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +19 -13
  203. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +66 -21
  204. package/skills/gsd-path-docs-audit/scripts/integration.py +434 -24
  205. package/skills/gsd-path-docs-audit/scripts/isolation.py +1077 -28
  206. package/skills/gsd-path-docs-audit/scripts/loop_run.py +20 -30
  207. package/skills/gsd-path-docs-audit/scripts/members.py +704 -0
  208. package/skills/gsd-path-docs-audit/scripts/path_config.py +2 -2
  209. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +61 -22
  210. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +176 -54
  211. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +1 -1
  212. package/skills/gsd-path-docs-audit/scripts/review_panel.py +1 -1
  213. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +140 -31
  214. package/skills/gsd-path-docs-audit/scripts/state_promote.py +2 -0
  215. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +18 -8
  216. package/skills/gsd-path-docs-audit/templates/docs-audit.md +1 -1
  217. package/skills/gsd-path-forensics/SKILL.md +2 -1
  218. package/skills/gsd-path-forensics/references/operating-rules.md +214 -0
  219. package/skills/gsd-path-forensics/scripts/_common.py +472 -19
  220. package/skills/gsd-path-forensics/scripts/discussion_records.py +19 -13
  221. package/skills/gsd-path-forensics/scripts/loop_run.py +20 -30
  222. package/skills/gsd-path-forensics/scripts/path_config.py +2 -2
  223. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +82 -31
  224. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +117 -22
  225. package/skills/gsd-path-forensics/scripts/review_panel.py +1 -1
  226. package/skills/gsd-path-forensics/scripts/worktree_paths.py +18 -8
  227. package/skills/gsd-path-inspect/SKILL.md +5 -4
  228. package/skills/gsd-path-inspect/references/codebase-mapper.md +2 -1
  229. package/skills/gsd-path-inspect/references/docs-auditor.md +2 -1
  230. package/skills/gsd-path-inspect/references/operating-rules.md +214 -0
  231. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  232. package/skills/gsd-path-inspect/scripts/_common.py +472 -19
  233. package/skills/gsd-path-inspect/scripts/archive_milestone.py +146 -73
  234. package/skills/gsd-path-inspect/scripts/build_recovery.py +4 -1
  235. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +14 -3
  236. package/skills/gsd-path-inspect/scripts/check_handoffs.py +116 -20
  237. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +60 -8
  238. package/skills/gsd-path-inspect/scripts/detect_project.py +345 -15
  239. package/skills/gsd-path-inspect/scripts/discussion_records.py +19 -13
  240. package/skills/gsd-path-inspect/scripts/discussion_validate.py +66 -21
  241. package/skills/gsd-path-inspect/scripts/integration.py +434 -24
  242. package/skills/gsd-path-inspect/scripts/isolation.py +1077 -28
  243. package/skills/gsd-path-inspect/scripts/loop_run.py +20 -30
  244. package/skills/gsd-path-inspect/scripts/members.py +704 -0
  245. package/skills/gsd-path-inspect/scripts/path_config.py +2 -2
  246. package/skills/gsd-path-inspect/scripts/pipeline_git.py +61 -22
  247. package/skills/gsd-path-inspect/scripts/pipeline_state.py +176 -54
  248. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +1 -1
  249. package/skills/gsd-path-inspect/scripts/review_panel.py +1 -1
  250. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +140 -31
  251. package/skills/gsd-path-inspect/scripts/state_promote.py +2 -0
  252. package/skills/gsd-path-inspect/scripts/workflow_run.py +103 -29
  253. package/skills/gsd-path-inspect/scripts/worktree_paths.py +18 -8
  254. package/skills/gsd-path-inspect/templates/codebase.md +1 -1
  255. package/skills/gsd-path-inspect/templates/docs-audit.md +1 -1
  256. package/skills/gsd-path-loop/SKILL.md +2 -1
  257. package/skills/gsd-path-loop/references/operating-rules.md +214 -0
  258. package/skills/gsd-path-loop/scripts/_common.py +472 -19
  259. package/skills/gsd-path-loop/scripts/discussion_records.py +19 -13
  260. package/skills/gsd-path-loop/scripts/loop_run.py +20 -30
  261. package/skills/gsd-path-loop/scripts/path_config.py +2 -2
  262. package/skills/gsd-path-loop/scripts/review_panel.py +1 -1
  263. package/skills/gsd-path-loop/scripts/worktree_paths.py +18 -8
  264. package/skills/gsd-path-migrate/SKILL.md +2 -1
  265. package/skills/gsd-path-migrate/references/operating-rules.md +214 -0
  266. package/skills/gsd-path-migrate/scripts/_common.py +472 -19
  267. package/skills/gsd-path-migrate/scripts/core_hook_gate.py +10 -1
  268. package/skills/gsd-path-migrate/scripts/core_hook_settings.py +11 -4
  269. package/skills/gsd-path-migrate/scripts/discussion_records.py +19 -13
  270. package/skills/gsd-path-migrate/scripts/loop_run.py +20 -30
  271. package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -2
  272. package/skills/gsd-path-migrate/scripts/path_config.py +2 -2
  273. package/skills/gsd-path-migrate/scripts/review_panel.py +1 -1
  274. package/skills/gsd-path-plan/SKILL.md +7 -1
  275. package/skills/gsd-path-plan/references/operating-rules.md +214 -0
  276. package/skills/gsd-path-plan/references/planner.md +8 -0
  277. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  278. package/skills/gsd-path-plan/scripts/_common.py +472 -19
  279. package/skills/gsd-path-plan/scripts/archive_milestone.py +146 -73
  280. package/skills/gsd-path-plan/scripts/build_recovery.py +4 -1
  281. package/skills/gsd-path-plan/scripts/check_handoffs.py +116 -20
  282. package/skills/gsd-path-plan/scripts/check_task_briefs.py +60 -8
  283. package/skills/gsd-path-plan/scripts/detect_project.py +345 -15
  284. package/skills/gsd-path-plan/scripts/discussion_records.py +19 -13
  285. package/skills/gsd-path-plan/scripts/discussion_validate.py +66 -21
  286. package/skills/gsd-path-plan/scripts/integration.py +434 -24
  287. package/skills/gsd-path-plan/scripts/isolation.py +1077 -28
  288. package/skills/gsd-path-plan/scripts/loop_run.py +20 -30
  289. package/skills/gsd-path-plan/scripts/members.py +704 -0
  290. package/skills/gsd-path-plan/scripts/path_config.py +2 -2
  291. package/skills/gsd-path-plan/scripts/pipeline_git.py +61 -22
  292. package/skills/gsd-path-plan/scripts/pipeline_state.py +176 -54
  293. package/skills/gsd-path-plan/scripts/promote_lookahead.py +1 -1
  294. package/skills/gsd-path-plan/scripts/review_panel.py +1 -1
  295. package/skills/gsd-path-plan/scripts/state_checkpoint.py +140 -31
  296. package/skills/gsd-path-plan/scripts/state_promote.py +2 -0
  297. package/skills/gsd-path-plan/scripts/workflow_run.py +103 -29
  298. package/skills/gsd-path-plan/scripts/worktree_paths.py +18 -8
  299. package/skills/gsd-path-plan/templates/task.md +1 -0
  300. package/skills/gsd-path-research/SKILL.md +2 -1
  301. package/skills/gsd-path-research/references/operating-rules.md +214 -0
  302. package/skills/gsd-path-research/scripts/_common.py +472 -19
  303. package/skills/gsd-path-research/scripts/archive_milestone.py +146 -73
  304. package/skills/gsd-path-research/scripts/build_recovery.py +4 -1
  305. package/skills/gsd-path-research/scripts/check_handoffs.py +116 -20
  306. package/skills/gsd-path-research/scripts/check_task_briefs.py +60 -8
  307. package/skills/gsd-path-research/scripts/detect_project.py +345 -15
  308. package/skills/gsd-path-research/scripts/discussion_records.py +19 -13
  309. package/skills/gsd-path-research/scripts/discussion_validate.py +66 -21
  310. package/skills/gsd-path-research/scripts/integration.py +434 -24
  311. package/skills/gsd-path-research/scripts/isolation.py +1077 -28
  312. package/skills/gsd-path-research/scripts/loop_run.py +20 -30
  313. package/skills/gsd-path-research/scripts/members.py +704 -0
  314. package/skills/gsd-path-research/scripts/path_config.py +2 -2
  315. package/skills/gsd-path-research/scripts/pipeline_git.py +61 -22
  316. package/skills/gsd-path-research/scripts/pipeline_state.py +176 -54
  317. package/skills/gsd-path-research/scripts/promote_lookahead.py +1 -1
  318. package/skills/gsd-path-research/scripts/review_panel.py +1 -1
  319. package/skills/gsd-path-research/scripts/state_checkpoint.py +140 -31
  320. package/skills/gsd-path-research/scripts/state_promote.py +2 -0
  321. package/skills/gsd-path-research/scripts/worktree_paths.py +18 -8
  322. package/skills/gsd-path-roadmap/SKILL.md +2 -1
  323. package/skills/gsd-path-roadmap/references/operating-rules.md +214 -0
  324. package/skills/gsd-path-roadmap/scripts/_common.py +472 -19
  325. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +146 -73
  326. package/skills/gsd-path-roadmap/scripts/build_recovery.py +4 -1
  327. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +116 -20
  328. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +60 -8
  329. package/skills/gsd-path-roadmap/scripts/detect_project.py +345 -15
  330. package/skills/gsd-path-roadmap/scripts/discussion_records.py +19 -13
  331. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +66 -21
  332. package/skills/gsd-path-roadmap/scripts/integration.py +434 -24
  333. package/skills/gsd-path-roadmap/scripts/isolation.py +1077 -28
  334. package/skills/gsd-path-roadmap/scripts/loop_run.py +20 -30
  335. package/skills/gsd-path-roadmap/scripts/members.py +704 -0
  336. package/skills/gsd-path-roadmap/scripts/path_config.py +2 -2
  337. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +61 -22
  338. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +176 -54
  339. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +1 -1
  340. package/skills/gsd-path-roadmap/scripts/review_panel.py +1 -1
  341. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +140 -31
  342. package/skills/gsd-path-roadmap/scripts/state_promote.py +2 -0
  343. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +18 -8
  344. package/skills/gsd-path-ship/SKILL.md +27 -10
  345. package/skills/gsd-path-ship/references/operating-rules.md +214 -0
  346. package/skills/gsd-path-ship/references/reviewer-wave.md +3 -1
  347. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  348. package/skills/gsd-path-ship/scripts/_common.py +472 -19
  349. package/skills/gsd-path-ship/scripts/archive_milestone.py +146 -73
  350. package/skills/gsd-path-ship/scripts/build_recovery.py +4 -1
  351. package/skills/gsd-path-ship/scripts/build_state.py +66 -23
  352. package/skills/gsd-path-ship/scripts/check_handoffs.py +116 -20
  353. package/skills/gsd-path-ship/scripts/check_task_briefs.py +60 -8
  354. package/skills/gsd-path-ship/scripts/detect_project.py +345 -15
  355. package/skills/gsd-path-ship/scripts/discussion_records.py +19 -13
  356. package/skills/gsd-path-ship/scripts/discussion_validate.py +66 -21
  357. package/skills/gsd-path-ship/scripts/integration.py +434 -24
  358. package/skills/gsd-path-ship/scripts/isolation.py +1077 -28
  359. package/skills/gsd-path-ship/scripts/lean_verification.py +99 -19
  360. package/skills/gsd-path-ship/scripts/loop_run.py +20 -30
  361. package/skills/gsd-path-ship/scripts/members.py +704 -0
  362. package/skills/gsd-path-ship/scripts/path_config.py +2 -2
  363. package/skills/gsd-path-ship/scripts/pipeline_git.py +61 -22
  364. package/skills/gsd-path-ship/scripts/pipeline_state.py +176 -54
  365. package/skills/gsd-path-ship/scripts/promote_lookahead.py +1 -1
  366. package/skills/gsd-path-ship/scripts/review_panel.py +1 -1
  367. package/skills/gsd-path-ship/scripts/state_checkpoint.py +140 -31
  368. package/skills/gsd-path-ship/scripts/state_promote.py +2 -0
  369. package/skills/gsd-path-ship/scripts/workflow_run.py +103 -29
  370. package/skills/gsd-path-ship/scripts/worktree_paths.py +18 -8
  371. package/skills/gsd-path-ship/templates/final-review.md +5 -2
  372. package/skills/gsd-path-ship/templates/gap-review.md +2 -1
  373. package/skills/gsd-path-ship/templates/wave-review.md +3 -1
  374. package/skills/gsd-path-undo/SKILL.md +2 -1
  375. package/skills/gsd-path-undo/references/operating-rules.md +214 -0
  376. package/skills/gsd-path-undo/scripts/_common.py +472 -19
  377. package/skills/gsd-path-undo/scripts/discussion_records.py +19 -13
  378. package/skills/gsd-path-undo/scripts/loop_run.py +20 -30
  379. package/skills/gsd-path-undo/scripts/path_config.py +2 -2
  380. package/skills/gsd-path-undo/scripts/pipeline_undo.py +117 -22
  381. package/skills/gsd-path-undo/scripts/review_panel.py +1 -1
  382. package/skills/gsd-path-undo/scripts/worktree_paths.py +18 -8
  383. package/skills/path/BUILD.md +7 -1
  384. package/skills/path/DECIDE.md +11 -4
  385. package/skills/path/DEFINE.md +8 -1
  386. package/skills/path/DOCS-AUDIT.md +6 -4
  387. package/skills/path/INSPECT.md +5 -4
  388. package/skills/path/PLAN.md +7 -1
  389. package/skills/path/RESEARCH.md +2 -1
  390. package/skills/path/ROADMAP.md +2 -1
  391. package/skills/path/SHIP.md +27 -10
  392. package/skills/path/SKILL.md +45 -1
  393. package/skills/path/references/build-native.md +47 -14
  394. package/skills/path/references/codebase-mapper.md +2 -1
  395. package/skills/path/references/docs-auditor.md +2 -1
  396. package/skills/path/references/operating-rules.md +214 -0
  397. package/skills/path/references/planner.md +8 -0
  398. package/skills/path/references/reviewer-wave.md +3 -1
  399. package/skills/path/scripts/_common.py +472 -19
  400. package/skills/path/scripts/archive_milestone.py +146 -73
  401. package/skills/path/scripts/bootstrap_repository.py +8 -5
  402. package/skills/path/scripts/build_recovery.py +4 -1
  403. package/skills/path/scripts/build_state.py +66 -23
  404. package/skills/path/scripts/check_docs_audit.py +14 -3
  405. package/skills/path/scripts/check_handoffs.py +116 -20
  406. package/skills/path/scripts/check_task_briefs.py +60 -8
  407. package/skills/path/scripts/check_update.py +2 -2
  408. package/skills/path/scripts/detect_project.py +345 -15
  409. package/skills/path/scripts/discussion_records.py +19 -13
  410. package/skills/path/scripts/discussion_validate.py +66 -21
  411. package/skills/path/scripts/dispatch_driver.py +111 -26
  412. package/skills/path/scripts/git_guard.py +116 -29
  413. package/skills/path/scripts/integration.py +434 -24
  414. package/skills/path/scripts/isolation.py +1077 -28
  415. package/skills/path/scripts/lean_verification.py +99 -19
  416. package/skills/path/scripts/loop_run.py +20 -30
  417. package/skills/path/scripts/members.py +704 -0
  418. package/skills/path/scripts/path_config.py +2 -2
  419. package/skills/path/scripts/pipeline_git.py +61 -22
  420. package/skills/path/scripts/pipeline_state.py +176 -54
  421. package/skills/path/scripts/promote_lookahead.py +1 -1
  422. package/skills/path/scripts/review_panel.py +1 -1
  423. package/skills/path/scripts/state_checkpoint.py +140 -31
  424. package/skills/path/scripts/state_promote.py +2 -0
  425. package/skills/path/scripts/status_runtime.py +36 -6
  426. package/skills/path/scripts/token_budget.py +12 -8
  427. package/skills/path/scripts/workflow_run.py +103 -29
  428. package/skills/path/scripts/worktree_paths.py +18 -8
  429. package/skills/path/templates/codebase.md +1 -1
  430. package/skills/path/templates/docs-audit.md +1 -1
  431. package/skills/path/templates/final-review.md +5 -2
  432. package/skills/path/templates/gap-review.md +2 -1
  433. package/skills/path/templates/task.md +1 -0
  434. package/skills/path/templates/wave-review.md +3 -1
@@ -17,12 +17,15 @@ from datetime import date
17
17
  from pathlib import Path, PurePosixPath
18
18
  from typing import Mapping, Optional, Sequence
19
19
 
20
- try:
21
- from isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
22
- except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
23
- if error.name != "isolation":
24
- raise
25
- from scripts.isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
20
+ if __package__:
21
+ from .isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
22
+ else:
23
+ try:
24
+ from isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
25
+ except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
26
+ if error.name != "isolation":
27
+ raise
28
+ from scripts.isolation import IsolationError, checkpoint as isolation_checkpoint, require_commit, require_full_sha, PROJECT_ENTRIES
26
29
 
27
30
 
28
31
  if __package__:
@@ -66,6 +69,11 @@ def _sha256(content: str) -> str:
66
69
  return hashlib.sha256(content.encode("utf-8")).hexdigest()
67
70
 
68
71
 
72
+ def _is_junk_file(path: Path) -> bool:
73
+ # Drift digests skip OS junk by name: Finder rewrites it whatever its ignore status.
74
+ return path.name in pipeline_state._common.OS_JUNK_NAMES and path.is_file() and not path.is_symlink()
75
+
76
+
69
77
  def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
70
78
  if path.is_symlink() or not path.is_dir():
71
79
  raise PipelineStateError(f"promotion path must be a real directory: {path}")
@@ -74,7 +82,7 @@ def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
74
82
  if child.is_symlink():
75
83
  raise PipelineStateError(f"promotion path contains a symlink: {child}")
76
84
  relative = child.relative_to(path).as_posix()
77
- if PurePosixPath(relative).parts[0] in excluded:
85
+ if PurePosixPath(relative).parts[0] in excluded or _is_junk_file(child):
78
86
  continue
79
87
  if child.is_dir():
80
88
  digest.update(f"d\0{relative}\0".encode())
@@ -87,15 +95,15 @@ def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
87
95
 
88
96
 
89
97
  def _checkpoint_artifact_digest(project: Path, mutable_paths: set[str]) -> str:
90
- """Hash every approval artifact except the helper-owned metadata files."""
98
+ """Hash approval artifacts except helper-owned metadata and OS junk."""
91
99
  digest = hashlib.sha256()
92
100
  for child in sorted(project.rglob("*")):
93
101
  if child.is_symlink():
94
102
  raise PipelineStateError(f"checkpoint path contains a symlink: {child}")
95
103
  relative = child.relative_to(project).as_posix()
96
- # Unsupported entries (OS junk) are refused by the checkpoint itself; leaving them
97
- # out lets a refused approval resume after the owner removes them.
98
- if relative in mutable_paths or relative.split("/", 1)[0] not in PROJECT_ENTRIES:
104
+ # Finder can rewrite OS junk during approval; it must not cause artifact drift.
105
+ if (relative in mutable_paths or relative.split("/", 1)[0] not in PROJECT_ENTRIES
106
+ or _is_junk_file(child)):
99
107
  continue
100
108
  if child.is_dir():
101
109
  digest.update(f"d\0{relative}\0".encode())
@@ -333,11 +341,7 @@ def _converge_checkpoint_file(path: Path, before: str, after: str, label: str) -
333
341
 
334
342
  def _unlink_checkpoint_journal(path: Path) -> None:
335
343
  path.unlink()
336
- descriptor = os.open(path.parent, os.O_RDONLY)
337
- try:
338
- os.fsync(descriptor)
339
- finally:
340
- os.close(descriptor)
344
+ pipeline_state._common.fsync_directory(path.parent)
341
345
 
342
346
 
343
347
  def _resume_checkpoint_locked(
@@ -439,41 +443,103 @@ def _validate_plan_briefs(repo: Path, kind: str, project_dir: str) -> None:
439
443
  if head.returncode != 0:
440
444
  # Pre-Git approval defers base-dependent checks to build.
441
445
  return
442
- try:
443
- from check_task_briefs import BriefError, validate_task_briefs
444
- except ModuleNotFoundError as error: # pragma: no cover - package imports
445
- if error.name != "check_task_briefs":
446
- raise
447
- from scripts.check_task_briefs import BriefError, validate_task_briefs
448
- try:
449
- import check_handoffs
450
- except ModuleNotFoundError as error:
451
- if error.name != "check_handoffs":
452
- raise
453
- from scripts import check_handoffs
446
+ if __package__:
447
+ from .check_task_briefs import BriefError, _member_bases, validate_task_briefs
448
+ else:
449
+ try:
450
+ from check_task_briefs import BriefError, _member_bases, validate_task_briefs
451
+ except ModuleNotFoundError as error: # pragma: no cover - package imports
452
+ if error.name != "check_task_briefs":
453
+ raise
454
+ from scripts.check_task_briefs import BriefError, _member_bases, validate_task_briefs
455
+ if __package__:
456
+ from . import check_handoffs
457
+ else:
458
+ try:
459
+ import check_handoffs
460
+ except ModuleNotFoundError as error:
461
+ if error.name != "check_handoffs":
462
+ raise
463
+ from scripts import check_handoffs
454
464
  try:
455
465
  tasks, dependency_files = check_handoffs.plan_brief_inputs(repo, project_dir)
456
466
  landed_bases = {}
467
+ member_base = _member_bases(repo)
457
468
  for task_id, text in tasks.items():
458
469
  if check_handoffs._task_scalar(text, task_id, "status") != "done":
459
470
  continue
460
471
  agent = check_handoffs._task_scalar(text, task_id, "agent")
461
472
  if agent in {"", "null"}:
462
473
  raise BriefError(f"{task_id} landed task has no recorded agent")
474
+ member = check_handoffs._strict_frontmatter(text, task_id).get("repo")
475
+ base_repo = repo
476
+ if member is not None:
477
+ located = member_base(member) if isinstance(member, str) and member else None
478
+ if located is None:
479
+ raise BriefError(f"repo: names no member in MEMBERS.md: {member}")
480
+ base_repo = located[0]
463
481
  recorded_base = check_handoffs._task_scalar(text, task_id, "base")
464
482
  try:
465
- landed_bases[task_id] = require_commit(repo, require_full_sha(recorded_base))
483
+ landed_bases[task_id] = require_commit(base_repo, require_full_sha(recorded_base))
466
484
  except IsolationError as error:
467
485
  raise BriefError(f"{task_id} landed task has invalid historical base: {error}") from error
468
486
  dependency_files[task_id] = set()
469
487
  validate_task_briefs(
470
488
  repo, head.stdout.strip(), f"{project_dir}/tasks",
471
489
  dependency_files=dependency_files, landed_bases=landed_bases,
490
+ member_base=member_base,
472
491
  )
492
+ if project_dir == ".project/next":
493
+ # Promotion checks lookahead member tasks from the bases their briefs were checked at.
494
+ named = {
495
+ str(check_handoffs._strict_frontmatter(text, task_id).get("repo"))
496
+ for task_id, text in tasks.items()
497
+ if check_handoffs._strict_frontmatter(text, task_id).get("repo")
498
+ and check_handoffs._task_scalar(text, task_id, "status") != "done"
499
+ }
500
+ if named:
501
+ bases = {name: member_base(name)[1] for name in sorted(named)}
502
+ milestone = pipeline_state.load_state(repo, project_dir)[0].milestone
503
+ path = _lookahead_member_bases_path(repo, str(milestone))
504
+ path.parent.mkdir(parents=True, exist_ok=True)
505
+ pipeline_state._common.atomic_write(path, json.dumps(
506
+ {"schema": LOOKAHEAD_MEMBER_BASES_SCHEMA, "milestone": milestone, "bases": bases},
507
+ indent=2, sort_keys=True) + "\n")
473
508
  except (BriefError, check_handoffs.HandoffError) as error:
474
509
  raise PipelineStateError(f"task brief validation failed: {error}") from error
475
510
 
476
511
 
512
+ LOOKAHEAD_MEMBER_BASES_SCHEMA = "gsd-path/lookahead-member-bases/v1"
513
+
514
+
515
+ def _lookahead_member_bases_path(repo: Path, milestone: str) -> Path:
516
+ common = pipeline_state._run_git(repo, "rev-parse", "--path-format=absolute", "--git-common-dir").stdout.strip()
517
+ return Path(common) / "gsd-path" / "lookahead-member-bases" / f"{milestone}.json"
518
+
519
+
520
+ def _lookahead_member_bases(repo: Path, milestone: str) -> Optional[dict]:
521
+ path = _lookahead_member_bases_path(repo, milestone)
522
+ if not path.is_file():
523
+ return None
524
+ value = json.loads(path.read_text(encoding="utf-8"))
525
+ if value.get("schema") != LOOKAHEAD_MEMBER_BASES_SCHEMA or value.get("milestone") != milestone:
526
+ return None
527
+ return value.get("bases")
528
+
529
+
530
+ def _shipped_member_merges(repo: Path, landing: str) -> dict:
531
+ """Member merges named by the ship commit the integration landing merged."""
532
+ if __package__:
533
+ from .pipeline_git import ship_member_rows
534
+ else:
535
+ from pipeline_git import ship_member_rows
536
+ ship = pipeline_state._run_git(repo, "rev-parse", "--verify", "--quiet", f"{landing}^2", check=False)
537
+ if ship.returncode != 0:
538
+ return {}
539
+ message = pipeline_state._run_git(repo, "show", "-s", "--format=%B", ship.stdout.strip()).stdout
540
+ return {row["name"]: row["merge"] for row in ship_member_rows(message)}
541
+
542
+
477
543
  def checkpoint_approval(
478
544
  repo: Path,
479
545
  kind: str,
@@ -1027,6 +1093,46 @@ def _classify_plan_drift(
1027
1093
  }
1028
1094
  approved = _approved_task_contracts(repo, checkpoint)
1029
1095
  current = _task_contracts_at(repo, revision)
1096
+ if __package__:
1097
+ from . import check_handoffs
1098
+ else:
1099
+ import check_handoffs
1100
+ # Member task paths live in member repos: compare each member from the base its brief
1101
+ # was checked at to the member merge the shipped milestone made (both fixed commits).
1102
+ task_repos = {
1103
+ task_id: str(check_handoffs._strict_frontmatter(contract.text, contract.path).get("repo") or "")
1104
+ for task_id, contract in approved.items()
1105
+ }
1106
+ active_member_tasks = {
1107
+ task_id for task_id, name in task_repos.items()
1108
+ if name and check_handoffs._task_scalar(approved[task_id].text, task_id, "status") != "done"
1109
+ }
1110
+ active_members = {task_repos[task_id] for task_id in active_member_tasks}
1111
+ member_changes: dict[str, list] = {}
1112
+ if active_members:
1113
+ bases = _lookahead_member_bases(repo, str(state.milestone)) or {}
1114
+ if any(name not in bases for name in active_members):
1115
+ return {
1116
+ "class": "unverifiable",
1117
+ "checkpoint": checkpoint,
1118
+ "task_ids": [],
1119
+ "changed_paths": [],
1120
+ "contract_paths": [],
1121
+ "member_tasks": True,
1122
+ "reason": "member bases were not recorded at plan approval",
1123
+ }
1124
+ if __package__:
1125
+ from . import members
1126
+ else:
1127
+ import members
1128
+ checkouts = {item["name"]: Path(item["checkout"]) for item in members.read_members(repo)}
1129
+ merges = _shipped_member_merges(repo, landing or revision)
1130
+ for name in active_members:
1131
+ member_changes[name] = [
1132
+ item for item in pipeline_state._run_git(
1133
+ checkouts[name], "diff", "--no-renames", "--name-only", "-z", bases[name], merges[name]
1134
+ ).stdout.split("\0") if item
1135
+ ] if name in merges else []
1030
1136
 
1031
1137
  contract_paths: set[str] = set()
1032
1138
  flagged_ids: set[str] = set()
@@ -1050,9 +1156,12 @@ def _classify_plan_drift(
1050
1156
 
1051
1157
  product_paths: set[str] = set()
1052
1158
  for task_id, contract in approved.items():
1159
+ member = task_repos.get(task_id)
1160
+ if member and task_id not in active_member_tasks:
1161
+ continue
1053
1162
  matches = sorted(
1054
- changed_path
1055
- for changed_path in changed
1163
+ (f"{member}:{changed_path}" if member else changed_path)
1164
+ for changed_path in (member_changes[member] if member else changed)
1056
1165
  if any(
1057
1166
  changed_path == path
1058
1167
  or changed_path.startswith(f"{path.rstrip('/')}/")
@@ -82,6 +82,8 @@ def _promotion_event(
82
82
  if isinstance(task_ids, list) and task_ids:
83
83
  return f"{prefix}; plan drift flagged tasks {', '.join(task_ids)}"
84
84
  return f"{prefix}; plan contract changed after approval"
85
+ if drift_class == "unverifiable" and drift.get("member_tasks"):
86
+ return f"{prefix}; plan drift unverifiable because member bases were not recorded at plan approval"
85
87
  if drift_class == "unverifiable":
86
88
  return f"{prefix}; plan drift unverifiable because approval checkpoint is missing"
87
89
  return prefix
@@ -13,10 +13,13 @@ import os
13
13
  import tempfile
14
14
  from pathlib import Path
15
15
 
16
- try:
17
- import _common
18
- except ImportError:
19
- from scripts import _common
16
+ if __package__:
17
+ from . import _common
18
+ else:
19
+ try:
20
+ import _common
21
+ except ImportError:
22
+ from scripts import _common
20
23
 
21
24
 
22
25
  def _git(primary: Path, *args: str) -> str:
@@ -27,7 +30,10 @@ def _git(primary: Path, *args: str) -> str:
27
30
 
28
31
 
29
32
  def _identity(path: Path) -> str:
30
- return hashlib.sha256(os.fsencode(path)).hexdigest()
33
+ digest = hashlib.sha256(os.fsencode(path)).hexdigest()
34
+ # Two identities nest in every managed path; full digests would use about
35
+ # 130 of Windows' 260-character MAX_PATH before any repository content.
36
+ return digest[:16] if os.name == "nt" else digest
31
37
 
32
38
 
33
39
  def _workspace(primary: Path, pin: bool) -> Path:
@@ -65,7 +71,7 @@ def _workspace(primary: Path, pin: bool) -> Path:
65
71
  receipt.parent.mkdir(parents=True, exist_ok=True)
66
72
  fd, temporary = tempfile.mkstemp(dir=receipt.parent)
67
73
  try:
68
- with os.fdopen(fd, "w", encoding="utf-8") as handle:
74
+ with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as handle:
69
75
  json.dump({"primary": str(primary), "root": str(workspace)}, handle)
70
76
  try:
71
77
  os.link(temporary, receipt)
@@ -78,15 +84,19 @@ def _workspace(primary: Path, pin: bool) -> Path:
78
84
 
79
85
  def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) -> Path:
80
86
  primary = primary.resolve()
81
- if kind not in {"task", "verify", "integrate"} or not name or Path(name).name != name or name in {".", ".."}:
87
+ if kind not in {"task", "verify", "integrate", "bound"} or not name or Path(name).name != name or name in {".", ".."}:
82
88
  raise ValueError("invalid managed worktree kind or name")
89
+ if kind == "bound":
90
+ return _workspace(primary, pin) / kind / name
83
91
  legacy = (primary.parent / f".{primary.name}-gsd-path-integrate-{name}"
84
92
  if kind == "integrate" else primary.parent / f"{primary.name}.gsd-path" / kind / name)
85
93
  branch = f"refs/heads/gsd-path-{kind}/{name}"
86
94
  records = _git(primary, "worktree", "list", "--porcelain", "-z").split("\0\0")
87
95
  for record in records:
88
96
  fields = record.split("\0")
89
- if f"worktree {legacy}" in fields and f"branch {branch}" in fields:
97
+ # Compare as paths: git prints forward slashes on Windows.
98
+ worktrees = [Path(field[len("worktree "):]) for field in fields if field.startswith("worktree ")]
99
+ if legacy in worktrees and f"branch {branch}" in fields:
90
100
  return legacy
91
101
  # Keep collision checks and missing-directory recovery at the old location.
92
102
  if os.path.lexists(legacy):
@@ -3,7 +3,8 @@ name: gsd-path-roadmap
3
3
  description: Slice an approved GSD Path program charter into a dependency-ordered roadmap of independently shippable milestones. Use only when the user explicitly invokes $gsd-path-roadmap or an active $gsd-path router explicitly routes to this phase.
4
4
  ---
5
5
 
6
- Before executing project helpers, read [runtime selection](references/runtime-selection.md).
6
+ Before executing project helpers, read [runtime selection](references/runtime-selection.md)
7
+ and [operating rules](references/operating-rules.md).
7
8
 
8
9
  # GSD Path Roadmap Phase
9
10
 
@@ -0,0 +1,214 @@
1
+ # Operating rules for phase work
2
+
3
+ These rules extend the project `AGENTS.md` block. Every GSD Path skill
4
+ bundles this file; spawned agents follow their role brief instead.
5
+
6
+ ## Files and state
7
+
8
+ - `.project/discuss/DIALOGUE.md` and `.project/discuss/ANSWERS.md` are the
9
+ append-only memory for any-phase discussion. Read them before continuing an
10
+ existing thread; never treat chat history alone as durable context.
11
+ - The discussion skill never commits. Every phase orchestrator treats only
12
+ complete append-only discussion records as expected bookkeeping and includes
13
+ them in its next normal `.project/` checkpoint; build does so before its next
14
+ clean layer base, and ship includes them in its transaction.
15
+ - Write every output to the handoff path in WORKFLOW.md, using the absolute
16
+ bundled template path supplied by the active phase skill. An output that
17
+ needs verbal explanation is defective.
18
+ - With no `.project/STATE.md`, route through the bundled
19
+ `scripts/detect_project.py initialize --repo <absolute-root> --template
20
+ <absolute-state-template> --require-git` helper; `route: setup-repository`
21
+ leaves the invocation folder unchanged and routes to repository setup before
22
+ state creation or branch binding. Never delete the invocation folder or its
23
+ state to satisfy bootstrap path checks. Do not classify from a directory listing
24
+ or conversation. Follow its JSON `verdict` and `route`. Reserve `classify`
25
+ for read-only inspection; do not use it as a state-initialization preflight.
26
+ - `.project/STATE.md` tracks phase position. Parse and validate it only with
27
+ the bundled `scripts/pipeline_state.py validate` command, route with its
28
+ `route` command, and make ordinary phase transitions only with its
29
+ expected-state `transition`. A journaled transaction helper may write only
30
+ the state fields its contract explicitly owns. Never reproduce these
31
+ deterministic operations in model reasoning. The
32
+ orchestrator alone owns task frontmatter base, isolated worktree/branch,
33
+ status, and agent; the landing commit is proven from git by `isolation.py
34
+ recover`, never recorded. Require `pipeline: gsd-path/v2`; never
35
+ consume an ambiguous or differently owned state file. Artifacts outrank
36
+ summaries; reconcile STATE.md when it disagrees with task frontmatter.
37
+ During a program build, `.project/next/STATE.md` may hold
38
+ the lookahead planning track for the next milestone; it follows the same
39
+ marker rule, owns no task frontmatter, and never binds a branch.
40
+ - STATE.integration_default is the project closeout choice and
41
+ STATE.integration is the current milestone choice. Both are `direct` or
42
+ `pull-request`; STATE.integration_source is `default` or `milestone` and
43
+ preserves explicit override provenance. Older v2 state defaults to `direct`,
44
+ and modes may be changed only through `pipeline_state.py
45
+ configure-integration` before build. A next milestone resets its current
46
+ choice from the project default.
47
+ - Spawned agents have isolated context. Follow the installed runtime dispatch
48
+ contract and brief them with exact input and output paths, constraints, a
49
+ deterministic logical task name, and a bounded responsibility. Independent
50
+ briefs may run in parallel up to available child capacity; a dependent
51
+ brief runs as soon as its dependencies complete.
52
+
53
+ ## Stay in role
54
+
55
+ - The codebase mapper and docs auditor observe and verify; they are strictly
56
+ read-only, report observations rather than judgments, and never resolve a
57
+ doc-vs-code conflict — that ruling belongs to the user.
58
+ - Build, test, lint, and help commands are not presumed read-safe. Read-only
59
+ roles run project commands only in orchestrator-created disposable worktrees
60
+ at a recorded revision; otherwise they use static evidence or mark the check
61
+ unverifiable. They never create worktrees or run commands in the source tree.
62
+ - Researchers gather evidence; they do not decide. A dimension is researched
63
+ only when it has open questions; the research phase records dispatched and
64
+ skipped dimensions. Brownfield adds `evidence-codebase.md` as settled input.
65
+ - The decider works from existing evidence; it does not re-research. An
66
+ unresolved or uncited required decision fails the synthesis gate.
67
+ - The planner reads both INTENT.md and SYNTHESIS.md and specs
68
+ deliverable-sized outcomes and constraints; every INTENT success criterion
69
+ maps to a task AC and Verify in PLAN.md Intent coverage. Coders own
70
+ implementation decisions inside those bounds.
71
+ - Coders implement only their full task contract, including owned INTENT
72
+ success criteria read from INTENT.md, and append their result to the
73
+ task Log. They never change task state, review acceptance, stage, commit, or
74
+ freelance outside declared files.
75
+ - The orchestrator dispatches, arbitrates, and creates task isolation and
76
+ verify sidecars through the bundled `scripts/isolation.py` helper — named
77
+ branches only, never a detached HEAD — lands task work serially, and
78
+ records each clean base in task frontmatter; `land` stamps the landed
79
+ state into the task's own commit, so a task has exactly one commit. It
80
+ writes no product code. When a done task's work already sits on the bound
81
+ branch without a landing commit, only an explicit owner ruling through
82
+ `isolation.py attest` may stand in for it: one `.project/`-only commit that
83
+ names the base, the attested HEAD, the declared files that changed, the
84
+ task Verify recorded as passing at that HEAD, and the ruling verbatim.
85
+ `recover` reports it as `attested`, never as a proven landing.
86
+ - All pipeline work for a milestone lives on `gsd-path/M00N` (M001, M002,
87
+ …) bound in STATE.branch. The next milestone binds a new unused
88
+ `gsd-path/M00N` at the remote default after the previous ship integrates.
89
+ Integration at ship is the only path from the bound branch to the default
90
+ branch — either Path's direct merge or a Path-owned PR merged by the user.
91
+ The bound branch never receives merges or back-merges and is never the
92
+ GitHub default.
93
+ - After initialization writes STATE.md, and before entering the first pipeline
94
+ phase in an existing Git repository, the router calls
95
+ `scripts/pipeline_git.py bind-initial` with the selected M00N and exact
96
+ fetched `origin/main` SHA. The helper alone checks worktree identity and
97
+ cleanliness, exact base, and every local, remote, and other-worktree
98
+ collision before creating or adopting the branch. The sole cleanliness
99
+ exception is untracked `.project/STATE.md`: validated v2 state in active
100
+ inspect or define, with null milestone, branch, and archive, in a real
101
+ directory containing only that regular file with no hard links. The helper
102
+ checks its identity and bytes across binding. Do not commit initialization
103
+ before binding. The router persists its
104
+ typed result in the new state. Build has no branch-creation authority.
105
+ - After `validate-integrated` passes and before any next-milestone file
106
+ changes, the router calls the bundled `scripts/pipeline_git.py bind-next`
107
+ helper with the previous bound branch, exact ship SHA, and exact current
108
+ `origin/main` SHA. The helper moves the clean primary worktree to the new
109
+ unused `gsd-path/M00N` branch at that SHA without moving the previous
110
+ branch or entering the default checkout, then retires the integrated
111
+ previous branch — deleted locally and on origin; the ship commit stays
112
+ reachable from the integration merge and its annotated tag. The router
113
+ persists the new branch in STATE; a wrong-SHA or colliding branch blocks.
114
+ After validated PR integration, `bind-next --allow-missing-previous` may
115
+ retire only the local previous branch when GitHub already auto-deleted its
116
+ remote branch.
117
+ `bind-initial`, this handoff, and the approved new-repository bootstrap are
118
+ the only bound-branch creation authorities, and the handoff's retirement
119
+ push is the router's only bound-branch deletion authority. When a lookahead
120
+ track exists, the router then calls `scripts/pipeline_state.py promote-next`;
121
+ only that journaled helper moves the track, updates state and roadmap,
122
+ classifies plan drift, and writes the router promotion commit.
123
+ - Build adopts the branch recorded in STATE.branch, never whatever is current
124
+ when a recorded branch exists. A new-GitHub REPOSITORY.md proves the
125
+ default checkout and first bound branch; later milestones may rebind
126
+ `gsd-path/M00N` without rewriting that artifact. Build ignores older
127
+ milestone ship and integrate commits inherited through main. A ship commit
128
+ for the current STATE.branch milestone must be an ancestor of origin/main;
129
+ if it is not, that milestone's integration is incomplete and control routes
130
+ to ship, not build. Direct mode requires the matching canonical `integrate:`
131
+ commit; PR mode requires tag metadata and a two-parent merge whose second
132
+ parent is the ship commit. A null branch returns
133
+ to the router; build never creates, selects, switches, or rebinds it.
134
+ - The ship phase makes exactly one commit on the bound branch — the
135
+ `.project/`-only ship commit recording
136
+ STATE.md, the final-review artifacts, and the archive — and additionally
137
+ owns the integration leg. Direct mode creates and pushes one `--no-ff` merge
138
+ onto `main` with subject
139
+ `integrate: M00N — merge gsd-path/M00N into main`. Pull-request mode creates
140
+ or reuses one GitHub.com PR and waits for the user to merge it with a merge
141
+ commit; it never auto-merges. Both modes create one annotated
142
+ `milestone/<NNN>-<slug>` tag after merge validation.
143
+ The roadmap and
144
+ plan phases each make exactly one approval checkpoint commit
145
+ (`.project/`-only, deferred to the build transition commit during a
146
+ new-repository transaction or before Git exists). Their bundled
147
+ `pipeline_state.py approve` command journals before changing STATE or
148
+ ROADMAP.md and owns that canonical checkpoint; a routed
149
+ `resume-checkpoint` must finish before phase work. The router makes one
150
+ bookkeeping commit through `pipeline_state.py promote-next` when promoting a
151
+ lookahead track at a milestone boundary. Every other commit belongs to the
152
+ orchestrator.
153
+ - Reviewers verify and block; they never fix. A block names the criterion,
154
+ observed result, evidence location, and concrete fix direction. An optional
155
+ review panel is advisory: the canonical reviewer remains the only wave
156
+ pass/fail, and panel findings never average or auto-replan. Same-model
157
+ agreement is not independent verification: matching verdicts from one
158
+ model family count as a single evidence path. Independence comes from
159
+ re-run commands, reconstructed patches, different sources, or a
160
+ different model family. Resolve panel
161
+ membership with the bundled `scripts/review_panel.py` helper; do not invent
162
+ model families or slugs. Create task isolation and verify sidecars with the
163
+ bundled `scripts/isolation.py` helper; do not invent `git worktree add` or
164
+ `--detach`. Undo unpublished pipeline work with `scripts/pipeline_undo.py`;
165
+ do not invent `git reset`. Diagnose a stuck pipeline with
166
+ `scripts/pipeline_diagnose.py`.
167
+ - A bundled helper that exits non-zero stops the current step. Print its
168
+ stderr verbatim, run `scripts/pipeline_diagnose.py diagnose --repo
169
+ <absolute-root>` (bundled with `$gsd-path-forensics`), and report both.
170
+ Do not rerun the same command unchanged unless the helper's own contract
171
+ names that exact rerun as its interruption recovery. Never repair state or
172
+ Git by hand instead.
173
+ - The discussion sidecar may run during any non-shipped phase. It grounds
174
+ answers in code and phase artifacts, may perform focused research when
175
+ needed, and writes only its discussion artifacts; it never changes phase
176
+ state or bypasses a phase gate.
177
+ - During an uncommitted archive transaction, discussion writes a complete
178
+ active copy that extends the archived pair. The ship phase reruns `prepare`;
179
+ the helper validates the prefix and atomically reconciles both files.
180
+ Discussion never edits an archive directly or writes after shipment.
181
+ - The loop runner wraps explicit skills in a bounded check → verify → fix →
182
+ verify pass driven by a LOOP.md spec. It never advances a phase gate
183
+ itself and never commits or pushes.
184
+ - Fix tasks use the complete task template, not an abbreviated finding.
185
+
186
+ ## New GitHub repositories
187
+
188
+ - Create a GitHub repository only from an explicit user request followed by an
189
+ approval of the exact owner/name, visibility, default-checkout path,
190
+ `gsd-path/M001` branch, and linked primary-worktree path. Before the
191
+ external action produces an artifact, present those proposed targets as the
192
+ inline **Review** surface using the active router's preview contract.
193
+ Do not write a
194
+ preview file into the invocation directory or another repository. Run the
195
+ bundled bootstrap helper's read-only `preview` command for this evidence.
196
+ - After approval, the bootstrap helper persists the exact targets under the
197
+ approved workspace before the first external mutation. Its `create` command
198
+ creates or verifies the remote, checkout, branch, and linked worktree one
199
+ stage at a time. A matching journal permits explicit resume and adoption; a
200
+ collision without that journal blocks. The helper removes the journal only
201
+ after writing owned STATE.md and fixed-format `.project/REPOSITORY.md` in the
202
+ linked worktree.
203
+ - During an approved new-repository transaction, the router may create the
204
+ first GSD Path branch and linked primary worktree at the verified
205
+ remote-default SHA and persist that branch in STATE.md and REPOSITORY.md.
206
+ Build must verify and adopt that exact binding from REPOSITORY.md, never a
207
+ free-form log. Task branches and task worktrees remain exclusively
208
+ build-orchestrator owned.
209
+ - Keep the cloned default checkout clean on the remote default branch. Run the
210
+ pipeline from the linked GSD Path worktree; never initialize `.project/` in
211
+ the default checkout, reuse an existing branch or path (except an explicitly
212
+ approved empty linked-worktree folder via `--reuse-empty-worktree`), move an existing
213
+ repository, or recover a partial GitHub creation without the exact approved
214
+ journal and re-verification.