gsd-pi 2.76.0 → 2.77.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 (536) hide show
  1. package/README.md +45 -25
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/mcp-server.d.ts +7 -0
  4. package/dist/mcp-server.js +35 -1
  5. package/dist/onboarding.js +45 -0
  6. package/dist/resource-loader.d.ts +1 -1
  7. package/dist/resource-loader.js +2 -8
  8. package/dist/resources/agents/researcher.md +1 -1
  9. package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
  10. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
  11. package/dist/resources/extensions/gsd/auto/loop.js +9 -0
  12. package/dist/resources/extensions/gsd/auto/phases.js +104 -11
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
  14. package/dist/resources/extensions/gsd/auto/session.js +22 -1
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
  16. package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
  18. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  19. package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
  20. package/dist/resources/extensions/gsd/auto-start.js +58 -57
  21. package/dist/resources/extensions/gsd/auto-verification.js +33 -0
  22. package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
  23. package/dist/resources/extensions/gsd/auto.js +70 -28
  24. package/dist/resources/extensions/gsd/blocked-models.js +68 -0
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +93 -1
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
  27. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
  28. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +12 -0
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +84 -23
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  33. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  34. package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  36. package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
  37. package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
  38. package/dist/resources/extensions/gsd/db-writer.js +88 -16
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
  40. package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
  41. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
  42. package/dist/resources/extensions/gsd/error-classifier.js +31 -3
  43. package/dist/resources/extensions/gsd/exec-history.js +120 -0
  44. package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
  45. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  46. package/dist/resources/extensions/gsd/gsd-db.js +168 -23
  47. package/dist/resources/extensions/gsd/guided-flow.js +190 -1
  48. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  49. package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
  50. package/dist/resources/extensions/gsd/init-wizard.js +15 -1
  51. package/dist/resources/extensions/gsd/key-manager.js +28 -0
  52. package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
  53. package/dist/resources/extensions/gsd/memory-store.js +19 -0
  54. package/dist/resources/extensions/gsd/model-router.js +36 -3
  55. package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
  56. package/dist/resources/extensions/gsd/preferences-types.js +9 -0
  57. package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
  58. package/dist/resources/extensions/gsd/preferences.js +17 -17
  59. package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
  60. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  62. package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  63. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  65. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  66. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  67. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  68. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
  69. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  70. package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
  71. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  72. package/dist/resources/extensions/gsd/state.js +43 -4
  73. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  74. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  75. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
  76. package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
  77. package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
  79. package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
  80. package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
  81. package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  82. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  83. package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
  84. package/dist/resources/extensions/search-the-web/native-search.js +45 -13
  85. package/dist/resources/skills/api-design/SKILL.md +190 -0
  86. package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
  87. package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
  88. package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
  89. package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
  90. package/dist/resources/skills/forensics/SKILL.md +153 -0
  91. package/dist/resources/skills/grill-me/SKILL.md +93 -0
  92. package/dist/resources/skills/handoff/SKILL.md +121 -0
  93. package/dist/resources/skills/observability/SKILL.md +174 -0
  94. package/dist/resources/skills/security-review/SKILL.md +181 -0
  95. package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
  96. package/dist/resources/skills/tdd/SKILL.md +112 -0
  97. package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
  98. package/dist/resources/skills/write-docs/SKILL.md +82 -0
  99. package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
  100. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  101. package/dist/web/standalone/.next/BUILD_ID +1 -1
  102. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  103. package/dist/web/standalone/.next/build-manifest.json +2 -2
  104. package/dist/web/standalone/.next/required-server-files.json +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/index.html +1 -1
  122. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  129. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  130. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
  132. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  133. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  134. package/dist/web/standalone/server.js +1 -1
  135. package/dist/welcome-screen.js +6 -1
  136. package/dist/wizard.js +2 -0
  137. package/package.json +1 -1
  138. package/packages/daemon/package.json +2 -2
  139. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  140. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  141. package/packages/mcp-server/dist/remote-questions.js +732 -0
  142. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  143. package/packages/mcp-server/dist/server.d.ts +7 -0
  144. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  145. package/packages/mcp-server/dist/server.js +70 -8
  146. package/packages/mcp-server/dist/server.js.map +1 -1
  147. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  148. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  149. package/packages/mcp-server/dist/session-manager.js +49 -1
  150. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  151. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
  152. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  153. package/packages/mcp-server/dist/workflow-tools.js +163 -25
  154. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  155. package/packages/mcp-server/package.json +4 -3
  156. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  157. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  158. package/packages/mcp-server/src/remote-questions.ts +916 -0
  159. package/packages/mcp-server/src/server.ts +89 -14
  160. package/packages/mcp-server/src/session-manager.ts +43 -1
  161. package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
  162. package/packages/mcp-server/src/workflow-tools.ts +215 -43
  163. package/packages/mcp-server/tsconfig.test.json +19 -0
  164. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  165. package/packages/native/package.json +1 -1
  166. package/packages/pi-agent-core/dist/agent-loop.js +12 -0
  167. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  168. package/packages/pi-agent-core/dist/types.d.ts +30 -0
  169. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  170. package/packages/pi-agent-core/dist/types.js.map +1 -1
  171. package/packages/pi-agent-core/package.json +1 -1
  172. package/packages/pi-agent-core/src/agent-loop.ts +14 -0
  173. package/packages/pi-agent-core/src/types.ts +34 -0
  174. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  176. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  177. package/packages/pi-ai/dist/models/custom.js +41 -0
  178. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  179. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  180. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  181. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
  182. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
  184. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
  185. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  186. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  187. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  188. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  189. package/packages/pi-ai/dist/providers/anthropic.js +13 -4
  190. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  192. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  193. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  194. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  195. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  196. package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
  197. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  198. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  199. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  200. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  201. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  202. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
  203. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
  204. package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
  205. package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
  206. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
  207. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
  208. package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
  209. package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
  210. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  211. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +12 -2
  212. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  213. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
  214. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  215. package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  216. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
  217. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
  218. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
  219. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
  220. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
  221. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
  222. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  223. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
  224. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  225. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
  226. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
  227. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
  228. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
  229. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
  230. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
  231. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
  232. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
  233. package/packages/pi-ai/package.json +1 -1
  234. package/packages/pi-ai/src/models/custom.ts +42 -0
  235. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  236. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
  237. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  238. package/packages/pi-ai/src/providers/anthropic.ts +15 -4
  239. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  240. package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
  241. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  242. package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
  243. package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
  244. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
  245. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
  246. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
  247. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
  248. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
  249. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
  250. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
  251. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  252. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  253. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  255. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/agent-session.js +32 -2
  257. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  259. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/extensions/loader.js +4 -0
  263. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
  265. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
  267. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +205 -2
  269. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts +53 -0
  272. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
  273. package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
  274. package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
  275. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
  276. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
  277. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
  278. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
  279. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  282. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
  284. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
  286. package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
  288. package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
  292. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  295. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  296. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  297. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
  298. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
  300. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
  302. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
  304. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
  305. package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
  306. package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
  308. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
  310. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
  313. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
  315. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -0
  317. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  320. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  321. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  335. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  336. package/packages/pi-coding-agent/package.json +1 -1
  337. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  338. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
  339. package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
  340. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  341. package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
  342. package/packages/pi-coding-agent/src/core/extensions/types.ts +258 -0
  343. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
  344. package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
  345. package/packages/pi-coding-agent/src/core/index.ts +10 -0
  346. package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
  347. package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
  348. package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
  349. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  350. package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
  351. package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
  352. package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
  353. package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
  354. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
  355. package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
  356. package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
  357. package/packages/pi-coding-agent/src/index.ts +16 -0
  358. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
  359. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
  360. package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
  361. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/package.json +1 -1
  364. package/packages/rpc-client/package.json +1 -1
  365. package/pkg/package.json +1 -1
  366. package/scripts/link-workspace-packages.cjs +1 -0
  367. package/src/resources/agents/researcher.md +1 -1
  368. package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
  369. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
  370. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
  371. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
  372. package/src/resources/extensions/gsd/auto/loop.ts +9 -0
  373. package/src/resources/extensions/gsd/auto/phases.ts +131 -10
  374. package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
  375. package/src/resources/extensions/gsd/auto/session.ts +35 -2
  376. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
  377. package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
  378. package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
  379. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  380. package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
  381. package/src/resources/extensions/gsd/auto-start.ts +60 -68
  382. package/src/resources/extensions/gsd/auto-verification.ts +33 -0
  383. package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
  384. package/src/resources/extensions/gsd/auto.ts +73 -28
  385. package/src/resources/extensions/gsd/blocked-models.ts +98 -0
  386. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -1
  387. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
  388. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
  389. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
  390. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -0
  391. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
  392. package/src/resources/extensions/gsd/bootstrap/system-context.ts +89 -26
  393. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  394. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  395. package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
  396. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  397. package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
  398. package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
  399. package/src/resources/extensions/gsd/db-writer.ts +88 -17
  400. package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
  401. package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
  402. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
  403. package/src/resources/extensions/gsd/error-classifier.ts +36 -3
  404. package/src/resources/extensions/gsd/exec-history.ts +153 -0
  405. package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
  406. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  407. package/src/resources/extensions/gsd/gsd-db.ts +186 -23
  408. package/src/resources/extensions/gsd/guided-flow.ts +222 -1
  409. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  410. package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
  411. package/src/resources/extensions/gsd/init-wizard.ts +15 -1
  412. package/src/resources/extensions/gsd/journal.ts +2 -1
  413. package/src/resources/extensions/gsd/key-manager.ts +28 -0
  414. package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
  415. package/src/resources/extensions/gsd/memory-store.ts +26 -0
  416. package/src/resources/extensions/gsd/model-router.ts +42 -1
  417. package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
  418. package/src/resources/extensions/gsd/preferences-types.ts +46 -0
  419. package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
  420. package/src/resources/extensions/gsd/preferences.ts +17 -17
  421. package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
  422. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  423. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  424. package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  425. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
  426. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  427. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  428. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  429. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  430. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
  431. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  432. package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
  433. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  434. package/src/resources/extensions/gsd/state.ts +45 -4
  435. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
  436. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
  437. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
  439. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  440. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
  441. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
  442. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  443. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
  444. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
  445. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  446. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
  447. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
  448. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  449. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  450. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  451. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
  452. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  453. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
  454. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
  455. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
  456. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  457. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
  458. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  459. package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
  460. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
  461. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
  462. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
  463. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
  464. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
  465. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
  466. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
  467. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
  468. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
  469. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  470. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  471. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
  472. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
  473. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  474. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +37 -0
  475. package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
  476. package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
  477. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  478. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  479. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  480. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  481. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  482. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
  483. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  484. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
  485. package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
  486. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  487. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
  488. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +103 -4
  489. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  490. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  491. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  492. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  493. package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
  494. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  495. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  496. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  497. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  498. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  499. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
  500. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -3
  501. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  502. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  503. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  504. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  505. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  506. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
  507. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  508. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  509. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
  510. package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
  511. package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
  512. package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
  513. package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
  514. package/src/resources/extensions/gsd/workflow-logger.ts +4 -1
  515. package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
  516. package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  517. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  518. package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
  519. package/src/resources/extensions/search-the-web/native-search.ts +48 -12
  520. package/src/resources/skills/api-design/SKILL.md +190 -0
  521. package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
  522. package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
  523. package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
  524. package/src/resources/skills/design-an-interface/SKILL.md +102 -0
  525. package/src/resources/skills/forensics/SKILL.md +153 -0
  526. package/src/resources/skills/grill-me/SKILL.md +93 -0
  527. package/src/resources/skills/handoff/SKILL.md +121 -0
  528. package/src/resources/skills/observability/SKILL.md +174 -0
  529. package/src/resources/skills/security-review/SKILL.md +181 -0
  530. package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
  531. package/src/resources/skills/tdd/SKILL.md +112 -0
  532. package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
  533. package/src/resources/skills/write-docs/SKILL.md +82 -0
  534. package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
  535. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_buildManifest.js +0 -0
  536. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_ssgManifest.js +0 -0
