gsd-pi 2.34.0 → 2.35.0-dev.30eec3f

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 (500) hide show
  1. package/dist/cli.js +7 -2
  2. package/dist/resource-loader.d.ts +1 -1
  3. package/dist/resource-loader.js +13 -1
  4. package/dist/resources/extensions/async-jobs/await-tool.js +0 -2
  5. package/dist/resources/extensions/async-jobs/job-manager.js +0 -6
  6. package/dist/resources/extensions/bg-shell/output-formatter.js +1 -19
  7. package/dist/resources/extensions/bg-shell/process-manager.js +0 -4
  8. package/dist/resources/extensions/bg-shell/types.js +0 -2
  9. package/dist/resources/extensions/context7/index.js +5 -0
  10. package/dist/resources/extensions/get-secrets-from-user.js +2 -30
  11. package/dist/resources/extensions/google-search/index.js +5 -0
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +43 -1
  13. package/dist/resources/extensions/gsd/auto-loop.js +10 -1
  14. package/dist/resources/extensions/gsd/auto-recovery.js +35 -0
  15. package/dist/resources/extensions/gsd/auto-start.js +35 -2
  16. package/dist/resources/extensions/gsd/auto.js +59 -4
  17. package/dist/resources/extensions/gsd/changelog.js +162 -0
  18. package/dist/resources/extensions/gsd/commands-bootstrap.js +1 -0
  19. package/dist/resources/extensions/gsd/commands-handlers.js +2 -2
  20. package/dist/resources/extensions/gsd/commands-inspect.js +10 -3
  21. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +5 -1
  22. package/dist/resources/extensions/gsd/commands.js +8 -1
  23. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  24. package/dist/resources/extensions/gsd/doctor-checks.js +113 -5
  25. package/dist/resources/extensions/gsd/doctor-environment.js +26 -17
  26. package/dist/resources/extensions/gsd/doctor-proactive.js +22 -0
  27. package/dist/resources/extensions/gsd/doctor.js +36 -0
  28. package/dist/resources/extensions/gsd/files.js +11 -2
  29. package/dist/resources/extensions/gsd/gitignore.js +54 -7
  30. package/dist/resources/extensions/gsd/guided-flow.js +5 -3
  31. package/dist/resources/extensions/gsd/health-widget-core.js +96 -0
  32. package/dist/resources/extensions/gsd/health-widget.js +97 -46
  33. package/dist/resources/extensions/gsd/index.js +10 -1
  34. package/dist/resources/extensions/gsd/migrate-external.js +55 -2
  35. package/dist/resources/extensions/gsd/paths.js +74 -7
  36. package/dist/resources/extensions/gsd/post-unit-hooks.js +4 -1
  37. package/dist/resources/extensions/gsd/preferences-validation.js +54 -1
  38. package/dist/resources/extensions/gsd/preferences.js +2 -0
  39. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  40. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  41. package/dist/resources/extensions/gsd/roadmap-mutations.js +55 -0
  42. package/dist/resources/extensions/gsd/session-lock.js +26 -2
  43. package/dist/resources/extensions/gsd/templates/plan.md +8 -0
  44. package/dist/resources/extensions/gsd/worktree-resolver.js +12 -0
  45. package/dist/resources/extensions/mcp-client/index.js +2 -1
  46. package/dist/resources/extensions/remote-questions/remote-command.js +2 -22
  47. package/dist/resources/extensions/shared/mod.js +1 -1
  48. package/dist/resources/extensions/shared/sanitize.js +30 -0
  49. package/dist/resources/extensions/subagent/index.js +6 -14
  50. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +4 -4
  51. package/package.json +2 -1
  52. package/packages/native/dist/native.d.ts +0 -2
  53. package/packages/native/dist/native.js +0 -2
  54. package/packages/native/src/native.ts +0 -3
  55. package/packages/pi-agent-core/dist/agent-loop.d.ts +14 -0
  56. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  57. package/packages/pi-agent-core/dist/agent-loop.js +24 -27
  58. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  59. package/packages/pi-agent-core/dist/agent.d.ts +1 -0
  60. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  61. package/packages/pi-agent-core/dist/agent.js +11 -22
  62. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  63. package/packages/pi-agent-core/dist/proxy.d.ts +1 -25
  64. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  65. package/packages/pi-agent-core/dist/proxy.js +3 -9
  66. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  67. package/packages/pi-agent-core/src/agent-loop.ts +30 -27
  68. package/packages/pi-agent-core/src/agent.ts +12 -23
  69. package/packages/pi-agent-core/src/proxy.ts +3 -9
  70. package/packages/pi-ai/dist/api-registry.d.ts +0 -2
  71. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  72. package/packages/pi-ai/dist/api-registry.js +0 -10
  73. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  74. package/packages/pi-ai/dist/providers/anthropic.d.ts +0 -8
  75. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  76. package/packages/pi-ai/dist/providers/anthropic.js +1 -1
  77. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  78. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  79. package/packages/pi-ai/dist/providers/azure-openai-responses.js +5 -41
  80. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  81. package/packages/pi-ai/dist/providers/github-copilot-headers.d.ts +0 -1
  82. package/packages/pi-ai/dist/providers/github-copilot-headers.d.ts.map +1 -1
  83. package/packages/pi-ai/dist/providers/github-copilot-headers.js +1 -1
  84. package/packages/pi-ai/dist/providers/github-copilot-headers.js.map +1 -1
  85. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts +1 -43
  86. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  87. package/packages/pi-ai/dist/providers/google-gemini-cli.js +2 -2
  88. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  89. package/packages/pi-ai/dist/providers/google-shared.d.ts +0 -4
  90. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  91. package/packages/pi-ai/dist/providers/google-shared.js +1 -1
  92. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  93. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  94. package/packages/pi-ai/dist/providers/openai-completions.js +10 -73
  95. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  96. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  97. package/packages/pi-ai/dist/providers/openai-responses.js +9 -80
  98. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  99. package/packages/pi-ai/dist/providers/openai-shared.d.ts +65 -0
  100. package/packages/pi-ai/dist/providers/openai-shared.d.ts.map +1 -0
  101. package/packages/pi-ai/dist/providers/openai-shared.js +146 -0
  102. package/packages/pi-ai/dist/providers/openai-shared.js.map +1 -0
  103. package/packages/pi-ai/dist/providers/register-builtins.d.ts +0 -1
  104. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  105. package/packages/pi-ai/dist/providers/register-builtins.js +1 -1
  106. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  107. package/packages/pi-ai/dist/utils/event-stream.d.ts +0 -2
  108. package/packages/pi-ai/dist/utils/event-stream.d.ts.map +1 -1
  109. package/packages/pi-ai/dist/utils/event-stream.js +0 -4
  110. package/packages/pi-ai/dist/utils/event-stream.js.map +1 -1
  111. package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  112. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +7 -135
  113. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
  114. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  115. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +7 -135
  116. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  117. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.d.ts +46 -0
  118. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.js +160 -0
  120. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.js.map +1 -0
  121. package/packages/pi-ai/dist/utils/overflow.d.ts +0 -4
  122. package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  123. package/packages/pi-ai/dist/utils/overflow.js +0 -6
  124. package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
  125. package/packages/pi-ai/dist/utils/validation.d.ts +0 -8
  126. package/packages/pi-ai/dist/utils/validation.d.ts.map +1 -1
  127. package/packages/pi-ai/dist/utils/validation.js +0 -14
  128. package/packages/pi-ai/dist/utils/validation.js.map +1 -1
  129. package/packages/pi-ai/src/api-registry.ts +0 -12
  130. package/packages/pi-ai/src/providers/anthropic.ts +1 -1
  131. package/packages/pi-ai/src/providers/azure-openai-responses.ts +11 -45
  132. package/packages/pi-ai/src/providers/github-copilot-headers.ts +1 -1
  133. package/packages/pi-ai/src/providers/google-gemini-cli.ts +2 -2
  134. package/packages/pi-ai/src/providers/google-shared.ts +1 -1
  135. package/packages/pi-ai/src/providers/openai-completions.ts +16 -86
  136. package/packages/pi-ai/src/providers/openai-responses.ts +16 -96
  137. package/packages/pi-ai/src/providers/openai-shared.ts +193 -0
  138. package/packages/pi-ai/src/providers/register-builtins.ts +1 -1
  139. package/packages/pi-ai/src/utils/event-stream.ts +0 -5
  140. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +14 -162
  141. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +13 -161
  142. package/packages/pi-ai/src/utils/oauth/google-oauth-utils.ts +201 -0
  143. package/packages/pi-ai/src/utils/overflow.ts +1 -8
  144. package/packages/pi-ai/src/utils/validation.ts +0 -15
  145. package/packages/pi-coding-agent/dist/config.d.ts +0 -9
  146. package/packages/pi-coding-agent/dist/config.d.ts.map +1 -1
  147. package/packages/pi-coding-agent/dist/config.js +4 -8
  148. package/packages/pi-coding-agent/dist/config.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +16 -63
  150. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/agent-session.js +104 -641
  152. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +0 -1
  154. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/auth-storage.js +4 -35
  156. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js +5 -43
  159. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +11 -69
  162. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +40 -0
  164. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/compaction/utils.js +78 -0
  166. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  167. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +77 -0
  168. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -0
  169. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +331 -0
  170. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -0
  171. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.d.ts +0 -4
  172. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  173. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.js +1 -1
  174. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +2 -2
  176. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/extensions/index.js +1 -1
  178. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +15 -5
  180. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/runner.js +129 -256
  182. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +49 -42
  184. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/extensions/types.js +2 -21
  186. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/keybindings.d.ts +0 -8
  188. package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/keybindings.js +2 -2
  190. package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/lock-utils.d.ts +39 -0
  192. package/packages/pi-coding-agent/dist/core/lock-utils.d.ts.map +1 -0
  193. package/packages/pi-coding-agent/dist/core/lock-utils.js +89 -0
  194. package/packages/pi-coding-agent/dist/core/lock-utils.js.map +1 -0
  195. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +0 -17
  196. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -62
  198. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +1 -1
  200. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  201. package/packages/pi-coding-agent/dist/core/lsp/config.js +2 -6
  202. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  203. package/packages/pi-coding-agent/dist/core/lsp/edits.d.ts +0 -5
  204. package/packages/pi-coding-agent/dist/core/lsp/edits.d.ts.map +1 -1
  205. package/packages/pi-coding-agent/dist/core/lsp/edits.js +1 -1
  206. package/packages/pi-coding-agent/dist/core/lsp/edits.js.map +1 -1
  207. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/lsp/index.js +52 -107
  209. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts +0 -1
  211. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -22
  213. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +0 -1
  215. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/lsp/types.js +0 -28
  217. package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +1 -6
  219. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/core/lsp/utils.js +1 -28
  221. package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/messages.d.ts +0 -8
  223. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/messages.js +5 -5
  225. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -3
  227. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  228. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -3
  229. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  230. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts +1 -26
  231. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -59
  233. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  235. package/packages/pi-coding-agent/dist/core/package-manager.js +2 -4
  236. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  237. package/packages/pi-coding-agent/dist/core/prompt-templates.d.ts +0 -17
  238. package/packages/pi-coding-agent/dist/core/prompt-templates.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/prompt-templates.js +2 -2
  240. package/packages/pi-coding-agent/dist/core/prompt-templates.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +2 -4
  242. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/resource-loader.js +46 -60
  244. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +87 -0
  246. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -0
  247. package/packages/pi-coding-agent/dist/core/retry-handler.js +295 -0
  248. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -0
  249. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +0 -5
  250. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/session-manager.js +5 -32
  252. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +8 -12
  254. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/settings-manager.js +78 -168
  256. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/skills.js +1 -3
  259. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  261. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/index.js +1 -1
  263. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/migrations.d.ts +0 -16
  265. package/packages/pi-coding-agent/dist/migrations.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/migrations.js +2 -2
  267. package/packages/pi-coding-agent/dist/migrations.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.d.ts +0 -2
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.js +2 -2
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.d.ts +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js +9 -26
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -13
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.d.ts +44 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.d.ts.map +1 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.js +61 -0
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.js.map +1 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.js +6 -9
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -24
  287. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  288. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +50 -512
  289. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts +71 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +514 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +65 -4
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +6 -23
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts +12 -0
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +175 -0
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -0
  302. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.d.ts +6 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.js +15 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  307. package/packages/pi-coding-agent/dist/modes/print-mode.js +2 -30
  308. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  309. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -28
  311. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.d.ts +19 -0
  313. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.js +45 -0
  315. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/utils/changelog.d.ts +0 -4
  317. package/packages/pi-coding-agent/dist/utils/changelog.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/utils/changelog.js +1 -1
  319. package/packages/pi-coding-agent/dist/utils/changelog.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts +0 -1
  321. package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/utils/clipboard-image.js +1 -1
  323. package/packages/pi-coding-agent/dist/utils/clipboard-image.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/utils/error.d.ts +5 -0
  325. package/packages/pi-coding-agent/dist/utils/error.d.ts.map +1 -0
  326. package/packages/pi-coding-agent/dist/utils/error.js +7 -0
  327. package/packages/pi-coding-agent/dist/utils/error.js.map +1 -0
  328. package/packages/pi-coding-agent/dist/utils/photon.d.ts +0 -19
  329. package/packages/pi-coding-agent/dist/utils/photon.d.ts.map +1 -1
  330. package/packages/pi-coding-agent/dist/utils/photon.js +1 -120
  331. package/packages/pi-coding-agent/dist/utils/photon.js.map +1 -1
  332. package/packages/pi-coding-agent/dist/utils/tools-manager.d.ts +0 -1
  333. package/packages/pi-coding-agent/dist/utils/tools-manager.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/utils/tools-manager.js +1 -1
  335. package/packages/pi-coding-agent/dist/utils/tools-manager.js.map +1 -1
  336. package/packages/pi-coding-agent/package.json +1 -1
  337. package/packages/pi-coding-agent/src/config.ts +5 -10
  338. package/packages/pi-coding-agent/src/core/agent-session.ts +117 -745
  339. package/packages/pi-coding-agent/src/core/auth-storage.ts +4 -38
  340. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +7 -53
  341. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +14 -74
  342. package/packages/pi-coding-agent/src/core/compaction/utils.ts +100 -0
  343. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +424 -0
  344. package/packages/pi-coding-agent/src/core/export-html/ansi-to-html.ts +1 -1
  345. package/packages/pi-coding-agent/src/core/extensions/index.ts +1 -21
  346. package/packages/pi-coding-agent/src/core/extensions/runner.ts +119 -256
  347. package/packages/pi-coding-agent/src/core/extensions/types.ts +50 -69
  348. package/packages/pi-coding-agent/src/core/keybindings.ts +2 -2
  349. package/packages/pi-coding-agent/src/core/lock-utils.ts +113 -0
  350. package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -73
  351. package/packages/pi-coding-agent/src/core/lsp/config.ts +2 -10
  352. package/packages/pi-coding-agent/src/core/lsp/edits.ts +1 -1
  353. package/packages/pi-coding-agent/src/core/lsp/index.ts +83 -152
  354. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -23
  355. package/packages/pi-coding-agent/src/core/lsp/types.ts +0 -29
  356. package/packages/pi-coding-agent/src/core/lsp/utils.ts +1 -33
  357. package/packages/pi-coding-agent/src/core/messages.ts +5 -5
  358. package/packages/pi-coding-agent/src/core/model-registry.ts +0 -2
  359. package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -77
  360. package/packages/pi-coding-agent/src/core/package-manager.ts +1 -4
  361. package/packages/pi-coding-agent/src/core/prompt-templates.ts +2 -2
  362. package/packages/pi-coding-agent/src/core/resource-loader.ts +56 -69
  363. package/packages/pi-coding-agent/src/core/retry-handler.ts +359 -0
  364. package/packages/pi-coding-agent/src/core/session-manager.ts +5 -34
  365. package/packages/pi-coding-agent/src/core/settings-manager.ts +87 -166
  366. package/packages/pi-coding-agent/src/core/skills.ts +1 -4
  367. package/packages/pi-coding-agent/src/index.ts +1 -7
  368. package/packages/pi-coding-agent/src/migrations.ts +2 -2
  369. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector-search.ts +2 -2
  370. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector.ts +17 -29
  371. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -13
  372. package/packages/pi-coding-agent/src/modes/interactive/components/tree-render-utils.ts +81 -0
  373. package/packages/pi-coding-agent/src/modes/interactive/components/tree-selector.ts +14 -19
  374. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +50 -561
  375. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +653 -0
  376. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +7 -26
  377. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +196 -0
  378. package/packages/pi-coding-agent/src/modes/interactive/utils/shorten-path.ts +14 -0
  379. package/packages/pi-coding-agent/src/modes/print-mode.ts +2 -30
  380. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -28
  381. package/packages/pi-coding-agent/src/modes/shared/command-context-actions.ts +53 -0
  382. package/packages/pi-coding-agent/src/utils/changelog.ts +1 -1
  383. package/packages/pi-coding-agent/src/utils/clipboard-image.ts +1 -1
  384. package/packages/pi-coding-agent/src/utils/error.ts +6 -0
  385. package/packages/pi-coding-agent/src/utils/photon.ts +0 -137
  386. package/packages/pi-coding-agent/src/utils/tools-manager.ts +1 -1
  387. package/packages/pi-tui/dist/components/editor.d.ts +0 -10
  388. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  389. package/packages/pi-tui/dist/components/editor.js +1 -1
  390. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  391. package/packages/pi-tui/dist/components/markdown.d.ts +5 -0
  392. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  393. package/packages/pi-tui/dist/components/markdown.js +25 -31
  394. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  395. package/packages/pi-tui/dist/keys.d.ts +0 -4
  396. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  397. package/packages/pi-tui/dist/keys.js +94 -162
  398. package/packages/pi-tui/dist/keys.js.map +1 -1
  399. package/packages/pi-tui/dist/overlay-layout.d.ts +55 -0
  400. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -0
  401. package/packages/pi-tui/dist/overlay-layout.js +288 -0
  402. package/packages/pi-tui/dist/overlay-layout.js.map +1 -0
  403. package/packages/pi-tui/dist/tui.d.ts +0 -22
  404. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  405. package/packages/pi-tui/dist/tui.js +6 -272
  406. package/packages/pi-tui/dist/tui.js.map +1 -1
  407. package/packages/pi-tui/dist/utils.d.ts +0 -7
  408. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  409. package/packages/pi-tui/dist/utils.js +0 -44
  410. package/packages/pi-tui/dist/utils.js.map +1 -1
  411. package/packages/pi-tui/src/components/editor.ts +1 -1
  412. package/packages/pi-tui/src/components/markdown.ts +25 -29
  413. package/packages/pi-tui/src/keys.ts +94 -173
  414. package/packages/pi-tui/src/overlay-layout.ts +372 -0
  415. package/packages/pi-tui/src/tui.ts +11 -312
  416. package/packages/pi-tui/src/utils.ts +0 -43
  417. package/pkg/dist/core/export-html/ansi-to-html.d.ts +0 -4
  418. package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  419. package/pkg/dist/core/export-html/ansi-to-html.js +1 -1
  420. package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -1
  421. package/pkg/dist/modes/interactive/theme/theme.d.ts +65 -4
  422. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  423. package/pkg/dist/modes/interactive/theme/theme.js +6 -23
  424. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  425. package/pkg/dist/modes/interactive/theme/themes.d.ts +12 -0
  426. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  427. package/pkg/dist/modes/interactive/theme/themes.js +175 -0
  428. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -0
  429. package/pkg/package.json +1 -1
  430. package/src/resources/extensions/async-jobs/await-tool.ts +0 -2
  431. package/src/resources/extensions/async-jobs/job-manager.ts +0 -7
  432. package/src/resources/extensions/bg-shell/output-formatter.ts +0 -17
  433. package/src/resources/extensions/bg-shell/process-manager.ts +0 -4
  434. package/src/resources/extensions/bg-shell/types.ts +0 -12
  435. package/src/resources/extensions/context7/index.ts +7 -0
  436. package/src/resources/extensions/get-secrets-from-user.ts +2 -35
  437. package/src/resources/extensions/google-search/index.ts +7 -0
  438. package/src/resources/extensions/gsd/auto-dispatch.ts +49 -1
  439. package/src/resources/extensions/gsd/auto-loop.ts +11 -1
  440. package/src/resources/extensions/gsd/auto-recovery.ts +39 -0
  441. package/src/resources/extensions/gsd/auto-start.ts +42 -2
  442. package/src/resources/extensions/gsd/auto.ts +61 -3
  443. package/src/resources/extensions/gsd/changelog.ts +213 -0
  444. package/src/resources/extensions/gsd/commands-bootstrap.ts +1 -0
  445. package/src/resources/extensions/gsd/commands-handlers.ts +2 -2
  446. package/src/resources/extensions/gsd/commands-inspect.ts +10 -3
  447. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +5 -1
  448. package/src/resources/extensions/gsd/commands.ts +9 -1
  449. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  450. package/src/resources/extensions/gsd/doctor-checks.ts +107 -5
  451. package/src/resources/extensions/gsd/doctor-environment.ts +26 -16
  452. package/src/resources/extensions/gsd/doctor-proactive.ts +24 -0
  453. package/src/resources/extensions/gsd/doctor-types.ts +9 -1
  454. package/src/resources/extensions/gsd/doctor.ts +35 -0
  455. package/src/resources/extensions/gsd/files.ts +12 -2
  456. package/src/resources/extensions/gsd/gitignore.ts +54 -7
  457. package/src/resources/extensions/gsd/guided-flow.ts +5 -3
  458. package/src/resources/extensions/gsd/health-widget-core.ts +129 -0
  459. package/src/resources/extensions/gsd/health-widget.ts +103 -59
  460. package/src/resources/extensions/gsd/index.ts +10 -1
  461. package/src/resources/extensions/gsd/migrate-external.ts +47 -2
  462. package/src/resources/extensions/gsd/paths.ts +73 -7
  463. package/src/resources/extensions/gsd/post-unit-hooks.ts +5 -1
  464. package/src/resources/extensions/gsd/preferences-validation.ts +54 -1
  465. package/src/resources/extensions/gsd/preferences.ts +2 -0
  466. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
  467. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
  468. package/src/resources/extensions/gsd/roadmap-mutations.ts +66 -0
  469. package/src/resources/extensions/gsd/session-lock.ts +29 -2
  470. package/src/resources/extensions/gsd/templates/plan.md +8 -0
  471. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +46 -0
  472. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +98 -2
  473. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +59 -3
  474. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +20 -0
  475. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +214 -0
  476. package/src/resources/extensions/gsd/tests/health-widget.test.ts +158 -0
  477. package/src/resources/extensions/gsd/tests/paths.test.ts +113 -0
  478. package/src/resources/extensions/gsd/tests/preferences.test.ts +40 -2
  479. package/src/resources/extensions/gsd/tests/test-utils.ts +165 -0
  480. package/src/resources/extensions/gsd/tests/validate-directory.test.ts +15 -0
  481. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +2 -0
  482. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +32 -0
  483. package/src/resources/extensions/gsd/worktree-resolver.ts +11 -0
  484. package/src/resources/extensions/mcp-client/index.ts +2 -1
  485. package/src/resources/extensions/remote-questions/remote-command.ts +2 -23
  486. package/src/resources/extensions/shared/mod.ts +1 -1
  487. package/src/resources/extensions/shared/sanitize.ts +36 -0
  488. package/src/resources/extensions/subagent/index.ts +6 -12
  489. package/src/resources/skills/create-gsd-extension/references/events-reference.md +4 -4
  490. package/dist/resources/extensions/shared/wizard-ui.js +0 -478
  491. package/packages/pi-coding-agent/dist/modes/interactive/theme/dark.json +0 -85
  492. package/packages/pi-coding-agent/dist/modes/interactive/theme/light.json +0 -84
  493. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.json +0 -335
  494. package/packages/pi-coding-agent/src/modes/interactive/theme/dark.json +0 -85
  495. package/packages/pi-coding-agent/src/modes/interactive/theme/light.json +0 -84
  496. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.json +0 -335
  497. package/pkg/dist/modes/interactive/theme/dark.json +0 -85
  498. package/pkg/dist/modes/interactive/theme/light.json +0 -84
  499. package/pkg/dist/modes/interactive/theme/theme-schema.json +0 -335
  500. package/src/resources/extensions/shared/wizard-ui.ts +0 -551
