gsd-pi 2.29.0 → 2.30.0-dev.7e1bbce

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 (328) hide show
  1. package/README.md +24 -17
  2. package/dist/cli.js +51 -0
  3. package/dist/extension-registry.d.ts +63 -0
  4. package/dist/extension-registry.js +166 -0
  5. package/dist/headless.js +4 -0
  6. package/dist/help-text.js +35 -0
  7. package/dist/loader.js +10 -1
  8. package/dist/resource-loader.js +11 -1
  9. package/dist/resources/extensions/async-jobs/extension-manifest.json +13 -0
  10. package/dist/resources/extensions/bg-shell/extension-manifest.json +14 -0
  11. package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
  12. package/dist/resources/extensions/browser-tools/extension-manifest.json +37 -0
  13. package/dist/resources/extensions/context7/extension-manifest.json +12 -0
  14. package/dist/resources/extensions/google-search/extension-manifest.json +12 -0
  15. package/dist/resources/extensions/gsd/auto-dashboard.ts +31 -0
  16. package/dist/resources/extensions/gsd/auto-dispatch.ts +32 -3
  17. package/dist/resources/extensions/gsd/auto-post-unit.ts +45 -13
  18. package/dist/resources/extensions/gsd/auto-prompts.ts +40 -17
  19. package/dist/resources/extensions/gsd/auto-recovery.ts +18 -23
  20. package/dist/resources/extensions/gsd/auto-start.ts +18 -32
  21. package/dist/resources/extensions/gsd/auto-worktree.ts +21 -182
  22. package/dist/resources/extensions/gsd/auto.ts +2 -24
  23. package/dist/resources/extensions/gsd/captures.ts +4 -10
  24. package/dist/resources/extensions/gsd/commands-extensions.ts +328 -0
  25. package/dist/resources/extensions/gsd/commands-handlers.ts +22 -2
  26. package/dist/resources/extensions/gsd/commands-logs.ts +13 -14
  27. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
  28. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  29. package/dist/resources/extensions/gsd/commands.ts +108 -24
  30. package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  31. package/dist/resources/extensions/gsd/detection.ts +2 -1
  32. package/dist/resources/extensions/gsd/doctor-checks.ts +49 -1
  33. package/dist/resources/extensions/gsd/doctor-types.ts +3 -1
  34. package/dist/resources/extensions/gsd/extension-manifest.json +18 -0
  35. package/dist/resources/extensions/gsd/forensics.ts +2 -2
  36. package/dist/resources/extensions/gsd/git-service.ts +3 -2
  37. package/dist/resources/extensions/gsd/gitignore.ts +9 -63
  38. package/dist/resources/extensions/gsd/gsd-db.ts +1 -165
  39. package/dist/resources/extensions/gsd/guided-flow.ts +8 -5
  40. package/dist/resources/extensions/gsd/index.ts +16 -3
  41. package/dist/resources/extensions/gsd/json-persistence.ts +16 -1
  42. package/dist/resources/extensions/gsd/md-importer.ts +3 -2
  43. package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
  44. package/dist/resources/extensions/gsd/migrate/command.ts +3 -2
  45. package/dist/resources/extensions/gsd/migrate/writer.ts +2 -1
  46. package/dist/resources/extensions/gsd/migrate-external.ts +123 -0
  47. package/dist/resources/extensions/gsd/paths.ts +24 -2
  48. package/dist/resources/extensions/gsd/post-unit-hooks.ts +6 -5
  49. package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
  50. package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
  51. package/dist/resources/extensions/gsd/preferences.ts +10 -5
  52. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
  53. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
  55. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
  56. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  57. package/dist/resources/extensions/gsd/queue-order.ts +10 -11
  58. package/dist/resources/extensions/gsd/repo-identity.ts +148 -0
  59. package/dist/resources/extensions/gsd/resource-version.ts +99 -0
  60. package/dist/resources/extensions/gsd/roadmap-slices.ts +22 -7
  61. package/dist/resources/extensions/gsd/session-forensics.ts +4 -3
  62. package/dist/resources/extensions/gsd/session-lock.ts +53 -4
  63. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  64. package/dist/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
  65. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  66. package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
  67. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  68. package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
  69. package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
  70. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  71. package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
  72. package/dist/resources/extensions/gsd/tests/git-service.test.ts +10 -37
  73. package/dist/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
  74. package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  75. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  76. package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
  77. package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
  78. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  79. package/dist/resources/extensions/gsd/triage-resolution.ts +2 -1
  80. package/dist/resources/extensions/gsd/types.ts +2 -0
  81. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  82. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  83. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  84. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  85. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  86. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  87. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  88. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  89. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  90. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  91. package/dist/resources/extensions/gsd/worktree-command.ts +1 -11
  92. package/dist/resources/extensions/gsd/worktree-manager.ts +3 -2
  93. package/dist/resources/extensions/gsd/worktree.ts +42 -5
  94. package/dist/resources/extensions/mac-tools/extension-manifest.json +16 -0
  95. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  96. package/dist/resources/extensions/mcporter/extension-manifest.json +12 -0
  97. package/dist/resources/extensions/remote-questions/discord-adapter.ts +8 -19
  98. package/dist/resources/extensions/remote-questions/extension-manifest.json +11 -0
  99. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  100. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -17
  101. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
  102. package/dist/resources/extensions/search-the-web/extension-manifest.json +13 -0
  103. package/dist/resources/extensions/slash-commands/extension-manifest.json +11 -0
  104. package/dist/resources/extensions/subagent/extension-manifest.json +13 -0
  105. package/dist/resources/extensions/ttsr/extension-manifest.json +11 -0
  106. package/dist/resources/extensions/universal-config/extension-manifest.json +13 -0
  107. package/dist/resources/extensions/voice/extension-manifest.json +12 -0
  108. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  109. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  110. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  111. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  112. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  113. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  114. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  115. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  116. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  117. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  118. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  119. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  120. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  121. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  122. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  123. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  124. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  125. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  126. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  127. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  128. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  129. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  130. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  131. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  132. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  133. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  134. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  135. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  136. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  137. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  138. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  139. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  140. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  141. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  142. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  143. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  144. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  145. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  146. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  147. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  148. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  149. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  150. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  151. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  152. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  153. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  154. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  155. package/dist/resources/skills/react-best-practices/SKILL.md +1 -1
  156. package/dist/worktree-cli.d.ts +34 -0
  157. package/dist/worktree-cli.js +294 -0
  158. package/dist/worktree-name-gen.d.ts +7 -0
  159. package/dist/worktree-name-gen.js +44 -0
  160. package/package.json +1 -1
  161. package/packages/native/dist/native.d.ts +2 -0
  162. package/packages/native/dist/native.js +19 -5
  163. package/packages/native/src/native.ts +23 -9
  164. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
  166. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  167. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
  169. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  170. package/packages/pi-coding-agent/package.json +1 -1
  171. package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
  172. package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
  173. package/pkg/package.json +1 -1
  174. package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
  175. package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
  176. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  177. package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
  178. package/src/resources/extensions/context7/extension-manifest.json +12 -0
  179. package/src/resources/extensions/google-search/extension-manifest.json +12 -0
  180. package/src/resources/extensions/gsd/auto-dashboard.ts +31 -0
  181. package/src/resources/extensions/gsd/auto-dispatch.ts +32 -3
  182. package/src/resources/extensions/gsd/auto-post-unit.ts +45 -13
  183. package/src/resources/extensions/gsd/auto-prompts.ts +40 -17
  184. package/src/resources/extensions/gsd/auto-recovery.ts +18 -23
  185. package/src/resources/extensions/gsd/auto-start.ts +18 -32
  186. package/src/resources/extensions/gsd/auto-worktree.ts +21 -182
  187. package/src/resources/extensions/gsd/auto.ts +2 -24
  188. package/src/resources/extensions/gsd/captures.ts +4 -10
  189. package/src/resources/extensions/gsd/commands-extensions.ts +328 -0
  190. package/src/resources/extensions/gsd/commands-handlers.ts +22 -2
  191. package/src/resources/extensions/gsd/commands-logs.ts +13 -14
  192. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
  193. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  194. package/src/resources/extensions/gsd/commands.ts +108 -24
  195. package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  196. package/src/resources/extensions/gsd/detection.ts +2 -1
  197. package/src/resources/extensions/gsd/doctor-checks.ts +49 -1
  198. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  199. package/src/resources/extensions/gsd/extension-manifest.json +18 -0
  200. package/src/resources/extensions/gsd/forensics.ts +2 -2
  201. package/src/resources/extensions/gsd/git-service.ts +3 -2
  202. package/src/resources/extensions/gsd/gitignore.ts +9 -63
  203. package/src/resources/extensions/gsd/gsd-db.ts +1 -165
  204. package/src/resources/extensions/gsd/guided-flow.ts +8 -5
  205. package/src/resources/extensions/gsd/index.ts +16 -3
  206. package/src/resources/extensions/gsd/json-persistence.ts +16 -1
  207. package/src/resources/extensions/gsd/md-importer.ts +3 -2
  208. package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
  209. package/src/resources/extensions/gsd/migrate/command.ts +3 -2
  210. package/src/resources/extensions/gsd/migrate/writer.ts +2 -1
  211. package/src/resources/extensions/gsd/migrate-external.ts +123 -0
  212. package/src/resources/extensions/gsd/paths.ts +24 -2
  213. package/src/resources/extensions/gsd/post-unit-hooks.ts +6 -5
  214. package/src/resources/extensions/gsd/preferences-models.ts +7 -1
  215. package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
  216. package/src/resources/extensions/gsd/preferences.ts +10 -5
  217. package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
  218. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  219. package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
  220. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
  221. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  222. package/src/resources/extensions/gsd/queue-order.ts +10 -11
  223. package/src/resources/extensions/gsd/repo-identity.ts +148 -0
  224. package/src/resources/extensions/gsd/resource-version.ts +99 -0
  225. package/src/resources/extensions/gsd/roadmap-slices.ts +22 -7
  226. package/src/resources/extensions/gsd/session-forensics.ts +4 -3
  227. package/src/resources/extensions/gsd/session-lock.ts +53 -4
  228. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  229. package/src/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
  230. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  231. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
  232. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  233. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
  234. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
  235. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  236. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
  237. package/src/resources/extensions/gsd/tests/git-service.test.ts +10 -37
  238. package/src/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
  239. package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  240. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  241. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
  242. package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
  243. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  244. package/src/resources/extensions/gsd/triage-resolution.ts +2 -1
  245. package/src/resources/extensions/gsd/types.ts +2 -0
  246. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  247. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  248. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  249. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  250. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  251. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  252. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  253. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  254. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  255. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  256. package/src/resources/extensions/gsd/worktree-command.ts +1 -11
  257. package/src/resources/extensions/gsd/worktree-manager.ts +3 -2
  258. package/src/resources/extensions/gsd/worktree.ts +42 -5
  259. package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
  260. package/src/resources/extensions/mcp-client/index.ts +459 -0
  261. package/src/resources/extensions/mcporter/extension-manifest.json +12 -0
  262. package/src/resources/extensions/remote-questions/discord-adapter.ts +8 -19
  263. package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
  264. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  265. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -17
  266. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
  267. package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
  268. package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
  269. package/src/resources/extensions/subagent/extension-manifest.json +13 -0
  270. package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
  271. package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
  272. package/src/resources/extensions/voice/extension-manifest.json +12 -0
  273. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  274. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  275. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  276. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  277. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  278. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  279. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  280. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  281. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  282. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  283. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  284. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  285. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  286. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  287. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  288. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  289. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  290. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  291. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  292. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  293. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  294. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  295. package/src/resources/skills/create-skill/SKILL.md +184 -0
  296. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  297. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  298. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  299. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  300. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  301. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  302. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  303. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  304. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  305. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  306. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  307. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  308. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  309. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  310. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  311. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  312. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  313. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  314. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  315. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  316. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  317. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  318. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  319. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  320. package/src/resources/skills/react-best-practices/SKILL.md +1 -1
  321. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
  322. package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
  323. package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
  324. package/dist/resources/extensions/mcporter/index.ts +0 -525
  325. package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
  326. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
  327. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
  328. package/src/resources/extensions/mcporter/index.ts +0 -525