@@ -3,12 +3,14 @@ import assert from 'node:assert/strict';
3
3
  import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
5
  import * as os from 'node:os';
6
+ import { createRequire } from 'node:module';
6
7
  import {
7
8
  openDatabase,
8
9
  closeDatabase,
9
10
  isDbAvailable,
10
11
  wasDbOpenAttempted,
11
12
  getDbProvider,
13
+ getDbStatus,
12
14
  insertDecision,
13
15
  getDecisionById,
14
16
  insertRequirement,
@@ -26,6 +28,8 @@ import {
26
28
  checkpointDatabase,
27
29
  } from '../gsd-db.ts';
28
30
 
31
+ const _require = createRequire(import.meta.url);
32
+
29
33
  // ═══════════════════════════════════════════════════════════════════════════
30
34
  // Helper: create a temp file path for file-backed DB tests
31
35
  // ═══════════════════════════════════════════════════════════════════════════
@@ -59,6 +63,20 @@ function withPlatform<T>(platform: NodeJS.Platform, fn: () => T): T {
59
63
  }
60
64
  }
61
65
 
66
+ function openRawSqliteForTest(dbPath: string): { exec(sql: string): void; close(): void } {
67
+ try {
68
+ const mod = _require('node:sqlite') as { DatabaseSync: new (path: string) => { exec(sql: string): void; close(): void } };
69
+ return new mod.DatabaseSync(dbPath);
70
+ } catch {
71
+ type SqliteCtor = new (path: string) => { exec(sql: string): void; close(): void };
72
+ const mod = _require('better-sqlite3') as
73
+ | SqliteCtor
74
+ | { default: SqliteCtor };
75
+ const DatabaseCtor: SqliteCtor = typeof mod === 'function' ? mod : mod.default;
76
+ return new DatabaseCtor(dbPath);
77
+ }
78
+ }
79
+
62
80
  // ═══════════════════════════════════════════════════════════════════════════
