@opengsd/gsd-path 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (476) hide show
  1. package/CHANGELOG.md +460 -341
  2. package/DOCS.md +16 -5
  3. package/FULL.md +67 -6
  4. package/HOOKS.md +158 -10
  5. package/MIGRATE.md +12 -0
  6. package/QUICK.md +4 -2
  7. package/README.md +136 -116
  8. package/RUNTIME.md +24 -6
  9. package/UPDATE.md +39 -3
  10. package/WORKFLOW.md +80 -4
  11. package/package.json +5 -2
  12. package/platforms/shared-agents/dispatch.md +13 -0
  13. package/scripts/_common.py +256 -2
  14. package/scripts/archive_milestone.py +14 -13
  15. package/scripts/build_recovery.py +155 -58
  16. package/scripts/build_state.py +274 -8
  17. package/scripts/check_docs_audit.py +77 -4
  18. package/scripts/check_handoffs.py +635 -57
  19. package/scripts/check_task_briefs.py +293 -32
  20. package/scripts/detect_project.py +260 -20
  21. package/scripts/discussion_records.py +9 -1
  22. package/scripts/discussion_validate.py +93 -35
  23. package/scripts/dispatch_driver.py +549 -53
  24. package/scripts/git_guard.py +27 -8
  25. package/scripts/guard_hook.py +2630 -210
  26. package/scripts/install.mjs +99 -11
  27. package/scripts/install.py +231 -46
  28. package/scripts/integration.py +244 -65
  29. package/scripts/isolation.py +539 -70
  30. package/scripts/loop_run.py +16 -4
  31. package/scripts/members.py +77 -32
  32. package/scripts/migrate_core.py +2 -0
  33. package/scripts/model_policy.py +5 -1
  34. package/scripts/path_config.py +3 -3
  35. package/scripts/pipeline_diagnose.py +17 -2
  36. package/scripts/pipeline_git.py +131 -42
  37. package/scripts/pipeline_state.py +139 -39
  38. package/scripts/pipeline_undo.py +118 -16
  39. package/scripts/promote_lookahead.py +3 -3
  40. package/scripts/review_findings.py +180 -44
  41. package/scripts/roadmap.py +9 -1
  42. package/scripts/runtime_store.py +21 -2
  43. package/scripts/skill-resources.json +9 -2
  44. package/scripts/state_checkpoint.py +39 -36
  45. package/scripts/state_promote.py +15 -4
  46. package/scripts/status_runtime.py +22 -4
  47. package/scripts/task_context.py +14 -3
  48. package/scripts/wizard.mjs +1 -0
  49. package/scripts/workflow_run.py +14 -4
  50. package/scripts/worktree_paths.py +54 -2
  51. package/skills/gsd-path/DEFINE.md +34 -5
  52. package/skills/gsd-path/PLAN.md +14 -3
  53. package/skills/gsd-path/RESEARCH.md +11 -0
  54. package/skills/gsd-path/ROADMAP.md +16 -6
  55. package/skills/gsd-path/SHIP.md +32 -5
  56. package/skills/gsd-path/SKILL.md +52 -24
  57. package/skills/gsd-path/references/build-native.md +112 -10
  58. package/skills/gsd-path/references/build-recovery.md +13 -0
  59. package/skills/gsd-path/references/coder.md +7 -3
  60. package/skills/gsd-path/references/dispatch.md +13 -0
  61. package/skills/gsd-path/references/docs-auditor.md +5 -0
  62. package/skills/gsd-path/references/operating-rules.md +11 -3
  63. package/skills/gsd-path/references/planner.md +26 -4
  64. package/skills/gsd-path/references/reviewer-final.md +20 -2
  65. package/skills/gsd-path/references/reviewer-wave.md +56 -12
  66. package/skills/gsd-path/references/reviewer.md +3 -1
  67. package/skills/gsd-path/references/runtime-selection.md +9 -0
  68. package/skills/gsd-path/references/spec-probes.md +150 -0
  69. package/skills/gsd-path/scripts/_common.py +256 -2
  70. package/skills/gsd-path/scripts/archive_milestone.py +14 -13
  71. package/skills/gsd-path/scripts/build_recovery.py +155 -58
  72. package/skills/gsd-path/scripts/build_state.py +274 -8
  73. package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
  74. package/skills/gsd-path/scripts/check_handoffs.py +635 -57
  75. package/skills/gsd-path/scripts/check_task_briefs.py +293 -32
  76. package/skills/gsd-path/scripts/detect_project.py +260 -20
  77. package/skills/gsd-path/scripts/discussion_records.py +9 -1
  78. package/skills/gsd-path/scripts/discussion_validate.py +93 -35
  79. package/skills/gsd-path/scripts/dispatch_driver.py +549 -53
  80. package/skills/gsd-path/scripts/git_guard.py +27 -8
  81. package/skills/gsd-path/scripts/integration.py +244 -65
  82. package/skills/gsd-path/scripts/isolation.py +539 -70
  83. package/skills/gsd-path/scripts/loop_run.py +16 -4
  84. package/skills/gsd-path/scripts/members.py +77 -32
  85. package/skills/gsd-path/scripts/model_policy.py +5 -1
  86. package/skills/gsd-path/scripts/path_config.py +3 -3
  87. package/skills/gsd-path/scripts/pipeline_git.py +131 -42
  88. package/skills/gsd-path/scripts/pipeline_state.py +139 -39
  89. package/skills/gsd-path/scripts/promote_lookahead.py +3 -3
  90. package/skills/gsd-path/scripts/review_findings.py +180 -44
  91. package/skills/gsd-path/scripts/roadmap.py +9 -1
  92. package/skills/gsd-path/scripts/state_checkpoint.py +39 -36
  93. package/skills/gsd-path/scripts/state_promote.py +15 -4
  94. package/skills/gsd-path/scripts/status_runtime.py +22 -4
  95. package/skills/gsd-path/scripts/task_context.py +14 -3
  96. package/skills/gsd-path/scripts/workflow_run.py +14 -4
  97. package/skills/gsd-path/scripts/worktree_paths.py +54 -2
  98. package/skills/gsd-path/templates/docs-audit.md +5 -1
  99. package/skills/gsd-path/templates/final-review.md +11 -2
  100. package/skills/gsd-path/templates/intent.md +30 -0
  101. package/skills/gsd-path/templates/patch-findings.md +3 -3
  102. package/skills/gsd-path/templates/plan.md +17 -2
  103. package/skills/gsd-path/templates/research-handoff.md +14 -3
  104. package/skills/gsd-path/templates/state.md +2 -1
  105. package/skills/gsd-path/templates/task.md +1 -0
  106. package/skills/gsd-path/templates/wave-review.md +28 -9
  107. package/skills/gsd-path-build/references/build-native.md +112 -10
  108. package/skills/gsd-path-build/references/build-recovery.md +13 -0
  109. package/skills/gsd-path-build/references/coder.md +7 -3
  110. package/skills/gsd-path-build/references/dispatch.md +13 -0
  111. package/skills/gsd-path-build/references/operating-rules.md +11 -3
  112. package/skills/gsd-path-build/references/reviewer-final.md +20 -2
  113. package/skills/gsd-path-build/references/reviewer-wave.md +56 -12
  114. package/skills/gsd-path-build/references/reviewer.md +3 -1
  115. package/skills/gsd-path-build/references/runtime-selection.md +9 -0
  116. package/skills/gsd-path-build/references/spec-probes.md +150 -0
  117. package/skills/gsd-path-build/scripts/_common.py +256 -2
  118. package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
  119. package/skills/gsd-path-build/scripts/build_recovery.py +155 -58
  120. package/skills/gsd-path-build/scripts/build_state.py +274 -8
  121. package/skills/gsd-path-build/scripts/check_handoffs.py +635 -57
  122. package/skills/gsd-path-build/scripts/check_task_briefs.py +293 -32
  123. package/skills/gsd-path-build/scripts/detect_project.py +260 -20
  124. package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
  125. package/skills/gsd-path-build/scripts/discussion_validate.py +93 -35
  126. package/skills/gsd-path-build/scripts/dispatch_driver.py +549 -53
  127. package/skills/gsd-path-build/scripts/integration.py +244 -65
  128. package/skills/gsd-path-build/scripts/isolation.py +539 -70
  129. package/skills/gsd-path-build/scripts/loop_run.py +16 -4
  130. package/skills/gsd-path-build/scripts/members.py +77 -32
  131. package/skills/gsd-path-build/scripts/model_policy.py +5 -1
  132. package/skills/gsd-path-build/scripts/path_config.py +3 -3
  133. package/skills/gsd-path-build/scripts/pipeline_git.py +131 -42
  134. package/skills/gsd-path-build/scripts/pipeline_state.py +139 -39
  135. package/skills/gsd-path-build/scripts/promote_lookahead.py +3 -3
  136. package/skills/gsd-path-build/scripts/review_findings.py +180 -44
  137. package/skills/gsd-path-build/scripts/roadmap.py +9 -1
  138. package/skills/gsd-path-build/scripts/state_checkpoint.py +39 -36
  139. package/skills/gsd-path-build/scripts/state_promote.py +15 -4
  140. package/skills/gsd-path-build/scripts/task_context.py +14 -3
  141. package/skills/gsd-path-build/scripts/workflow_run.py +14 -4
  142. package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
  143. package/skills/gsd-path-build/templates/task.md +1 -0
  144. package/skills/gsd-path-build/templates/wave-review.md +28 -9
  145. package/skills/gsd-path-decide/references/dispatch.md +13 -0
  146. package/skills/gsd-path-decide/references/operating-rules.md +11 -3
  147. package/skills/gsd-path-decide/references/runtime-selection.md +9 -0
  148. package/skills/gsd-path-decide/scripts/_common.py +256 -2
  149. package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
  150. package/skills/gsd-path-decide/scripts/build_recovery.py +155 -58
  151. package/skills/gsd-path-decide/scripts/check_handoffs.py +635 -57
  152. package/skills/gsd-path-decide/scripts/check_task_briefs.py +293 -32
  153. package/skills/gsd-path-decide/scripts/detect_project.py +260 -20
  154. package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
  155. package/skills/gsd-path-decide/scripts/discussion_validate.py +93 -35
  156. package/skills/gsd-path-decide/scripts/integration.py +244 -65
  157. package/skills/gsd-path-decide/scripts/isolation.py +539 -70
  158. package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
  159. package/skills/gsd-path-decide/scripts/members.py +77 -32
  160. package/skills/gsd-path-decide/scripts/model_policy.py +5 -1
  161. package/skills/gsd-path-decide/scripts/path_config.py +3 -3
  162. package/skills/gsd-path-decide/scripts/pipeline_git.py +131 -42
  163. package/skills/gsd-path-decide/scripts/pipeline_state.py +139 -39
  164. package/skills/gsd-path-decide/scripts/promote_lookahead.py +3 -3
  165. package/skills/gsd-path-decide/scripts/roadmap.py +9 -1
  166. package/skills/gsd-path-decide/scripts/state_checkpoint.py +39 -36
  167. package/skills/gsd-path-decide/scripts/state_promote.py +15 -4
  168. package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
  169. package/skills/gsd-path-define/SKILL.md +34 -5
  170. package/skills/gsd-path-define/references/build-recovery.md +13 -0
  171. package/skills/gsd-path-define/references/operating-rules.md +11 -3
  172. package/skills/gsd-path-define/references/runtime-selection.md +9 -0
  173. package/skills/gsd-path-define/references/spec-probes.md +150 -0
  174. package/skills/gsd-path-define/scripts/_common.py +256 -2
  175. package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
  176. package/skills/gsd-path-define/scripts/build_recovery.py +155 -58
  177. package/skills/gsd-path-define/scripts/check_handoffs.py +635 -57
  178. package/skills/gsd-path-define/scripts/check_task_briefs.py +293 -32
  179. package/skills/gsd-path-define/scripts/detect_project.py +260 -20
  180. package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
  181. package/skills/gsd-path-define/scripts/discussion_validate.py +93 -35
  182. package/skills/gsd-path-define/scripts/integration.py +244 -65
  183. package/skills/gsd-path-define/scripts/isolation.py +539 -70
  184. package/skills/gsd-path-define/scripts/loop_run.py +16 -4
  185. package/skills/gsd-path-define/scripts/members.py +77 -32
  186. package/skills/gsd-path-define/scripts/model_policy.py +5 -1
  187. package/skills/gsd-path-define/scripts/path_config.py +3 -3
  188. package/skills/gsd-path-define/scripts/pipeline_git.py +131 -42
  189. package/skills/gsd-path-define/scripts/pipeline_state.py +139 -39
  190. package/skills/gsd-path-define/scripts/promote_lookahead.py +3 -3
  191. package/skills/gsd-path-define/scripts/roadmap.py +9 -1
  192. package/skills/gsd-path-define/scripts/state_checkpoint.py +39 -36
  193. package/skills/gsd-path-define/scripts/state_promote.py +15 -4
  194. package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
  195. package/skills/gsd-path-define/templates/intent.md +30 -0
  196. package/skills/gsd-path-define/templates/state.md +2 -1
  197. package/skills/gsd-path-discuss/references/operating-rules.md +11 -3
  198. package/skills/gsd-path-discuss/references/runtime-selection.md +9 -0
  199. package/skills/gsd-path-discuss/scripts/_common.py +256 -2
  200. package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
  201. package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
  202. package/skills/gsd-path-discuss/scripts/model_policy.py +5 -1
  203. package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
  204. package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
  205. package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
  206. package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
  207. package/skills/gsd-path-docs-audit/references/operating-rules.md +11 -3
  208. package/skills/gsd-path-docs-audit/references/runtime-selection.md +9 -0
  209. package/skills/gsd-path-docs-audit/scripts/_common.py +256 -2
  210. package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
  211. package/skills/gsd-path-docs-audit/scripts/build_recovery.py +155 -58
  212. package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
  213. package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +635 -57
  214. package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +293 -32
  215. package/skills/gsd-path-docs-audit/scripts/detect_project.py +260 -20
  216. package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
  217. package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +93 -35
  218. package/skills/gsd-path-docs-audit/scripts/integration.py +244 -65
  219. package/skills/gsd-path-docs-audit/scripts/isolation.py +539 -70
  220. package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
  221. package/skills/gsd-path-docs-audit/scripts/members.py +77 -32
  222. package/skills/gsd-path-docs-audit/scripts/model_policy.py +5 -1
  223. package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
  224. package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +131 -42
  225. package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +139 -39
  226. package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +3 -3
  227. package/skills/gsd-path-docs-audit/scripts/roadmap.py +9 -1
  228. package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +39 -36
  229. package/skills/gsd-path-docs-audit/scripts/state_promote.py +15 -4
  230. package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
  231. package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
  232. package/skills/gsd-path-forensics/references/operating-rules.md +11 -3
  233. package/skills/gsd-path-forensics/references/runtime-selection.md +9 -0
  234. package/skills/gsd-path-forensics/scripts/_common.py +256 -2
  235. package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
  236. package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
  237. package/skills/gsd-path-forensics/scripts/model_policy.py +5 -1
  238. package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
  239. package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
  240. package/skills/gsd-path-forensics/scripts/pipeline_undo.py +118 -16
  241. package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
  242. package/skills/gsd-path-inspect/references/dispatch.md +13 -0
  243. package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
  244. package/skills/gsd-path-inspect/references/operating-rules.md +11 -3
  245. package/skills/gsd-path-inspect/references/runtime-selection.md +9 -0
  246. package/skills/gsd-path-inspect/scripts/_common.py +256 -2
  247. package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
  248. package/skills/gsd-path-inspect/scripts/build_recovery.py +155 -58
  249. package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
  250. package/skills/gsd-path-inspect/scripts/check_handoffs.py +635 -57
  251. package/skills/gsd-path-inspect/scripts/check_task_briefs.py +293 -32
  252. package/skills/gsd-path-inspect/scripts/detect_project.py +260 -20
  253. package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
  254. package/skills/gsd-path-inspect/scripts/discussion_validate.py +93 -35
  255. package/skills/gsd-path-inspect/scripts/integration.py +244 -65
  256. package/skills/gsd-path-inspect/scripts/isolation.py +539 -70
  257. package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
  258. package/skills/gsd-path-inspect/scripts/members.py +77 -32
  259. package/skills/gsd-path-inspect/scripts/model_policy.py +5 -1
  260. package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
  261. package/skills/gsd-path-inspect/scripts/pipeline_git.py +131 -42
  262. package/skills/gsd-path-inspect/scripts/pipeline_state.py +139 -39
  263. package/skills/gsd-path-inspect/scripts/promote_lookahead.py +3 -3
  264. package/skills/gsd-path-inspect/scripts/roadmap.py +9 -1
  265. package/skills/gsd-path-inspect/scripts/state_checkpoint.py +39 -36
  266. package/skills/gsd-path-inspect/scripts/state_promote.py +15 -4
  267. package/skills/gsd-path-inspect/scripts/workflow_run.py +14 -4
  268. package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
  269. package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
  270. package/skills/gsd-path-inspect/templates/state.md +2 -1
  271. package/skills/gsd-path-loop/references/operating-rules.md +11 -3
  272. package/skills/gsd-path-loop/references/runtime-selection.md +9 -0
  273. package/skills/gsd-path-loop/scripts/_common.py +256 -2
  274. package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
  275. package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
  276. package/skills/gsd-path-loop/scripts/model_policy.py +5 -1
  277. package/skills/gsd-path-loop/scripts/path_config.py +3 -3
  278. package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
  279. package/skills/gsd-path-migrate/SKILL.md +8 -0
  280. package/skills/gsd-path-migrate/references/operating-rules.md +11 -3
  281. package/skills/gsd-path-migrate/references/runtime-selection.md +9 -0
  282. package/skills/gsd-path-migrate/scripts/_common.py +256 -2
  283. package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
  284. package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
  285. package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -0
  286. package/skills/gsd-path-migrate/scripts/model_policy.py +5 -1
  287. package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
  288. package/skills/gsd-path-plan/SKILL.md +14 -3
  289. package/skills/gsd-path-plan/references/build-recovery.md +13 -0
  290. package/skills/gsd-path-plan/references/dispatch.md +13 -0
  291. package/skills/gsd-path-plan/references/operating-rules.md +11 -3
  292. package/skills/gsd-path-plan/references/planner.md +26 -4
  293. package/skills/gsd-path-plan/references/runtime-selection.md +9 -0
  294. package/skills/gsd-path-plan/references/spec-probes.md +150 -0
  295. package/skills/gsd-path-plan/scripts/_common.py +256 -2
  296. package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
  297. package/skills/gsd-path-plan/scripts/build_recovery.py +155 -58
  298. package/skills/gsd-path-plan/scripts/check_handoffs.py +635 -57
  299. package/skills/gsd-path-plan/scripts/check_task_briefs.py +293 -32
  300. package/skills/gsd-path-plan/scripts/detect_project.py +260 -20
  301. package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
  302. package/skills/gsd-path-plan/scripts/discussion_validate.py +93 -35
  303. package/skills/gsd-path-plan/scripts/integration.py +244 -65
  304. package/skills/gsd-path-plan/scripts/isolation.py +539 -70
  305. package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
  306. package/skills/gsd-path-plan/scripts/members.py +77 -32
  307. package/skills/gsd-path-plan/scripts/model_policy.py +5 -1
  308. package/skills/gsd-path-plan/scripts/path_config.py +3 -3
  309. package/skills/gsd-path-plan/scripts/pipeline_git.py +131 -42
  310. package/skills/gsd-path-plan/scripts/pipeline_state.py +139 -39
  311. package/skills/gsd-path-plan/scripts/promote_lookahead.py +3 -3
  312. package/skills/gsd-path-plan/scripts/roadmap.py +9 -1
  313. package/skills/gsd-path-plan/scripts/state_checkpoint.py +39 -36
  314. package/skills/gsd-path-plan/scripts/state_promote.py +15 -4
  315. package/skills/gsd-path-plan/scripts/workflow_run.py +14 -4
  316. package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
  317. package/skills/gsd-path-plan/templates/patch-findings.md +3 -3
  318. package/skills/gsd-path-plan/templates/plan.md +17 -2
  319. package/skills/gsd-path-plan/templates/task.md +1 -0
  320. package/skills/gsd-path-research/SKILL.md +11 -0
  321. package/skills/gsd-path-research/references/dispatch.md +13 -0
  322. package/skills/gsd-path-research/references/operating-rules.md +11 -3
  323. package/skills/gsd-path-research/references/runtime-selection.md +9 -0
  324. package/skills/gsd-path-research/scripts/_common.py +256 -2
  325. package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
  326. package/skills/gsd-path-research/scripts/build_recovery.py +155 -58
  327. package/skills/gsd-path-research/scripts/check_handoffs.py +635 -57
  328. package/skills/gsd-path-research/scripts/check_task_briefs.py +293 -32
  329. package/skills/gsd-path-research/scripts/detect_project.py +260 -20
  330. package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
  331. package/skills/gsd-path-research/scripts/discussion_validate.py +93 -35
  332. package/skills/gsd-path-research/scripts/integration.py +244 -65
  333. package/skills/gsd-path-research/scripts/isolation.py +539 -70
  334. package/skills/gsd-path-research/scripts/loop_run.py +16 -4
  335. package/skills/gsd-path-research/scripts/members.py +77 -32
  336. package/skills/gsd-path-research/scripts/model_policy.py +5 -1
  337. package/skills/gsd-path-research/scripts/path_config.py +3 -3
  338. package/skills/gsd-path-research/scripts/pipeline_git.py +131 -42
  339. package/skills/gsd-path-research/scripts/pipeline_state.py +139 -39
  340. package/skills/gsd-path-research/scripts/promote_lookahead.py +3 -3
  341. package/skills/gsd-path-research/scripts/roadmap.py +9 -1
  342. package/skills/gsd-path-research/scripts/state_checkpoint.py +39 -36
  343. package/skills/gsd-path-research/scripts/state_promote.py +15 -4
  344. package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
  345. package/skills/gsd-path-research/templates/research-handoff.md +14 -3
  346. package/skills/gsd-path-roadmap/SKILL.md +16 -6
  347. package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
  348. package/skills/gsd-path-roadmap/references/operating-rules.md +11 -3
  349. package/skills/gsd-path-roadmap/references/runtime-selection.md +9 -0
  350. package/skills/gsd-path-roadmap/scripts/_common.py +256 -2
  351. package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
  352. package/skills/gsd-path-roadmap/scripts/build_recovery.py +155 -58
  353. package/skills/gsd-path-roadmap/scripts/check_handoffs.py +635 -57
  354. package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +293 -32
  355. package/skills/gsd-path-roadmap/scripts/detect_project.py +260 -20
  356. package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
  357. package/skills/gsd-path-roadmap/scripts/discussion_validate.py +93 -35
  358. package/skills/gsd-path-roadmap/scripts/integration.py +244 -65
  359. package/skills/gsd-path-roadmap/scripts/isolation.py +539 -70
  360. package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
  361. package/skills/gsd-path-roadmap/scripts/members.py +77 -32
  362. package/skills/gsd-path-roadmap/scripts/model_policy.py +5 -1
  363. package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
  364. package/skills/gsd-path-roadmap/scripts/pipeline_git.py +131 -42
  365. package/skills/gsd-path-roadmap/scripts/pipeline_state.py +139 -39
  366. package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +3 -3
  367. package/skills/gsd-path-roadmap/scripts/roadmap.py +9 -1
  368. package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +39 -36
  369. package/skills/gsd-path-roadmap/scripts/state_promote.py +15 -4
  370. package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
  371. package/skills/gsd-path-ship/SKILL.md +32 -5
  372. package/skills/gsd-path-ship/references/dispatch.md +13 -0
  373. package/skills/gsd-path-ship/references/operating-rules.md +11 -3
  374. package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
  375. package/skills/gsd-path-ship/references/reviewer-wave.md +56 -12
  376. package/skills/gsd-path-ship/references/reviewer.md +3 -1
  377. package/skills/gsd-path-ship/references/runtime-selection.md +9 -0
  378. package/skills/gsd-path-ship/references/spec-probes.md +150 -0
  379. package/skills/gsd-path-ship/scripts/_common.py +256 -2
  380. package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
  381. package/skills/gsd-path-ship/scripts/build_recovery.py +155 -58
  382. package/skills/gsd-path-ship/scripts/build_state.py +274 -8
  383. package/skills/gsd-path-ship/scripts/check_handoffs.py +635 -57
  384. package/skills/gsd-path-ship/scripts/check_task_briefs.py +293 -32
  385. package/skills/gsd-path-ship/scripts/detect_project.py +260 -20
  386. package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
  387. package/skills/gsd-path-ship/scripts/discussion_validate.py +93 -35
  388. package/skills/gsd-path-ship/scripts/integration.py +244 -65
  389. package/skills/gsd-path-ship/scripts/isolation.py +539 -70
  390. package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
  391. package/skills/gsd-path-ship/scripts/members.py +77 -32
  392. package/skills/gsd-path-ship/scripts/model_policy.py +5 -1
  393. package/skills/gsd-path-ship/scripts/path_config.py +3 -3
  394. package/skills/gsd-path-ship/scripts/pipeline_git.py +131 -42
  395. package/skills/gsd-path-ship/scripts/pipeline_state.py +139 -39
  396. package/skills/gsd-path-ship/scripts/promote_lookahead.py +3 -3
  397. package/skills/gsd-path-ship/scripts/roadmap.py +9 -1
  398. package/skills/gsd-path-ship/scripts/state_checkpoint.py +39 -36
  399. package/skills/gsd-path-ship/scripts/state_promote.py +15 -4
  400. package/skills/gsd-path-ship/scripts/workflow_run.py +14 -4
  401. package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
  402. package/skills/gsd-path-ship/templates/final-review.md +11 -2
  403. package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
  404. package/skills/gsd-path-ship/templates/wave-review.md +28 -9
  405. package/skills/gsd-path-undo/references/operating-rules.md +11 -3
  406. package/skills/gsd-path-undo/references/runtime-selection.md +9 -0
  407. package/skills/gsd-path-undo/scripts/_common.py +256 -2
  408. package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
  409. package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
  410. package/skills/gsd-path-undo/scripts/model_policy.py +5 -1
  411. package/skills/gsd-path-undo/scripts/path_config.py +3 -3
  412. package/skills/gsd-path-undo/scripts/pipeline_undo.py +118 -16
  413. package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
  414. package/skills/path/DEFINE.md +34 -5
  415. package/skills/path/PLAN.md +14 -3
  416. package/skills/path/RESEARCH.md +11 -0
  417. package/skills/path/ROADMAP.md +16 -6
  418. package/skills/path/SHIP.md +32 -5
  419. package/skills/path/SKILL.md +52 -24
  420. package/skills/path/references/build-native.md +112 -10
  421. package/skills/path/references/build-recovery.md +13 -0
  422. package/skills/path/references/coder.md +7 -3
  423. package/skills/path/references/dispatch.md +13 -0
  424. package/skills/path/references/docs-auditor.md +5 -0
  425. package/skills/path/references/operating-rules.md +11 -3
  426. package/skills/path/references/planner.md +26 -4
  427. package/skills/path/references/reviewer-final.md +20 -2
  428. package/skills/path/references/reviewer-wave.md +56 -12
  429. package/skills/path/references/reviewer.md +3 -1
  430. package/skills/path/references/runtime-selection.md +9 -0
  431. package/skills/path/references/spec-probes.md +150 -0
  432. package/skills/path/scripts/_common.py +256 -2
  433. package/skills/path/scripts/archive_milestone.py +14 -13
  434. package/skills/path/scripts/build_recovery.py +155 -58
  435. package/skills/path/scripts/build_state.py +274 -8
  436. package/skills/path/scripts/check_docs_audit.py +77 -4
  437. package/skills/path/scripts/check_handoffs.py +635 -57
  438. package/skills/path/scripts/check_task_briefs.py +293 -32
  439. package/skills/path/scripts/detect_project.py +260 -20
  440. package/skills/path/scripts/discussion_records.py +9 -1
  441. package/skills/path/scripts/discussion_validate.py +93 -35
  442. package/skills/path/scripts/dispatch_driver.py +549 -53
  443. package/skills/path/scripts/git_guard.py +27 -8
  444. package/skills/path/scripts/integration.py +244 -65
  445. package/skills/path/scripts/isolation.py +539 -70
  446. package/skills/path/scripts/loop_run.py +16 -4
  447. package/skills/path/scripts/members.py +77 -32
  448. package/skills/path/scripts/model_policy.py +5 -1
  449. package/skills/path/scripts/path_config.py +3 -3
  450. package/skills/path/scripts/pipeline_git.py +131 -42
  451. package/skills/path/scripts/pipeline_state.py +139 -39
  452. package/skills/path/scripts/promote_lookahead.py +3 -3
  453. package/skills/path/scripts/review_findings.py +180 -44
  454. package/skills/path/scripts/roadmap.py +9 -1
  455. package/skills/path/scripts/state_checkpoint.py +39 -36
  456. package/skills/path/scripts/state_promote.py +15 -4
  457. package/skills/path/scripts/status_runtime.py +22 -4
  458. package/skills/path/scripts/task_context.py +14 -3
  459. package/skills/path/scripts/workflow_run.py +14 -4
  460. package/skills/path/scripts/worktree_paths.py +54 -2
  461. package/skills/path/templates/docs-audit.md +5 -1
  462. package/skills/path/templates/final-review.md +11 -2
  463. package/skills/path/templates/intent.md +30 -0
  464. package/skills/path/templates/patch-findings.md +3 -3
  465. package/skills/path/templates/plan.md +17 -2
  466. package/skills/path/templates/research-handoff.md +14 -3
  467. package/skills/path/templates/state.md +2 -1
  468. package/skills/path/templates/task.md +1 -0
  469. package/skills/path/templates/wave-review.md +28 -9
  470. package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  471. package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  472. package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  473. package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
  474. package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  475. package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
  476. package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