@@ -11,6 +11,7 @@ import type { GSDState } from "./types.js";
11
11
  import { getCurrentBranch } from "./worktree.js";
12
12
  import { getActiveHook } from "./post-unit-hooks.js";
13
13
  import { getLedger, getProjectTotals, formatCost, formatTokenCount, formatTierSavings } from "./metrics.js";
14
+ import { getHealthTrend, getConsecutiveErrorUnits } from "./doctor-proactive.js";
14
15
  import {
15
16
  resolveMilestoneFile,
16
17
  resolveSliceFile,
@@ -535,6 +536,31 @@ export function updateProgressWidget(
535
536
  * Build a compact string-array representation of the progress widget.
536
537
  * Used as a fallback when the factory-based widget cannot render (RPC mode).
537
538
  */
539
+ // ─── Model Health Indicator ───────────────────────────────────────────────────
540
+
541
+ /**
542
+ * Compute a traffic-light health indicator from observable signals.
543
+ * 🟢 progressing well — no errors, trend stable/improving
544
+ * 🟡 struggling — some errors or degrading trend
545
+ * 🔴 stuck — consecutive errors, likely needs attention
546
+ */
547
+ export function getModelHealthIndicator(): { emoji: string; label: string } {
548
+ const trend = getHealthTrend();
549
+ const consecutiveErrors = getConsecutiveErrorUnits();
550
+
551
+ if (consecutiveErrors >= 3) {
552
+ return { emoji: "🔴", label: "stuck" };
553
+ }
554
+ if (consecutiveErrors >= 1 || trend === "degrading") {
555
+ return { emoji: "🟡", label: "struggling" };
556
+ }
557
+ if (trend === "improving") {
558
+ return { emoji: "🟢", label: "progressing well" };
559
+ }
560
+ // stable or unknown
561
+ return { emoji: "🟢", label: "progressing" };
562
+ }
563
+
538
564
  function buildProgressTextLines(
539
565
  verb: string,
540
566
  phaseLabel: string,
@@ -583,6 +609,11 @@ function buildProgressTextLines(
583
609
  }
584
610
 
585
611
  if (next) lines.push(` Next: ${next}`);
612
+
613
+ // Model health indicator
614
+ const health = getModelHealthIndicator();
615
+ lines.push(` Health: ${health.emoji} ${health.label}`);
616
+
586
617
  lines.push(` ${widgetPwd}`);
587
618
 
588
619
  return lines;
@@ -12,7 +12,7 @@
12
12
  import type { GSDState } from "./types.js";
13
13
  import type { GSDPreferences } from "./preferences.js";
14
14
  import type { UatType } from "./files.js";
15
- import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
15
+ import { loadFile, extractUatType, loadActiveOverrides, parseRoadmap } from "./files.js";
16
16
  import {
17
17
  resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile,
18
18
  relSliceFile, buildMilestoneFileName,
@@ -123,11 +123,40 @@ const DISPATCH_RULES: DispatchRule[] = [
123
123
  };
124
124
  },
125
125
  },
126
+ {
127
+ name: "uat-verdict-gate (non-PASS blocks progression)",
128
+ match: async ({ mid, basePath, prefs }) => {
129
+ // Only applies when UAT dispatch is enabled
130
+ if (!prefs?.uat_dispatch) return null;
131
+
132
+ const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
133
+ const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
134
+ if (!roadmapContent) return null;
135
+
136
+ const roadmap = parseRoadmap(roadmapContent);
137
+ for (const slice of roadmap.slices.filter(s => s.done)) {
138
+ const resultFile = resolveSliceFile(basePath, mid, slice.id, "UAT-RESULT");
139
+ if (!resultFile) continue;
140
+ const content = await loadFile(resultFile);
141
+ if (!content) continue;
142
+ const verdictMatch = content.match(/verdict:\s*([\w-]+)/i);
143
+ const verdict = verdictMatch?.[1]?.toLowerCase();
144
+ if (verdict && verdict !== "pass" && verdict !== "passed") {
145
+ return {
146
+ action: "stop" as const,
147
+ reason: `UAT verdict for ${slice.id} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
148
+ level: "warning" as const,
149
+ };
150
+ }
151
+ }
152
+ return null;
153
+ },
154
+ },
126
155
  {
127
156
  name: "reassess-roadmap (post-completion)",
128
157
  match: async ({ state, mid, midTitle, basePath, prefs }) => {
129
- // Phase skip: skip reassess when preference or profile says so
130
- if (prefs?.phases?.skip_reassess) return null;
158
+ // Reassess is opt-in: only fire when explicitly enabled
159
+ if (!prefs?.phases?.reassess_after_slice) return null;
131
160
  const needsReassess = await checkNeedsReassessment(basePath, mid, state);
132
161
  if (!needsReassess) return null;
133
162
  return {
@@ -37,7 +37,6 @@ import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences } from "./pref
37
37
  import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
38
38
  import { COMPLETION_TRANSITION_CODES } from "./doctor-types.js";
39
39
  import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
40
- import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
41
40
  import { resetRewriteCircuitBreaker } from "./auto-dispatch.js";
42
41
  import { isDbAvailable } from "./gsd-db.js";
43
42
  import { consumeSignal } from "./session-status-io.js";
@@ -176,7 +175,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
176
175
  );
177
176
  try {
178
177
  const { formatDoctorIssuesForPrompt, formatDoctorReport } = await import("./doctor.js");
179
- const { dispatchDoctorHeal } = await import("./commands.js");
178
+ const { dispatchDoctorHeal } = await import("./commands-handlers.js");
180
179
  const actionable = report.issues.filter(i => i.severity === "error");
181
180
  const reportText = formatDoctorReport(report, { scope: doctorScope, includeWarnings: true });
182
181
  const structuredIssues = formatDoctorIssuesForPrompt(actionable);
@@ -202,23 +201,17 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
202
201
  }
203
202
  }
204
203
 
205
- // Prune dead bg-shell processes
204
+ // Prune dead bg-shell processes and kill non-persistent live ones.
205
+ // Without killing live processes between units, dev servers spawned during
206
+ // one task keep ports bound, causing conflicts in subsequent tasks (#1209).
206
207
  try {
207
- const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
208
+ const { pruneDeadProcesses, killSessionProcesses } = await import("../bg-shell/process-manager.js");
208
209
  pruneDeadProcesses();
210
+ killSessionProcesses();
209
211
  } catch {
210
212
  // Non-fatal
211
213
  }
212
214
 
213
- // Sync worktree state back to project root
214
- if (s.originalBasePath && s.originalBasePath !== s.basePath) {
215
- try {
216
- syncStateToProjectRoot(s.basePath, s.originalBasePath, s.currentMilestoneId);
217
- } catch {
218
- // Non-fatal
219
- }
220
- }
221
-
222
215
  // Rewrite-docs completion
223
216
  if (s.currentUnit.type === "rewrite-docs") {
224
217
  try {
@@ -328,6 +321,45 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
328
321
  }
329
322
  }
330
323
 
324
+ // ── Mechanical completion (ADR-003) ──
325
+ // After task execution, attempt mechanical slice and milestone completion
326
+ // instead of dispatching LLM sessions for complete-slice / validate-milestone.
327
+ if (s.currentUnit?.type === "execute-task" && !s.stepMode) {
328
+ try {
329
+ const [mid, sid] = s.currentUnit.id.split("/");
330
+ if (mid && sid) {
331
+ const state = await deriveState(s.basePath);
332
+ if (state.phase === "summarizing" && state.activeSlice?.id === sid) {
333
+ const { mechanicalSliceCompletion } = await import("./mechanical-completion.js");
334
+ const ok = await mechanicalSliceCompletion(s.basePath, mid, sid);
335
+ if (ok) {
336
+ invalidateAllCaches();
337
+ autoCommitCurrentBranch(s.basePath, "mechanical-completion", `${mid}/${sid}`);
338
+ ctx.ui.notify(`Mechanical completion: ${sid} summary + roadmap updated.`, "info");
339
+
340
+ // Re-derive state — check if milestone is now ready for validation
341
+ invalidateAllCaches();
342
+ const postSliceState = await deriveState(s.basePath);
343
+ if (postSliceState.phase === "validating-milestone" || postSliceState.phase === "completing-milestone") {
344
+ const { aggregateMilestoneVerification, generateMilestoneSummary } = await import("./mechanical-completion.js");
345
+ const validation = await aggregateMilestoneVerification(s.basePath, mid);
346
+ if (validation.verdict !== "failed") {
347
+ await generateMilestoneSummary(s.basePath, mid);
348
+ invalidateAllCaches();
349
+ autoCommitCurrentBranch(s.basePath, "mechanical-milestone-completion", mid);
350
+ ctx.ui.notify(`Mechanical completion: ${mid} validation + summary written.`, "info");
351
+ }
352
+ }
353
+ }
354
+ // If !ok, summarizing phase persists → dispatch rule fires as LLM fallback
355
+ }
356
+ }
357
+ } catch (err) {
358
+ process.stderr.write(`gsd-mechanical: completion failed: ${(err as Error).message}\n`);
359
+ // Non-fatal — fall through to normal dispatch
360
+ }
361
+ }
362
+
331
363
  // ── Post-unit hooks ──
332
364
  if (s.currentUnit && !s.stepMode) {
333
365
  const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
@@ -530,11 +530,21 @@ export async function checkNeedsRunUat(
530
530
  const uatContent = await loadFile(uatFile);
531
531
  if (!uatContent) return null;
532
532
 
533
- // If UAT result already exists, skip (idempotent)
533
+ // If UAT result already exists with a PASS verdict, skip (idempotent).
534
+ // Non-PASS verdicts (FAIL, surfaced-for-human-review) should block slice
535
+ // progression — return the slice for re-evaluation (#1231).
534
536
  const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
535
537
  if (uatResultFile) {
536
- const hasResult = !!(await loadFile(uatResultFile));
537
- if (hasResult) return null;
538
+ const resultContent = await loadFile(uatResultFile);
539
+ if (resultContent) {
540
+ const verdictMatch = resultContent.match(/verdict:\s*([\w-]+)/i);
541
+ const verdict = verdictMatch?.[1]?.toLowerCase();
542
+ if (verdict === "pass" || verdict === "passed") return null; // PASS — skip
543
+ // Non-PASS verdict exists — don't re-run UAT, but don't advance either.
544
+ // Return null here since the UAT already ran; the dispatch table's
545
+ // complete-slice rule should check the verdict before advancing.
546
+ // For now, returning the slice signals it still needs attention.
547
+ }
538
548
  }
539
549
 
540
550
  // Classify UAT type; unknown type → treat as human-experience (human review)
@@ -589,14 +599,18 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
589
599
  const { inlinePriorMilestoneSummary } = await import("./files.js");
590
600
  const priorSummaryInline = await inlinePriorMilestoneSummary(mid, base);
591
601
  if (priorSummaryInline) inlined.push(priorSummaryInline);
592
- if (inlineLevel !== "minimal") {
593
- const projectInline = await inlineProjectFromDb(base);
594
- if (projectInline) inlined.push(projectInline);
595
- const requirementsInline = await inlineRequirementsFromDb(base, undefined, inlineLevel);
596
- if (requirementsInline) inlined.push(requirementsInline);
597
- const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
598
- if (decisionsInline) inlined.push(decisionsInline);
599
- }
602
+ // Build source file paths for the planner to read on demand (reduces inlining)
603
+ const sourcePaths: string[] = [];
604
+ if (existsSync(resolveGsdRootFile(base, "PROJECT")))
605
+ sourcePaths.push(`- **Project**: \`${relGsdRootFile("PROJECT")}\``);
606
+ if (existsSync(resolveGsdRootFile(base, "REQUIREMENTS")))
607
+ sourcePaths.push(`- **Requirements**: \`${relGsdRootFile("REQUIREMENTS")}\``);
608
+ if (existsSync(resolveGsdRootFile(base, "DECISIONS")))
609
+ sourcePaths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
610
+ const sourceFilePaths = sourcePaths.length > 0
611
+ ? sourcePaths.join("\n")
612
+ : "_No project/requirements/decisions files found._";
613
+
600
614
  const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
601
615
  if (knowledgeInlinePM) inlined.push(knowledgeInlinePM);
602
616
  inlined.push(inlineTemplate("roadmap", "Roadmap"));
@@ -615,6 +629,7 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
615
629
 
616
630
  const outputRelPath = relMilestoneFile(base, mid, "ROADMAP");
617
631
  const secretsOutputPath = join(base, relMilestoneFile(base, mid, "SECRETS"));
632
+ const researchOutputRelPath = relMilestoneFile(base, mid, "RESEARCH");
618
633
  return loadPrompt("plan-milestone", {
619
634
  workingDirectory: base,
620
635
  milestoneId: mid, milestoneTitle: midTitle,
@@ -624,6 +639,9 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
624
639
  outputPath: join(base, outputRelPath),
625
640
  secretsOutputPath,
626
641
  inlinedContext,
642
+ sourceFilePaths,
643
+ researchOutputPath: join(base, researchOutputRelPath),
644
+ ...buildSkillDiscoveryVars(),
627
645
  });
628
646
  }
629
647
 
@@ -686,12 +704,16 @@ export async function buildPlanSlicePrompt(
686
704
  inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
687
705
  const researchInline = await inlineFileOptional(researchPath, researchRel, "Slice Research");
688
706
  if (researchInline) inlined.push(researchInline);
689
- if (inlineLevel !== "minimal") {
690
- const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
691
- if (decisionsInline) inlined.push(decisionsInline);
692
- const requirementsInline = await inlineRequirementsFromDb(base, sid, inlineLevel);
693
- if (requirementsInline) inlined.push(requirementsInline);
694
- }
707
+ // Build source file paths for the planner to read on demand (reduces inlining)
708
+ const sliceSourcePaths: string[] = [];
709
+ if (existsSync(resolveGsdRootFile(base, "REQUIREMENTS")))
710
+ sliceSourcePaths.push(`- **Requirements**: \`${relGsdRootFile("REQUIREMENTS")}\``);
711
+ if (existsSync(resolveGsdRootFile(base, "DECISIONS")))
712
+ sliceSourcePaths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
713
+ const sliceSourceFilePaths = sliceSourcePaths.length > 0
714
+ ? sliceSourcePaths.join("\n")
715
+ : "_No requirements/decisions files found._";
716
+
695
717
  const knowledgeInlinePS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
696
718
  if (knowledgeInlinePS) inlined.push(knowledgeInlinePS);
697
719
  inlined.push(inlineTemplate("plan", "Slice Plan"));
@@ -726,6 +748,7 @@ export async function buildPlanSlicePrompt(
726
748
  dependencySummaries: depContent,
727
749
  executorContextConstraints,
728
750
  commitInstruction,
751
+ sourceFilePaths: sliceSourceFilePaths,
729
752
  });
730
753
  }
731
754
 
@@ -35,10 +35,12 @@ import {
35
35
  resolveMilestoneFile,
36
36
  clearPathCache,
37
37
  resolveGsdRootFile,
38
+ gsdRoot,
38
39
  } from "./paths.js";
39
40
  import { isValidationTerminal } from "./state.js";
40
41
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
41
42
  import { atomicWriteSync } from "./atomic-write.js";
43
+ import { loadJsonFileOrNull } from "./json-persistence.js";
42
44
  import { dirname, join } from "node:path";
43
45
 
44
46
  // ─── Artifact Resolution & Verification ───────────────────────────────────────
@@ -354,20 +356,19 @@ export function skipExecuteTask(
354
356
 
355
357
  // ─── Disk-backed completed-unit helpers ───────────────────────────────────────
356
358
 
359
+ function isStringArray(data: unknown): data is string[] {
360
+ return Array.isArray(data) && data.every(item => typeof item === "string");
361
+ }
362
+
357
363
  /** Path to the persisted completed-unit keys file. */
358
364
  export function completedKeysPath(base: string): string {
359
- return join(base, ".gsd", "completed-units.json");
365
+ return join(gsdRoot(base), "completed-units.json");
360
366
  }
361
367
 
362
368
  /** Write a completed unit key to disk (read-modify-write append to set). */
363
369
  export function persistCompletedKey(base: string, key: string): void {
364
370
  const file = completedKeysPath(base);
365
- let keys: string[] = [];
366
- try {
367
- if (existsSync(file)) {
368
- keys = JSON.parse(readFileSync(file, "utf-8"));
369
- }
370
- } catch (e) { /* corrupt file — start fresh */ void e; }
371
+ const keys = loadJsonFileOrNull(file, isStringArray) ?? [];
371
372
  const keySet = new Set(keys);
372
373
  if (!keySet.has(key)) {
373
374
  keys.push(key);
@@ -378,27 +379,21 @@ export function persistCompletedKey(base: string, key: string): void {
378
379
  /** Remove a stale completed unit key from disk. */
379
380
  export function removePersistedKey(base: string, key: string): void {
380
381
  const file = completedKeysPath(base);
381
- try {
382
- if (existsSync(file)) {
383
- const keys: string[] = JSON.parse(readFileSync(file, "utf-8"));
384
- const filtered = keys.filter(k => k !== key);
385
- // Only write if the key was actually present
386
- if (filtered.length !== keys.length) {
387
- atomicWriteSync(file, JSON.stringify(filtered));
388
- }
389
- }
390
- } catch (e) { /* non-fatal: removePersistedKey failure */ void e; }
382
+ const keys = loadJsonFileOrNull(file, isStringArray);
383
+ if (!keys) return;
384
+ const filtered = keys.filter(k => k !== key);
385
+ if (filtered.length !== keys.length) {
386
+ atomicWriteSync(file, JSON.stringify(filtered));
387
+ }
391
388
  }
392
389
 
393
390
  /** Load all completed unit keys from disk into the in-memory set. */
394
391
  export function loadPersistedKeys(base: string, target: Set<string>): void {
395
392
  const file = completedKeysPath(base);
396
- try {
397
- if (existsSync(file)) {
398
- const keys: string[] = JSON.parse(readFileSync(file, "utf-8"));
399
- for (const k of keys) target.add(k);
400
- }
401
- } catch (e) { /* non-fatal: loadPersistedKeys failure */ void e; }
393
+ const keys = loadJsonFileOrNull(file, isStringArray);
394
+ if (keys) {
395
+ for (const k of keys) target.add(k);
396
+ }
402
397
  }
403
398
 
404
399
  // ─── Merge State Reconciliation ───────────────────────────────────────────────
@@ -16,6 +16,8 @@ import type {
16
16
  import { deriveState } from "./state.js";
17
17
  import { loadFile, getManifestStatus } from "./files.js";
18
18
  import { loadEffectiveGSDPreferences, resolveSkillDiscoveryMode, getIsolationMode } from "./preferences.js";
19
+ import { isInsideWorktree, ensureGsdSymlink } from "./repo-identity.js";
20
+ import { migrateToExternalState, recoverFailedMigration } from "./migrate-external.js";
19
21
  import { sendDesktopNotification } from "./notifications.js";
20
22
  import { sendRemoteNotification } from "../remote-questions/notify.js";
21
23
  import {
@@ -48,7 +50,7 @@ import {
48
50
  getAutoWorktreePath,
49
51
  isInAutoWorktree,
50
52
  } from "./auto-worktree.js";
51
- import { readResourceVersion } from "./auto-worktree-sync.js";
53
+ import { readResourceVersion } from "./resource-version.js";
52
54
  import { initMetrics, getLedger } from "./metrics.js";
53
55
  import { initRoutingHistory } from "./routing-history.js";
54
56
  import { restoreHookState, resetHookState, clearPersistedHookState } from "./post-unit-hooks.js";
@@ -61,7 +63,6 @@ import { debugLog, enableDebug, isDebugEnabled, getDebugLogPath } from "./debug-
61
63
  import type { AutoSession } from "./auto/session.js";
62
64
  import { existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from "node:fs";
63
65
  import { join } from "node:path";
64
- import { sep as pathSep } from "node:path";
65
66
 
66
67
  export interface BootstrapDeps {
67
68
  shouldUseWorktreeIsolation: () => boolean;
@@ -113,8 +114,17 @@ export async function bootstrapAutoSession(
113
114
  ensureGitignore(base, { commitDocs, manageGitignore });
114
115
  if (manageGitignore !== false) untrackRuntimeFiles(base);
115
116
 
117
+ // Migrate legacy in-project .gsd/ to external state directory
118
+ recoverFailedMigration(base);
119
+ const migration = migrateToExternalState(base);
120
+ if (migration.error) {
121
+ ctx.ui.notify(`External state migration warning: ${migration.error}`, "warning");
122
+ }
123
+ // Ensure symlink exists (handles fresh projects and post-migration)
124
+ ensureGsdSymlink(base);
125
+
116
126
  // Bootstrap .gsd/ if it doesn't exist
117
- const gsdDir = join(base, ".gsd");
127
+ const gsdDir = gsdRoot(base);
118
128
  if (!existsSync(gsdDir)) {
119
129
  mkdirSync(join(gsdDir, "milestones"), { recursive: true });
120
130
  if (commitDocs !== false) {
@@ -204,18 +214,6 @@ export async function bootstrapAutoSession(
204
214
 
205
215
  let state = await deriveState(base);
206
216
 
207
- // Stale worktree state recovery (#654)
208
- if (
209
- state.activeMilestone &&
210
- shouldUseWorktreeIsolation() &&
211
- !detectWorktreeName(base)
212
- ) {
213
- const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
214
- if (wtPath) {
215
- state = await deriveState(wtPath);
216
- }
217
- }
218
-
219
217
  // Milestone branch recovery (#601)
220
218
  let hasSurvivorBranch = false;
221
219
  if (
@@ -223,7 +221,7 @@ export async function bootstrapAutoSession(
223
221
  (state.phase === "pre-planning" || state.phase === "needs-discussion") &&
224
222
  shouldUseWorktreeIsolation() &&
225
223
  !detectWorktreeName(base) &&
226
- !base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)
224
+ !isInsideWorktree(base)
227
225
  ) {
228
226
  const milestoneBranch = `milestone/${state.activeMilestone.id}`;
229
227
  const { nativeBranchExists } = await import("./native-git-bridge.js");
@@ -333,14 +331,7 @@ export async function bootstrapAutoSession(
333
331
  // ── Auto-worktree setup ──
334
332
  s.originalBasePath = base;
335
333
 
336
- const isUnderGsdWorktrees = (p: string): boolean => {
337
- const marker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
338
- if (p.includes(marker)) return true;
339
- const worktreesSuffix = `${pathSep}.gsd${pathSep}worktrees`;
340
- return p.endsWith(worktreesSuffix);
341
- };
342
-
343
- if (s.currentMilestoneId && shouldUseWorktreeIsolation() && !detectWorktreeName(base) && !isUnderGsdWorktrees(base)) {
334
+ if (s.currentMilestoneId && shouldUseWorktreeIsolation() && !detectWorktreeName(base) && !isInsideWorktree(base)) {
344
335
  try {
345
336
  const existingWtPath = getAutoWorktreePath(base, s.currentMilestoneId);
346
337
  if (existingWtPath) {
@@ -355,11 +346,6 @@ export async function bootstrapAutoSession(
355
346
  ctx.ui.notify(`Created auto-worktree at ${wtPath}`, "info");
356
347
  }
357
348
  registerSigtermHandler(s.originalBasePath);
358
-
359
- // Load completed keys from BOTH locations
360
- if (s.basePath !== s.originalBasePath) {
361
- loadPersistedKeys(s.basePath, s.completedKeySet);
362
- }
363
349
  } catch (err) {
364
350
  ctx.ui.notify(
365
351
  `Auto-worktree setup failed: ${err instanceof Error ? err.message : String(err)}. Continuing in project root.`,
@@ -369,8 +355,8 @@ export async function bootstrapAutoSession(
369
355
  }
370
356
 
371
357
  // ── DB lifecycle ──
372
- const gsdDbPath = join(s.basePath, ".gsd", "gsd.db");
373
- const gsdDirPath = join(s.basePath, ".gsd");
358
+ const gsdDbPath = join(gsdRoot(s.basePath), "gsd.db");
359
+ const gsdDirPath = gsdRoot(s.basePath);
374
360
  if (existsSync(gsdDirPath) && !existsSync(gsdDbPath)) {
375
361
  const hasDecisions = existsSync(join(gsdDirPath, "DECISIONS.md"));
376
362
  const hasRequirements = existsSync(join(gsdDirPath, "REQUIREMENTS.md"));
@@ -476,7 +462,7 @@ export async function bootstrapAutoSession(
476
462
 
477
463
  // Pre-flight: validate milestone queue
478
464
  try {
479
- const msDir = join(base, ".gsd", "milestones");
465
+ const msDir = join(gsdRoot(base), "milestones");
480
466
  if (existsSync(msDir)) {
481
467
  const milestoneIds = readdirSync(msDir, { withFileTypes: true })
482
468
  .filter(d => d.isDirectory() && /^M\d{3}/.test(d.name))