63
81
  // gsd-db tests
64
82
  // ═══════════════════════════════════════════════════════════════════════════
@@ -81,7 +99,7 @@ describe('gsd-db', () => {
81
99
  // Check schema_version table
82
100
  const adapter = _getAdapter()!;
83
101
  const version = adapter.prepare('SELECT MAX(version) as version FROM schema_version').get();
84
- assert.deepStrictEqual(version?.['version'], 20, 'schema version should be 20');
102
+ assert.deepStrictEqual(version?.['version'], 22, 'schema version should be 22');
85
103
 
86
104
  // Check tables exist by querying them
87
105
  const dRows = adapter.prepare('SELECT count(*) as cnt FROM decisions').get();
@@ -404,6 +422,348 @@ describe('gsd-db', () => {
404
422
  cleanup(dbPath);
405
423
  });
406
424
 
425
+ test('gsd-db: legacy DB missing memories.scope opens and bootstraps index columns', () => {
426
+ const dbPath = tempDbPath();
427
+ const legacyDb = openRawSqliteForTest(dbPath);
428
+ legacyDb.exec(`
429
+ CREATE TABLE schema_version (
430
+ version INTEGER NOT NULL,
431
+ applied_at TEXT NOT NULL
432
+ );
433
+ INSERT INTO schema_version(version, applied_at) VALUES (17, '2026-04-20T00:00:00.000Z');
434
+ CREATE TABLE memories (
435
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
436
+ id TEXT NOT NULL UNIQUE,
437
+ category TEXT NOT NULL,
438
+ content TEXT NOT NULL,
439
+ confidence REAL NOT NULL DEFAULT 0.8,
440
+ source_unit_type TEXT,
441
+ source_unit_id TEXT,
442
+ created_at TEXT NOT NULL,
443
+ updated_at TEXT NOT NULL,
444
+ superseded_by TEXT DEFAULT NULL,
445
+ hit_count INTEGER NOT NULL DEFAULT 0
446
+ );
447
+ INSERT INTO memories(id, category, content, created_at, updated_at)
448
+ VALUES ('legacy-memory', 'note', 'legacy row', '2026-04-20T00:00:00.000Z', '2026-04-20T00:00:00.000Z');
449
+ `);
450
+ legacyDb.close();
451
+
452
+ assert.equal(openDatabase(dbPath), true, 'openDatabase should succeed for legacy DB missing memories.scope');
453
+
454
+ const adapter = _getAdapter()!;
455
+ const columns = adapter.prepare('PRAGMA table_info(memories)').all();
456
+ const names = columns.map((row) => row['name']);
457
+ assert.ok(names.includes('scope'), 'memories.scope should be added during bootstrap');
458
+ assert.ok(names.includes('tags'), 'memories.tags should be added during bootstrap');
459
+
460
+ const row = adapter.prepare(`SELECT scope, tags FROM memories WHERE id = 'legacy-memory'`).get();
461
+ assert.equal(row?.['scope'], 'project', 'legacy rows should receive default scope');
462
+ assert.equal(row?.['tags'], '[]', 'legacy rows should receive default tags');
463
+
464
+ const index = adapter.prepare(
465
+ "SELECT name FROM sqlite_master WHERE type = 'index' AND name = 'idx_memories_scope'",
466
+ ).get();
467
+ assert.equal(index?.['name'], 'idx_memories_scope', 'scope index should be created after bootstrap columns are present');
468
+
469
+ cleanup(dbPath);
470
+ });
471
+
472
+ test('gsd-db: pre-v18 DB with memory_sources missing scope opens without crash (issue #4607)', () => {
473
+ // Regression: initSchema() ran CREATE INDEX on memories.scope and
474
+ // memory_sources.scope unconditionally, before the v18 migration adds those
475
+ // columns to existing rows. Databases at schema v17 that had a
476
+ // memory_sources table without the scope column crashed on open with
477
+ // "no such column: scope".
478
+ // The fix moves those index statements inside the v18 migration guard so
479
+ // they only execute after the column already exists.
480
+ const dbPath = tempDbPath();
481
+ const legacyDb = openRawSqliteForTest(dbPath);
482
+
483
+ // Build a realistic v17 schema: full table set that existed before v18,
484
+ // with memory_sources present but missing the scope column that v18 adds.
485
+ legacyDb.exec(`
486
+ CREATE TABLE schema_version (
487
+ version INTEGER NOT NULL,
488
+ applied_at TEXT NOT NULL
489
+ );
490
+ INSERT INTO schema_version(version, applied_at) VALUES (17, '2026-01-01T00:00:00.000Z');
491
+
492
+ CREATE TABLE decisions (
493
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
494
+ id TEXT NOT NULL UNIQUE,
495
+ when_context TEXT NOT NULL DEFAULT '',
496
+ scope TEXT NOT NULL DEFAULT '',
497
+ decision TEXT NOT NULL DEFAULT '',
498
+ choice TEXT NOT NULL DEFAULT '',
499
+ rationale TEXT NOT NULL DEFAULT '',
500
+ revisable TEXT NOT NULL DEFAULT '',
501
+ made_by TEXT NOT NULL DEFAULT 'agent',
502
+ superseded_by TEXT DEFAULT NULL
503
+ );
504
+
505
+ CREATE TABLE requirements (
506
+ id TEXT PRIMARY KEY,
507
+ class TEXT NOT NULL DEFAULT '',
508
+ status TEXT NOT NULL DEFAULT '',
509
+ description TEXT NOT NULL DEFAULT '',
510
+ why TEXT NOT NULL DEFAULT '',
511
+ source TEXT NOT NULL DEFAULT '',
512
+ primary_owner TEXT NOT NULL DEFAULT '',
513
+ supporting_slices TEXT NOT NULL DEFAULT '',
514
+ validation TEXT NOT NULL DEFAULT '',
515
+ notes TEXT NOT NULL DEFAULT '',
516
+ full_content TEXT NOT NULL DEFAULT '',
517
+ superseded_by TEXT DEFAULT NULL
518
+ );
519
+
520
+ CREATE TABLE memories (
521
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
522
+ id TEXT NOT NULL UNIQUE,
523
+ category TEXT NOT NULL,
524
+ content TEXT NOT NULL,
525
+ confidence REAL NOT NULL DEFAULT 0.8,
526
+ source_unit_type TEXT,
527
+ source_unit_id TEXT,
528
+ created_at TEXT NOT NULL,
529
+ updated_at TEXT NOT NULL,
530
+ superseded_by TEXT DEFAULT NULL,
531
+ hit_count INTEGER NOT NULL DEFAULT 0
532
+ );
533
+
534
+ CREATE TABLE memory_processed_units (
535
+ unit_key TEXT PRIMARY KEY,
536
+ activity_file TEXT,
537
+ processed_at TEXT NOT NULL
538
+ );
539
+
540
+ -- memory_sources existed before v18 but lacked the scope column
541
+ CREATE TABLE memory_sources (
542
+ id TEXT PRIMARY KEY,
543
+ kind TEXT NOT NULL,
544
+ uri TEXT,
545
+ title TEXT,
546
+ content TEXT NOT NULL,
547
+ content_hash TEXT NOT NULL UNIQUE,
548
+ imported_at TEXT NOT NULL
549
+ );
550
+
551
+ CREATE TABLE milestones (
552
+ id TEXT PRIMARY KEY,
553
+ title TEXT NOT NULL DEFAULT '',
554
+ status TEXT NOT NULL DEFAULT 'active',
555
+ depends_on TEXT NOT NULL DEFAULT '[]',
556
+ created_at TEXT NOT NULL DEFAULT '',
557
+ completed_at TEXT DEFAULT NULL,
558
+ vision TEXT NOT NULL DEFAULT '',
559
+ success_criteria TEXT NOT NULL DEFAULT '[]',
560
+ key_risks TEXT NOT NULL DEFAULT '[]',
561
+ proof_strategy TEXT NOT NULL DEFAULT '[]',
562
+ verification_contract TEXT NOT NULL DEFAULT '',
563
+ verification_integration TEXT NOT NULL DEFAULT '',
564
+ verification_operational TEXT NOT NULL DEFAULT '',
565
+ verification_uat TEXT NOT NULL DEFAULT '',
566
+ definition_of_done TEXT NOT NULL DEFAULT '[]',
567
+ requirement_coverage TEXT NOT NULL DEFAULT '',
568
+ boundary_map_markdown TEXT NOT NULL DEFAULT ''
569
+ );
570
+
571
+ CREATE TABLE slices (
572
+ milestone_id TEXT NOT NULL,
573
+ id TEXT NOT NULL,
574
+ title TEXT NOT NULL DEFAULT '',
575
+ status TEXT NOT NULL DEFAULT 'pending',
576
+ risk TEXT NOT NULL DEFAULT 'medium',
577
+ depends TEXT NOT NULL DEFAULT '[]',
578
+ demo TEXT NOT NULL DEFAULT '',
579
+ created_at TEXT NOT NULL DEFAULT '',
580
+ completed_at TEXT DEFAULT NULL,
581
+ full_summary_md TEXT NOT NULL DEFAULT '',
582
+ full_uat_md TEXT NOT NULL DEFAULT '',
583
+ goal TEXT NOT NULL DEFAULT '',
584
+ success_criteria TEXT NOT NULL DEFAULT '',
585
+ proof_level TEXT NOT NULL DEFAULT '',
586
+ integration_closure TEXT NOT NULL DEFAULT '',
587
+ observability_impact TEXT NOT NULL DEFAULT '',
588
+ sequence INTEGER DEFAULT 0,
589
+ PRIMARY KEY (milestone_id, id)
590
+ );
591
+
592
+ CREATE TABLE tasks (
593
+ milestone_id TEXT NOT NULL,
594
+ slice_id TEXT NOT NULL,
595
+ id TEXT NOT NULL,
596
+ title TEXT NOT NULL DEFAULT '',
597
+ status TEXT NOT NULL DEFAULT 'pending',
598
+ one_liner TEXT NOT NULL DEFAULT '',
599
+ narrative TEXT NOT NULL DEFAULT '',
600
+ verification_result TEXT NOT NULL DEFAULT '',
601
+ duration TEXT NOT NULL DEFAULT '',
602
+ completed_at TEXT DEFAULT NULL,
603
+ blocker_discovered INTEGER DEFAULT 0,
604
+ deviations TEXT NOT NULL DEFAULT '',
605
+ known_issues TEXT NOT NULL DEFAULT '',
606
+ key_files TEXT NOT NULL DEFAULT '[]',
607
+ key_decisions TEXT NOT NULL DEFAULT '[]',
608
+ full_summary_md TEXT NOT NULL DEFAULT '',
609
+ description TEXT NOT NULL DEFAULT '',
610
+ estimate TEXT NOT NULL DEFAULT '',
611
+ files TEXT NOT NULL DEFAULT '[]',
612
+ verify TEXT NOT NULL DEFAULT '',
613
+ inputs TEXT NOT NULL DEFAULT '[]',
614
+ expected_output TEXT NOT NULL DEFAULT '[]',
615
+ observability_impact TEXT NOT NULL DEFAULT '',
616
+ full_plan_md TEXT NOT NULL DEFAULT '',
617
+ sequence INTEGER DEFAULT 0,
618
+ blocker_source TEXT NOT NULL DEFAULT '',
619
+ escalation_pending INTEGER NOT NULL DEFAULT 0,
620
+ escalation_awaiting_review INTEGER NOT NULL DEFAULT 0,
621
+ escalation_artifact_path TEXT DEFAULT NULL,
622
+ escalation_override_applied_at TEXT DEFAULT NULL,
623
+ PRIMARY KEY (milestone_id, slice_id, id)
624
+ );
625
+
626
+ CREATE TABLE replan_history (
627
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
628
+ milestone_id TEXT NOT NULL DEFAULT '',
629
+ slice_id TEXT DEFAULT NULL,
630
+ task_id TEXT DEFAULT NULL,
631
+ summary TEXT NOT NULL DEFAULT '',
632
+ previous_artifact_path TEXT DEFAULT NULL,
633
+ replacement_artifact_path TEXT DEFAULT NULL,
634
+ full_content TEXT NOT NULL DEFAULT '',
635
+ created_at TEXT NOT NULL DEFAULT ''
636
+ );
637
+
638
+ CREATE TABLE quality_gates (
639
+ milestone_id TEXT NOT NULL,
640
+ slice_id TEXT NOT NULL,
641
+ gate_id TEXT NOT NULL,
642
+ scope TEXT NOT NULL DEFAULT 'slice',
643
+ task_id TEXT NOT NULL DEFAULT '',
644
+ status TEXT NOT NULL DEFAULT 'pending',
645
+ verdict TEXT NOT NULL DEFAULT '',
646
+ rationale TEXT NOT NULL DEFAULT '',
647
+ findings TEXT NOT NULL DEFAULT '',
648
+ evaluated_at TEXT DEFAULT NULL,
649
+ PRIMARY KEY (milestone_id, slice_id, gate_id, task_id)
650
+ );
651
+
652
+ CREATE TABLE verification_evidence (
653
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
654
+ task_id TEXT NOT NULL DEFAULT '',
655
+ slice_id TEXT NOT NULL DEFAULT '',
656
+ milestone_id TEXT NOT NULL DEFAULT '',
657
+ command TEXT NOT NULL DEFAULT '',
658
+ exit_code INTEGER DEFAULT 0,
659
+ verdict TEXT NOT NULL DEFAULT '',
660
+ duration_ms INTEGER DEFAULT 0,
661
+ created_at TEXT NOT NULL DEFAULT ''
662
+ );
663
+
664
+ CREATE TABLE slice_dependencies (
665
+ milestone_id TEXT NOT NULL,
666
+ slice_id TEXT NOT NULL,
667
+ depends_on_slice_id TEXT NOT NULL,
668
+ PRIMARY KEY (milestone_id, slice_id, depends_on_slice_id)
669
+ );
670
+
671
+ CREATE TABLE gate_runs (
672
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
673
+ trace_id TEXT NOT NULL,
674
+ turn_id TEXT NOT NULL,
675
+ gate_id TEXT NOT NULL,
676
+ gate_type TEXT NOT NULL DEFAULT '',
677
+ unit_type TEXT DEFAULT NULL,
678
+ unit_id TEXT DEFAULT NULL,
679
+ milestone_id TEXT DEFAULT NULL,
680
+ slice_id TEXT DEFAULT NULL,
681
+ task_id TEXT DEFAULT NULL,
682
+ outcome TEXT NOT NULL DEFAULT 'pass',
683
+ failure_class TEXT NOT NULL DEFAULT 'none',
684
+ rationale TEXT NOT NULL DEFAULT '',
685
+ findings TEXT NOT NULL DEFAULT '',
686
+ attempt INTEGER NOT NULL DEFAULT 1,
687
+ max_attempts INTEGER NOT NULL DEFAULT 1,
688
+ retryable INTEGER NOT NULL DEFAULT 0,
689
+ evaluated_at TEXT NOT NULL DEFAULT ''
690
+ );
691
+
692
+ CREATE TABLE turn_git_transactions (
693
+ trace_id TEXT NOT NULL,
694
+ turn_id TEXT NOT NULL,
695
+ unit_type TEXT DEFAULT NULL,
696
+ unit_id TEXT DEFAULT NULL,
697
+ stage TEXT NOT NULL DEFAULT 'turn-start',
698
+ action TEXT NOT NULL DEFAULT 'status-only',
699
+ push INTEGER NOT NULL DEFAULT 0,
700
+ status TEXT NOT NULL DEFAULT 'ok',
701
+ error TEXT DEFAULT NULL,
702
+ metadata_json TEXT NOT NULL DEFAULT '{}',
703
+ updated_at TEXT NOT NULL DEFAULT '',
704
+ PRIMARY KEY (trace_id, turn_id, stage)
705
+ );
706
+
707
+ CREATE TABLE audit_events (
708
+ event_id TEXT PRIMARY KEY,
709
+ trace_id TEXT NOT NULL,
710
+ turn_id TEXT DEFAULT NULL,
711
+ caused_by TEXT DEFAULT NULL,
712
+ category TEXT NOT NULL,
713
+ type TEXT NOT NULL,
714
+ ts TEXT NOT NULL,
715
+ payload_json TEXT NOT NULL DEFAULT '{}'
716
+ );
717
+
718
+ CREATE TABLE audit_turn_index (
719
+ trace_id TEXT NOT NULL,
720
+ turn_id TEXT NOT NULL,
721
+ first_ts TEXT NOT NULL,
722
+ last_ts TEXT NOT NULL,
723
+ event_count INTEGER NOT NULL DEFAULT 0,
724
+ PRIMARY KEY (trace_id, turn_id)
725
+ );
726
+
727
+ CREATE INDEX idx_memories_active ON memories(superseded_by);
728
+ CREATE INDEX idx_tasks_active ON tasks(milestone_id, slice_id, status);
729
+ CREATE INDEX idx_slices_active ON slices(milestone_id, status);
730
+ CREATE INDEX idx_milestones_status ON milestones(status);
731
+ CREATE INDEX idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status);
732
+ CREATE INDEX idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id);
733
+ CREATE INDEX idx_slice_deps_target ON slice_dependencies(milestone_id, depends_on_slice_id);
734
+ CREATE INDEX idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending);
735
+ `);
736
+ legacyDb.close();
737
+
738
+ // This must not throw — before the fix, initSchema() crashed with
739
+ // "no such column: scope" when it tried to CREATE INDEX on memory_sources.scope
740
+ // before the v18 migration had added that column.
741
+ assert.doesNotThrow(
742
+ () => openDatabase(dbPath),
743
+ 'openDatabase must not throw on a v17 DB where memory_sources lacks scope',
744
+ );
745
+
746
+ const adapter = _getAdapter()!;
747
+
748
+ // After open+migrate, memories.scope must exist
749
+ const memCols = adapter.prepare('PRAGMA table_info(memories)').all().map((r) => r['name']);
750
+ assert.ok(memCols.includes('scope'), 'memories.scope must be present after migration');
751
+
752
+ // idx_memories_scope must be created by the v18 migration
753
+ const scopeIdx = adapter
754
+ .prepare("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_memories_scope'")
755
+ .get();
756
+ assert.ok(scopeIdx, 'idx_memories_scope must exist after open on v17 DB');
757
+
758
+ // idx_memory_sources_scope must be created by the v18 migration
759
+ const srcScopeIdx = adapter
760
+ .prepare("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_memory_sources_scope'")
761
+ .get();
762
+ assert.ok(srcScopeIdx, 'idx_memory_sources_scope must exist after open on v17 DB');
763
+
764
+ cleanup(dbPath);
765
+ });
766
+
407
767
  test('gsd-db: rowToTask tolerates legacy comma-separated task arrays', () => {
408
768
  openDatabase(':memory:');
409
769
 
@@ -561,6 +921,92 @@ describe('gsd-db', () => {
561
921
  });
562
922
  });
563
923
 
924
+ // ─── getDbStatus ───────────────────────────────────────────────────────────
925
+
926
+ describe('getDbStatus', () => {
927
+ test('getDbStatus: initial state before any open', () => {
928
+ closeDatabase();
929
+ const status = getDbStatus();
930
+ assert.strictEqual(status.available, false, 'available false before open');
931
+ assert.strictEqual(status.attempted, false, 'attempted false before open');
932
+ assert.strictEqual(status.lastError, null, 'lastError null before open');
933
+ assert.strictEqual(status.lastPhase, null, 'lastPhase null before open');
934
+ });
935
+
936
+ test('getDbStatus: available after successful open', () => {
937
+ openDatabase(':memory:');
938
+ const status = getDbStatus();
939
+ assert.strictEqual(status.available, true, 'available true after open');
940
+ assert.strictEqual(status.attempted, true, 'attempted true after open');
941
+ assert.ok(status.provider !== null, 'provider set after open');
942
+ assert.strictEqual(status.lastError, null, 'lastError null on success');
943
+ assert.strictEqual(status.lastPhase, null, 'lastPhase null on success');
944
+ closeDatabase();
945
+ });
946
+
947
+ test('getDbStatus: resets lastError/lastPhase after closeDatabase', () => {
948
+ // Simulate a failed open to set error state
949
+ const corruptPath = path.join(os.tmpdir(), `gsd-corrupt-${Date.now()}.db`);
950
+ fs.writeFileSync(corruptPath, Buffer.from('not a sqlite file at all!!!!!'));
951
+ try {
952
+ openDatabase(corruptPath);
953
+ } catch {
954
+ // expected
955
+ }
956
+ assert.ok(getDbStatus().lastError !== null, 'lastError set after failed open');
957
+
958
+ // closeDatabase should clear it even though no DB was opened
959
+ closeDatabase();
960
+ const status = getDbStatus();
961
+ assert.strictEqual(status.lastError, null, 'lastError cleared by closeDatabase');
962
+ assert.strictEqual(status.lastPhase, null, 'lastPhase cleared by closeDatabase');
963
+ assert.strictEqual(status.attempted, false, 'attempted reset by closeDatabase');
964
+ fs.unlinkSync(corruptPath);
965
+ });
966
+
967
+ test('getDbStatus: captures open-phase error on corrupt file', () => {
968
+ closeDatabase();
969
+ const corruptPath = path.join(os.tmpdir(), `gsd-corrupt-${Date.now()}.db`);
970
+ fs.writeFileSync(corruptPath, Buffer.from('not a sqlite file at all!!!!!'));
971
+ try {
972
+ openDatabase(corruptPath);
973
+ } catch {
974
+ // expected — both providers should reject a non-SQLite file
975
+ }
976
+ const status = getDbStatus();
977
+ if (!status.available) {
978
+ // open failed (expected in most environments)
979
+ assert.strictEqual(status.attempted, true, 'attempted true after failed open');
980
+ // provider may reject at raw-open level ("open") or at SQL init level ("initSchema")
981
+ assert.ok(
982
+ status.lastPhase === 'open' || status.lastPhase === 'initSchema',
983
+ `lastPhase should be "open" or "initSchema", got: ${status.lastPhase}`,
984
+ );
985
+ assert.ok(status.lastError instanceof Error, 'lastError is an Error');
986
+ }
987
+ // If somehow it succeeded (unlikely with garbage content), that's also fine
988
+ closeDatabase();
989
+ try { fs.unlinkSync(corruptPath); } catch { /* best effort */ }
990
+ });
991
+
992
+ test('getDbStatus: error state resets on next successful open', () => {
993
+ closeDatabase();
994
+ const corruptPath = path.join(os.tmpdir(), `gsd-corrupt-${Date.now()}.db`);
995
+ fs.writeFileSync(corruptPath, Buffer.from('not a sqlite file at all!!!!!'));
996
+ try { openDatabase(corruptPath); } catch { /* expected */ }
997
+ assert.ok(!getDbStatus().available, 'DB unavailable after corrupt open');
998
+
999
+ // Now open a valid in-memory DB — error state should clear
1000
+ openDatabase(':memory:');
1001
+ const status = getDbStatus();
1002
+ assert.strictEqual(status.available, true, 'available after valid open');
1003
+ assert.strictEqual(status.lastError, null, 'lastError cleared on successful open');
1004
+ assert.strictEqual(status.lastPhase, null, 'lastPhase cleared on successful open');
1005
+ closeDatabase();
1006
+ try { fs.unlinkSync(corruptPath); } catch { /* best effort */ }
1007
+ });
1008
+ });
1009
+
564
1010
  // ─── Final Report ──────────────────────────────────────────────────────────
565
1011
 
566
1012
  });