@@ -590,7 +590,8 @@ export async function loadFile(path: string): Promise<string | null> {
590
590
  try {
591
591
  return await fs.readFile(path, 'utf-8');
592
592
  } catch (err: unknown) {
593
- if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;
593
+ const code = (err as NodeJS.ErrnoException).code;
594
+ if (code === 'ENOENT' || code === 'EISDIR') return null;
594
595
  throw err;
595
596
  }
596
597
  }
@@ -804,7 +805,7 @@ export async function inlinePriorMilestoneSummary(mid: string, base: string): Pr
804
805
  * file not on disk) - callers can distinguish "no manifest" from "empty manifest".
805
806
  */
806
807
  export async function getManifestStatus(
807
- base: string, milestoneId: string,
808
+ base: string, milestoneId: string, projectRoot?: string,
808
809
  ): Promise<ManifestStatus | null> {
809
810
  const resolvedPath = resolveMilestoneFile(base, milestoneId, 'SECRETS');
810
811
  if (!resolvedPath) return null;
@@ -814,9 +815,18 @@ export async function getManifestStatus(
814
815
 
815
816
  const manifest = parseSecretsManifest(content);
816
817
  const keys = manifest.entries.map(e => e.key);
818
+
819
+ // Check both the base path .env AND the project root .env (#1387).
820
+ // In worktree mode, base is the worktree path which may not have .env.
821
+ // The project root's .env is where the user actually defined their keys.
817
822
  const existingKeys = await checkExistingEnvKeys(keys, resolve(base, '.env'));
818
823
  const existingSet = new Set(existingKeys);
819
824
 
825
+ if (projectRoot && projectRoot !== base) {
826
+ const rootKeys = await checkExistingEnvKeys(keys, resolve(projectRoot, '.env'));
827
+ for (const k of rootKeys) existingSet.add(k);
828
+ }
829
+
820
830
  const result: ManifestStatus = {
821
831
  pending: [],
822
832
  collected: [],
@@ -7,8 +7,8 @@
7
7
  */
8
8
 
9
9
  import { join } from "node:path";
10
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
11
- import { nativeRmCached } from "./native-git-bridge.js";
10
+ import { existsSync, lstatSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { nativeRmCached, nativeLsFiles } from "./native-git-bridge.js";
12
12
  import { gsdRoot } from "./paths.js";
13
13
 
14
14
  /**
@@ -79,12 +79,47 @@ const BASELINE_PATTERNS = [
79
79
  ];
80
80
 
81
81
  /**
82
- * Ensure basePath/.gitignore contains a blanket `.gsd/` ignore.
83
- * Creates the file if missing; appends `.gsd/` if not present.
82
+ * Check whether `.gsd/` contains files tracked by git.
83
+ * If so, the project intentionally keeps `.gsd/` in version control
84
+ * and we must NOT add `.gsd` to `.gitignore` or attempt migration.
85
+ *
86
+ * Returns true if git tracks at least one file under `.gsd/`.
87
+ * Returns false (safe to ignore) if:
88
+ * - Not a git repo
89
+ * - `.gsd/` is a symlink (external state, should be ignored)
90
+ * - `.gsd/` doesn't exist
91
+ * - No tracked files found under `.gsd/`
92
+ */
93
+ export function hasGitTrackedGsdFiles(basePath: string): boolean {
94
+ const localGsd = join(basePath, ".gsd");
95
+
96
+ // If .gsd doesn't exist or is already a symlink, no tracked files concern
97
+ if (!existsSync(localGsd)) return false;
98
+ try {
99
+ if (lstatSync(localGsd).isSymbolicLink()) return false;
100
+ } catch {
101
+ return false;
102
+ }
103
+
104
+ // Check if git tracks any files under .gsd/
105
+ try {
106
+ const tracked = nativeLsFiles(basePath, ".gsd");
107
+ return tracked.length > 0;
108
+ } catch {
109
+ // Not a git repo or git not available — safe to proceed
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Ensure basePath/.gitignore contains baseline ignore patterns.
116
+ * Creates the file if missing; appends missing patterns.
84
117
  * Returns true if the file was created or modified, false if already complete.
85
118
  *
86
- * `.gsd/` state is managed externally (symlinked to `~/.gsd/projects/<hash>/`),
87
- * so the entire directory is always gitignored.
119
+ * **Safety check:** If `.gsd/` contains git-tracked files (i.e., the project
120
+ * intentionally keeps `.gsd/` in version control), the `.gsd` ignore pattern
121
+ * is excluded to prevent data loss. Only the `.gsd` pattern is affected —
122
+ * all other baseline patterns are still applied normally.
88
123
  */
89
124
  export function ensureGitignore(
90
125
  basePath: string,
@@ -108,8 +143,15 @@ export function ensureGitignore(
108
143
  .filter((l) => l && !l.startsWith("#")),
109
144
  );
110
145
 
146
+ // Determine which patterns to apply. If .gsd/ has tracked files,
147
+ // exclude the ".gsd" pattern to prevent deleting tracked state.
148
+ const gsdIsTracked = hasGitTrackedGsdFiles(basePath);
149
+ const patternsToApply = gsdIsTracked
150
+ ? BASELINE_PATTERNS.filter((p) => p !== ".gsd")
151
+ : BASELINE_PATTERNS;
152
+
111
153
  // Find patterns not yet present
112
- const missing = BASELINE_PATTERNS.filter((p) => !existingLines.has(p));
154
+ const missing = patternsToApply.filter((p) => !existingLines.has(p));
113
155
 
114
156
  if (missing.length === 0) return false;
115
157
 
@@ -135,6 +177,11 @@ export function ensureGitignore(
135
177
  * already in the index even after .gitignore is updated.
136
178
  *
137
179
  * Only removes from the index (`--cached`), never from disk. Idempotent.
180
+ *
181
+ * Note: These are strictly runtime/ephemeral paths (activity logs, lock files,
182
+ * metrics, STATE.md). They are always safe to untrack, even when the project
183
+ * intentionally keeps other `.gsd/` files (like PROJECT.md, milestones/) in
184
+ * version control.
138
185
  */
139
186
  export function untrackRuntimeFiles(basePath: string): void {
140
187
  const runtimePaths = GSD_RUNTIME_PATTERNS;
@@ -191,7 +191,7 @@ type UIContext = ExtensionContext;
191
191
  * This is the only way the wizard triggers work — everything else is the LLM's job.
192
192
  */
193
193
  function dispatchWorkflow(pi: ExtensionAPI, note: string, customType = "gsd-run"): void {
194
- const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
194
+ const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md");
195
195
  const workflow = readFileSync(workflowPath, "utf-8");
196
196
 
197
197
  pi.sendMessage(
@@ -788,9 +788,11 @@ export async function showSmartEntry(
788
788
  // ── Self-heal stale runtime records from crashed auto-mode sessions ──
789
789
  selfHealRuntimeRecords(basePath, ctx);
790
790
 
791
- // Check for crash from previous auto-mode session
791
+ // Check for crash from previous auto-mode session.
792
+ // Skip if the lock was written by the current process — acquireSessionLock()
793
+ // writes to the same file, so we'd always false-positive (#1398).
792
794
  const crashLock = readCrashLock(basePath);
793
- if (crashLock) {
795
+ if (crashLock && crashLock.pid !== process.pid) {
794
796
  clearLock(basePath);
795
797
 
796
798
  // Bootstrap crash with zero completed units = no work was lost.
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Pure GSD health widget logic.
3
+ *
4
+ * Separates project-state detection and line rendering from the widget's
5
+ * runtime integrations so the regressions can be tested directly.
6
+ */
7
+
8
+ import { existsSync, readdirSync } from "node:fs";
9
+ import { gsdRoot } from "./paths.js";
10
+ import { join } from "node:path";
11
+ import type { GSDState, Phase } from "./types.js";
12
+
13
+ export type HealthWidgetProjectState = "none" | "initialized" | "active";
14
+
15
+ export interface HealthWidgetData {
16
+ projectState: HealthWidgetProjectState;
17
+ budgetCeiling: number | undefined;
18
+ budgetSpent: number;
19
+ providerIssue: string | null;
20
+ environmentErrorCount: number;
21
+ environmentWarningCount: number;
22
+ lastRefreshed: number;
23
+ executionPhase?: Phase;
24
+ executionStatus?: string;
25
+ executionTarget?: string;
26
+ nextAction?: string;
27
+ blocker?: string | null;
28
+ activeMilestoneId?: string;
29
+ activeSliceId?: string;
30
+ activeTaskId?: string;
31
+ progress?: GSDState["progress"];
32
+ eta?: string | null;
33
+ }
34
+
35
+ export function detectHealthWidgetProjectState(basePath: string): HealthWidgetProjectState {
36
+ const root = gsdRoot(basePath);
37
+ if (!existsSync(root)) return "none";
38
+
39
+ // Lightweight milestone count — avoids the full detectProjectState() scan
40
+ // (CI markers, Makefile targets, etc.) that is unnecessary on the 60s refresh.
41
+ try {
42
+ const milestonesDir = join(root, "milestones");
43
+ if (existsSync(milestonesDir)) {
44
+ const entries = readdirSync(milestonesDir, { withFileTypes: true });
45
+ if (entries.some(e => e.isDirectory())) return "active";
46
+ }
47
+ } catch { /* non-fatal */ }
48
+
49
+ return "initialized";
50
+ }
51
+
52
+ function formatCost(n: number): string {
53
+ return n >= 1 ? `$${n.toFixed(2)}` : `${(n * 100).toFixed(1)}¢`;
54
+ }
55
+
56
+ function formatProgress(progress?: GSDState["progress"]): string | null {
57
+ if (!progress) return null;
58
+
59
+ const parts: string[] = [];
60
+ parts.push(`M ${progress.milestones.done}/${progress.milestones.total}`);
61
+ if (progress.slices) parts.push(`S ${progress.slices.done}/${progress.slices.total}`);
62
+ if (progress.tasks) parts.push(`T ${progress.tasks.done}/${progress.tasks.total}`);
63
+ return parts.length > 0 ? `Progress: ${parts.join(" · ")}` : null;
64
+ }
65
+
66
+ function formatEnvironmentSummary(errorCount: number, warningCount: number): string | null {
67
+ if (errorCount <= 0 && warningCount <= 0) return null;
68
+
69
+ const parts: string[] = [];
70
+ if (errorCount > 0) parts.push(`${errorCount} error${errorCount > 1 ? "s" : ""}`);
71
+ if (warningCount > 0) parts.push(`${warningCount} warning${warningCount > 1 ? "s" : ""}`);
72
+ return `Env: ${parts.join(", ")}`;
73
+ }
74
+
75
+ function formatBudgetSummary(data: HealthWidgetData): string | null {
76
+ if (data.budgetCeiling !== undefined && data.budgetCeiling > 0) {
77
+ const pct = Math.min(100, (data.budgetSpent / data.budgetCeiling) * 100);
78
+ return `Budget: ${formatCost(data.budgetSpent)}/${formatCost(data.budgetCeiling)} (${pct.toFixed(0)}%)`;
79
+ }
80
+ if (data.budgetSpent > 0) {
81
+ return `Spent: ${formatCost(data.budgetSpent)}`;
82
+ }
83
+ return null;
84
+ }
85
+
86
+ function buildExecutionHeadline(data: HealthWidgetData): string {
87
+ const status = data.executionStatus ?? "Active project";
88
+ const target = data.executionTarget ?? data.blocker ?? "loading status…";
89
+ return ` GSD ${status}${target ? ` - ${target}` : ""}`;
90
+ }
91
+
92
+ /**
93
+ * Build compact health lines for the widget.
94
+ * Returns a string array suitable for setWidget().
95
+ */
96
+ export function buildHealthLines(data: HealthWidgetData): string[] {
97
+ if (data.projectState === "none") {
98
+ return [" GSD No project loaded — run /gsd to start"];
99
+ }
100
+
101
+ if (data.projectState === "initialized") {
102
+ return [" GSD Project initialized — run /gsd to continue setup"];
103
+ }
104
+
105
+ const lines = [buildExecutionHeadline(data)];
106
+ const details: string[] = [];
107
+
108
+ const progress = formatProgress(data.progress);
109
+ if (progress) details.push(progress);
110
+
111
+ if (data.providerIssue) details.push(data.providerIssue);
112
+
113
+ const environment = formatEnvironmentSummary(
114
+ data.environmentErrorCount,
115
+ data.environmentWarningCount,
116
+ );
117
+ if (environment) details.push(environment);
118
+
119
+ const budget = formatBudgetSummary(data);
120
+ if (budget) details.push(budget);
121
+
122
+ if (data.eta) details.push(data.eta);
123
+
124
+ if (details.length > 0) {
125
+ lines.push(` ${details.join(" │ ")}`);
126
+ }
127
+
128
+ return lines;
129
+ }
@@ -9,41 +9,37 @@
9
9
  */
10
10
 
11
11
  import type { ExtensionContext } from "@gsd/pi-coding-agent";
12
+ import type { GSDState } from "./types.js";
12
13
  import { runProviderChecks, summariseProviderIssues } from "./doctor-providers.js";
13
14
  import { runEnvironmentChecks } from "./doctor-environment.js";
14
15
  import { loadEffectiveGSDPreferences } from "./preferences.js";
15
16
  import { loadLedgerFromDisk, getProjectTotals } from "./metrics.js";
17
+ import { describeNextUnit, estimateTimeRemaining, updateSliceProgressCache } from "./auto-dashboard.js";
16
18
  import { projectRoot } from "./commands.js";
17
-
18
- // ── Types ──────────────────────────────────────────────────────────────────────
19
-
20
- interface HealthWidgetData {
21
- hasProject: boolean;
22
- budgetCeiling: number | undefined;
23
- budgetSpent: number;
24
- providerIssue: string | null; // compact summary from summariseProviderIssues()
25
- environmentErrorCount: number;
26
- environmentWarningCount: number;
27
- lastRefreshed: number;
28
- }
19
+ import { deriveState, invalidateStateCache } from "./state.js";
20
+ import {
21
+ buildHealthLines,
22
+ detectHealthWidgetProjectState,
23
+ type HealthWidgetData,
24
+ } from "./health-widget-core.js";
29
25
 
30
26
  // ── Data loader ────────────────────────────────────────────────────────────────
31
27
 
32
- function loadHealthWidgetData(basePath: string): HealthWidgetData {
33
- let hasProject = false;
28
+ function loadBaseHealthWidgetData(basePath: string): HealthWidgetData {
34
29
  let budgetCeiling: number | undefined;
35
30
  let budgetSpent = 0;
36
31
  let providerIssue: string | null = null;
37
32
  let environmentErrorCount = 0;
38
33
  let environmentWarningCount = 0;
39
34
 
35
+ const projectState = detectHealthWidgetProjectState(basePath);
36
+
40
37
  try {
41
38
  const prefs = loadEffectiveGSDPreferences();
42
39
  budgetCeiling = prefs?.preferences?.budget_ceiling;
43
40
 
44
41
  const ledger = loadLedgerFromDisk(basePath);
45
42
  if (ledger) {
46
- hasProject = true;
47
43
  const totals = getProjectTotals(ledger.units ?? []);
48
44
  budgetSpent = totals.cost;
49
45
  }
@@ -63,7 +59,7 @@ function loadHealthWidgetData(basePath: string): HealthWidgetData {
63
59
  } catch { /* non-fatal */ }
64
60
 
65
61
  return {
66
- hasProject,
62
+ projectState,
67
63
  budgetCeiling,
68
64
  budgetSpent,
69
65
  providerIssue,
@@ -73,54 +69,88 @@ function loadHealthWidgetData(basePath: string): HealthWidgetData {
73
69
  };
74
70
  }
75
71
 
76
- // ── Rendering ──────────────────────────────────────────────────────────────────
77
-
78
- function formatCost(n: number): string {
79
- return n >= 1 ? `$${n.toFixed(2)}` : `${(n * 100).toFixed(1)}¢`;
72
+ function compactText(text: string, max = 64): string {
73
+ const trimmed = text.replace(/\s+/g, " ").trim();
74
+ if (trimmed.length <= max) return trimmed;
75
+ return `${trimmed.slice(0, max - 1).trimEnd()}…`;
80
76
  }
81
77
 
82
- /**
83
- * Build compact health lines for the widget.
84
- * Returns a string array suitable for setWidget().
85
- */
86
- export function buildHealthLines(data: HealthWidgetData): string[] {
87
- if (!data.hasProject) {
88
- return [" GSD No project loaded — run /gsd to start"];
78
+ function summarizeExecutionStatus(state: GSDState): string {
79
+ switch (state.phase) {
80
+ case "blocked": return "Blocked";
81
+ case "paused": return "Paused";
82
+ case "complete": return "Complete";
83
+ case "executing": return "Executing";
84
+ case "planning": return "Planning";
85
+ case "pre-planning": return "Pre-planning";
86
+ case "summarizing": return "Summarizing";
87
+ case "validating-milestone": return "Validating";
88
+ case "completing-milestone": return "Completing";
89
+ case "needs-discussion": return "Needs discussion";
90
+ case "replanning-slice": return "Replanning";
91
+ default: return "Active";
89
92
  }
93
+ }
90
94
 
91
- const parts: string[] = [];
92
-
93
- // System status signal
94
- const totalIssues = data.environmentErrorCount + data.environmentWarningCount + (data.providerIssue ? 1 : 0);
95
- if (totalIssues === 0) {
96
- parts.push(" System OK");
97
- } else if (data.environmentErrorCount > 0 || data.providerIssue?.includes("")) {
98
- parts.push(`✗ ${totalIssues} issue${totalIssues > 1 ? "s" : ""}`);
99
- } else {
100
- parts.push(`⚠ ${totalIssues} warning${totalIssues > 1 ? "s" : ""}`);
95
+ function summarizeExecutionTarget(state: GSDState): string {
96
+ switch (state.phase) {
97
+ case "needs-discussion":
98
+ return state.activeMilestone ? `Discuss ${state.activeMilestone.id}` : "Discuss milestone draft";
99
+ case "pre-planning":
100
+ return state.activeMilestone ? `Plan ${state.activeMilestone.id}` : "Research & plan milestone";
101
+ case "planning":
102
+ return state.activeSlice ? `Plan ${state.activeSlice.id}` : "Plan next slice";
103
+ case "executing":
104
+ return state.activeTask ? `Execute ${state.activeTask.id}` : "Execute next task";
105
+ case "summarizing":
106
+ return state.activeSlice ? `Complete ${state.activeSlice.id}` : "Complete current slice";
107
+ case "validating-milestone":
108
+ return state.activeMilestone ? `Validate ${state.activeMilestone.id}` : "Validate milestone";
109
+ case "completing-milestone":
110
+ return state.activeMilestone ? `Complete ${state.activeMilestone.id}` : "Complete milestone";
111
+ case "replanning-slice":
112
+ return state.activeSlice ? `Replan ${state.activeSlice.id}` : "Replan current slice";
113
+ case "blocked":
114
+ return `waiting on ${compactText(state.blockers[0] ?? state.nextAction, 56)}`;
115
+ case "paused":
116
+ return compactText(state.nextAction || "waiting to resume", 56);
117
+ case "complete":
118
+ return "All milestones complete";
119
+ default:
120
+ return compactText(describeNextUnit(state).label, 56);
101
121
  }
122
+ }
102
123
 
103
- // Budget
104
- if (data.budgetCeiling !== undefined && data.budgetCeiling > 0) {
105
- const pct = Math.min(100, (data.budgetSpent / data.budgetCeiling) * 100);
106
- parts.push(`Budget: ${formatCost(data.budgetSpent)}/${formatCost(data.budgetCeiling)} (${pct.toFixed(0)}%)`);
107
- } else if (data.budgetSpent > 0) {
108
- parts.push(`Spent: ${formatCost(data.budgetSpent)}`);
109
- }
124
+ async function enrichHealthWidgetData(basePath: string, baseData: HealthWidgetData): Promise<HealthWidgetData> {
125
+ if (baseData.projectState !== "active") return baseData;
110
126
 
111
- // Provider issue (if any)
112
- if (data.providerIssue) {
113
- parts.push(data.providerIssue);
114
- }
127
+ try {
128
+ invalidateStateCache();
129
+ const state = await deriveState(basePath);
115
130
 
116
- // Environment issues
117
- if (data.environmentErrorCount > 0) {
118
- parts.push(`Env: ${data.environmentErrorCount} error${data.environmentErrorCount > 1 ? "s" : ""}`);
119
- } else if (data.environmentWarningCount > 0) {
120
- parts.push(`Env: ${data.environmentWarningCount} warning${data.environmentWarningCount > 1 ? "s" : ""}`);
121
- }
131
+ if (state.activeMilestone) {
132
+ // Warm the slice-progress cache so estimateTimeRemaining() has data
133
+ updateSliceProgressCache(basePath, state.activeMilestone.id, state.activeSlice?.id);
134
+ }
122
135
 
123
- return [` ${parts.join(" │ ")}`];
136
+ return {
137
+ ...baseData,
138
+ executionPhase: state.phase,
139
+ executionStatus: summarizeExecutionStatus(state),
140
+ executionTarget: summarizeExecutionTarget(state),
141
+ nextAction: state.nextAction,
142
+ blocker: state.blockers[0] ?? null,
143
+ activeMilestoneId: state.activeMilestone?.id,
144
+ activeSliceId: state.activeSlice?.id,
145
+ activeTaskId: state.activeTask?.id,
146
+ progress: state.progress,
147
+ eta: state.phase === "blocked" || state.phase === "paused" || state.phase === "complete"
148
+ ? null
149
+ : estimateTimeRemaining(),
150
+ };
151
+ } catch {
152
+ return baseData;
153
+ }
124
154
  }
125
155
 
126
156
  // ── Widget init ────────────────────────────────────────────────────────────────
@@ -137,20 +167,34 @@ export function initHealthWidget(ctx: ExtensionContext): void {
137
167
  const basePath = projectRoot();
138
168
 
139
169
  // String-array fallback — used in RPC mode (factory is a no-op there)
140
- const initialData = loadHealthWidgetData(basePath);
170
+ const initialData = loadBaseHealthWidgetData(basePath);
141
171
  ctx.ui.setWidget("gsd-health", buildHealthLines(initialData), { placement: "belowEditor" });
142
172
 
143
173
  // Factory-based widget for TUI mode — replaces the string-array above
144
174
  ctx.ui.setWidget("gsd-health", (_tui, _theme) => {
145
175
  let data = initialData;
146
176
  let cachedLines: string[] | undefined;
177
+ let refreshInFlight = false;
147
178
 
148
- const refreshTimer = setInterval(() => {
179
+ const refresh = async () => {
180
+ if (refreshInFlight) return;
181
+ refreshInFlight = true;
149
182
  try {
150
- data = loadHealthWidgetData(basePath);
183
+ const baseData = loadBaseHealthWidgetData(basePath);
184
+ data = await enrichHealthWidgetData(basePath, baseData);
151
185
  cachedLines = undefined;
152
186
  _tui.requestRender();
153
- } catch { /* non-fatal */ }
187
+ } catch { /* non-fatal */ } finally {
188
+ refreshInFlight = false;
189
+ }
190
+ };
191
+
192
+ // Fire first enrichment immediately. requestRender() inside is a no-op
193
+ // if the widget has not yet rendered, so this is safe before factory return.
194
+ void refresh();
195
+
196
+ const refreshTimer = setInterval(() => {
197
+ void refresh();
154
198
  }, REFRESH_INTERVAL_MS);
155
199
 
156
200
  return {
@@ -175,7 +175,16 @@ export default function (pi: ExtensionAPI) {
175
175
  // Pipe closed — nothing we can write; just exit cleanly
176
176
  process.exit(0);
177
177
  }
178
- // Re-throw anything that isn't EPIPE so real crashes still surface
178
+ if ((err as NodeJS.ErrnoException).code === "ENOENT" &&
179
+ (err as any).syscall?.startsWith("spawn")) {
180
+ // spawn ENOENT — command not found (e.g., npx on Windows).
181
+ // This surfaces as an uncaught exception from child_process but
182
+ // is not a fatal process error. Log and continue instead of
183
+ // crashing auto-mode (#1384).
184
+ process.stderr.write(`[gsd] spawn ENOENT: ${(err as any).path ?? "unknown"} — command not found\n`);
185
+ return;
186
+ }
187
+ // Re-throw anything that isn't EPIPE/ENOENT so real crashes still surface
179
188
  throw err;
180
189
  };
181
190
  process.on("uncaughtException", _gsdEpipeGuard);
@@ -6,10 +6,11 @@
6
6
  * symlink replaces the original directory so all paths remain valid.
7
7
  */
8
8
 
9
- import { existsSync, lstatSync, mkdirSync, readdirSync, renameSync, cpSync, rmSync, symlinkSync } from "node:fs";
9
+ import { existsSync, lstatSync, mkdirSync, readdirSync, realpathSync, renameSync, cpSync, rmSync, symlinkSync } from "node:fs";
10
10
  import { join } from "node:path";
11
11
  import { externalGsdRoot } from "./repo-identity.js";
12
12
  import { getErrorMessage } from "./error-utils.js";
13
+ import { hasGitTrackedGsdFiles } from "./gitignore.js";
13
14
 
14
15
  export interface MigrationResult {
15
16
  migrated: boolean;
@@ -51,6 +52,28 @@ export function migrateToExternalState(basePath: string): MigrationResult {
51
52
  return { migrated: false, error: `Cannot stat .gsd: ${getErrorMessage(err)}` };
52
53
  }
53
54
 
55
+ // Skip if .gsd/ contains git-tracked files — the project intentionally
56
+ // keeps .gsd/ in version control and migration would destroy that.
57
+ if (hasGitTrackedGsdFiles(basePath)) {
58
+ return { migrated: false };
59
+ }
60
+
61
+ // Skip if .gsd/worktrees/ has active worktree directories (#1337).
62
+ // On Windows, active git worktrees hold OS-level directory handles that
63
+ // prevent rename/delete. Attempting migration causes EBUSY and data loss.
64
+ const worktreesDir = join(localGsd, "worktrees");
65
+ if (existsSync(worktreesDir)) {
66
+ try {
67
+ const entries = readdirSync(worktreesDir, { withFileTypes: true });
68
+ if (entries.some(e => e.isDirectory())) {
69
+ return { migrated: false };
70
+ }
71
+ } catch {
72
+ // Can't read worktrees dir — skip migration to be safe
73
+ return { migrated: false };
74
+ }
75
+ }
76
+
54
77
  const externalPath = externalGsdRoot(basePath);
55
78
  const migratingPath = join(basePath, ".gsd.migrating");
56
79
 
@@ -99,7 +122,29 @@ export function migrateToExternalState(basePath: string): MigrationResult {
99
122
  // Create symlink .gsd -> external path
100
123
  symlinkSync(externalPath, localGsd, "junction");
101
124
 
102
- // Remove .gsd.migrating
125
+ // Verify the symlink resolves correctly before removing the backup (#1377).
126
+ // On Windows, junction creation can silently succeed but resolve to the wrong
127
+ // target, or the external dir may not be accessible. If verification fails,
128
+ // restore from the backup.
129
+ try {
130
+ const resolved = realpathSync(localGsd);
131
+ const resolvedExternal = realpathSync(externalPath);
132
+ if (resolved !== resolvedExternal) {
133
+ // Symlink points to wrong target — restore backup
134
+ try { rmSync(localGsd, { force: true }); } catch { /* may not exist */ }
135
+ renameSync(migratingPath, localGsd);
136
+ return { migrated: false, error: `Migration verification failed: symlink resolves to ${resolved}, expected ${resolvedExternal}` };
137
+ }
138
+ // Verify we can read through the symlink
139
+ readdirSync(localGsd);
140
+ } catch (verifyErr) {
141
+ // Symlink broken or unreadable — restore backup
142
+ try { rmSync(localGsd, { force: true }); } catch { /* may not exist */ }
143
+ try { renameSync(migratingPath, localGsd); } catch { /* best-effort restore */ }
144
+ return { migrated: false, error: `Migration verification failed: ${getErrorMessage(verifyErr)}` };
145
+ }
146
+
147
+ // Remove .gsd.migrating only after symlink is verified
103
148
  rmSync(migratingPath, { recursive: true, force: true });
104
149
 
105
150
  return { migrated: true };