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
@@ -0,0 +1,413 @@
1
+ /**
2
+ * Regression test for issue #4591: SCHEMA_VERSION gap — v21 migration
3
+ * existed but the constant was never bumped from 20.
4
+ *
5
+ * Root cause: PR #4496 added the v21 migration block but left
6
+ * SCHEMA_VERSION = 20. Because migrateSchema() short-circuits when
7
+ * currentVersion >= SCHEMA_VERSION, a DB already at v20 would skip the
8
+ * v21 block entirely, leaving memories without the structured_fields
9
+ * column and no v21 stamp in schema_version.
10
+ *
11
+ * This file verifies the correct behaviour: opening a v20 DB must result
12
+ * in the structured_fields column being present and schema_version
13
+ * recording version 21.
14
+ */
15
+
16
+ import test from 'node:test';
17
+ import assert from 'node:assert/strict';
18
+ import * as fs from 'node:fs';
19
+ import * as path from 'node:path';
20
+ import * as os from 'node:os';
21
+ import { createRequire } from 'node:module';
22
+
23
+ import {
24
+ openDatabase,
25
+ closeDatabase,
26
+ _getAdapter,
27
+ } from '../gsd-db.ts';
28
+
29
+ const _require = createRequire(import.meta.url);
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Helpers
33
+ // ---------------------------------------------------------------------------
34
+
35
+ function makeTmp(): string {
36
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-v21-'));
37
+ }
38
+
39
+ function cleanup(base: string): void {
40
+ try { closeDatabase(); } catch { /* noop */ }
41
+ try { fs.rmSync(base, { recursive: true, force: true }); } catch { /* noop */ }
42
+ }
43
+
44
+ /**
45
+ * Create a minimal SQLite DB stamped at schema v20.
46
+ *
47
+ * The memories table intentionally omits the structured_fields column —
48
+ * that column is what the v21 migration adds. All other tables that exist
49
+ * after the v20 migration are present so that migrateSchema() can run
50
+ * without tripping over missing prerequisites.
51
+ */
52
+ function createV20Db(dbPath: string): void {
53
+ const sqlite = _require('node:sqlite') as {
54
+ DatabaseSync: new (p: string) => {
55
+ exec(sql: string): void;
56
+ close(): void;
57
+ };
58
+ };
59
+ const db = new sqlite.DatabaseSync(dbPath);
60
+ db.exec('PRAGMA journal_mode=WAL');
61
+ db.exec(`
62
+ CREATE TABLE schema_version (
63
+ version INTEGER NOT NULL,
64
+ applied_at TEXT NOT NULL
65
+ );
66
+ INSERT INTO schema_version (version, applied_at) VALUES (20, '2026-01-01T00:00:00.000Z');
67
+
68
+ CREATE TABLE decisions (
69
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
70
+ id TEXT NOT NULL UNIQUE,
71
+ when_context TEXT NOT NULL DEFAULT '',
72
+ scope TEXT NOT NULL DEFAULT '',
73
+ decision TEXT NOT NULL DEFAULT '',
74
+ choice TEXT NOT NULL DEFAULT '',
75
+ rationale TEXT NOT NULL DEFAULT '',
76
+ revisable TEXT NOT NULL DEFAULT '',
77
+ made_by TEXT NOT NULL DEFAULT 'agent',
78
+ source TEXT NOT NULL DEFAULT 'discussion',
79
+ superseded_by TEXT DEFAULT NULL
80
+ );
81
+ CREATE TABLE requirements (
82
+ id TEXT PRIMARY KEY,
83
+ class TEXT NOT NULL DEFAULT '',
84
+ status TEXT NOT NULL DEFAULT '',
85
+ description TEXT NOT NULL DEFAULT '',
86
+ why TEXT NOT NULL DEFAULT '',
87
+ source TEXT NOT NULL DEFAULT '',
88
+ primary_owner TEXT NOT NULL DEFAULT '',
89
+ supporting_slices TEXT NOT NULL DEFAULT '',
90
+ validation TEXT NOT NULL DEFAULT '',
91
+ notes TEXT NOT NULL DEFAULT '',
92
+ full_content TEXT NOT NULL DEFAULT '',
93
+ superseded_by TEXT DEFAULT NULL
94
+ );
95
+ CREATE TABLE artifacts (
96
+ path TEXT PRIMARY KEY,
97
+ artifact_type TEXT NOT NULL DEFAULT '',
98
+ milestone_id TEXT DEFAULT NULL,
99
+ slice_id TEXT DEFAULT NULL,
100
+ task_id TEXT DEFAULT NULL,
101
+ full_content TEXT NOT NULL DEFAULT '',
102
+ imported_at TEXT NOT NULL DEFAULT ''
103
+ );
104
+
105
+ CREATE TABLE memories (
106
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
107
+ id TEXT NOT NULL UNIQUE,
108
+ category TEXT NOT NULL,
109
+ content TEXT NOT NULL,
110
+ confidence REAL NOT NULL DEFAULT 0.8,
111
+ source_unit_type TEXT,
112
+ source_unit_id TEXT,
113
+ created_at TEXT NOT NULL,
114
+ updated_at TEXT NOT NULL,
115
+ superseded_by TEXT DEFAULT NULL,
116
+ hit_count INTEGER NOT NULL DEFAULT 0,
117
+ scope TEXT NOT NULL DEFAULT 'project',
118
+ tags TEXT NOT NULL DEFAULT '[]'
119
+ );
120
+ CREATE TABLE memory_processed_units (
121
+ unit_key TEXT PRIMARY KEY,
122
+ activity_file TEXT,
123
+ processed_at TEXT NOT NULL
124
+ );
125
+ CREATE TABLE memory_sources (
126
+ id TEXT PRIMARY KEY,
127
+ kind TEXT NOT NULL,
128
+ uri TEXT,
129
+ title TEXT,
130
+ content TEXT NOT NULL,
131
+ content_hash TEXT NOT NULL UNIQUE,
132
+ imported_at TEXT NOT NULL,
133
+ scope TEXT NOT NULL DEFAULT 'project',
134
+ tags TEXT NOT NULL DEFAULT '[]'
135
+ );
136
+ CREATE TABLE memory_embeddings (
137
+ memory_id TEXT PRIMARY KEY,
138
+ model TEXT NOT NULL,
139
+ dim INTEGER NOT NULL,
140
+ vector BLOB NOT NULL,
141
+ updated_at TEXT NOT NULL
142
+ );
143
+ CREATE TABLE memory_relations (
144
+ from_id TEXT NOT NULL,
145
+ to_id TEXT NOT NULL,
146
+ rel TEXT NOT NULL,
147
+ confidence REAL NOT NULL DEFAULT 0.8,
148
+ created_at TEXT NOT NULL,
149
+ PRIMARY KEY (from_id, to_id, rel)
150
+ );
151
+
152
+ CREATE TABLE milestones (
153
+ id TEXT PRIMARY KEY,
154
+ title TEXT NOT NULL DEFAULT '',
155
+ status TEXT NOT NULL DEFAULT 'active',
156
+ depends_on TEXT NOT NULL DEFAULT '[]',
157
+ created_at TEXT NOT NULL DEFAULT '',
158
+ completed_at TEXT DEFAULT NULL,
159
+ vision TEXT NOT NULL DEFAULT '',
160
+ success_criteria TEXT NOT NULL DEFAULT '[]',
161
+ key_risks TEXT NOT NULL DEFAULT '[]',
162
+ proof_strategy TEXT NOT NULL DEFAULT '[]',
163
+ verification_contract TEXT NOT NULL DEFAULT '',
164
+ verification_integration TEXT NOT NULL DEFAULT '',
165
+ verification_operational TEXT NOT NULL DEFAULT '',
166
+ verification_uat TEXT NOT NULL DEFAULT '',
167
+ definition_of_done TEXT NOT NULL DEFAULT '[]',
168
+ requirement_coverage TEXT NOT NULL DEFAULT '',
169
+ boundary_map_markdown TEXT NOT NULL DEFAULT ''
170
+ );
171
+ CREATE TABLE slices (
172
+ milestone_id TEXT NOT NULL,
173
+ id TEXT NOT NULL,
174
+ title TEXT NOT NULL DEFAULT '',
175
+ status TEXT NOT NULL DEFAULT 'pending',
176
+ risk TEXT NOT NULL DEFAULT 'medium',
177
+ depends TEXT NOT NULL DEFAULT '[]',
178
+ demo TEXT NOT NULL DEFAULT '',
179
+ created_at TEXT NOT NULL DEFAULT '',
180
+ completed_at TEXT DEFAULT NULL,
181
+ full_summary_md TEXT NOT NULL DEFAULT '',
182
+ full_uat_md TEXT NOT NULL DEFAULT '',
183
+ goal TEXT NOT NULL DEFAULT '',
184
+ success_criteria TEXT NOT NULL DEFAULT '',
185
+ proof_level TEXT NOT NULL DEFAULT '',
186
+ integration_closure TEXT NOT NULL DEFAULT '',
187
+ observability_impact TEXT NOT NULL DEFAULT '',
188
+ sequence INTEGER DEFAULT 0,
189
+ replan_triggered_at TEXT DEFAULT NULL,
190
+ is_sketch INTEGER NOT NULL DEFAULT 0,
191
+ sketch_scope TEXT NOT NULL DEFAULT '',
192
+ PRIMARY KEY (milestone_id, id)
193
+ );
194
+ CREATE TABLE tasks (
195
+ milestone_id TEXT NOT NULL,
196
+ slice_id TEXT NOT NULL,
197
+ id TEXT NOT NULL,
198
+ title TEXT NOT NULL DEFAULT '',
199
+ status TEXT NOT NULL DEFAULT 'pending',
200
+ one_liner TEXT NOT NULL DEFAULT '',
201
+ narrative TEXT NOT NULL DEFAULT '',
202
+ verification_result TEXT NOT NULL DEFAULT '',
203
+ duration TEXT NOT NULL DEFAULT '',
204
+ completed_at TEXT DEFAULT NULL,
205
+ blocker_discovered INTEGER DEFAULT 0,
206
+ deviations TEXT NOT NULL DEFAULT '',
207
+ known_issues TEXT NOT NULL DEFAULT '',
208
+ key_files TEXT NOT NULL DEFAULT '[]',
209
+ key_decisions TEXT NOT NULL DEFAULT '[]',
210
+ full_summary_md TEXT NOT NULL DEFAULT '',
211
+ description TEXT NOT NULL DEFAULT '',
212
+ estimate TEXT NOT NULL DEFAULT '',
213
+ files TEXT NOT NULL DEFAULT '[]',
214
+ verify TEXT NOT NULL DEFAULT '',
215
+ inputs TEXT NOT NULL DEFAULT '[]',
216
+ expected_output TEXT NOT NULL DEFAULT '[]',
217
+ observability_impact TEXT NOT NULL DEFAULT '',
218
+ full_plan_md TEXT NOT NULL DEFAULT '',
219
+ sequence INTEGER DEFAULT 0,
220
+ blocker_source TEXT NOT NULL DEFAULT '',
221
+ escalation_pending INTEGER NOT NULL DEFAULT 0,
222
+ escalation_awaiting_review INTEGER NOT NULL DEFAULT 0,
223
+ escalation_artifact_path TEXT DEFAULT NULL,
224
+ escalation_override_applied_at TEXT DEFAULT NULL,
225
+ PRIMARY KEY (milestone_id, slice_id, id)
226
+ );
227
+ CREATE TABLE verification_evidence (
228
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
229
+ task_id TEXT NOT NULL DEFAULT '',
230
+ slice_id TEXT NOT NULL DEFAULT '',
231
+ milestone_id TEXT NOT NULL DEFAULT '',
232
+ command TEXT NOT NULL DEFAULT '',
233
+ exit_code INTEGER DEFAULT 0,
234
+ verdict TEXT NOT NULL DEFAULT '',
235
+ duration_ms INTEGER DEFAULT 0,
236
+ created_at TEXT NOT NULL DEFAULT ''
237
+ );
238
+ CREATE TABLE replan_history (
239
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
240
+ milestone_id TEXT NOT NULL DEFAULT '',
241
+ slice_id TEXT DEFAULT NULL,
242
+ task_id TEXT DEFAULT NULL,
243
+ summary TEXT NOT NULL DEFAULT '',
244
+ previous_artifact_path TEXT DEFAULT NULL,
245
+ replacement_artifact_path TEXT DEFAULT NULL,
246
+ created_at TEXT NOT NULL DEFAULT ''
247
+ );
248
+ CREATE TABLE assessments (
249
+ path TEXT PRIMARY KEY,
250
+ milestone_id TEXT NOT NULL DEFAULT '',
251
+ slice_id TEXT DEFAULT NULL,
252
+ task_id TEXT DEFAULT NULL,
253
+ status TEXT NOT NULL DEFAULT '',
254
+ scope TEXT NOT NULL DEFAULT '',
255
+ full_content TEXT NOT NULL DEFAULT '',
256
+ created_at TEXT NOT NULL DEFAULT ''
257
+ );
258
+ CREATE TABLE quality_gates (
259
+ milestone_id TEXT NOT NULL,
260
+ slice_id TEXT NOT NULL,
261
+ gate_id TEXT NOT NULL,
262
+ scope TEXT NOT NULL DEFAULT 'slice',
263
+ task_id TEXT NOT NULL DEFAULT '',
264
+ status TEXT NOT NULL DEFAULT 'pending',
265
+ verdict TEXT NOT NULL DEFAULT '',
266
+ rationale TEXT NOT NULL DEFAULT '',
267
+ findings TEXT NOT NULL DEFAULT '',
268
+ evaluated_at TEXT DEFAULT NULL,
269
+ PRIMARY KEY (milestone_id, slice_id, gate_id, task_id)
270
+ );
271
+ CREATE TABLE slice_dependencies (
272
+ milestone_id TEXT NOT NULL,
273
+ slice_id TEXT NOT NULL,
274
+ depends_on_slice_id TEXT NOT NULL,
275
+ PRIMARY KEY (milestone_id, slice_id, depends_on_slice_id)
276
+ );
277
+ CREATE TABLE gate_runs (
278
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
279
+ trace_id TEXT NOT NULL,
280
+ turn_id TEXT NOT NULL,
281
+ gate_id TEXT NOT NULL,
282
+ gate_type TEXT NOT NULL DEFAULT '',
283
+ unit_type TEXT DEFAULT NULL,
284
+ unit_id TEXT DEFAULT NULL,
285
+ milestone_id TEXT DEFAULT NULL,
286
+ slice_id TEXT DEFAULT NULL,
287
+ task_id TEXT DEFAULT NULL,
288
+ outcome TEXT NOT NULL DEFAULT 'pass',
289
+ failure_class TEXT NOT NULL DEFAULT 'none',
290
+ rationale TEXT NOT NULL DEFAULT '',
291
+ findings TEXT NOT NULL DEFAULT '',
292
+ attempt INTEGER NOT NULL DEFAULT 1,
293
+ max_attempts INTEGER NOT NULL DEFAULT 1,
294
+ retryable INTEGER NOT NULL DEFAULT 0,
295
+ evaluated_at TEXT NOT NULL DEFAULT ''
296
+ );
297
+ CREATE TABLE turn_git_transactions (
298
+ trace_id TEXT NOT NULL,
299
+ turn_id TEXT NOT NULL,
300
+ unit_type TEXT DEFAULT NULL,
301
+ unit_id TEXT DEFAULT NULL,
302
+ stage TEXT NOT NULL DEFAULT 'turn-start',
303
+ action TEXT NOT NULL DEFAULT 'status-only',
304
+ push INTEGER NOT NULL DEFAULT 0,
305
+ status TEXT NOT NULL DEFAULT 'ok',
306
+ error TEXT DEFAULT NULL,
307
+ metadata_json TEXT NOT NULL DEFAULT '{}',
308
+ updated_at TEXT NOT NULL DEFAULT '',
309
+ PRIMARY KEY (trace_id, turn_id, stage)
310
+ );
311
+ CREATE TABLE audit_events (
312
+ event_id TEXT PRIMARY KEY,
313
+ trace_id TEXT NOT NULL,
314
+ turn_id TEXT DEFAULT NULL,
315
+ caused_by TEXT DEFAULT NULL,
316
+ category TEXT NOT NULL,
317
+ type TEXT NOT NULL,
318
+ ts TEXT NOT NULL,
319
+ payload_json TEXT NOT NULL DEFAULT '{}'
320
+ );
321
+ CREATE TABLE audit_turn_index (
322
+ trace_id TEXT NOT NULL,
323
+ turn_id TEXT NOT NULL,
324
+ first_ts TEXT NOT NULL,
325
+ last_ts TEXT NOT NULL,
326
+ event_count INTEGER NOT NULL DEFAULT 0,
327
+ PRIMARY KEY (trace_id, turn_id)
328
+ );
329
+ `);
330
+ db.exec('PRAGMA wal_checkpoint(TRUNCATE)');
331
+ db.close();
332
+ try { fs.unlinkSync(`${dbPath}-wal`); } catch { /* may not exist */ }
333
+ try { fs.unlinkSync(`${dbPath}-shm`); } catch { /* may not exist */ }
334
+ }
335
+
336
+ // ---------------------------------------------------------------------------
337
+ // Tests
338
+ // ---------------------------------------------------------------------------
339
+
340
+ test('schema v21 migration: structured_fields column added when upgrading from v20', () => {
341
+ const base = makeTmp();
342
+ const dbPath = path.join(base, 'gsd.db');
343
+ createV20Db(dbPath);
344
+
345
+ try {
346
+ openDatabase(dbPath);
347
+
348
+ const db = _getAdapter()!;
349
+
350
+ // The v21 migration must have added the structured_fields column.
351
+ const cols = db.prepare('PRAGMA table_info(memories)').all() as Array<Record<string, unknown>>;
352
+ const colNames = new Set(cols.map((c) => c['name'] as string));
353
+ assert.ok(
354
+ colNames.has('structured_fields'),
355
+ 'v21 migration must add structured_fields column to memories table',
356
+ );
357
+ } finally {
358
+ cleanup(base);
359
+ }
360
+ });
361
+
362
+ test('schema v21 migration: version 21 is recorded in schema_version after upgrading from v20', () => {
363
+ const base = makeTmp();
364
+ const dbPath = path.join(base, 'gsd.db');
365
+ createV20Db(dbPath);
366
+
367
+ try {
368
+ openDatabase(dbPath);
369
+
370
+ const db = _getAdapter()!;
371
+
372
+ // Verify that version 21 was recorded. A missing stamp means the
373
+ // migration code executed but never committed its version row — the
374
+ // precise failure mode described in issue #4591.
375
+ const versions = db
376
+ .prepare('SELECT version FROM schema_version ORDER BY version')
377
+ .all() as Array<Record<string, unknown>>;
378
+ const versionNums = versions.map((r) => r['version'] as number);
379
+
380
+ assert.ok(
381
+ versionNums.includes(21),
382
+ `schema_version must contain a row for version 21 after upgrade from v20; found: [${versionNums.join(', ')}]`,
383
+ );
384
+ } finally {
385
+ cleanup(base);
386
+ }
387
+ });
388
+
389
+ test('schema v21 migration: upgrading from v20 lands on current SCHEMA_VERSION', () => {
390
+ const base = makeTmp();
391
+ const dbPath = path.join(base, 'gsd.db');
392
+ createV20Db(dbPath);
393
+
394
+ try {
395
+ openDatabase(dbPath);
396
+
397
+ const db = _getAdapter()!;
398
+
399
+ const maxVersion = (
400
+ db.prepare('SELECT MAX(version) as v FROM schema_version').get() as Record<string, unknown>
401
+ )?.['v'] as number;
402
+
403
+ // The DB must reach the current SCHEMA_VERSION. If the v21 block was
404
+ // skipped (as it would be when SCHEMA_VERSION was still 20), this
405
+ // assertion catches it.
406
+ assert.ok(
407
+ maxVersion >= 21,
408
+ `DB upgraded from v20 must reach at least schema version 21; got ${maxVersion}`,
409
+ );
410
+ } finally {
411
+ cleanup(base);
412
+ }
413
+ });
@@ -1,19 +1,15 @@
1
1
  /**
2
2
  * session-start-footer.test.ts
3
3
  *
4
- * Verifies that register-hooks.ts suppresses the built-in footer by calling
5
- * ctx.ui.setFooter(hideFooter) in both session_start and session_switch when
6
- * isAutoActive() is true.
4
+ * Verifies that register-hooks.ts suppresses the gsd-health widget (not the
5
+ * built-in footer) when isAutoActive() is true, and that setFooter is never
6
+ * called by the extension in either session_start or session_switch.
7
7
  *
8
8
  * Testing strategy:
9
- * Two layers:
10
- * 1. Source-code regression guard: ensures the guard and setFooter call are
11
- * structurally present in register-hooks.ts for both event handlers.
12
- * (node:test does not support mock.module without --experimental-test-module-mocks,
13
- * so structural analysis is the correct approach here.)
9
+ * 1. Source-code regression guards: structural checks on register-hooks.ts.
14
10
  * 2. Behavioral integration test: fires the live session_start handler with a
15
- * fake ctx when isAutoActive() is false (its default at test time) and
16
- * confirms setFooter is NOT called — verifying the guard is conditional.
11
+ * fake ctx when isAutoActive() is false (default) and confirms neither
12
+ * setFooter nor setWidget("gsd-health") is called.
17
13
  *
18
14
  * Relates to #4314.
19
15
  */