@@ -178,6 +178,33 @@ test("init-wizard: multiple project files detected together", (t) => {
178
178
  }
179
179
  });
180
180
 
181
+ // ─── Git init + initial commit regression (#4530) ───────────────────────────
182
+
183
+ import { execFileSync } from "node:child_process";
184
+ import { nativeInit, nativeAddAll, nativeCommit } from "../native-git-bridge.ts";
185
+
186
+ test("init-wizard: nativeInit + nativeAddAll + nativeCommit produces a reachable HEAD (#4530)", (t) => {
187
+ // Regression: showProjectInit called nativeInit but never committed, leaving
188
+ // the branch unborn. git log and git worktree add both fail on zero-commit repos.
189
+ const dir = makeTempDir("git-init-commit");
190
+ t.after(() => { cleanup(dir); });
191
+
192
+ nativeInit(dir, "main");
193
+ execFileSync("git", ["config", "user.email", "test@test.com"], { cwd: dir });
194
+ execFileSync("git", ["config", "user.name", "Test"], { cwd: dir });
195
+ writeFileSync(join(dir, ".gitignore"), "*.log\n", "utf-8");
196
+
197
+ nativeAddAll(dir);
198
+ nativeCommit(dir, "chore: init project");
199
+
200
+ // git log must succeed (was: fatal: your current branch 'main' does not have any commits yet)
201
+ const subject = execFileSync("git", ["log", "-1", "--format=%s"], {
202
+ cwd: dir,
203
+ encoding: "utf-8",
204
+ }).trim();
205
+ assert.equal(subject, "chore: init project");
206
+ });
207
+
181
208
  test("init-wizard: v1 with both .planning/ and .gsd/ prioritizes v2", (t) => {
182
209
  const dir = makeTempDir("both-v1-v2");
183
210
  try {
@@ -43,6 +43,17 @@ Test
43
43
 
44
44
  ## Boundary Map
45
45
  _None_
46
+ `);
47
+ writeFileSync(join(milestoneDir, "M001-SUMMARY.md"), `---
48
+ id: M001
49
+ title: "Test Milestone"
50
+ status: complete
51
+ completed_at: 2026-04-18T00:00:00Z
52
+ ---
53
+
54
+ # M001: Test Milestone
55
+
56
+ Completed.
46
57
  `);
47
58
 
48
59
  run("git add -A", dir);
@@ -16,6 +16,7 @@ import { tmpdir } from "node:os";
16
16
  import { execSync } from "node:child_process";
17
17
 
18
18
  import { runGSDDoctor } from "../../doctor.ts";
19
+ import { closeDatabase, insertMilestone, insertSlice, openDatabase } from "../../gsd-db.ts";
19
20
  function run(cmd: string, cwd: string): string {
20
21
  return execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
21
22
  }
@@ -55,6 +56,17 @@ Test
55
56
 
56
57
  ## Boundary Map
57
58
  _None_
59
+ `);
60
+ writeFileSync(join(msDir, "M001-SUMMARY.md"), `---
61
+ id: M001
62
+ title: "Test Milestone"
63
+ status: complete
64
+ completed_at: 2026-04-18T00:00:00Z
65
+ ---
66
+
67
+ # M001: Test Milestone
68
+
69
+ Completed.
58
70
  `);
59
71
 
60
72
  // Commit .gsd files
@@ -64,6 +76,47 @@ _None_
64
76
  return dir;
65
77
  }
66
78
 
79
+ /** Create a repo whose slices are done but milestone closeout is still pending. */
80
+ function createRepoWithSlicesDoneButNoMilestoneSummary(): string {
81
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "doc-git-test-")));
82
+ run("git init", dir);
83
+ run("git config user.email test@test.com", dir);
84
+ run("git config user.name Test", dir);
85
+
86
+ writeFileSync(join(dir, "README.md"), "# test\n");
87
+ run("git add .", dir);
88
+ run("git commit -m init", dir);
89
+ run("git branch -M main", dir);
90
+
91
+ const msDir = join(dir, ".gsd", "milestones", "M001");
92
+ mkdirSync(msDir, { recursive: true });
93
+ writeFileSync(join(msDir, "ROADMAP.md"), `---
94
+ id: M001
95
+ title: "Completing Milestone"
96
+ ---
97
+
98
+ # M001: Completing Milestone
99
+
100
+ ## Vision
101
+ Test
102
+
103
+ ## Success Criteria
104
+ - Done
105
+
106
+ ## Slices
107
+ - [x] **S01: Test slice** \`risk:low\` \`depends:[]\`
108
+ > After this: done
109
+
110
+ ## Boundary Map
111
+ _None_
112
+ `);
113
+
114
+ run("git add -A", dir);
115
+ run("git commit -m \"add completing milestone\"", dir);
116
+
117
+ return dir;
118
+ }
119
+
67
120
  /** Write a .gsd/PREFERENCES.md with the given git isolation mode. */