@@ -55,10 +55,22 @@ try:
55
55
  fcntl.flock(fd, fcntl.LOCK_EX)
56
56
 
57
57
  except ImportError: # Windows does not provide POSIX file locks.
58
+ import errno
58
59
  import msvcrt
60
+ import time
59
61
 
60
62
  def lock_exclusive(fd: int) -> None:
61
- msvcrt.locking(fd, msvcrt.LK_LOCK, 1)
63
+ delay = 0.01
64
+ while True:
65
+ try:
66
+ os.lseek(fd, 0, os.SEEK_SET)
67
+ msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
68
+ return
69
+ except OSError as error:
70
+ if error.errno not in (errno.EACCES, errno.EAGAIN, errno.EDEADLK):
71
+ raise
72
+ time.sleep(delay)
73
+ delay = min(delay * 2, 0.25)
62
74
 
63
75
 
64
76
  IGNORE_DIRS = {
@@ -217,16 +229,20 @@ HTML_BLOCK_START = re.compile(
217
229
  re.IGNORECASE,
218
230
  )
219
231
  REPARSE_NAME_SURROGATE = 0x20000000
220
- ANCHORED_EVIDENCE_SUPPORTED = (
232
+ _POSIX_ANCHORED_EVIDENCE_SUPPORTED = (
221
233
  hasattr(os, "O_DIRECTORY")
222
234
  and hasattr(os, "O_NOFOLLOW")
223
235
  and os.open in os.supports_dir_fd
224
236
  and os.stat in os.supports_dir_fd
225
237
  and os.stat in os.supports_follow_symlinks
226
238
  )
239
+ WINDOWS_ANCHORED_EVIDENCE_SUPPORTED = os.name == "nt"
240
+ ANCHORED_EVIDENCE_SUPPORTED = (
241
+ _POSIX_ANCHORED_EVIDENCE_SUPPORTED or WINDOWS_ANCHORED_EVIDENCE_SUPPORTED
242
+ )
227
243
  LISTDIR_DIR_FD_SUPPORTED = os.listdir in getattr(os, "supports_fd", ())
228
244
  ANCHORED_STATE_CREATE_SUPPORTED = (
229
- ANCHORED_EVIDENCE_SUPPORTED
245
+ _POSIX_ANCHORED_EVIDENCE_SUPPORTED
230
246
  and LISTDIR_DIR_FD_SUPPORTED
231
247
  and os.mkdir in getattr(os, "supports_dir_fd", ())
232
248
  and os.unlink in getattr(os, "supports_dir_fd", ())
@@ -269,11 +285,12 @@ def is_link_like_status(status: os.stat_result) -> bool:
269
285
  def is_link_like(path: Path, status: os.stat_result) -> bool:
270
286
  if is_link_like_status(status):
271
287
  return True
272
- isjunction = getattr(os.path, "isjunction", None)
273
- if os.name != "nt" or isjunction is None:
288
+ if os.name != "nt":
274
289
  return False
275
290
  try:
276
- return bool(isjunction(path))
291
+ return is_link_like_status(os.lstat(path))
292
+ except FileNotFoundError:
293
+ return False
277
294
  except OSError as error:
278
295
  raise DetectError(f"cannot inspect link-like evidence: {path}: {error}") from error
279
296
 
@@ -332,7 +349,7 @@ def is_managed_pipeline_directory(relative: str, root: Path) -> bool:
332
349
  return is_verified_skill_bundle(relative, root)
333
350
 
334
351
 
335
- def is_verified_skill_bundle_at(relative: str, directory_fd: int) -> bool:
352
+ def is_verified_skill_bundle_at(relative: str, directory_fd: int, root: Path) -> bool:
336
353
  parts = PurePosixPath(relative).parts
337
354
  if not parts:
338
355
  return False
@@ -342,19 +359,45 @@ def is_verified_skill_bundle_at(relative: str, directory_fd: int) -> bool:
342
359
  return False
343
360
  if is_verified_installer_bundle(parts):
344
361
  return True
362
+ if _POSIX_ANCHORED_EVIDENCE_SUPPORTED:
363
+ try:
364
+ status = os.stat(
365
+ "SKILL.md",
366
+ dir_fd=directory_fd,
367
+ follow_symlinks=False,
368
+ )
369
+ except FileNotFoundError:
370
+ return False
371
+ except OSError as error:
372
+ raise DetectError(
373
+ f"cannot inspect managed skill bundle: {relative}: {error}"
374
+ ) from error
375
+ return not is_link_like_status(status) and stat.S_ISREG(status.st_mode)
376
+ skill_fd = None
345
377
  try:
346
- status = os.stat(
378
+ win = get_windows_handles()
379
+ skill_fd = win.open_relative(
380
+ directory_fd,
347
381
  "SKILL.md",
348
- dir_fd=directory_fd,
349
- follow_symlinks=False,
382
+ _FILE_READ_ATTRIBUTES,
383
+ _PIN_SHARE,
384
+ _FILE_OPEN,
385
+ 0,
350
386
  )
387
+ status = os.fstat(skill_fd)
351
388
  except FileNotFoundError:
352
389
  return False
353
390
  except OSError as error:
391
+ if getattr(error, "winerror", None) == 2:
392
+ return False
354
393
  raise DetectError(
355
394
  f"cannot inspect managed skill bundle: {relative}: {error}"
356
395
  ) from error
357
- return not is_link_like_status(status) and stat.S_ISREG(status.st_mode)
396
+ finally:
397
+ if skill_fd is not None:
398
+ os.close(skill_fd)
399
+ skill = root.joinpath(*parts) / "SKILL.md"
400
+ return not is_link_like(skill, status) and stat.S_ISREG(status.st_mode)
358
401
 
359
402
 
360
403
  def is_fixed_managed_pipeline_artifact(relative: str) -> bool:
@@ -423,13 +466,20 @@ def read_regular_evidence(
423
466
  ) from error
424
467
  if not relative.parts:
425
468
  raise DetectError(f"{evidence_name} evidence path is empty: {path}")
426
- if ANCHORED_EVIDENCE_SUPPORTED:
469
+ if _POSIX_ANCHORED_EVIDENCE_SUPPORTED:
427
470
  return read_anchored_evidence(
428
471
  relative,
429
472
  root,
430
473
  missing_ok=missing_ok,
431
474
  evidence_name=evidence_name,
432
475
  )
476
+ if WINDOWS_ANCHORED_EVIDENCE_SUPPORTED:
477
+ return read_windows_anchored_evidence(
478
+ relative,
479
+ root,
480
+ missing_ok=missing_ok,
481
+ evidence_name=evidence_name,
482
+ )
433
483
  return read_lstat_open_evidence(
434
484
  relative,
435
485
  root,
@@ -447,6 +497,17 @@ def directory_flags() -> int:
447
497
  )
448
498
 
449
499
 
500
+ def listdir_anchored(dir_fd: int) -> list[str]:
501
+ """List names through a fresh directory descriptor under dir_fd."""
502
+ fresh = os.open(".", directory_flags(), dir_fd=dir_fd)
503
+ try:
504
+ if not os.path.samestat(os.fstat(fresh), os.fstat(dir_fd)):
505
+ raise DetectError("anchored directory listing lost its identity")
506
+ return os.listdir(fresh)
507
+ finally:
508
+ os.close(fresh)
509
+
510
+
450
511
  def file_flags() -> int:
451
512
  return (
452
513
  os.O_RDONLY
@@ -766,9 +827,12 @@ def raise_walk_error(error: OSError) -> None:
766
827
 
767
828
 
768
829
  def iter_worktree_files(root: Path) -> Iterable[str]:
769
- if ANCHORED_EVIDENCE_SUPPORTED and LISTDIR_DIR_FD_SUPPORTED:
830
+ if _POSIX_ANCHORED_EVIDENCE_SUPPORTED and LISTDIR_DIR_FD_SUPPORTED:
770
831
  yield from iter_worktree_files_anchored(root)
771
832
  return
833
+ if WINDOWS_ANCHORED_EVIDENCE_SUPPORTED:
834
+ yield from iter_worktree_files_windows_anchored(root)
835
+ return
772
836
  for dirpath, dirnames, filenames in os.walk(
773
837
  root,
774
838
  followlinks=False,
@@ -826,7 +890,7 @@ def iter_from_dir_fd(
826
890
  dir_fd: int, relative_dir: str, root: Path
827
891
  ) -> Iterable[str]:
828
892
  try:
829
- names = os.listdir(dir_fd)
893
+ names = listdir_anchored(dir_fd)
830
894
  except OSError as error:
831
895
  raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
832
896
  for name in names:
@@ -862,7 +926,7 @@ def iter_from_dir_fd(
862
926
  raise DetectError(
863
927
  f"filesystem evidence changed while traversing: {relative}"
864
928
  )
865
- if is_verified_skill_bundle_at(relative, child):
929
+ if is_verified_skill_bundle_at(relative, child, root):
866
930
  continue
867
931
  yield from iter_from_dir_fd(child, relative, root)
868
932
  finally:
@@ -1227,10 +1291,17 @@ def project_slug(root: Path) -> str:
1227
1291
  return slug or "project"
1228
1292
 
1229
1293
 
1230
- def filled_state_template(template: str, slug: str, phase: str) -> str:
1294
+ def filled_state_template(
1295
+ template: str, slug: str, phase: str, default_branch: str = "main"
1296
+ ) -> str:
1231
1297
  if "<slug>" not in template:
1232
1298
  raise DetectError("state template missing slug placeholder")
1233
1299
  text = template.replace("<slug>", slug)
1300
+ text, count = re.subn(
1301
+ r"(?m)^default_branch: main\b", lambda _: f"default_branch: {default_branch}", text, count=1
1302
+ )
1303
+ if count != 1:
1304
+ raise DetectError("state template missing default_branch: main line")
1234
1305
  text, count = re.subn(r"(?m)^phase: define\b", f"phase: {phase}", text, count=1)
1235
1306
  if count != 1:
1236
1307
  raise DetectError("state template missing phase: define line")
@@ -1302,7 +1373,7 @@ def close_file_descriptors(
1302
1373
 
1303
1374
  def project_entries(project_fd: int, project: Path) -> set:
1304
1375
  """Names in .project without ignored OS junk (Finder may add .DS_Store at any time)."""
1305
- entries = set(os.listdir(project_fd))
1376
+ entries = set(listdir_anchored(project_fd))
1306
1377
  for name in entries & _common.OS_JUNK_NAMES:
1307
1378
  try:
1308
1379
  status = os.stat(name, dir_fd=project_fd, follow_symlinks=False)
@@ -1413,12 +1484,12 @@ def write_state_anchored(
1413
1484
  follow_symlinks=False,
1414
1485
  )
1415
1486
  except FileNotFoundError as error:
1416
- if "STATE.md" in os.listdir(project_fd):
1487
+ if "STATE.md" in listdir_anchored(project_fd):
1417
1488
  raise DetectError("STATE.md already exists") from error
1418
1489
  raise DetectError("temporary STATE.md disappeared") from error
1419
1490
  if not os.path.samestat(created_status, named_temporary):
1420
1491
  raise DetectError("temporary STATE.md changed before writing")
1421
- if "STATE.md" in os.listdir(project_fd):
1492
+ if "STATE.md" in listdir_anchored(project_fd):
1422
1493
  raise DetectError("STATE.md already exists")
1423
1494
  os.ftruncate(state_fd, 0)
1424
1495
  write_all(state_fd, payload)
@@ -1653,6 +1724,167 @@ class _WindowsHandles:
1653
1724
  raise ctypes.WinError(ctypes.get_last_error())
1654
1725
 
1655
1726
 
1727
+ _WINDOWS_HANDLES: Optional[_WindowsHandles] = None
1728
+
1729
+
1730
+ def get_windows_handles() -> _WindowsHandles:
1731
+ global _WINDOWS_HANDLES
1732
+ if _WINDOWS_HANDLES is None:
1733
+ _WINDOWS_HANDLES = _WindowsHandles()
1734
+ return _WINDOWS_HANDLES
1735
+
1736
+
1737
+ def _windows_missing_ok(error: OSError) -> bool:
1738
+ return getattr(error, "winerror", None) in {2, 3}
1739
+
1740
+
1741
+ def read_windows_anchored_evidence(
1742
+ relative: Path,
1743
+ root: Path,
1744
+ *,
1745
+ missing_ok: bool,
1746
+ evidence_name: str,
1747
+ ) -> Optional[str]:
1748
+ win = get_windows_handles()
1749
+ descriptors: list[int] = []
1750
+ try:
1751
+ descriptors.append(win.open_root(root))
1752
+ opened_root = os.fstat(descriptors[-1])
1753
+ if not stat.S_ISDIR(opened_root.st_mode):
1754
+ raise DetectError(f"repo evidence is not a directory: {root}")
1755
+ for index, part in enumerate(relative.parts):
1756
+ current = root.joinpath(*relative.parts[: index + 1])
1757
+ final = index == len(relative.parts) - 1
1758
+ access = _GENERIC_READ if final else _DIRECTORY_ACCESS
1759
+ options = _FILE_NON_DIRECTORY_FILE if final else _FILE_DIRECTORY_FILE
1760
+ try:
1761
+ descriptor = win.open_relative(
1762
+ descriptors[-1],
1763
+ part,
1764
+ access,
1765
+ _PIN_SHARE,
1766
+ _FILE_OPEN,
1767
+ options,
1768
+ )
1769
+ except OSError as error:
1770
+ if missing_ok and _windows_missing_ok(error):
1771
+ return None
1772
+ raise DetectError(
1773
+ f"filesystem evidence disappeared: {root / relative}"
1774
+ ) from error
1775
+ descriptors.append(descriptor)
1776
+ actual = os.fstat(descriptor)
1777
+ if is_link_like(current, actual):
1778
+ raise DetectError(
1779
+ f"link-like {evidence_name} evidence is not allowed: {current}"
1780
+ )
1781
+ if final and not stat.S_ISREG(actual.st_mode):
1782
+ raise DetectError(
1783
+ f"{evidence_name} evidence is not a regular file: {current}"
1784
+ )
1785
+ if not final and not stat.S_ISDIR(actual.st_mode):
1786
+ raise DetectError(
1787
+ f"{evidence_name} evidence parent is not a directory: {current}"
1788
+ )
1789
+ with os.fdopen(descriptors.pop(), "rb") as stream:
1790
+ data = stream.read()
1791
+ except DetectError:
1792
+ raise
1793
+ except OSError as error:
1794
+ raise DetectError(
1795
+ f"cannot read {evidence_name} evidence: {root / relative}"
1796
+ ) from error
1797
+ finally:
1798
+ for descriptor in reversed(descriptors):
1799
+ os.close(descriptor)
1800
+ try:
1801
+ return data.decode("utf-8")
1802
+ except UnicodeDecodeError as error:
1803
+ raise DetectError(
1804
+ f"cannot read {evidence_name} evidence: {root / relative}"
1805
+ ) from error
1806
+
1807
+
1808
+ def iter_worktree_files_windows_anchored(root: Path) -> Iterable[str]:
1809
+ win = get_windows_handles()
1810
+ try:
1811
+ root_fd = win.open_root(root)
1812
+ except OSError as error:
1813
+ raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
1814
+ try:
1815
+ root_status = os.fstat(root_fd)
1816
+ if not stat.S_ISDIR(root_status.st_mode):
1817
+ raise DetectError(f"repo evidence is not a directory: {root}")
1818
+ yield from iter_from_windows_dir_fd(root_fd, "", root, win)
1819
+ finally:
1820
+ os.close(root_fd)
1821
+
1822
+
1823
+ def iter_from_windows_dir_fd(
1824
+ dir_fd: int, relative_dir: str, root: Path, win: _WindowsHandles
1825
+ ) -> Iterable[str]:
1826
+ scan_dir = root if not relative_dir else root.joinpath(*PurePosixPath(relative_dir).parts)
1827
+ try:
1828
+ # Windows CPython cannot listdir(dir_fd); paths come from the pinned walk.
1829
+ names = os.listdir(scan_dir)
1830
+ except OSError as error:
1831
+ raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
1832
+ for name in names:
1833
+ relative = f"{relative_dir}/{name}" if relative_dir else name
1834
+ if is_ignored(relative) or name == ".project":
1835
+ continue
1836
+ path = root.joinpath(*PurePosixPath(relative).parts)
1837
+ try:
1838
+ child_fd = win.open_relative(
1839
+ dir_fd,
1840
+ name,
1841
+ _DIRECTORY_ACCESS,
1842
+ _PIN_SHARE,
1843
+ _FILE_OPEN,
1844
+ _FILE_DIRECTORY_FILE,
1845
+ )
1846
+ except OSError:
1847
+ child_fd = None
1848
+ else:
1849
+ status = os.fstat(child_fd)
1850
+ if is_link_like(path, status):
1851
+ os.close(child_fd)
1852
+ continue
1853
+ if stat.S_ISDIR(status.st_mode):
1854
+ try:
1855
+ if is_verified_skill_bundle_at(relative, child_fd, root):
1856
+ continue
1857
+ yield from iter_from_windows_dir_fd(
1858
+ child_fd, relative, root, win
1859
+ )
1860
+ finally:
1861
+ os.close(child_fd)
1862
+ continue
1863
+ os.close(child_fd)
1864
+ try:
1865
+ file_fd = win.open_relative(
1866
+ dir_fd,
1867
+ name,
1868
+ _FILE_READ_ATTRIBUTES,
1869
+ _PIN_SHARE,
1870
+ _FILE_OPEN,
1871
+ _FILE_NON_DIRECTORY_FILE,
1872
+ )
1873
+ except OSError as error:
1874
+ raise DetectError(
1875
+ f"cannot inspect filesystem evidence: {relative}: {error}"
1876
+ ) from error
1877
+ try:
1878
+ status = os.fstat(file_fd)
1879
+ if is_link_like(path, status) or not stat.S_ISREG(status.st_mode):
1880
+ continue
1881
+ if is_fixed_managed_pipeline_artifact(relative):
1882
+ continue
1883
+ yield relative
1884
+ finally:
1885
+ os.close(file_fd)
1886
+
1887
+
1656
1888
  def windows_project_entries(project: Path) -> set:
1657
1889
  """project_entries for a .project held open without delete sharing."""
1658
1890
  entries = set(os.listdir(project))
@@ -1805,6 +2037,14 @@ def initialize(
1805
2037
  )
1806
2038
  if git.returncode != 0 or git.stdout.strip() != "true":
1807
2039
  return {**payload, "route": "setup-repository", "wrote_state": False}
2040
+ default_branch = _common.origin_default_branch(root)
2041
+ if not _common.valid_default_branch(default_branch):
2042
+ return {**payload, "wrote_state": False, "error": (
2043
+ f"origin default branch {default_branch!r} cannot be recorded in STATE.md: "
2044
+ "it is a GSD Path reserved name or it has a character that STATE frontmatter "
2045
+ "cannot hold. Rename the default branch, then run "
2046
+ "`git remote set-head origin --auto`."
2047
+ )}
1808
2048
  expected = "inspect" if payload["verdict"] == "brownfield" else "define"
1809
2049
  if phase is None:
1810
2050
  phase = expected
@@ -1818,7 +2058,7 @@ def initialize(
1818
2058
  return payload
1819
2059
  write_state_anchored(
1820
2060
  root,
1821
- filled_state_template(raw, project_slug(root), phase),
2061
+ filled_state_template(raw, project_slug(root), phase, default_branch),
1822
2062
  root_status,
1823
2063
  project_status,
1824
2064
  )
@@ -7,6 +7,7 @@ import json
7
7
  import os
8
8
  import shutil
9
9
  import sys
10
+ import traceback
10
11
 
11
12
  # Runtime helpers must not modify their immutable installation.
12
13
  sys.dont_write_bytecode = True
@@ -33,7 +34,7 @@ def _load_pipeline_modules():
33
34
  try:
34
35
  from scripts import archive_milestone, pipeline_state, _common
35
36
  return _common, archive_milestone, pipeline_state
36
- except ModuleNotFoundError as error:
37
+ except ImportError as error: # a foreign `scripts` package
37
38
  if error.name not in {
38
39
  "scripts",
39
40
  "scripts.archive_milestone",
@@ -41,6 +42,13 @@ def _load_pipeline_modules():
41
42
  "scripts._common",
42
43
  }:
43
44
  raise
45
+ # A plain ImportError raised while a `scripts` module loaded is not a
46
+ # foreign package. A missing module falls back, as before.
47
+ if not isinstance(error, ModuleNotFoundError) and any(
48
+ frame.f_globals.get("__name__", "").startswith("scripts.")
49
+ for frame, _ in traceback.walk_tb(error.__traceback__)
50
+ ):
51
+ raise
44
52
  shared_scripts = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
45
53
  sys.path.insert(0, str(shared_scripts))
46
54
  import archive_milestone