gsd-pi 2.81.0 → 2.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/README.md +36 -24
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto/loop.js +111 -8
  4. package/dist/resources/extensions/gsd/auto/phases.js +190 -97
  5. package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
  6. package/dist/resources/extensions/gsd/auto/session.js +9 -0
  7. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
  8. package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
  9. package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
  11. package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
  12. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
  13. package/dist/resources/extensions/gsd/auto-start.js +20 -23
  14. package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
  15. package/dist/resources/extensions/gsd/auto-verification.js +12 -6
  16. package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
  17. package/dist/resources/extensions/gsd/auto.js +265 -76
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
  19. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -2
  20. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
  21. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
  22. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
  23. package/dist/resources/extensions/gsd/git-service.js +2 -1
  24. package/dist/resources/extensions/gsd/gsd-db.js +7 -23
  25. package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
  26. package/dist/resources/extensions/gsd/health-widget.js +4 -10
  27. package/dist/resources/extensions/gsd/markdown-renderer.js +0 -95
  28. package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
  29. package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
  30. package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
  31. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
  32. package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  33. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  34. package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
  35. package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
  36. package/dist/resources/extensions/gsd/session-lock.js +40 -0
  37. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
  38. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
  39. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
  40. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
  41. package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
  42. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
  43. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
  44. package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
  45. package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
  46. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
  47. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
  48. package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
  49. package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
  50. package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
  51. package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
  52. package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
  53. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  54. package/dist/resources/extensions/gsd/worktree-lifecycle.js +722 -316
  55. package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
  56. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  57. package/dist/web/standalone/.next/BUILD_ID +1 -1
  58. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  59. package/dist/web/standalone/.next/build-manifest.json +2 -2
  60. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/index.html +1 -1
  77. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  84. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  86. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  87. package/dist/welcome-screen.d.ts +0 -7
  88. package/dist/welcome-screen.js +60 -69
  89. package/package.json +1 -1
  90. package/packages/daemon/package.json +2 -2
  91. package/packages/mcp-server/package.json +2 -2
  92. package/packages/native/package.json +1 -1
  93. package/packages/pi-agent-core/package.json +1 -1
  94. package/packages/pi-ai/package.json +1 -1
  95. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
  96. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
  97. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
  98. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
  99. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
  100. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
  102. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
  103. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
  104. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
  105. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
  106. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
  107. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
  108. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
  109. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
  110. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  112. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
  113. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  114. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
  115. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
  117. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
  119. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  120. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
  121. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  122. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
  124. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
  128. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
  130. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
  131. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
  132. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
  133. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
  134. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
  135. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
  136. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
  137. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
  138. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  139. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
  140. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  141. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  142. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  143. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  144. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  145. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  146. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
  147. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
  150. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
  152. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
  153. package/packages/pi-coding-agent/package.json +1 -1
  154. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
  155. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
  156. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
  157. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
  158. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
  159. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
  160. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
  161. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
  162. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
  163. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
  164. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
  165. package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
  166. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
  167. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  168. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
  169. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
  170. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
  171. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  172. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
  173. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  174. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  175. package/packages/pi-tui/dist/overlay-layout.js +9 -6
  176. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  177. package/packages/pi-tui/package.json +1 -1
  178. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
  179. package/packages/pi-tui/src/overlay-layout.ts +10 -7
  180. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  181. package/packages/rpc-client/package.json +1 -1
  182. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  183. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  184. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  185. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  186. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  187. package/pkg/dist/modes/interactive/theme/theme.js +105 -1
  188. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  189. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  190. package/pkg/dist/modes/interactive/theme/themes.js +27 -26
  191. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  192. package/pkg/package.json +1 -1
  193. package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
  194. package/src/resources/extensions/gsd/auto/loop.ts +113 -9
  195. package/src/resources/extensions/gsd/auto/phases.ts +144 -19
  196. package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
  197. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  198. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  199. package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
  200. package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
  201. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
  202. package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
  203. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  204. package/src/resources/extensions/gsd/auto-start.ts +22 -22
  205. package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
  206. package/src/resources/extensions/gsd/auto-verification.ts +12 -6
  207. package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
  208. package/src/resources/extensions/gsd/auto.ts +295 -75
  209. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
  210. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -2
  211. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
  212. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
  213. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
  214. package/src/resources/extensions/gsd/git-service.ts +2 -0
  215. package/src/resources/extensions/gsd/gsd-db.ts +7 -23
  216. package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
  217. package/src/resources/extensions/gsd/health-widget.ts +6 -10
  218. package/src/resources/extensions/gsd/journal.ts +2 -0
  219. package/src/resources/extensions/gsd/markdown-renderer.ts +4 -95
  220. package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
  221. package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
  222. package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
  223. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
  224. package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  225. package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  226. package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
  227. package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
  228. package/src/resources/extensions/gsd/session-lock.ts +41 -0
  229. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  230. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
  231. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
  232. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
  233. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  234. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  235. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  236. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  237. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  238. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  239. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
  240. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  241. package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
  242. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  243. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
  244. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +654 -176
  245. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +291 -4
  246. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +16 -1
  247. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
  248. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  249. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
  250. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
  251. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
  252. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  253. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
  254. package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
  255. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
  256. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
  257. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
  258. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
  259. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
  260. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
  261. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
  262. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
  263. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
  264. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
  265. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
  266. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
  267. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +24 -1
  268. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
  269. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
  270. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
  271. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +65 -58
  272. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
  273. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
  274. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
  275. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
  276. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  277. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
  278. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
  279. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +572 -118
  280. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
  281. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
  282. package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
  283. package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
  284. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  285. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  286. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1151 -524
  287. package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
  288. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
  289. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → S44UQTFCUdA44dkjfYt6S}/_buildManifest.js +0 -0
  290. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → S44UQTFCUdA44dkjfYt6S}/_ssgManifest.js +0 -0
