@opengsd/gsd-pi 1.0.2-dev.e70300c → 1.0.2-dev.fb7ddf1

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 (480) hide show
  1. package/README.md +63 -12
  2. package/dist/headless-answers.js +2 -1
  3. package/dist/headless-events.d.ts +1 -0
  4. package/dist/headless-events.js +8 -1
  5. package/dist/onboarding.js +22 -3
  6. package/dist/resource-loader.d.ts +7 -0
  7. package/dist/resource-loader.js +44 -9
  8. package/dist/resources/.managed-resources-content-hash +1 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
  10. package/dist/resources/extensions/context7/index.js +12 -2
  11. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  12. package/dist/resources/extensions/google-cli/index.js +30 -0
  13. package/dist/resources/extensions/google-cli/models.js +55 -0
  14. package/dist/resources/extensions/google-cli/package.json +11 -0
  15. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  16. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +81 -1
  18. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  19. package/dist/resources/extensions/gsd/auto/phases.js +38 -1
  20. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  21. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  22. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  23. package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
  24. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  25. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
  28. package/dist/resources/extensions/gsd/auto-verification.js +14 -2
  29. package/dist/resources/extensions/gsd/auto-worktree.js +34 -1
  30. package/dist/resources/extensions/gsd/auto.js +40 -2
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  32. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
  33. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  36. package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
  37. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  38. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  39. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  40. package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
  41. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  42. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  43. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  44. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  45. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  46. package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
  47. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  48. package/dist/resources/extensions/gsd/doctor.js +7 -2
  49. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  50. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  51. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  52. package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
  53. package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
  54. package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
  55. package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
  56. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  57. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  58. package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
  59. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  60. package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
  61. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  62. package/dist/resources/extensions/gsd/preferences.js +14 -2
  63. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  65. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  67. package/dist/resources/extensions/gsd/prompts/system.md +3 -20
  68. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  69. package/dist/resources/extensions/gsd/repo-identity.js +36 -6
  70. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
  72. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  73. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  74. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  75. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  76. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  77. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  78. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  79. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  80. package/dist/resources/extensions/gsd/skills.js +60 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  82. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  83. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  85. package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
  86. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  87. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  88. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  89. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  90. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  91. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  92. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  93. package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
  94. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  95. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  96. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  97. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  98. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  99. package/dist/resources/extensions/subagent/index.js +8 -15
  100. package/dist/resources/shared/package-manager-detection.js +36 -0
  101. package/dist/resources/skills/agent-browser/SKILL.md +1 -1
  102. package/dist/resources/skills/api-design/SKILL.md +1 -1
  103. package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
  104. package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
  105. package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
  106. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  107. package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  108. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  109. package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
  110. package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
  111. package/dist/resources/skills/forensics/SKILL.md +2 -2
  112. package/dist/resources/skills/grill-me/SKILL.md +1 -1
  113. package/dist/resources/skills/handoff/SKILL.md +1 -1
  114. package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  115. package/dist/resources/skills/observability/SKILL.md +1 -1
  116. package/dist/resources/skills/security-review/SKILL.md +1 -1
  117. package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
  118. package/dist/resources/skills/tdd/SKILL.md +1 -1
  119. package/dist/resources/skills/write-docs/SKILL.md +1 -1
  120. package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
  121. package/dist/update-check.d.ts +6 -2
  122. package/dist/update-check.js +7 -3
  123. package/dist/web/standalone/.next/BUILD_ID +1 -1
  124. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  125. package/dist/web/standalone/.next/build-manifest.json +2 -2
  126. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  127. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/index.html +1 -1
  145. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  152. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  153. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  155. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  156. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  157. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  158. package/package.json +5 -2
  159. package/packages/cloud-mcp-gateway/package.json +2 -2
  160. package/packages/contracts/dist/rpc.test.js +5 -0
  161. package/packages/contracts/dist/rpc.test.js.map +1 -1
  162. package/packages/contracts/dist/workflow.d.ts +15 -0
  163. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  164. package/packages/contracts/dist/workflow.js +16 -0
  165. package/packages/contracts/dist/workflow.js.map +1 -1
  166. package/packages/contracts/dist/workflow.test.js +1 -0
  167. package/packages/contracts/dist/workflow.test.js.map +1 -1
  168. package/packages/contracts/package.json +1 -1
  169. package/packages/daemon/package.json +4 -4
  170. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  171. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  172. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  173. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  174. package/packages/gsd-agent-core/package.json +5 -5
  175. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  177. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  180. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  182. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  184. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  186. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  198. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  202. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
  205. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  206. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
  208. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  209. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
  210. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  211. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
  212. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  213. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  214. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
  215. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  216. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  217. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  218. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  219. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  220. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  221. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  222. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  223. package/packages/gsd-agent-modes/package.json +7 -7
  224. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  225. package/packages/mcp-server/dist/server.js +7 -1
  226. package/packages/mcp-server/dist/server.js.map +1 -1
  227. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +47 -8
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/package.json +3 -3
  232. package/packages/native/package.json +1 -1
  233. package/packages/pi-agent-core/dist/agent-loop.js +16 -14
  234. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  235. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  236. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  237. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  238. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  239. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  240. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  241. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  242. package/packages/pi-agent-core/package.json +1 -1
  243. package/packages/pi-ai/dist/models.generated.d.ts +48 -206
  244. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  245. package/packages/pi-ai/dist/models.generated.js +67 -220
  246. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  247. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  248. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  249. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  250. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  252. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/types.d.ts +2 -0
  254. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/types.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
  257. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
  258. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
  259. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
  261. package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
  262. package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
  263. package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
  264. package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
  265. package/packages/pi-ai/package.json +1 -1
  266. package/packages/pi-coding-agent/README.md +1 -1
  267. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  268. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  271. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  274. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  276. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  278. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
  281. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
  283. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
  285. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
  288. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  289. package/packages/pi-coding-agent/package.json +8 -8
  290. package/packages/pi-tui/package.json +1 -1
  291. package/packages/rpc-client/package.json +2 -2
  292. package/pkg/package.json +1 -1
  293. package/scripts/install/detect-existing.js +17 -3
  294. package/scripts/install/npm-global.js +103 -33
  295. package/scripts/install.js +1 -0
  296. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
  297. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
  298. package/src/resources/extensions/context7/index.ts +15 -2
  299. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  300. package/src/resources/extensions/google-cli/index.ts +34 -0
  301. package/src/resources/extensions/google-cli/models.ts +57 -0
  302. package/src/resources/extensions/google-cli/package.json +11 -0
  303. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  304. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  305. package/src/resources/extensions/gsd/auto/loop.ts +96 -1
  306. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  307. package/src/resources/extensions/gsd/auto/phases.ts +47 -1
  308. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  309. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  310. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  311. package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
  312. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  313. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  314. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  315. package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
  316. package/src/resources/extensions/gsd/auto-verification.ts +18 -2
  317. package/src/resources/extensions/gsd/auto-worktree.ts +45 -1
  318. package/src/resources/extensions/gsd/auto.ts +50 -2
  319. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  320. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
  321. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  322. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
  323. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  324. package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
  325. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  326. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  327. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  328. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  329. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  330. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  331. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  332. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  333. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  334. package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
  335. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  336. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  337. package/src/resources/extensions/gsd/doctor.ts +7 -2
  338. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  339. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  340. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  341. package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
  342. package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
  343. package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
  344. package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
  345. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  346. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  347. package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
  348. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  349. package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
  350. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  351. package/src/resources/extensions/gsd/preferences.ts +17 -2
  352. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  353. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  354. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  355. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  356. package/src/resources/extensions/gsd/prompts/system.md +3 -20
  357. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  358. package/src/resources/extensions/gsd/repo-identity.ts +35 -7
  359. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  360. package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
  361. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  362. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  363. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  364. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  365. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  366. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  367. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  368. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  369. package/src/resources/extensions/gsd/skills.ts +75 -0
  370. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  371. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  372. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  373. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  374. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  375. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
  376. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  377. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
  378. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  379. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
  380. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  381. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
  382. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  383. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  384. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  385. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  386. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  387. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
  388. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  389. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
  390. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  391. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  393. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  394. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
  395. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  396. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  397. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
  398. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  399. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
  400. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
  401. package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
  402. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  403. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
  404. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
  405. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
  406. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  407. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  408. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  409. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
  410. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
  411. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
  412. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  413. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
  414. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  415. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  416. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
  417. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  418. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  419. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  420. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  421. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  422. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  423. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  424. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
  425. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  426. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  427. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  428. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  429. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  430. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  431. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  432. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
  433. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  434. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  435. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  436. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
  437. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
  438. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  439. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  440. package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
  441. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  442. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  443. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  444. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  445. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  446. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  447. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  448. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
  449. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  450. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  451. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  452. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  453. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  454. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  455. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  456. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  457. package/src/resources/extensions/subagent/index.ts +8 -15
  458. package/src/resources/shared/package-manager-detection.ts +39 -0
  459. package/src/resources/skills/agent-browser/SKILL.md +1 -1
  460. package/src/resources/skills/api-design/SKILL.md +1 -1
  461. package/src/resources/skills/code-optimizer/SKILL.md +6 -11
  462. package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
  463. package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
  464. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  465. package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  466. package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  467. package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
  468. package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
  469. package/src/resources/skills/forensics/SKILL.md +2 -2
  470. package/src/resources/skills/grill-me/SKILL.md +1 -1
  471. package/src/resources/skills/handoff/SKILL.md +1 -1
  472. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  473. package/src/resources/skills/observability/SKILL.md +1 -1
  474. package/src/resources/skills/security-review/SKILL.md +1 -1
  475. package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
  476. package/src/resources/skills/tdd/SKILL.md +1 -1
  477. package/src/resources/skills/write-docs/SKILL.md +1 -1
  478. package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
  479. /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
  480. /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
