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