@@ -35,16 +31,14 @@ const HOOKS_SOURCE = readFileSync(
35
31
 
36
32
  // ─── Source-code regression guards ──────────────────────────────────────────
37
33
 
38
- test("register-hooks.ts imports hideFooter from auto-dashboard", () => {
34
+ test("register-hooks.ts does NOT import hideFooter", () => {
39
35
  assert.ok(
40
- HOOKS_SOURCE.includes('import { hideFooter } from "../auto-dashboard.js"') ||
41
- HOOKS_SOURCE.includes("import { hideFooter } from '../auto-dashboard.js'"),
42
- "register-hooks.ts must import hideFooter from auto-dashboard.js",
36
+ !HOOKS_SOURCE.includes("hideFooter"),
37
+ "register-hooks.ts must not reference hideFooter footer is no longer swapped in auto mode",
43
38
  );
44
39
  });
45
40
 
46
- test("session_start handler calls ctx.ui.setFooter(hideFooter) when isAutoActive()", () => {
47
- // Locate the session_start handler body (up to the next pi.on call)
41
+ test("session_start handler guards initHealthWidget with !isAutoActive()", () => {
48
42
  const sessionStartIdx = HOOKS_SOURCE.indexOf('"session_start"');
49
43
  assert.ok(sessionStartIdx > -1, "session_start handler must exist");
50
44
 
@@ -58,20 +52,23 @@ test("session_start handler calls ctx.ui.setFooter(hideFooter) when isAutoActive
58
52
  "session_start handler must call isAutoActive()",
59
53
  );
60
54
  assert.ok(
61
- sessionStartBody.includes("ctx.ui.setFooter(hideFooter)"),
62
- "session_start handler must call ctx.ui.setFooter(hideFooter)",
55
+ sessionStartBody.includes("initHealthWidget"),
56
+ "session_start handler must reference initHealthWidget",
57
+ );
58
+ assert.ok(
59
+ !sessionStartBody.includes("setFooter"),
60
+ "session_start handler must NOT call setFooter",
63
61
  );
64
62
 
65
- // Guard must wrap the setFooter call
66
63
  const guardIdx = sessionStartBody.indexOf("isAutoActive()");
67
- const setFooterIdx = sessionStartBody.indexOf("ctx.ui.setFooter(hideFooter)");
64
+ const healthIdx = sessionStartBody.indexOf("initHealthWidget");
68
65
  assert.ok(
69
- guardIdx < setFooterIdx,
70
- "isAutoActive() guard must appear before ctx.ui.setFooter(hideFooter) in session_start",
66
+ guardIdx < healthIdx,
67
+ "isAutoActive() guard must appear before initHealthWidget in session_start",
71
68
  );
72
69
  });
73
70
 
74
- test("session_switch handler calls ctx.ui.setFooter(hideFooter) when isAutoActive()", () => {
71
+ test("session_switch handler suppresses gsd-health when isAutoActive()", () => {
75
72
  const sessionSwitchIdx = HOOKS_SOURCE.indexOf('"session_switch"');
76
73
  assert.ok(sessionSwitchIdx > -1, "session_switch handler must exist");
77
74
 
@@ -85,21 +82,18 @@ test("session_switch handler calls ctx.ui.setFooter(hideFooter) when isAutoActiv
85
82
  "session_switch handler must call isAutoActive()",
86
83
  );
87
84
  assert.ok(
88
- sessionSwitchBody.includes("ctx.ui.setFooter(hideFooter)"),
89
- "session_switch handler must call ctx.ui.setFooter(hideFooter)",
85
+ sessionSwitchBody.includes('setWidget("gsd-health", undefined)'),
86
+ "session_switch handler must call setWidget(\"gsd-health\", undefined) when auto is active",
90
87
  );
91
-
92
- const guardIdx = sessionSwitchBody.indexOf("isAutoActive()");
93
- const setFooterIdx = sessionSwitchBody.indexOf("ctx.ui.setFooter(hideFooter)");
94
88
  assert.ok(
95
- guardIdx < setFooterIdx,
96
- "isAutoActive() guard must appear before ctx.ui.setFooter(hideFooter) in session_switch",
89
+ !sessionSwitchBody.includes("setFooter"),
90
+ "session_switch handler must NOT call setFooter",
97
91
  );
98
92
  });
99
93
 
100
- // ─── Behavioral test: setFooter NOT called when auto-mode is inactive ────────
94
+ // ─── Behavioral test: neither setFooter nor health suppression when auto inactive
101
95
 
102
- test("session_start does NOT call setFooter when isAutoActive() is false (default)", async (t) => {
96
+ test("session_start does NOT call setFooter or suppress gsd-health when isAutoActive() is false", async (t) => {
103
97
  const dir = join(
104
98
  tmpdir(),
105
99
  `gsd-footer-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
@@ -114,6 +108,7 @@ test("session_start does NOT call setFooter when isAutoActive() is false (defaul
114
108
  });
115
109
 
116
110
  let setFooterCallCount = 0;
111
+ let healthWidgetHideCount = 0;
117
112
 
118
113
  const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
119
114
  const pi = {
@@ -137,17 +132,14 @@ test("session_start does NOT call setFooter when isAutoActive() is false (defaul
137
132
  },
138
133
  setWorkingMessage: () => {},
139
134
  onTerminalInput: () => () => {},
140
- setWidget: () => {},
135
+ setWidget: (key: string, value: unknown) => {
136
+ if (key === "gsd-health" && value === undefined) healthWidgetHideCount++;
137
+ },
141
138
  },
142
139
  sessionManager: { getSessionId: () => null },
143
140
  model: null,
144
141
  } as any);
145
142
 
146
- // isAutoActive() is false at test time (no auto session started),
147
- // so setFooter must not be called.
148
- assert.equal(
149
- setFooterCallCount,
150
- 0,
151
- "setFooter must NOT be called when isAutoActive() returns false",
152
- );
143
+ assert.equal(setFooterCallCount, 0, "setFooter must NOT be called when isAutoActive() is false");
144
+ assert.equal(healthWidgetHideCount, 0, "gsd-health must NOT be hidden when isAutoActive() is false");
153
145
  });
@@ -378,3 +378,59 @@ test("#2505: back-to-back merges preserve queued CONTEXT files", () => {
378
378
  rmSync(repo, { recursive: true, force: true });
379
379
  }
380
380
  });
381
+
382
+ // #4573: When `.gsd` is a gitignored symlink (ADR-002 layout) and the project
383
+ // `.gitignore` contains `.gsd`, `git stash push --include-untracked -- <pathspec>`
384
+ // fatals with "The following paths are ignored by one of your .gitignore files".
385
+ // The prior tests used a symlinked `.gsd` but no `.gitignore`, so this failure
386
+ // mode was invisible to CI. Fixture must include BOTH the symlink AND the
387
+ // ignore rule to reproduce the bug on pre-fix code.
388
+ test("#4573: gitignored .gsd symlink does not break pre-merge stash", () => {
389
+ const repo = realpathSync(mkdtempSync(join(tmpdir(), "wt-4573-ignored-symlink-")));
390
+ const stateDir = realpathSync(mkdtempSync(join(tmpdir(), "wt-4573-state-")));
391
+ try {
392
+ run("git init", repo);
393
+ run("git config user.email test@test.com", repo);
394
+ run("git config user.name Test", repo);
395
+ writeFileSync(join(repo, "README.md"), "# test\n");
396
+ // Matches what BASELINE_PATTERNS in gitignore.ts writes for real projects.
397
+ writeFileSync(join(repo, ".gitignore"), ".gsd\n.gsd-id\n");
398
+ symlinkSync(stateDir, join(repo, ".gsd"));
399
+ run("git add README.md .gitignore", repo);
400
+ run("git commit -m init", repo);
401
+ run("git branch -M main", repo);
402
+
403
+ const wtPath = createAutoWorktree(repo, "M001");
404
+ const worktreeName = wtPath.replaceAll("\\", "/").split("/").pop() || "M001";
405
+ const sliceBranch = `slice/${worktreeName}/S01`;
406
+ run(`git checkout -b "${sliceBranch}"`, wtPath);
407
+ writeFileSync(join(wtPath, "app.ts"), "export const app = true;\n");
408
+ run("git add app.ts", wtPath);
409
+ run('git commit -m "add feature"', wtPath);
410
+ run("git checkout milestone/M001", wtPath);
411
+ run(`git merge --no-ff "${sliceBranch}" -m "merge S01"`, wtPath);
412
+
413
+ // Dirty a tracked file so the pre-merge stash branch actually runs.
414
+ writeFileSync(join(repo, "README.md"), "# test\n\nDirty.\n");
415
+
416
+ const result = mergeMilestoneToMain(
417
+ repo,
418
+ "M001",
419
+ makeRoadmap("M001", "Feature", [{ id: "S01", title: "Feature" }]),
420
+ );
421
+
422
+ assert.ok(
423
+ result.commitMessage.includes("GSD-Milestone: M001"),
424
+ "merge must succeed despite gitignored .gsd symlink",
425
+ );
426
+ assert.ok(existsSync(join(repo, "app.ts")), "milestone code merged to main");
427
+ assert.equal(
428
+ lstatSync(join(repo, ".gsd")).isSymbolicLink(),
429
+ true,
430
+ ".gsd symlink remains in place",
431
+ );
432
+ } finally {
433
+ rmSync(repo, { recursive: true, force: true });
434
+ rmSync(stateDir, { recursive: true, force: true });
435
+ }
436
+ });