68
121
  function writePreferencesFile(dir: string, isolation: "none" | "worktree" | "branch"): void {
69
122
  const gsdDir = join(dir, ".gsd");
@@ -299,6 +352,31 @@ describe('doctor-git', async () => {
299
352
  } else {
300
353
  }
301
354
 
355
+ // ─── Test 6b: completing-milestone worktree NOT flagged ────────────
356
+ if (process.platform !== "win32") {
357
+ test('completing-milestone worktree safety (DB-backed, no summary)', async () => {
358
+ const dir = createRepoWithSlicesDoneButNoMilestoneSummary();
359
+ cleanups.push(dir);
360
+
361
+ mkdirSync(join(dir, ".gsd", "worktrees"), { recursive: true });
362
+ run("git worktree add -b milestone/M001 .gsd/worktrees/M001", dir);
363
+
364
+ const dbPath = join(dir, ".gsd", "gsd.db");
365
+ assert.equal(openDatabase(dbPath), true, "opens gsd.db");
366
+ try {
367
+ insertMilestone({ id: "M001", title: "Completing Milestone", status: "active" });
368
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Test slice", status: "complete", risk: "low", depends: [] });
369
+
370
+ const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
371
+ const orphanIssues = detect.issues.filter(i => i.code === "orphaned_auto_worktree");
372
+ assert.deepStrictEqual(orphanIssues.length, 0, "completing milestone NOT flagged as orphaned");
373
+ } finally {
374
+ closeDatabase();
375
+ }
376
+ });
377
+ } else {
378
+ }
379
+
302
380
  // ─── Test 7: none-mode skips orphaned worktree check ───────────────
303
381
  // NOTE: loadEffectiveGSDPreferences() resolves PROJECT_PREFERENCES_PATH
304
382
  // at module load time from process.cwd(). We write the prefs file to
@@ -1235,6 +1235,7 @@ describe('git-service', async () => {
1235
1235
  const content = readFileSync(join(repo, ".gitignore"), "utf-8");
1236
1236
  const lines = content.split("\n").map(l => l.trim()).filter(l => l && !l.startsWith("#"));
1237
1237
  assert.ok(lines.includes(".gsd"), "ensureGitignore: .gitignore contains .gsd");
1238
+ assert.ok(lines.includes(".mcp.json"), "ensureGitignore: .gitignore contains .mcp.json");
1238
1239
 
1239
1240
  // Idempotent — calling again doesn't add duplicates
1240
1241
  const modified2 = ensureGitignore(repo);
@@ -107,6 +107,7 @@ test("ensureGitignore does NOT add .gsd when .gsd/ has tracked files (#1364)", (
107
107
  // Other baseline patterns should still be present
108
108
  assert.ok(lines.includes(".DS_Store"), "Expected .DS_Store in .gitignore");
109
109
  assert.ok(lines.includes("node_modules/"), "Expected node_modules/ in .gitignore");
110
+ assert.ok(lines.includes(".mcp.json"), "Expected .mcp.json in .gitignore");
110
111
  } finally {
111
112
  cleanup(dir);
112
113
  }