@@ -4,10 +4,12 @@
4
4
  * Shows current LLM context window usage and session token totals.
5
5
  */
6
6
 
7
- import type { ExtensionCommandContext, ContextUsage, SessionEntry } from "@gsd/pi-coding-agent";
7
+ import type { ExtensionCommandContext, ContextUsage, SessionEntry, Theme } from "@gsd/pi-coding-agent";
8
+ import { Key, matchesKey } from "@gsd/pi-tui";
8
9
 
9
10
  import { formatCost, formatPercent, formatTokenCount } from "./metrics.js";
10
11
  import { loadEffectiveGSDPreferences } from "./preferences.js";
12
+ import { renderDialogFrame, renderKeyHints } from "./tui/render-kit.js";
11
13
 
12
14
  export interface SessionTokenTotals {
13
15
  input: number;
@@ -160,6 +162,101 @@ export function formatUsageReport(options: {
160
162
  return lines.join("\n");
161
163
  }
162
164
 
165
+ async function showUsageDialog(
166
+ ctx: ExtensionCommandContext,
167
+ reportText: string,
168
+ ): Promise<boolean | undefined> {
169
+ return ctx.ui.custom<boolean>((tui, theme: Theme, _kb, done) => {
170
+ let cachedLines: string[] | undefined;
171
+ let cachedWidth: number | undefined;
172
+ let cachedRows: number | undefined;
173
+ let cachedScrollOffset: number | undefined;
174
+ let scrollOffset = 0;
175
+ let lastMaxScroll = 0;
176
+ let lastVisibleRows = 1;
177
+
178
+ function render(width: number): string[] {
179
+ const terminalRows = process.stdout.rows || 0;
180
+ if (
181
+ cachedLines &&
182
+ cachedWidth === width &&
183
+ cachedRows === terminalRows &&
184
+ cachedScrollOffset === scrollOffset
185
+ ) {
186
+ return cachedLines;
187
+ }
188
+
189
+ const contentWidth = Math.max(1, width - 4);
190
+ const body = reportText.split("\n");
191
+ if (body[0] === "Context Usage") body.shift();
192
+ while (body[0] === "") body.shift();
193
+ const maxOverlayRows = terminalRows > 0 ? Math.max(5, Math.floor(terminalRows * 0.8)) : 24;
194
+ const frameRows = 4;
195
+ const visibleRows = Math.max(1, maxOverlayRows - frameRows);
196
+ const maxScroll = Math.max(0, body.length - visibleRows);
197
+ scrollOffset = Math.min(Math.max(scrollOffset, 0), maxScroll);
198
+ lastMaxScroll = maxScroll;
199
+ lastVisibleRows = visibleRows;
200
+ const visible = body.slice(scrollOffset, scrollOffset + visibleRows);
201
+ const scrollable = body.length > visibleRows;
202
+
203
+ cachedLines = renderDialogFrame(theme, "Context Usage", visible, width, {
204
+ footer: renderKeyHints(theme, scrollable ? ["↑↓ scroll", "any key close"] : ["any key close"], contentWidth),
205
+ scroll: { offset: scrollOffset, visibleRows, totalRows: body.length },
206
+ });
207
+ cachedWidth = width;
208
+ cachedRows = terminalRows;
209
+ cachedScrollOffset = scrollOffset;
210
+ return cachedLines;
211
+ }
212
+
213
+ function scrollBy(delta: number): boolean {
214
+ if (lastMaxScroll <= 0) return false;
215
+ const nextOffset = Math.min(Math.max(scrollOffset + delta, 0), lastMaxScroll);
216
+ if (nextOffset !== scrollOffset) {
217
+ scrollOffset = nextOffset;
218
+ cachedLines = undefined;
219
+ cachedScrollOffset = undefined;
220
+ tui.requestRender();
221
+ }
222
+ return true;
223
+ }
224
+
225
+ return {
226
+ render,
227
+ invalidate: () => {
228
+ cachedLines = undefined;
229
+ cachedWidth = undefined;
230
+ cachedRows = undefined;
231
+ cachedScrollOffset = undefined;
232
+ },
233
+ handleInput: (data: string) => {
234
+ if (matchesKey(data, Key.down) || matchesKey(data, "j")) {
235
+ if (scrollBy(1)) return;
236
+ }
237
+ if (matchesKey(data, Key.up) || matchesKey(data, "k")) {
238
+ if (scrollBy(-1)) return;
239
+ }
240
+ if (matchesKey(data, Key.pageDown)) {
241
+ if (scrollBy(lastVisibleRows)) return;
242
+ }
243
+ if (matchesKey(data, Key.pageUp)) {
244
+ if (scrollBy(-lastVisibleRows)) return;
245
+ }
246
+ done(true);
247
+ },
248
+ };
249
+ }, {
250
+ overlay: true,
251
+ overlayOptions: {
252
+ width: "70%",
253
+ minWidth: 64,
254
+ maxHeight: "80%",
255
+ anchor: "center",
256
+ },
257
+ });
258
+ }
259
+
163
260
  export async function handleUsage(args: string, ctx: ExtensionCommandContext): Promise<void> {
164
261
  const contextUsage = ctx.getContextUsage?.();
165
262
  const sessionTotals = scanSessionTokenTotals(ctx.sessionManager.getEntries());
@@ -187,8 +284,16 @@ export async function handleUsage(args: string, ctx: ExtensionCommandContext): P
187
284
  return;
188
285
  }
189
286
 
190
- ctx.ui.notify(
191
- formatUsageReport({ modelLabel, contextUsage, sessionTotals }),
192
- "info",
193
- );
287
+ const reportText = formatUsageReport({ modelLabel, contextUsage, sessionTotals });
288
+
289
+ if (ctx.hasUI) {
290
+ try {
291
+ const result = await showUsageDialog(ctx, reportText);
292
+ if (result !== undefined) return;
293
+ } catch {
294
+ // Fall back to text notify below when custom overlays are unavailable.
295
+ }
296
+ }
297
+
298
+ ctx.ui.notify(reportText, "info");
194
299
  }
@@ -10,6 +10,7 @@
10
10
  import type { Theme } from "@gsd/pi-coding-agent";
11
11
  import { matchesKey, Key, truncateToWidth } from "@gsd/pi-tui";
12
12
 
13
+ import { renderDialogFrame, renderKeyHints } from "./tui/render-kit.js";
13
14
  import {
14
15
  loadEffectiveGSDPreferences,
15
16
  loadGlobalGSDPreferences,
@@ -231,6 +232,7 @@ export class GSDConfigOverlay {
231
232
  private onClose: () => void;
232
233
  private sections: ConfigSection[];
233
234
  private cachedLines?: string[];
235
+ private cachedWidth?: number;
234
236
  private scrollOffset = 0;
235
237
  private disposed = false;
236
238
 
@@ -247,6 +249,7 @@ export class GSDConfigOverlay {
247
249
 
248
250
  invalidate(): void {
249
251
  this.cachedLines = undefined;
252
+ this.cachedWidth = undefined;
250
253
  }
251
254
 
252
255
  dispose(): void {
@@ -286,16 +289,13 @@ export class GSDConfigOverlay {
286
289
  }
287
290
 
288
291
  render(width: number): string[] {
289
- if (this.cachedLines) return this.cachedLines;
292
+ if (this.cachedLines && this.cachedWidth === width) return this.cachedLines;
290
293
 
291
294
  const t = this.theme;
292
- const w = Math.max(width, 50);
295
+ const w = Math.max(1, width);
296
+ const contentWidth = Math.max(1, w - 4);
293
297
  const allLines: string[] = [];
294
298
 
295
- // Header
296
- allLines.push(t.bold(t.fg("accent", " GSD Configuration ")));
297
- allLines.push(t.fg("muted", "\u2500".repeat(w)));
298
-
299
299
  // Find max label width for alignment
300
300
  let maxLabel = 0;
301
301
  for (const section of this.sections) {
@@ -306,26 +306,29 @@ export class GSDConfigOverlay {
306
306
  const labelPad = Math.min(maxLabel + 2, 24);
307
307
 
308
308
  for (const section of this.sections) {
309
- allLines.push("");
309
+ if (allLines.length > 0) allLines.push("");
310
310
  allLines.push(t.bold(t.fg("accent", ` ${section.title}`)));
311
311
 
312
312
  for (const row of section.rows) {
313
313
  const label = t.fg("muted", ` ${row.label.padEnd(labelPad)}`);
314
314
  const value = row.accent ? t.bold(row.value) : row.value;
315
- allLines.push(truncateToWidth(`${label}${value}`, w));
315
+ allLines.push(truncateToWidth(`${label}${value}`, contentWidth));
316
316
  }
317
317
  }
318
318
 
319
- allLines.push("");
320
- allLines.push(t.fg("muted", ` ${"\u2500".repeat(w - 4)}`));
321
- allLines.push(t.fg("muted", " esc/q close \u2502 \u2191\u2193/jk scroll \u2502 /gsd prefs to edit"));
322
-
323
319
  // Apply scroll
324
- const maxScroll = Math.max(0, allLines.length - 20);
320
+ const terminalRows = process.stdout.rows || 32;
321
+ const maxBodyRows = Math.max(1, Math.min(allLines.length, terminalRows - 12));
322
+ const maxScroll = Math.max(0, allLines.length - maxBodyRows);
325
323
  this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
326
- const visible = allLines.slice(this.scrollOffset);
324
+ const visible = allLines.slice(this.scrollOffset, this.scrollOffset + maxBodyRows);
325
+ const footer = renderKeyHints(t, ["esc/q close", "\u2191\u2193/jk scroll", "/gsd prefs to edit"], contentWidth);
327
326
 
328
- this.cachedLines = visible;
329
- return visible;
327
+ this.cachedLines = renderDialogFrame(t, "GSD Configuration", visible, w, {
328
+ footer,
329
+ scroll: { offset: this.scrollOffset, visibleRows: maxBodyRows, totalRows: allLines.length },
330
+ });
331
+ this.cachedWidth = width;
332
+ return this.cachedLines;
330
333
  }
331
334
  }
@@ -3,11 +3,11 @@
3
3
  */
4
4
 
5
5
  import type { Theme, ThemeColor } from "@gsd/pi-coding-agent";
6
- import { matchesKey, Key, truncateToWidth, visibleWidth } from "@gsd/pi-tui";
6
+ import { matchesKey, Key, truncateToWidth } from "@gsd/pi-tui";
7
7
 
8
8
  import type { ContextBreakdownReport, ContextSectionBreakdown } from "./commands-context.js";
9
9
  import { formatTokenCount } from "./metrics.js";
10
- import { renderProgressBar, rightAlign } from "./tui/render-kit.js";
10
+ import { renderDialogFrame, renderKeyHints, renderProgressBar, rightAlign } from "./tui/render-kit.js";
11
11
 
12
12
  const SECTION_COLORS: ThemeColor[] = ["accent", "success", "warning", "borderAccent", "text"];
13
13
 
@@ -70,6 +70,7 @@ export class GSDContextOverlay {
70
70
  private onClose: () => void;
71
71
  private report: ContextBreakdownReport;
72
72
  private cachedLines?: string[];
73
+ private cachedWidth?: number;
73
74
  private scrollOffset = 0;
74
75
  private disposed = false;
75
76
 
@@ -87,6 +88,7 @@ export class GSDContextOverlay {
87
88
 
88
89
  invalidate(): void {
89
90
  this.cachedLines = undefined;
91
+ this.cachedWidth = undefined;
90
92
  }
91
93
 
92
94
  dispose(): void {
@@ -125,24 +127,22 @@ export class GSDContextOverlay {
125
127
  }
126
128
 
127
129
  render(width: number): string[] {
128
- if (this.cachedLines) return this.cachedLines;
130
+ if (this.cachedLines && this.cachedWidth === width) return this.cachedLines;
129
131
 
130
132
  const theme = this.theme;
131
- const w = Math.max(width, 60);
133
+ const w = Math.max(1, width);
134
+ const contentWidth = Math.max(1, w - 4);
132
135
  const totals = getContextChartTotals(this.report);
133
136
  const chartTotal = Math.max(totals.inContext, totals.estimated, 1);
134
137
  const lines: string[] = [];
135
138
 
136
- lines.push(theme.bold(theme.fg("accent", " Context Breakdown ")));
137
- lines.push(theme.fg("muted", "─".repeat(w)));
138
-
139
139
  if (this.report.modelLabel) {
140
- lines.push(rightAlign(theme.fg("muted", "Model"), theme.fg("text", this.report.modelLabel), w));
140
+ lines.push(rightAlign(theme.fg("muted", "Model"), theme.fg("text", this.report.modelLabel), contentWidth));
141
141
  }
142
142
 
143
143
  lines.push("");
144
144
  if (totals.window != null) {
145
- const usageBarWidth = Math.max(20, w - 28);
145
+ const usageBarWidth = Math.max(8, contentWidth - 28);
146
146
  const usageBar = renderProgressBar(theme, totals.inContext, totals.window, usageBarWidth, {
147
147
  filledColor: totals.inContext / totals.window > 0.85 ? "warning" : "accent",
148
148
  });
@@ -151,7 +151,7 @@ export class GSDContextOverlay {
151
151
  lines.push(` ${theme.fg("muted", "Estimated")} ${theme.fg("text", formatTokenCount(chartTotal))}`);
152
152
  }
153
153
 
154
- const splitWidth = Math.max(16, Math.floor((w - 8) / 2));
154
+ const splitWidth = Math.max(8, Math.floor((contentWidth - 8) / 2));
155
155
  const systemBar = renderProgressBar(theme, totals.systemTokens, chartTotal, splitWidth, { filledColor: "accent" });
156
156
  const convBar = renderProgressBar(theme, totals.conversationTokens, chartTotal, splitWidth, { filledColor: "success" });
157
157
  lines.push("");
@@ -160,11 +160,11 @@ export class GSDContextOverlay {
160
160
 
161
161
  lines.push("");
162
162
  lines.push(theme.bold(theme.fg("accent", " System prompt")));
163
- lines.push(...renderSectionBars(theme, this.report.systemSections, chartTotal, w, 22));
163
+ lines.push(...renderSectionBars(theme, this.report.systemSections, chartTotal, contentWidth, 22));
164
164
 
165
165
  lines.push("");
166
166
  lines.push(theme.bold(theme.fg("accent", " Conversation")));
167
- lines.push(...renderSectionBars(theme, this.report.conversationSections, chartTotal, w, 22));
167
+ lines.push(...renderSectionBars(theme, this.report.conversationSections, chartTotal, contentWidth, 22));
168
168
 
169
169
  lines.push("");
170
170
  lines.push(theme.bold(theme.fg("accent", " Skills")));
@@ -172,7 +172,7 @@ export class GSDContextOverlay {
172
172
  if (skills.available.length > 0) {
173
173
  lines.push(` ${theme.fg("muted", "Available")} ${theme.fg("text", `${skills.available.length}`)}`);
174
174
  const preview = skills.available.slice(0, 8).join(", ");
175
- lines.push(truncateToWidth(` ${preview}${skills.available.length > 8 ? "…" : ""}`, w));
175
+ lines.push(truncateToWidth(` ${preview}${skills.available.length > 8 ? "…" : ""}`, contentWidth));
176
176
  } else {
177
177
  lines.push(theme.fg("dim", " none in prompt"));
178
178
  }
@@ -187,13 +187,18 @@ export class GSDContextOverlay {
187
187
  lines.push(theme.bold(theme.fg("accent", " Agents")));
188
188
  lines.push(` ${theme.fg("muted", "Subagent spawns")} ${theme.fg("text", String(this.report.subagentSpawns))}`);
189
189
 
190
- lines.push("");
191
- lines.push(theme.fg("muted", ` ${"─".repeat(Math.max(0, w - 4))}`));
192
- lines.push(theme.fg("muted", " esc/q close │ ↑↓ scroll │ /gsd context --open for browser chart"));
193
-
194
- const maxScroll = Math.max(0, lines.length - 24);
190
+ const terminalRows = process.stdout.rows || 32;
191
+ const maxBodyRows = Math.max(1, Math.min(lines.length, terminalRows - 12));
192
+ const maxScroll = Math.max(0, lines.length - maxBodyRows);
195
193
  this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
196
- this.cachedLines = lines.slice(this.scrollOffset);
194
+ const visible = lines.slice(this.scrollOffset, this.scrollOffset + maxBodyRows);
195
+ const footer = renderKeyHints(theme, ["esc/q close", "↑↓ scroll", "/gsd context --open"], contentWidth);
196
+
197
+ this.cachedLines = renderDialogFrame(theme, "Context Breakdown", visible, w, {
198
+ footer,
199
+ scroll: { offset: this.scrollOffset, visibleRows: maxBodyRows, totalRows: lines.length },
200
+ });
201
+ this.cachedWidth = width;
197
202
  return this.cachedLines;
198
203
  }
199
204
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import type { Theme } from "@gsd/pi-coding-agent";
11
- import { truncateToWidth, visibleWidth, matchesKey, Key } from "@gsd/pi-tui";
11
+ import { truncateToWidth, matchesKey, Key } from "@gsd/pi-tui";
12
12
  import { deriveState } from "./state.js";
13
13
  import { loadFile } from "./files.js";
14
14
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
@@ -29,6 +29,7 @@ import { estimateTimeRemaining } from "./auto-dashboard.js";
29
29
  import { computeProgressScore, formatProgressLine } from "./progress-score.js";
30
30
  import { runEnvironmentChecks, type EnvironmentCheckResult } from "./doctor-environment.js";
31
31
  import { formattedShortcutPair } from "./shortcut-defs.js";
32
+ import { renderDialogFrame, renderKeyHints } from "./tui/render-kit.js";
32
33
 
33
34
  export function unitLabel(type: string): string {
34
35
  switch (type) {
@@ -258,35 +259,26 @@ export class GSDDashboardOverlay {
258
259
 
259
260
  const content = this.buildContentLines(width);
260
261
  const viewportHeight = Math.max(5, process.stdout.rows ? process.stdout.rows - 8 : 24);
261
- const chromeHeight = 2;
262
- const visibleContentRows = Math.max(1, viewportHeight - chromeHeight);
262
+ const visibleContentRows = Math.max(1, viewportHeight - 4);
263
263
  const maxScroll = Math.max(0, content.length - visibleContentRows);
264
264
  this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
265
265
  const visibleContent = content.slice(this.scrollOffset, this.scrollOffset + visibleContentRows);
266
-
267
- const lines = this.wrapInBox(visibleContent, width);
266
+ const contentWidth = Math.max(1, width - 4);
267
+ const footer = renderKeyHints(
268
+ this.theme,
269
+ ["↑↓ scroll", "g/G top/end", `Esc/${formattedShortcutPair("dashboard")} close`],
270
+ contentWidth,
271
+ );
272
+ const lines = renderDialogFrame(this.theme, "GSD Dashboard", visibleContent, width, {
273
+ footer,
274
+ scroll: { offset: this.scrollOffset, visibleRows: visibleContentRows, totalRows: content.length },
275
+ });
268
276
 
269
277
  this.cachedWidth = width;
270
278
  this.cachedLines = lines;
271
279
  return lines;
272
280
  }
273
281
 
274
- private wrapInBox(inner: string[], width: number): string[] {
275
- const th = this.theme;
276
- const border = (s: string) => th.fg("borderAccent", s);
277
- const innerWidth = width - 4;
278
- const lines: string[] = [];
279
-
280
- lines.push(border("╭" + "─".repeat(width - 2) + "╮"));
281
- for (const line of inner) {
282
- const truncated = truncateToWidth(line, innerWidth);
283
- const padWidth = Math.max(0, innerWidth - visibleWidth(truncated));
284
- lines.push(border("│") + " " + truncated + " ".repeat(padWidth) + " " + border("│"));
285
- }
286
- lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
287
- return lines;
288
- }
289
-
290
282
  private buildContentLines(width: number): string[] {
291
283
  const th = this.theme;
292
284
  const shellWidth = width - 4;
@@ -303,7 +295,6 @@ export class GSDDashboardOverlay {
303
295
  const hr = () => row(th.fg("dim", "─".repeat(contentWidth)));
304
296
  const centered = (content: string) => row(centerLine(content, contentWidth));
305
297
 
306
- const title = th.fg("accent", th.bold("GSD Dashboard"));
307
298
  const isRemote = !!this.dashData.remoteSession;
308
299
  const status = this.dashData.active
309
300
  ? `${Date.now() % 2000 < 1000 ? th.fg("success", "●") : th.fg("dim", "○")} ${th.fg("success", "AUTO")}`
@@ -328,7 +319,7 @@ export class GSDDashboardOverlay {
328
319
  } else if (isRemote) {
329
320
  elapsedParts = th.fg("dim", `since ${this.dashData.remoteSession!.startedAt.replace("T", " ").slice(0, 19)}`);
330
321
  }
331
- lines.push(row(joinColumns(`${title} ${status}${worktreeTag}`, elapsedParts, contentWidth)));
322
+ lines.push(row(joinColumns(`${status}${worktreeTag}`, elapsedParts, contentWidth)));
332
323
 
333
324
  // Progress score — traffic light indicator (#1221)
334
325
  if (this.dashData.active || this.dashData.paused) {
@@ -610,10 +601,6 @@ export class GSDDashboardOverlay {
610
601
  }
611
602
  }
612
603
 
613
- lines.push(blank());
614
- lines.push(hr());
615
- lines.push(centered(th.fg("dim", `↑↓ scroll · g/G top/end · Esc/${formattedShortcutPair("dashboard")} close`)));
616
-
617
604
  return lines;
618
605
  }
619
606
 
@@ -3,6 +3,7 @@ import { join } from "node:path";
3
3
 
4
4
  import type { DoctorIssue } from "./doctor-types.js";
5
5
  import { isDbAvailable, _getAdapter } from "./gsd-db.js";
6
+ import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
6
7
  import { resolveGsdPathContract, resolveMilestoneFile } from "./paths.js";
7
8
  import { deriveState } from "./state.js";
8
9
  import { readEvents } from "./workflow-events.js";
@@ -151,6 +152,104 @@ export async function checkEngineHealth(
151
152
  } catch {
152
153
  // Non-fatal — duplicate ID check failed
153
154
  }
155
+
156
+ // e. Completed milestone dispatch history but DB reopened without an explicit reopen event.
157
+ try {
158
+ const reopened = adapter
159
+ .prepare(
160
+ `SELECT m.id, m.status, ud.started_at, ud.ended_at
161
+ FROM milestones m
162
+ JOIN unit_dispatches ud ON ud.milestone_id = m.id
163
+ WHERE m.status NOT IN ('complete', 'done', 'skipped', 'closed')
164
+ AND ud.unit_type = 'complete-milestone'
165
+ AND ud.unit_id = m.id
166
+ AND ud.status = 'completed'
167
+ AND ud.id = (
168
+ SELECT latest.id
169
+ FROM unit_dispatches latest
170
+ WHERE latest.milestone_id = m.id
171
+ AND latest.unit_type = 'complete-milestone'
172
+ AND latest.unit_id = m.id
173
+ AND latest.status = 'completed'
174
+ ORDER BY COALESCE(latest.ended_at, latest.started_at) DESC, latest.id DESC
175
+ LIMIT 1
176
+ )
177
+ ORDER BY m.id`,
178
+ )
179
+ .all() as Array<{ id: string; status: string; started_at: string | null; ended_at: string | null }>;
180
+
181
+ for (const row of reopened) {
182
+ const completedAt = row.ended_at ?? row.started_at ?? null;
183
+ const reopenAt = latestExplicitReopenAt(basePath, row.id);
184
+ if (reopenAt && (!completedAt || Date.parse(reopenAt) > Date.parse(completedAt))) continue;
185
+ issues.push({
186
+ severity: "error",
187
+ code: "completed_milestone_reopened",
188
+ scope: "milestone",
189
+ unitId: row.id,
190
+ message: `Milestone ${row.id} has completed complete-milestone dispatch history but DB status is ${row.status}. Explicitly reopen or recover before planning it again.`,
191
+ fixable: false,
192
+ });
193
+ }
194
+ } catch {
195
+ // Non-fatal — completed-milestone reopen check failed
196
+ }
197
+
198
+ // f. Completion artifacts disagree with open DB hierarchy rows.
199
+ try {
200
+ const rows = adapter
201
+ .prepare(
202
+ `SELECT a.path, a.artifact_type, a.milestone_id, a.slice_id, a.task_id, a.imported_at,
203
+ m.status AS milestone_status,
204
+ s.status AS slice_status,
205
+ t.status AS task_status,
206
+ (SELECT COUNT(*) FROM tasks tt WHERE tt.milestone_id = a.milestone_id AND tt.slice_id = a.slice_id) AS task_count
207
+ FROM artifacts a
208
+ JOIN milestones m ON m.id = a.milestone_id
209
+ LEFT JOIN slices s ON s.milestone_id = a.milestone_id AND s.id = a.slice_id
210
+ LEFT JOIN tasks t ON t.milestone_id = a.milestone_id AND t.slice_id = a.slice_id AND t.id = a.task_id
211
+ WHERE a.artifact_type = 'SUMMARY'
212
+ AND m.status NOT IN ('complete', 'done', 'skipped', 'closed')`,
213
+ )
214
+ .all() as Array<{
215
+ path: string;
216
+ milestone_id: string;
217
+ slice_id: string | null;
218
+ task_id: string | null;
219
+ imported_at: string | null;
220
+ slice_status: string | null;
221
+ task_status: string | null;
222
+ task_count: number;
223
+ }>;
224
+
225
+ const seen = new Set<string>();
226
+ for (const row of rows) {
227
+ const reopenAt = latestExplicitReopenAt(basePath, row.milestone_id);
228
+ if (!isAfter(row.imported_at, reopenAt)) continue;
229
+ const isSliceSummary = row.slice_id && !row.task_id && row.slice_status && !["complete", "done", "skipped", "closed"].includes(row.slice_status);
230
+ const isTaskSummary = row.slice_id && row.task_id && (!row.task_status || !["complete", "done", "skipped", "closed"].includes(row.task_status));
231
+ const isTaskArtifactWithoutDbTasks = row.slice_id && row.task_id && Number(row.task_count) === 0;
232
+ if (!isSliceSummary && !isTaskSummary && !isTaskArtifactWithoutDbTasks) continue;
233
+
234
+ const unitId = row.task_id
235
+ ? `${row.milestone_id}/${row.slice_id}/${row.task_id}`
236
+ : row.slice_id
237
+ ? `${row.milestone_id}/${row.slice_id}`
238
+ : row.milestone_id;
239
+ if (seen.has(unitId)) continue;
240
+ seen.add(unitId);
241
+ issues.push({
242
+ severity: "error",
243
+ code: "artifact_db_status_divergence",
244
+ scope: row.task_id ? "task" : row.slice_id ? "slice" : "milestone",
245
+ unitId,
246
+ message: `Completion artifact ${row.path} exists while DB state for ${unitId} is still open or missing. Runtime will not import it silently; run explicit recovery/repair after review.`,
247
+ fixable: false,
248
+ });
249
+ }
250
+ } catch {
251
+ // Non-fatal — artifact/DB status drift check failed
252
+ }
154
253
  }
155
254
  } catch {
156
255
  // Non-fatal — DB constraint checks failed entirely
@@ -1,7 +1,7 @@
1
1
  // gsd-pi doctor git health checks
2
2
  import { spawnSync } from "node:child_process";
3
- import { existsSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
4
- import { join } from "node:path";
3
+ import { cpSync, existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
5
 
6
6
  import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
7
7
  import { loadFile } from "./files.js";
@@ -56,11 +56,47 @@ function isSameOrNestedPath(candidate: string, container: string): boolean {
56
56
  normalizedCandidate.startsWith(`${normalizedContainer}/`);
57
57
  }
58
58
 
59
- function hasProjectContentOnDisk(dirPath: string): boolean {
59
+ function normalizeGitPath(path: string): string {
60
+ return path.replaceAll("\\", "/").replace(/^\.\//, "");
61
+ }
62
+
63
+ function isProjectContentPath(path: string): boolean {
64
+ const normalized = normalizeGitPath(path);
65
+ if (!normalized || normalized.endsWith("/")) return false;
66
+ if (normalized === ".gitignore" || normalized === ".gitattributes") return false;
67
+ if (normalized.endsWith(".DS_Store")) return false;
68
+ const parts = normalized.split("/");
69
+ return !parts.some(part => part === ".git" || part === ".gsd");
70
+ }
71
+
72
+ function gitLines(basePath: string, args: string[]): string[] {
73
+ const result = spawnSync("git", args, {
74
+ cwd: basePath,
75
+ encoding: "utf-8",
76
+ });
77
+ if (result.status !== 0) return [];
78
+ return result.stdout
79
+ .split("\n")
80
+ .map(line => normalizeGitPath(line.trim()))
81
+ .filter(isProjectContentPath);
82
+ }
83
+
84
+ function listProjectContentFiles(basePath: string): string[] {
85
+ return [...new Set([
86
+ ...gitLines(basePath, ["ls-files"]),
87
+ ...gitLines(basePath, ["ls-files", "--others", "--exclude-standard"]),
88
+ ])];
89
+ }
90
+
91
+ function hasMaterializedProjectContentFallback(dirPath: string): boolean {
60
92
  try {
61
93
  for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
62
- if (entry.name === ".git" || entry.name === ".gsd") continue;
94
+ if (!isProjectContentPath(entry.name)) continue;
63
95
  if (entry.name === ".DS_Store") continue;
96
+ if (entry.isDirectory()) {
97
+ if (hasMaterializedProjectContentFallback(join(dirPath, entry.name))) return true;
98
+ continue;
99
+ }
64
100
  return true;
65
101
  }
66
102
  } catch {
@@ -69,6 +105,27 @@ function hasProjectContentOnDisk(dirPath: string): boolean {
69
105
  return false;
70
106
  }
71
107
 
108
+ function hasProjectContentOnDisk(dirPath: string): boolean {
109
+ const gitProjectFiles = listProjectContentFiles(dirPath);
110
+ if (gitProjectFiles.length > 0) {
111
+ return gitProjectFiles.some(file => existsSync(join(dirPath, file)));
112
+ }
113
+ return hasMaterializedProjectContentFallback(dirPath);
114
+ }
115
+
116
+ function copyProjectRootContentIntoWorktree(projectRoot: string, worktreeRoot: string): number {
117
+ let copied = 0;
118
+ for (const relPath of listProjectContentFiles(projectRoot)) {
119
+ const src = join(projectRoot, relPath);
120
+ if (!existsSync(src)) continue;
121
+ const dst = join(worktreeRoot, relPath);
122
+ mkdirSync(dirname(dst), { recursive: true });
123
+ cpSync(src, dst, { recursive: true, force: true });
124
+ copied++;
125
+ }
126
+ return copied;
127
+ }
128
+
72
129
  function getSnapshotDiffCheckFailure(basePath: string): string | null {
73
130
  const failures: string[] = [];
74
131
 
@@ -176,7 +233,17 @@ export async function checkGitHealth(
176
233
  if (reset.status !== 0) {
177
234
  throw new Error(reset.stderr || reset.error?.message || "git reset --hard failed");
178
235
  }
179
- fixesApplied.push(`recreated empty worktree ${wt.path}`);
236
+ const copied = !hasProjectContentOnDisk(recreated.path) && hasProjectContentOnDisk(basePath)
237
+ ? copyProjectRootContentIntoWorktree(basePath, recreated.path)
238
+ : 0;
239
+ if (!hasProjectContentOnDisk(recreated.path) && hasProjectContentOnDisk(basePath)) {
240
+ throw new Error("recreated worktree still has no project content");
241
+ }
242
+ fixesApplied.push(
243
+ copied > 0
244
+ ? `recreated empty worktree ${wt.path} and copied ${copied} project file${copied === 1 ? "" : "s"} from project root`
245
+ : `recreated empty worktree ${wt.path}`,
246
+ );
180
247
  } catch {
181
248
  fixesApplied.push(`failed to recreate empty worktree ${wt.path}`);
182
249
  }