@@ -89,14 +89,59 @@ test("emitAutoExit records reason and unmerged-work signal", () => {
89
89
  reason: "pause",
90
90
  milestoneId: "M003",
91
91
  milestoneMerged: false,
92
+ isolationMode: "worktree",
93
+ worktreeActive: true,
92
94
  });
93
95
  const entries = queryJournal(base, { eventType: "auto-exit" });
94
96
  assert.equal(entries.length, 1);
95
97
  assert.equal(entries[0].data?.reason, "pause");
96
98
  assert.equal(entries[0].data?.milestoneMerged, false);
99
+ assert.equal(entries[0].data?.isolationMode, "worktree");
100
+ assert.equal(entries[0].data?.worktreeActive, true);
97
101
  } finally { cleanup(base); }
98
102
  });
99
103
 
104
+ test("summarizeWorktreeTelemetry only counts unmerged exits from active worktrees", (t) => {
105
+ const base = makeTmpBase();
106
+ t.after(() => cleanup(base));
107
+
108
+ emitAutoExit(base, {
109
+ reason: "pause",
110
+ milestoneId: "M003",
111
+ milestoneMerged: false,
112
+ isolationMode: "none",
113
+ worktreeActive: false,
114
+ });
115
+ emitAutoExit(base, {
116
+ reason: "stop",
117
+ milestoneId: "M004",
118
+ milestoneMerged: false,
119
+ isolationMode: "branch",
120
+ worktreeActive: false,
121
+ });
122
+ emitAutoExit(base, {
123
+ reason: "other",
124
+ milestoneId: "M005",
125
+ milestoneMerged: false,
126
+ isolationMode: "worktree",
127
+ worktreeActive: false,
128
+ });
129
+ emitAutoExit(base, {
130
+ reason: "blocked",
131
+ milestoneId: "M006",
132
+ milestoneMerged: false,
133
+ });
134
+
135
+ const summary = summarizeWorktreeTelemetry(base);
136
+ assert.equal(summary.exitsWithUnmergedWork, 0);
137
+ assert.deepStrictEqual(summary.exitsByReason, {
138
+ "pause": 1,
139
+ "stop": 1,
140
+ "other": 1,
141
+ "blocked": 1,
142
+ });
143
+ });
144
+
100
145
  test("summarizeWorktreeTelemetry aggregates events correctly", () => {
101
146
  const base = makeTmpBase();
102
147
  try {
@@ -110,8 +155,20 @@ test("summarizeWorktreeTelemetry aggregates events correctly", () => {
110
155
  emitWorktreeOrphaned(base, "M002", { reason: "in-progress-unmerged", commitsAhead: 2 });
111
156
  emitWorktreeOrphaned(base, "M003", { reason: "complete-unmerged" });
112
157
 
113
- emitAutoExit(base, { reason: "pause", milestoneId: "M002", milestoneMerged: false });
114
- emitAutoExit(base, { reason: "stop", milestoneId: "M002", milestoneMerged: false });
158
+ emitAutoExit(base, {
159
+ reason: "pause",
160
+ milestoneId: "M002",
161
+ milestoneMerged: false,
162
+ isolationMode: "worktree",
163
+ worktreeActive: true,
164
+ });
165
+ emitAutoExit(base, {
166
+ reason: "stop",
167
+ milestoneId: "M002",
168
+ milestoneMerged: false,
169
+ isolationMode: "worktree",
170
+ worktreeActive: true,
171
+ });
115
172
  emitAutoExit(base, { reason: "all-complete", milestoneId: "M001", milestoneMerged: true });
116
173
 
117
174
  const summary = summarizeWorktreeTelemetry(base);
@@ -242,6 +242,24 @@ test('planning-dispatch: blocks recon agent under closeout policy', () => {
242
242
  assert.doesNotMatch(r.reason!, /read-only specialists/);
243
243
  });
244
244
 
245
+ test('complete-slice closeout policy blocks edits to user source', () => {
246
+ const r = shouldBlockPlanningUnit('edit', join(BASE, 'src', 'main.ts'), BASE, 'complete-slice', PLANNING_DISPATCH_REVIEW);
247
+ assert.strictEqual(r.block, true);
248
+ assert.match(r.reason!, /complete-slice/);
249
+ assert.match(r.reason!, /writes are restricted to \.gsd/);
250
+ });
251
+
252
+ test('complete-slice closeout policy blocks non-allowlisted verification bash', () => {
253
+ const r = shouldBlockPlanningUnit('bash', 'go test ./...', BASE, 'complete-slice', PLANNING_DISPATCH_REVIEW);
254
+ assert.strictEqual(r.block, true);
255
+ assert.match(r.reason!, /bash is restricted/);
256
+ });
257
+
258
+ test('complete-slice closeout policy allows gsd_exec verification surface', () => {
259
+ const r = shouldBlockPlanningUnit('gsd_exec', '', BASE, 'complete-slice', PLANNING_DISPATCH_REVIEW);
260
+ assert.strictEqual(r.block, false);
261
+ });
262
+
245
263
  test('planning-dispatch: still blocks writes to user source (write isolation preserved)', () => {
246
264
  const r = shouldBlockPlanningUnit('write', join(BASE, 'src', 'main.ts'), BASE, 'plan-slice', PLANNING_DISPATCH);
247
265
  assert.strictEqual(r.block, true);
@@ -0,0 +1,109 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Shared terminal rendering helpers for GSD extension TUI surfaces.
3
+
4
+ import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
5
+
6
+ export interface ThemeLike {
7
+ fg(color: string, text: string): string;
8
+ bold(text: string): string;
9
+ }
10
+
11
+ export function safeLine(text: string, width: number, ellipsis = "…"): string {
12
+ if (width <= 0) return "";
13
+ return truncateToWidth(text, width, ellipsis);
14
+ }
15
+
16
+ export function padRightVisible(text: string, width: number): string {
17
+ if (width <= 0) return "";
18
+ const truncated = safeLine(text, width);
19
+ const pad = Math.max(0, width - visibleWidth(truncated));
20
+ return truncated + " ".repeat(pad);
21
+ }
22
+
23
+ export function rightAlign(left: string, right: string, width: number): string {
24
+ if (width <= 0) return "";
25
+ if (!right) return safeLine(left, width);
26
+ if (!left) return safeLine(" ".repeat(Math.max(0, width - visibleWidth(right))) + right, width);
27
+ const gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));
28
+ return safeLine(left + " ".repeat(gap) + right, width);
29
+ }
30
+
31
+ export function wrapVisibleText(text: string, width: number): string[] {
32
+ if (width <= 0) return [text];
33
+ return wrapTextWithAnsi(text, width).map((line) =>
34
+ visibleWidth(line) > width ? truncateToWidth(line, width, "…") : line,
35
+ );
36
+ }
37
+
38
+ export function renderBar(theme: ThemeLike, width: number, color = "muted"): string {
39
+ return safeLine(theme.fg(color, "─".repeat(Math.max(0, width))), width, "");
40
+ }
41
+
42
+ export function renderKeyHints(theme: ThemeLike, hints: string[], width: number): string {
43
+ return safeLine(theme.fg("dim", hints.filter(Boolean).join(" │ ")), width);
44
+ }
45
+
46
+ export function renderProgressBar(
47
+ theme: ThemeLike,
48
+ done: number,
49
+ total: number,
50
+ width: number,
51
+ options: {
52
+ filledColor?: string;
53
+ emptyColor?: string;
54
+ filledChar?: string;
55
+ emptyChar?: string;
56
+ } = {},
57
+ ): string {
58
+ const barWidth = Math.max(0, width);
59
+ const pct = total > 0 ? Math.max(0, Math.min(1, done / total)) : 0;
60
+ const filled = Math.round(pct * barWidth);
61
+ const filledChar = options.filledChar ?? "█";
62
+ const emptyChar = options.emptyChar ?? "░";
63
+ return (
64
+ theme.fg(options.filledColor ?? "success", filledChar.repeat(filled)) +
65
+ theme.fg(options.emptyColor ?? "dim", emptyChar.repeat(barWidth - filled))
66
+ );
67
+ }
68
+
69
+ export function statusGlyph(
70
+ theme: ThemeLike,
71
+ level: "active" | "idle" | "warning" | "error" | "success",
72
+ ): string {
73
+ switch (level) {
74
+ case "active": return theme.fg("success", "●");
75
+ case "success": return theme.fg("success", "✓");
76
+ case "warning": return theme.fg("warning", "!");
77
+ case "error": return theme.fg("error", "x");
78
+ case "idle":
79
+ default: return theme.fg("dim", "○");
80
+ }
81
+ }
82
+
83
+ export function renderFrame(
84
+ theme: ThemeLike,
85
+ inner: string[],
86
+ width: number,
87
+ options: { borderColor?: string; paddingX?: number } = {},
88
+ ): string[] {
89
+ if (width < 4) return inner.map((line) => safeLine(line, width));
90
+
91
+ const borderColor = options.borderColor ?? "borderAccent";
92
+ const paddingX = Math.max(0, options.paddingX ?? 1);
93
+ const contentWidth = Math.max(0, width - 2 - paddingX * 2);
94
+ const border = (text: string) => theme.fg(borderColor, text);
95
+ const pad = " ".repeat(paddingX);
96
+
97
+ const lines = [border("╭" + "─".repeat(width - 2) + "╮")];
98
+ for (const line of inner) {
99
+ lines.push(
100
+ border("│") +
101
+ pad +
102
+ padRightVisible(line, contentWidth) +
103
+ pad +
104
+ border("│"),
105
+ );
106
+ }
107
+ lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
108
+ return lines.map((line) => safeLine(line, width, ""));
109
+ }
@@ -1,5 +1,5 @@
1
- // GSD Watch — Header renderer: ASCII logo, session info, MCP status, remote questions
2
- // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
1
+ // Project/App: GSD-2
2
+ // File Purpose: Watch-mode terminal header and splash renderer for GSD project status.
3
3
 
4
4
  import { execFileSync } from "node:child_process";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -8,31 +8,67 @@ import { join } from "node:path";
8
8
  import { visibleWidth, truncateToWidth } from "@gsd/pi-tui";
9
9
  import { loadEffectiveGSDPreferences } from "../preferences.js";
10
10
  import { gsdHome } from "../gsd-home.js";
11
+ import { splashPalette } from "./splash-palette.js";
11
12
 
12
13
  // ─── Constants ────────────────────────────────────────────────────────────────
13
14
 
14
- /**
15
- * GSD ASCII logo — inlined here because the canonical src/logo.ts is outside
16
- * the resources rootDir and cannot be imported directly.
17
- */
18
15
  const GSD_LOGO: readonly string[] = [
19
- ' ██████╗ ███████╗██████╗ ',
20
- ' ██╔════╝ ██╔════╝██╔══██╗',
21
- ' ██║ ███╗███████╗██║ ██║',
22
- ' ██║ ██║╚════██║██║ ██║',
23
- ' ╚██████╔╝███████║██████╔╝',
24
- ' ╚═════╝ ╚══════╝╚═════╝ ',
16
+ " ██████╗ ███████╗██████╗ ",
17
+ " ██╔════╝ ██╔════╝██╔══██╗",
18
+ " ██║ ███╗███████╗██║ ██║",
19
+ " ██║ ██║╚════██║██║ ██║",
20
+ " ╚██████╔╝███████║██████╔╝",
21
+ " ╚═════╝ ╚══════╝╚═════╝ ",
25
22
  ];
26
23
 
27
- /** Separator character for the horizontal divider line. */
28
- const SEPARATOR_CHAR = "─";
29
-
30
- /** Vertical bar between logo and info panel. */
31
- const PANEL_DIVIDER = "│";
32
-
33
24
  /** Label column width for Model/Provider/Directory/Branch rows. */
34
25
  const LABEL_COL_WIDTH = 10;
35
26
 
27
+ const ANSI_RESET = "\x1b[0m";
28
+ const ANSI_BOLD = "\x1b[1m";
29
+
30
+ function rgb(hex: string): string {
31
+ const cleaned = hex.replace("#", "");
32
+ const r = Number.parseInt(cleaned.slice(0, 2), 16);
33
+ const g = Number.parseInt(cleaned.slice(2, 4), 16);
34
+ const b = Number.parseInt(cleaned.slice(4, 6), 16);
35
+ return `\x1b[38;2;${r};${g};${b}m`;
36
+ }
37
+
38
+ const colors = {
39
+ accent: rgb(splashPalette.accent),
40
+ border: rgb(splashPalette.border),
41
+ muted: rgb(splashPalette.muted),
42
+ dim: rgb(splashPalette.dim),
43
+ text: rgb(splashPalette.text),
44
+ success: rgb(splashPalette.success),
45
+ };
46
+
47
+ function color(text: string, colorCode: string): string {
48
+ return `${colorCode}${text}${ANSI_RESET}`;
49
+ }
50
+
51
+ function bold(text: string): string {
52
+ return `${ANSI_BOLD}${text}${ANSI_RESET}`;
53
+ }
54
+
55
+ function padVisible(text: string, width: number): string {
56
+ const clipped = truncateToWidth(text, Math.max(0, width), "");
57
+ return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
58
+ }
59
+
60
+ function rightAlign(left: string, right: string, width: number): string {
61
+ if (!right) return truncateToWidth(left, width, "");
62
+ const gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));
63
+ return truncateToWidth(left + " ".repeat(gap) + right, width, "");
64
+ }
65
+
66
+ function frameLine(content: string, width: number): string {
67
+ if (width < 3) return truncateToWidth(content, Math.max(0, width), "");
68
+ const innerWidth = Math.max(0, width - 2);
69
+ return `${color("│", colors.border)}${padVisible(content, innerWidth)}${color("│", colors.border)}`;
70
+ }
71
+
36
72
  // ─── Data Readers ─────────────────────────────────────────────────────────────
37
73
 
38
74
  /**
@@ -163,12 +199,11 @@ export function gatherHeaderData(projectRoot: string): HeaderData {
163
199
  * Returns empty string if value is empty.
164
200
  */
165
201
  function formatInfoLine(label: string, value: string, availableWidth: number): string {
166
- const bold = `\x1b[1m${label}\x1b[0m`;
167
- const labelVis = visibleWidth(bold);
168
- const padding = " ".repeat(Math.max(1, LABEL_COL_WIDTH - labelVis));
202
+ const labelText = bold(color(label, colors.text));
203
+ const padding = " ".repeat(Math.max(1, LABEL_COL_WIDTH - label.length));
169
204
  const maxValueWidth = Math.max(1, availableWidth - LABEL_COL_WIDTH);
170
205
  const truncValue = truncateToWidth(value, maxValueWidth, "…");
171
- return bold + padding + truncValue;
206
+ return labelText + padding + color(truncValue, colors.muted);
172
207
  }
173
208
 
174
209
  /**
@@ -181,7 +216,7 @@ export function formatMcpRow(servers: string[], width: number): string {
181
216
  // Capitalize first letter of each server name
182
217
  const items = servers.map(s => {
183
218
  const cap = s.charAt(0).toUpperCase() + s.slice(1);
184
- return `${cap} ✓`;
219
+ return `${color(cap, colors.accent)} ${color("✓", colors.success)}`;
185
220
  });
186
221
 
187
222
  const full = items.join(" · ");
@@ -194,59 +229,65 @@ export function formatMcpRow(servers: string[], width: number): string {
194
229
  /**
195
230
  * Render the full header as an array of terminal-safe strings.
196
231
  *
197
- * Layout: GSD ASCII logo on the left, info panel on the right separated by │.
198
- * Below: MCP server row, remote questions row, separator line.
232
+ * Layout: compact GSD mark on the left with a command-center status panel on
233
+ * the right. This keeps the splash visual while making the actionable command
234
+ * and workspace state easier to scan.
199
235
  */
200
236
  export function renderHeaderLines(data: HeaderData, width: number): string[] {
201
- const lines: string[] = [];
202
-
203
- // Logo is 6 lines tall. Info panel has: title + blank + model + provider + directory + branch = 6 lines
237
+ if (width < 40) return renderStackedHeader(data, width);
238
+ const outerWidth = width;
239
+ const innerWidth = Math.max(0, outerWidth - 2);
204
240
  const logoLines = GSD_LOGO;
205
- const logoWidth = Math.max(...logoLines.map(l => visibleWidth(l)));
241
+ const logoWidth = Math.max(...logoLines.map((line) => visibleWidth(line)));
242
+ const gap = ` ${color("│", colors.dim)} `;
243
+ const panelWidth = innerWidth - logoWidth - visibleWidth(gap);
206
244
 
207
- // Calculate available width for the info panel
208
- // Layout: logo + " " + "│" + " " = logoWidth + 3
209
- const dividerOverhead = 3; // " │ "
210
- const infoPanelWidth = width - logoWidth - dividerOverhead;
211
-
212
- // If terminal is too narrow for side-by-side, fall back to stacked layout
213
- if (infoPanelWidth < 20) {
245
+ if (panelWidth < 44) {
214
246
  return renderStackedHeader(data, width);
215
247
  }
216
248
 
217
- // Build info panel lines (6 lines to match logo height)
218
- const infoLines: string[] = [
219
- `\x1b[1mGet Shit Done\x1b[0m`,
220
- "",
221
- formatInfoLine("Model", data.model, infoPanelWidth),
222
- formatInfoLine("Provider", data.provider, infoPanelWidth),
223
- formatInfoLine("Directory", data.directory, infoPanelWidth),
224
- formatInfoLine("Branch", data.branch, infoPanelWidth),
249
+ const mcpRow = formatMcpRow(data.mcpServers, Math.max(1, panelWidth - 9)) || color("none configured", colors.dim);
250
+ const panelLines = [
251
+ rightAlign(
252
+ `${color("GSD", colors.accent)} ${bold(color("Project Console", colors.text))}`,
253
+ color("idle", colors.muted),
254
+ panelWidth,
255
+ ),
256
+ rightAlign(
257
+ `${color("Project", colors.muted)} ${color(data.directory, colors.text)}`,
258
+ `${color("Command", colors.muted)} ${color("/gsd start", colors.accent)}`,
259
+ panelWidth,
260
+ ),
261
+ rightAlign(
262
+ `${color("Branch", colors.muted)} ${color(data.branch, colors.text)}`,
263
+ `${color("Mode", colors.muted)} ${color("manual", colors.text)}`,
264
+ panelWidth,
265
+ ),
266
+ rightAlign(
267
+ `${color("MCP", colors.muted)} ${mcpRow}`,
268
+ `${color("Model", colors.muted)} ${color(data.model, colors.text)}`,
269
+ panelWidth,
270
+ ),
271
+ rightAlign(
272
+ `${color("Provider", colors.muted)} ${color(data.provider, colors.text)}`,
273
+ `${color("Workspace", colors.muted)} ${color(data.directory, colors.text)}`,
274
+ panelWidth,
275
+ ),
276
+ rightAlign(
277
+ color("/gsd to begin", colors.accent),
278
+ `${color("/gsd templates", colors.muted)} ${color("/gsd help", colors.muted)}`,
279
+ panelWidth,
280
+ ),
225
281
  ];
226
282
 
227
- // Merge logo and info panel side by side
228
- const maxLines = Math.max(logoLines.length, infoLines.length);
229
- for (let i = 0; i < maxLines; i++) {
230
- const logoLine = i < logoLines.length ? logoLines[i] : "";
231
- const infoLine = i < infoLines.length ? infoLines[i] : "";
232
-
233
- // Pad logo line to consistent width
234
- const logoPad = " ".repeat(Math.max(0, logoWidth - visibleWidth(logoLine)));
235
- lines.push(`${logoLine}${logoPad} ${PANEL_DIVIDER} ${infoLine}`);
236
- }
237
-
238
- // Blank line after logo+info block
239
- lines.push("");
240
-
241
- // MCP server row
242
- const mcpRow = formatMcpRow(data.mcpServers, width);
243
- if (mcpRow) {
244
- lines.push(` ${mcpRow}`);
283
+ const lines = [
284
+ color("╭" + "─".repeat(Math.max(0, outerWidth - 2)) + "╮", colors.border),
285
+ ];
286
+ for (let i = 0; i < logoLines.length; i++) {
287
+ const logo = padVisible(color(logoLines[i], colors.border), logoWidth);
288
+ lines.push(frameLine(`${logo}${gap}${panelLines[i] ?? ""}`, outerWidth));
245
289
  }
246
-
247
- // Separator line
248
- lines.push(SEPARATOR_CHAR.repeat(width));
249
-
290
+ lines.push(color("╰" + "─".repeat(Math.max(0, outerWidth - 2)) + "╯", colors.border));
250
291
  return lines;
251
292
  }
252
293
 
@@ -254,25 +295,26 @@ export function renderHeaderLines(data: HeaderData, width: number): string[] {
254
295
  * Fallback stacked layout for narrow terminals (< 20 cols for info panel).
255
296
  */
256
297
  function renderStackedHeader(data: HeaderData, width: number): string[] {
257
- const lines: string[] = [];
298
+ const outerWidth = Math.max(0, width);
299
+ if (outerWidth < 3) {
300
+ return [color(truncateToWidth("GSD", outerWidth, ""), colors.accent)];
301
+ }
302
+ const lines: string[] = [color("╭" + "─".repeat(Math.max(0, outerWidth - 2)) + "╮", colors.border)];
258
303
 
259
304
  // Title
260
- lines.push(`\x1b[1mGet Shit Done\x1b[0m`);
261
- lines.push("");
305
+ lines.push(frameLine(`${color("GSD", colors.accent)} ${bold(color("Project Console", colors.text))}`, outerWidth));
262
306
 
263
307
  // Info
264
- lines.push(formatInfoLine("Model", data.model, width));
265
- lines.push(formatInfoLine("Provider", data.provider, width));
266
- lines.push(formatInfoLine("Directory", data.directory, width));
267
- lines.push(formatInfoLine("Branch", data.branch, width));
268
- lines.push("");
308
+ lines.push(frameLine(formatInfoLine("Project", data.directory, outerWidth - 2), outerWidth));
309
+ lines.push(frameLine(formatInfoLine("Command", "/gsd start", outerWidth - 2), outerWidth));
310
+ lines.push(frameLine(formatInfoLine("Branch", data.branch, outerWidth - 2), outerWidth));
311
+ lines.push(frameLine(formatInfoLine("Model", data.model, outerWidth - 2), outerWidth));
269
312
 
270
313
  // MCP
271
- const mcpRow = formatMcpRow(data.mcpServers, width);
272
- if (mcpRow) lines.push(` ${mcpRow}`);
273
-
274
- // Separator
275
- lines.push(SEPARATOR_CHAR.repeat(width));
314
+ const mcpRow = formatMcpRow(data.mcpServers, Math.max(1, outerWidth - 7));
315
+ if (mcpRow) lines.push(frameLine(`${color("MCP", colors.muted)} ${mcpRow}`, outerWidth));
316
+ lines.push(frameLine(`${color("/gsd to begin", colors.accent)} ${color("/gsd help", colors.muted)}`, outerWidth));
317
+ lines.push(color("╰" + "─".repeat(Math.max(0, outerWidth - 2)) + "╯", colors.border));
276
318
 
277
319
  return lines;
278
320
  }
@@ -0,0 +1,11 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Shared RGB palette for the pre-theme GSD watch splash.
3
+
4
+ export const splashPalette = {
5
+ accent: "#8db7ff",
6
+ border: "#a7ba78",
7
+ muted: "#7d889f",
8
+ dim: "#4d5870",
9
+ text: "#dce4f2",
10
+ success: "#a8c978",
11
+ } as const;
@@ -322,7 +322,7 @@ export function getRequiredWorkflowToolsForGuidedUnit(unitType: string): string[
322
322
  case "execute-task":
323
323
  return ["gsd_task_complete"];
324
324
  case "complete-slice":
325
- return ["gsd_slice_complete"];
325
+ return ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice"];
326
326
  default:
327
327
  return [];
328
328
  }
@@ -351,7 +351,7 @@ export function getRequiredWorkflowToolsForAutoUnit(unitType: string): string[]
351
351
  case "reactive-execute":
352
352
  return ["gsd_task_complete"];
353
353
  case "complete-slice":
354
- return ["gsd_slice_complete"];
354
+ return ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice"];
355
355
  case "replan-slice":
356
356
  return ["gsd_replan_slice"];
357
357
  case "reassess-roadmap":