gsd-pi 2.81.0 → 2.82.0-dev.ed17d078d

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 (503) hide show
  1. package/README.md +60 -30
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  4. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  5. package/dist/resources/extensions/gsd/auto/loop.js +111 -8
  6. package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
  7. package/dist/resources/extensions/gsd/auto/phases.js +199 -97
  8. package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
  9. package/dist/resources/extensions/gsd/auto/session.js +9 -0
  10. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
  11. package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
  14. package/dist/resources/extensions/gsd/auto-prompts.js +11 -3
  15. package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
  16. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +20 -23
  18. package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
  19. package/dist/resources/extensions/gsd/auto-verification.js +12 -6
  20. package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
  21. package/dist/resources/extensions/gsd/auto.js +386 -106
  22. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +13 -2
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  26. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
  27. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
  28. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
  29. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  30. package/dist/resources/extensions/gsd/context-store.js +112 -0
  31. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  32. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  33. package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
  34. package/dist/resources/extensions/gsd/git-service.js +2 -1
  35. package/dist/resources/extensions/gsd/gsd-db.js +7 -23
  36. package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
  37. package/dist/resources/extensions/gsd/health-widget.js +4 -10
  38. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  39. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  40. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  41. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  42. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
  43. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  44. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  45. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  46. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  47. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  48. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  49. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  50. package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
  51. package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
  52. package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
  53. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
  54. package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  56. package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
  57. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  58. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  59. package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
  60. package/dist/resources/extensions/gsd/session-lock.js +40 -0
  61. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
  62. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
  63. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
  64. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
  65. package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
  66. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
  68. package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
  69. package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
  70. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
  71. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
  72. package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
  73. package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
  74. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  75. package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
  76. package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
  77. package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  79. package/dist/resources/extensions/gsd/worktree-lifecycle.js +722 -316
  80. package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
  81. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  82. package/dist/web/standalone/.next/BUILD_ID +1 -1
  83. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  84. package/dist/web/standalone/.next/build-manifest.json +3 -3
  85. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  86. package/dist/web/standalone/.next/required-server-files.json +3 -3
  87. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  98. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  162. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/index.html +1 -1
  192. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  193. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  197. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/page.js +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  201. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  202. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware.js +2 -2
  205. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  207. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  208. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  209. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  215. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  216. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  217. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  218. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  221. package/dist/web/standalone/server.js +1 -1
  222. package/dist/welcome-screen.d.ts +0 -7
  223. package/dist/welcome-screen.js +60 -69
  224. package/package.json +3 -2
  225. package/packages/daemon/package.json +2 -2
  226. package/packages/mcp-server/README.md +2 -0
  227. package/packages/mcp-server/package.json +2 -2
  228. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  229. package/packages/native/package.json +1 -1
  230. package/packages/pi-agent-core/package.json +1 -1
  231. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  232. package/packages/pi-ai/dist/index.d.ts +2 -2
  233. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  234. package/packages/pi-ai/dist/index.js +1 -1
  235. package/packages/pi-ai/dist/index.js.map +1 -1
  236. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  237. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  238. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  239. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  240. package/packages/pi-ai/package.json +1 -1
  241. package/packages/pi-ai/src/index.ts +7 -2
  242. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  243. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  245. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
  303. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  305. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  307. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  308. package/packages/pi-coding-agent/package.json +1 -1
  309. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  310. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
  311. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
  312. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
  313. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
  314. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
  315. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
  316. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
  317. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
  318. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
  319. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
  320. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
  321. package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
  322. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
  323. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  324. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
  325. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
  326. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
  327. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  328. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  329. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
  330. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  331. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  332. package/packages/pi-tui/dist/overlay-layout.js +9 -6
  333. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  334. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  335. package/packages/pi-tui/dist/tui.js +5 -0
  336. package/packages/pi-tui/dist/tui.js.map +1 -1
  337. package/packages/pi-tui/package.json +1 -1
  338. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
  339. package/packages/pi-tui/src/overlay-layout.ts +10 -7
  340. package/packages/pi-tui/src/tui.ts +6 -0
  341. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  342. package/packages/rpc-client/package.json +1 -1
  343. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  344. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  345. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  346. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  347. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  348. package/pkg/dist/modes/interactive/theme/theme.js +105 -1
  349. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  350. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  351. package/pkg/dist/modes/interactive/theme/themes.js +27 -26
  352. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  353. package/pkg/package.json +1 -1
  354. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  355. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  356. package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
  357. package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
  358. package/src/resources/extensions/gsd/auto/loop.ts +113 -9
  359. package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
  360. package/src/resources/extensions/gsd/auto/phases.ts +158 -19
  361. package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
  362. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  363. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  364. package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
  365. package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
  366. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
  367. package/src/resources/extensions/gsd/auto-prompts.ts +11 -3
  368. package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
  369. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  370. package/src/resources/extensions/gsd/auto-start.ts +22 -22
  371. package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
  372. package/src/resources/extensions/gsd/auto-verification.ts +12 -6
  373. package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
  374. package/src/resources/extensions/gsd/auto.ts +424 -106
  375. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
  376. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
  377. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
  378. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  379. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
  380. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
  381. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
  382. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  383. package/src/resources/extensions/gsd/context-store.ts +120 -1
  384. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  385. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  386. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  387. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  388. package/src/resources/extensions/gsd/git-service.ts +2 -0
  389. package/src/resources/extensions/gsd/gsd-db.ts +7 -23
  390. package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
  391. package/src/resources/extensions/gsd/health-widget.ts +6 -10
  392. package/src/resources/extensions/gsd/journal.ts +2 -0
  393. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  394. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  395. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  396. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  397. package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
  398. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  399. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  400. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  401. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  402. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  403. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  404. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  405. package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
  406. package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
  407. package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
  408. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
  409. package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  410. package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  411. package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
  412. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  413. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  414. package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
  415. package/src/resources/extensions/gsd/session-lock.ts +41 -0
  416. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  417. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
  418. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
  419. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
  420. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  421. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  422. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  423. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  424. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  425. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  426. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
  427. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  428. package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
  429. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  430. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  431. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
  432. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
  433. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
  434. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +291 -4
  435. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +20 -5
  436. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
  437. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  438. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  439. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  440. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
  441. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  442. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  443. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  444. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
  445. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
  446. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  447. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  448. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  449. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
  450. package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
  451. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  452. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
  453. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  454. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
  455. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  456. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
  457. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
  458. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  459. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  460. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  461. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  462. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
  463. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  464. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
  465. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  466. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  467. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
  468. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
  469. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
  470. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
  471. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  472. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
  473. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
  474. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
  475. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  476. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
  477. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
  478. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  479. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
  480. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +65 -58
  481. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
  482. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
  483. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
  484. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
  485. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  486. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
  487. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
  488. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +572 -118
  489. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
  490. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
  491. package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
  492. package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
  493. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  494. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  495. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  496. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1151 -524
  497. package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
  498. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  501. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
  502. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → YEvjuT-fsFfYQhDSWtueS}/_buildManifest.js +0 -0
  503. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → YEvjuT-fsFfYQhDSWtueS}/_ssgManifest.js +0 -0
@@ -6,6 +6,31 @@ import { debugLog } from "../debug-logger.js";
6
6
  import { logWarning } from "../workflow-logger.js";
7
7
  import { resolveAutoSupervisorConfig } from "../preferences.js";
8
8
  import { formatAutoUnitWorkingMessage } from "../working-output-messages.js";
9
+ import { readUnitRuntimeRecord } from "../unit-runtime.js";
10
+ const UNIT_FAILSAFE_BUFFER_MS = 30_000;
11
+ const UNIT_FAILSAFE_RECHECK_MS = 30_000;
12
+ export function shouldDeferUnitFailsafeTimeout(runtime, opts) {
13
+ if (!runtime)
14
+ return false;
15
+ if (opts.currentUnitStartedAt === undefined)
16
+ return false;
17
+ if (runtime.startedAt !== opts.currentUnitStartedAt)
18
+ return false;
19
+ if (runtime.lastProgressAt <= 0)
20
+ return false;
21
+ const progressAgeMs = opts.nowMs - runtime.lastProgressAt;
22
+ if (progressAgeMs < 0)
23
+ return false;
24
+ if (progressAgeMs > opts.freshProgressMs)
25
+ return false;
26
+ if (runtime.phase === "recovered")
27
+ return true;
28
+ if (runtime.lastProgressKind.includes("recovery"))
29
+ return true;
30
+ if (runtime.recoveryAttempts && runtime.recoveryAttempts > 0)
31
+ return true;
32
+ return progressAgeMs >= 0 && progressAgeMs <= opts.freshProgressMs;
33
+ }
9
34
  // Tracks the latest session-switch attempt so a late timeout settlement from an
10
35
  // older runUnit() call cannot clear the guard for a newer one.
11
36
  let sessionSwitchGeneration = 0;
@@ -145,16 +170,54 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
145
170
  // If supervision fails to resolve unitPromise within 30s, treat as cancelled.
146
171
  // Without this, a crashed agent that never emits agent_end hangs the loop (#3161).
147
172
  const supervisor = resolveAutoSupervisorConfig();
148
- const UNIT_HARD_TIMEOUT_MS = Math.max(30_000, ((supervisor.hard_timeout_minutes ?? 30) * 60 * 1000) + 30_000);
173
+ const UNIT_HARD_TIMEOUT_MS = Math.max(UNIT_FAILSAFE_BUFFER_MS, ((supervisor.hard_timeout_minutes ?? 30) * 60 * 1000) + UNIT_FAILSAFE_BUFFER_MS);
174
+ const freshProgressMs = Math.max(UNIT_FAILSAFE_BUFFER_MS, ((supervisor.idle_timeout_minutes ?? 10) * 60 * 1000) + UNIT_FAILSAFE_BUFFER_MS);
149
175
  let unitTimeoutHandle;
150
176
  let result;
151
177
  try {
152
178
  pi.sendMessage({ customType: "gsd-auto", content: prompt, display: s.verbose }, { triggerTurn: true });
153
179
  debugLog("runUnit", { phase: "awaiting-agent-end", unitType, unitId });
154
180
  const timeoutResult = new Promise((resolve) => {
155
- unitTimeoutHandle = setTimeout(() => {
181
+ const settleOrDefer = () => {
182
+ let runtime;
183
+ try {
184
+ runtime = readUnitRuntimeRecord(s.basePath, unitType, unitId);
185
+ }
186
+ catch (error) {
187
+ debugLog("runUnit", {
188
+ phase: "unit-failsafe-runtime-read-failed",
189
+ unitType,
190
+ unitId,
191
+ error: error instanceof Error ? error.message : String(error),
192
+ });
193
+ resolve({
194
+ status: "cancelled",
195
+ errorContext: {
196
+ message: "Unit hard timeout — supervision may have failed; runtime progress could not be read",
197
+ category: "timeout",
198
+ isTransient: true,
199
+ },
200
+ });
201
+ return;
202
+ }
203
+ if (shouldDeferUnitFailsafeTimeout(runtime, {
204
+ nowMs: Date.now(),
205
+ currentUnitStartedAt: s.currentUnit?.startedAt,
206
+ freshProgressMs,
207
+ })) {
208
+ debugLog("runUnit", {
209
+ phase: "unit-failsafe-deferred",
210
+ unitType,
211
+ unitId,
212
+ runtimePhase: runtime?.phase,
213
+ lastProgressKind: runtime?.lastProgressKind,
214
+ });
215
+ unitTimeoutHandle = setTimeout(settleOrDefer, UNIT_FAILSAFE_RECHECK_MS);
216
+ return;
217
+ }
156
218
  resolve({ status: "cancelled", errorContext: { message: "Unit hard timeout — supervision may have failed", category: "timeout", isTransient: true } });
157
- }, UNIT_HARD_TIMEOUT_MS);
219
+ };
220
+ unitTimeoutHandle = setTimeout(settleOrDefer, UNIT_HARD_TIMEOUT_MS);
158
221
  });
159
222
  result = await runWithTurnGeneration(capturedTurnGen, () => Promise.race([unitPromise, timeoutResult]));
160
223
  }
@@ -25,6 +25,7 @@ export class AutoSession {
25
25
  // ── Lifecycle ────────────────────────────────────────────────────────────
26
26
  active = false;
27
27
  paused = false;
28
+ completionStopInProgress = false;
28
29
  stepMode = false;
29
30
  verbose = false;
30
31
  activeEngineId = null;
@@ -88,6 +89,7 @@ export class AutoSession {
88
89
  pendingCrashRecovery = null;
89
90
  pendingVerificationRetry = null;
90
91
  verificationRetryCount = new Map();
92
+ verificationRetryFailureHashes = new Map();
91
93
  pausedSessionFile = null;
92
94
  pausedUnitType = null;
93
95
  pausedUnitId = null;
@@ -207,6 +209,7 @@ export class AutoSession {
207
209
  // Lifecycle
208
210
  this.active = false;
209
211
  this.paused = false;
212
+ this.completionStopInProgress = false;
210
213
  this.stepMode = false;
211
214
  this.verbose = false;
212
215
  this.activeEngineId = null;
@@ -250,6 +253,7 @@ export class AutoSession {
250
253
  this.pendingCrashRecovery = null;
251
254
  this.pendingVerificationRetry = null;
252
255
  this.verificationRetryCount.clear();
256
+ this.verificationRetryFailureHashes.clear();
253
257
  this.pausedSessionFile = null;
254
258
  this.pausedUnitType = null;
255
259
  this.pausedUnitId = null;
@@ -282,6 +286,11 @@ export class AutoSession {
282
286
  this.orchestration = null;
283
287
  // Loop promise state lives in auto-loop.ts module scope
284
288
  }
289
+ resetAfterStop(options = {}) {
290
+ const completionStopInProgress = options.preserveCompletionSurface ? this.completionStopInProgress : false;
291
+ this.reset();
292
+ this.completionStopInProgress = completionStopInProgress;
293
+ }
285
294
  toJSON() {
286
295
  const orchestrationStatus = this.orchestration?.getStatus();
287
296
  return {
@@ -0,0 +1,43 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Central retry policy for auto-mode verification redispatches.
3
+ import { createHash } from "node:crypto";
4
+ export const VERIFICATION_RETRY_BASE_DELAY_MS = 2_000;
5
+ export const VERIFICATION_RETRY_MAX_DELAY_MS = 30_000;
6
+ export const VERIFICATION_RETRY_JITTER_RATIO = 0.1;
7
+ export function verificationRetryKey(unitType, unitId) {
8
+ return `${unitType}:${unitId}`;
9
+ }
10
+ export function hashVerificationFailureContext(failureContext) {
11
+ const normalized = failureContext.replace(/\r\n/g, "\n").trim();
12
+ return createHash("sha256").update(normalized).digest("hex");
13
+ }
14
+ export function verificationRetryDelayMs(attempt, random = Math.random) {
15
+ const safeAttempt = Math.max(1, Math.floor(attempt));
16
+ const baseDelayMs = Math.min(VERIFICATION_RETRY_MAX_DELAY_MS, VERIFICATION_RETRY_BASE_DELAY_MS * 2 ** (safeAttempt - 1));
17
+ const jitterSpanMs = Math.round(baseDelayMs * VERIFICATION_RETRY_JITTER_RATIO);
18
+ const jitterMs = Math.round((random() - 0.5) * 2 * jitterSpanMs);
19
+ const delayMs = Math.min(VERIFICATION_RETRY_MAX_DELAY_MS, Math.max(0, baseDelayMs + jitterMs));
20
+ return { delayMs, baseDelayMs };
21
+ }
22
+ export function decideVerificationRetry(input) {
23
+ const { retryInfo, unitType } = input;
24
+ if (!retryInfo || !unitType) {
25
+ return { action: "pause", reason: "missing-retry-context" };
26
+ }
27
+ const key = verificationRetryKey(unitType, retryInfo.unitId);
28
+ const failureHash = hashVerificationFailureContext(retryInfo.failureContext);
29
+ if (input.previousFailureHash === failureHash) {
30
+ return {
31
+ action: "pause",
32
+ reason: "duplicate-failure-context",
33
+ key,
34
+ failureHash,
35
+ };
36
+ }
37
+ return {
38
+ action: "delay",
39
+ key,
40
+ failureHash,
41
+ ...verificationRetryDelayMs(retryInfo.attempt, input.random),
42
+ };
43
+ }
@@ -1,7 +1,6 @@
1
1
  // GSD-2 + src/resources/extensions/gsd/auto-dashboard.ts - Auto-mode progress widget rendering and dashboard helpers.
2
- import { getCurrentBranch } from "./worktree.js";
3
2
  import { getActiveHook } from "./post-unit-hooks.js";
4
- import { getLedger, getProjectTotals } from "./metrics.js";
3
+ import { getLedger } from "./metrics.js";
5
4
  import { getErrorMessage } from "./error-utils.js";
6
5
  import { nativeIsRepo } from "./native-git-bridge.js";
7
6
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
@@ -10,15 +9,12 @@ import { execFileSync } from "node:child_process";
10
9
  import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
11
10
  import { makeUI } from "../shared/tui.js";
12
11
  import { GLYPH, INDENT } from "../shared/mod.js";
12
+ import { padRightVisible, renderFrame, renderProgressBar, rightAlign, wrapVisibleText } from "./tui/render-kit.js";
13
13
  import { computeProgressScore } from "./progress-score.js";
14
- import { getActiveWorktreeName } from "./worktree-command.js";
15
14
  import { getGlobalGSDPreferencesPath, getProjectGSDPreferencesPath, parsePreferencesMarkdown, } from "./preferences.js";
16
- import { resolveServiceTierIcon, getEffectiveServiceTier } from "./service-tier.js";
17
15
  import { parseUnitId } from "./unit-id.js";
18
- import { formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-session-stats.js";
19
16
  import { logWarning } from "./workflow-logger.js";
20
17
  import { formattedShortcutPair } from "./shortcut-defs.js";
21
- import { homedir } from "node:os";
22
18
  import { readUnitRuntimeRecord } from "./unit-runtime.js";
23
19
  // ─── UAT Slice Extraction ─────────────────────────────────────────────────────
24
20
  /**
@@ -468,6 +464,7 @@ export function _resetWidgetModeForTests() {
468
464
  export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
469
465
  if (!ctx.hasUI)
470
466
  return;
467
+ ctx.ui.setWidget("gsd-outcome", undefined);
471
468
  // Welcome header is a startup-only banner — permanently suppress it once
472
469
  // auto-mode activates. The dashboard widget owns all status from here.
473
470
  // Note: setHeader(undefined) restores the built-in header (logo +
@@ -497,53 +494,11 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
497
494
  if (mid) {
498
495
  updateSliceProgressCache(accessors.getBasePath(), mid.id, slice?.id);
499
496
  }
500
- // Cache git branch at widget creation time (not per render)
501
- let cachedBranch = null;
502
- try {
503
- cachedBranch = getCurrentBranch(accessors.getBasePath());
504
- }
505
- catch (err) { /* not in git repo */
506
- logWarning("dashboard", `git branch detection failed: ${err instanceof Error ? err.message : String(err)}`);
507
- }
508
- // Cache short pwd (last 2 path segments only) + worktree/branch info
509
- let widgetPwd;
510
- {
511
- let fullPwd = process.cwd();
512
- const widgetHome = homedir();
513
- if (widgetHome && (fullPwd === widgetHome || fullPwd.startsWith(widgetHome + "/") || fullPwd.startsWith(widgetHome + "\\"))) {
514
- fullPwd = `~${fullPwd.slice(widgetHome.length)}`;
515
- }
516
- const parts = fullPwd.split("/");
517
- widgetPwd = parts.length > 2 ? parts.slice(-2).join("/") : fullPwd;
518
- }
519
- const worktreeName = getActiveWorktreeName();
520
- if (worktreeName && cachedBranch) {
521
- widgetPwd = `${widgetPwd} (\u2387 ${cachedBranch})`;
522
- }
523
- else if (cachedBranch) {
524
- widgetPwd = `${widgetPwd} (${cachedBranch})`;
525
- }
526
- // Pre-fetch last commit for display
527
- refreshLastCommit(accessors.getBasePath());
528
- // Cache the effective service tier at widget creation time (reads preferences)
529
- const effectiveServiceTier = getEffectiveServiceTier();
530
497
  ctx.ui.setWidget("gsd-progress", (tui, theme) => {
531
498
  let pulseBright = true;
532
499
  let cachedLines;
533
500
  let cachedWidth;
534
- let cachedRtkLabel;
535
501
  let cachedRuntimeRecord = null;
536
- const refreshRtkLabel = () => {
537
- try {
538
- const sessionId = ctx.sessionManager.getSessionId();
539
- const savings = sessionId ? getRtkSessionSavings(accessors.getBasePath(), sessionId) : null;
540
- cachedRtkLabel = formatRtkSavingsLabel(savings);
541
- }
542
- catch (err) {
543
- logWarning("dashboard", `RTK savings lookup failed: ${err instanceof Error ? err.message : String(err)}`);
544
- cachedRtkLabel = null;
545
- }
546
- };
547
502
  const refreshRuntimeRecord = () => {
548
503
  try {
549
504
  cachedRuntimeRecord = readUnitRuntimeRecord(accessors.getBasePath(), unitType, unitId);
@@ -552,7 +507,6 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
552
507
  cachedRuntimeRecord = null;
553
508
  }
554
509
  };
555
- refreshRtkLabel();
556
510
  refreshRuntimeRecord();
557
511
  const pulseTimer = setInterval(() => {
558
512
  pulseBright = !pulseBright;
@@ -568,7 +522,6 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
568
522
  if (mid) {
569
523
  updateSliceProgressCache(accessors.getBasePath(), mid.id, slice?.id);
570
524
  }
571
- refreshRtkLabel();
572
525
  refreshRuntimeRecord();
573
526
  cachedLines = undefined;
574
527
  }
@@ -635,44 +588,6 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
635
588
  lines.push(`${pad} ${signalStr}`);
636
589
  }
637
590
  }
638
- // ── Gather stats (needed by multiple modes) ─────────────────────
639
- const cmdCtx = accessors.getCmdCtx();
640
- let totalInput = 0;
641
- let totalCacheRead = 0;
642
- if (cmdCtx) {
643
- for (const entry of cmdCtx.sessionManager.getEntries()) {
644
- if (entry.type === "message") {
645
- const msgEntry = entry;
646
- if (msgEntry.message?.role === "assistant") {
647
- const u = msgEntry.message.usage;
648
- if (u) {
649
- totalInput += u.input || 0;
650
- totalCacheRead += u.cacheRead || 0;
651
- }
652
- }
653
- }
654
- }
655
- }
656
- const mLedger = getLedger();
657
- const autoTotals = mLedger ? getProjectTotals(mLedger.units) : null;
658
- const cumulativeCost = autoTotals?.cost ?? 0;
659
- const cxUsage = cmdCtx?.getContextUsage?.();
660
- const cxWindow = cxUsage?.contextWindow ?? cmdCtx?.model?.contextWindow ?? 0;
661
- const cxPctVal = cxUsage?.percent ?? 0;
662
- const cxPct = cxUsage?.percent !== null ? cxPctVal.toFixed(1) : "?";
663
- // Model display — prefer dispatched model ID (set after selectAndApplyModel
664
- // + hook overrides) over cmdCtx?.model which can be stale (#2899).
665
- const dispatchedModelId = accessors.getCurrentDispatchedModelId();
666
- const modelId = dispatchedModelId
667
- ? dispatchedModelId.split("/").slice(1).join("/") || dispatchedModelId
668
- : (cmdCtx?.model?.id ?? "");
669
- const modelProvider = dispatchedModelId
670
- ? dispatchedModelId.split("/")[0] || ""
671
- : (cmdCtx?.model?.provider ?? "");
672
- const tierIcon = resolveServiceTierIcon(effectiveServiceTier, modelId);
673
- const modelDisplay = (modelProvider && modelId
674
- ? `${modelProvider}/${modelId}`
675
- : modelId) + (tierIcon ? ` ${tierIcon}` : "");
676
591
  // ── Mode: off — return empty ──────────────────────────────────
677
592
  if (widgetMode === "off") {
678
593
  cachedLines = [];
@@ -686,7 +601,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
686
601
  cachedWidth = width;
687
602
  return lines;
688
603
  }
689
- // ── Mode: small — header + progress bar + compact stats ───────
604
+ // ── Mode: small — header + active work progress ───────────────
690
605
  if (widgetMode === "small") {
691
606
  lines.push("");
692
607
  // Action line
@@ -698,10 +613,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
698
613
  if (shouldRenderRoadmapProgress(roadmapSlices)) {
699
614
  const { done, total, activeSliceTasks } = roadmapSlices;
700
615
  const barWidth = Math.max(6, Math.min(18, Math.floor(width * 0.25)));
701
- const pct = total > 0 ? done / total : 0;
702
- const filled = Math.round(pct * barWidth);
703
- const bar = theme.fg("success", "━".repeat(filled))
704
- + theme.fg("dim", "─".repeat(barWidth - filled));
616
+ const bar = renderProgressBar(theme, done, total, barWidth);
705
617
  let meta = `${theme.fg("text", `${done}`)}${theme.fg("dim", `/${total} slices`)}`;
706
618
  if (activeSliceTasks && activeSliceTasks.total > 0) {
707
619
  const tn = Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
@@ -709,20 +621,6 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
709
621
  }
710
622
  lines.push(`${pad}${bar} ${meta}`);
711
623
  }
712
- // Compact stats: cost + context only
713
- const smallStats = [];
714
- if (cumulativeCost)
715
- smallStats.push(theme.fg("warning", `$${cumulativeCost.toFixed(2)}`));
716
- const cxDisplay = `${cxPct}%ctx`;
717
- if (cxPctVal > 90)
718
- smallStats.push(theme.fg("error", cxDisplay));
719
- else if (cxPctVal > 70)
720
- smallStats.push(theme.fg("warning", cxDisplay));
721
- else
722
- smallStats.push(theme.fg("dim", cxDisplay));
723
- if (smallStats.length > 0) {
724
- lines.push(rightAlign("", smallStats.join(theme.fg("dim", " ")), width));
725
- }
726
624
  lines.push(...ui.bar());
727
625
  cachedLines = lines;
728
626
  cachedWidth = width;
@@ -730,11 +628,10 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
730
628
  }
731
629
  // ── Mode: full — complete two-column layout ───────────────────
732
630
  lines.push("");
733
- // Context section: milestone + slice + model
631
+ // Context section: milestone + slice. Footer owns model/cost/context.
734
632
  const hasContext = !!(mid || (slice && unitType !== "research-milestone" && unitType !== "plan-milestone"));
735
633
  if (mid) {
736
- const modelTag = modelDisplay ? theme.fg("muted", ` ${modelDisplay}`) : "";
737
- lines.push(truncateToWidth(`${pad}${theme.fg("dim", mid.title)}${modelTag}`, width, "…"));
634
+ lines.push(truncateToWidth(`${pad}${theme.fg("dim", mid.title)}`, width, ""));
738
635
  }
739
636
  if (slice && unitType !== "research-milestone" && unitType !== "plan-milestone") {
740
637
  lines.push(truncateToWidth(`${pad}${theme.fg("text", theme.bold(`${slice.id}: ${slice.title}`))}`, width, "…"));
@@ -759,10 +656,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
759
656
  if (shouldRenderRoadmapProgress(roadmapSlices)) {
760
657
  const { done, total, activeSliceTasks } = roadmapSlices;
761
658
  const barWidth = Math.max(6, Math.min(18, Math.floor(leftColWidth * 0.4)));
762
- const pct = total > 0 ? done / total : 0;
763
- const filled = Math.round(pct * barWidth);
764
- const bar = theme.fg("success", "━".repeat(filled))
765
- + theme.fg("dim", "─".repeat(barWidth - filled));
659
+ const bar = renderProgressBar(theme, done, total, barWidth);
766
660
  let meta = `${theme.fg("text", `${done}`)}${theme.fg("dim", `/${total} slices`)}`;
767
661
  if (activeSliceTasks && activeSliceTasks.total > 0) {
768
662
  const taskNum = isHook
@@ -818,7 +712,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
818
712
  if (maxRows > 0) {
819
713
  lines.push("");
820
714
  for (let i = 0; i < maxRows; i++) {
821
- const left = padToWidth(truncateToWidth(leftLines[i] ?? "", leftColWidth, "…"), leftColWidth);
715
+ const left = padRightVisible(truncateToWidth(leftLines[i] ?? "", leftColWidth, "…"), leftColWidth);
822
716
  const right = rightLines[i] ?? "";
823
717
  lines.push(`${left}${right}`);
824
718
  }
@@ -831,46 +725,8 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
831
725
  lines.push(truncateToWidth(l, width, "…"));
832
726
  }
833
727
  }
834
- // ── Footer: simplified stats + pwd + last commit + hints ────────
728
+ // ── Auto controls. Footer owns cwd/branch/model/cost/context. ───
835
729
  lines.push("");
836
- {
837
- const sp = [];
838
- if (totalCacheRead + totalInput > 0) {
839
- const hitRate = Math.round((totalCacheRead / (totalCacheRead + totalInput)) * 100);
840
- const hitColor = hitRate >= 70 ? "success" : hitRate >= 40 ? "warning" : "error";
841
- sp.push(theme.fg(hitColor, `${hitRate}%hit`));
842
- }
843
- if (cumulativeCost)
844
- sp.push(theme.fg("warning", `$${cumulativeCost.toFixed(2)}`));
845
- const CX_BAR_WIDTH = 8;
846
- const cxBarFilled = Math.min(CX_BAR_WIDTH, Math.max(0, Math.round((cxPctVal / 100) * CX_BAR_WIDTH)));
847
- const cxBarColor = cxPctVal > 90 ? "error" : cxPctVal > 70 ? "warning" : "success";
848
- const cxBar = theme.fg(cxBarColor, "━".repeat(cxBarFilled)) +
849
- theme.fg("dim", "─".repeat(CX_BAR_WIDTH - cxBarFilled));
850
- const cxPctText = `${cxPct}%/${formatWidgetTokens(cxWindow)}`;
851
- const cxColorized = cxPctVal > 90
852
- ? theme.fg("error", cxPctText)
853
- : cxPctVal > 70
854
- ? theme.fg("warning", cxPctText)
855
- : cxPctText;
856
- sp.push(`${cxBar} ${cxColorized}`);
857
- const statsLine = sp.map(p => p.includes("\x1b[") ? p : theme.fg("dim", p))
858
- .join(theme.fg("dim", " "));
859
- if (statsLine) {
860
- lines.push(rightAlign("", statsLine, width));
861
- }
862
- if (cachedRtkLabel) {
863
- lines.push(rightAlign("", theme.fg("dim", cachedRtkLabel), width));
864
- }
865
- }
866
- // Last commit info
867
- const lastCommit = getLastCommit(accessors.getBasePath());
868
- const maxCommitLen = 65;
869
- const commitMsg = lastCommit
870
- ? lastCommit.message.length > maxCommitLen
871
- ? lastCommit.message.slice(0, maxCommitLen - 1) + "…"
872
- : lastCommit.message
873
- : "";
874
730
  // Step-mode guidance — shown above keyboard hints when auto is paused
875
731
  if (accessors.isStepMode()) {
876
732
  lines.push(`${pad}${theme.fg("accent", "→")} ${theme.fg("dim", "Ctrl+N to advance to next step · /gsd status for overview")}`);
@@ -881,16 +737,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
881
737
  hintParts.push(`${formattedShortcutPair("dashboard")} dashboard`);
882
738
  hintParts.push(`${formattedShortcutPair("parallel")} parallel`);
883
739
  const hintStr = theme.fg("dim", hintParts.join(" | "));
884
- const commitStr = lastCommit
885
- ? theme.fg("dim", `${lastCommit.timeAgo} ago: ${commitMsg}`)
886
- : "";
887
- const locationStr = theme.fg("dim", widgetPwd);
888
- if (commitStr) {
889
- lines.push(rightAlign(`${pad}${locationStr} · ${commitStr}`, hintStr, width));
890
- }
891
- else {
892
- lines.push(rightAlign(`${pad}${locationStr}`, hintStr, width));
893
- }
740
+ lines.push(rightAlign("", hintStr, width));
894
741
  lines.push(...ui.bar());
895
742
  cachedLines = lines;
896
743
  cachedWidth = width;
@@ -908,18 +755,175 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
908
755
  };
909
756
  });
910
757
  }
911
- // ─── Right-align Helper ───────────────────────────────────────────────────────
912
- /** Right-align helper: build a line with left content and right content. */
913
- function rightAlign(left, right, width) {
914
- const leftVis = visibleWidth(left);
915
- const rightVis = visibleWidth(right);
916
- const gap = Math.max(1, width - leftVis - rightVis);
917
- return truncateToWidth(left + " ".repeat(gap) + right, width, "…");
918
- }
919
- /** Pad a string with trailing spaces to fill exactly `colWidth` (ANSI-aware). */
920
- function padToWidth(s, colWidth) {
921
- const vis = visibleWidth(s);
922
- if (vis >= colWidth)
923
- return truncateToWidth(s, colWidth, "…");
924
- return s + " ".repeat(colWidth - vis);
758
+ export function setCompletionProgressWidget(ctx, snapshot) {
759
+ if (!ctx.hasUI)
760
+ return;
761
+ ctx.ui.setWidget("gsd-outcome", undefined);
762
+ if (typeof ctx.ui?.setHeader === "function") {
763
+ ctx.ui.setHeader(() => ({
764
+ render() { return []; },
765
+ invalidate() { },
766
+ }));
767
+ }
768
+ if (typeof ctx.ui?.setStatus === "function") {
769
+ ctx.ui.setStatus("gsd-step", undefined);
770
+ }
771
+ ctx.ui.setWidget("gsd-progress", (_tui, theme) => ({
772
+ render(width) {
773
+ const ui = makeUI(theme, width);
774
+ const pad = INDENT.base;
775
+ const lines = [];
776
+ const contentWidth = Math.max(20, width - visibleWidth(pad));
777
+ const add = (line = "") => {
778
+ lines.push(line ? truncateToWidth(`${pad}${line}`, width, "…") : "");
779
+ };
780
+ const addSection = (label, value, indent = "") => {
781
+ const clean = normalizeRollupText(value);
782
+ if (!clean)
783
+ return;
784
+ add(`${indent}${theme.fg("accent", label)} ${theme.fg("text", truncateToWidth(clean, contentWidth - indent.length - label.length - 1, "…"))}`);
785
+ };
786
+ const addList = (label, values, limit, indent = "") => {
787
+ const clean = (values ?? []).map(normalizeRollupText).filter((v) => !!v);
788
+ if (clean.length === 0)
789
+ return;
790
+ const shown = clean.slice(0, limit);
791
+ const more = clean.length > shown.length ? ` (+${clean.length - shown.length} more)` : "";
792
+ add(`${indent}${theme.fg("accent", label)} ${theme.fg("text", truncateToWidth(shown.join("; ") + more, contentWidth - indent.length - label.length - 1, "…"))}`);
793
+ };
794
+ lines.push(...ui.bar());
795
+ const elapsed = formatAutoElapsed(snapshot.startedAt);
796
+ const heading = snapshot.allMilestonesComplete
797
+ ? "All milestones complete"
798
+ : snapshot.milestoneId
799
+ ? `Milestone ${snapshot.milestoneId} roll-up`
800
+ : "Milestone roll-up";
801
+ lines.push(rightAlign(`${pad}${theme.fg("accent", theme.bold(heading))}`, elapsed ? theme.fg("dim", elapsed) : "", width));
802
+ if (snapshot.milestoneTitle) {
803
+ add(theme.fg("text", snapshot.milestoneTitle));
804
+ }
805
+ lines.push("");
806
+ add(theme.fg("accent", "Outcome"));
807
+ addSection("", snapshot.oneLiner, " ");
808
+ const changed = [
809
+ ...(snapshot.successCriteriaResults ? [snapshot.successCriteriaResults] : []),
810
+ ...(snapshot.requirementOutcomes ? [snapshot.requirementOutcomes] : []),
811
+ ...(snapshot.keyDecisions ?? []),
812
+ ].map(normalizeRollupText).filter((v) => !!v).slice(0, 4);
813
+ if (changed.length > 0) {
814
+ lines.push("");
815
+ add(theme.fg("accent", "What changed"));
816
+ for (const item of changed)
817
+ add(` - ${theme.fg("text", item)}`);
818
+ }
819
+ const verification = [
820
+ snapshot.definitionOfDoneResults,
821
+ snapshot.deviations ? `Deviations: ${snapshot.deviations}` : null,
822
+ snapshot.followUps ? `Follow-ups: ${snapshot.followUps}` : null,
823
+ ].map(normalizeRollupText).filter((v) => !!v);
824
+ if (verification.length > 0 || (snapshot.keyFiles?.length ?? 0) > 0) {
825
+ lines.push("");
826
+ add(theme.fg("accent", "Verification"));
827
+ for (const item of verification.slice(0, 3))
828
+ add(` - ${theme.fg("text", item)}`);
829
+ addList("Files:", snapshot.keyFiles, 4, " ");
830
+ }
831
+ if ((snapshot.lessonsLearned?.length ?? 0) > 0) {
832
+ lines.push("");
833
+ addList("Lessons:", snapshot.lessonsLearned, 2);
834
+ }
835
+ const hasSliceTotals = typeof snapshot.completedSlices === "number" && typeof snapshot.totalSlices === "number" && snapshot.totalSlices > 0;
836
+ lines.push("");
837
+ const stats = [];
838
+ if (hasSliceTotals)
839
+ stats.push(theme.fg("success", `${snapshot.completedSlices}/${snapshot.totalSlices} slices`));
840
+ if (snapshot.unitCount > 0)
841
+ stats.push(theme.fg("dim", `${snapshot.unitCount} units`));
842
+ if (snapshot.totalTokens > 0)
843
+ stats.push(theme.fg("dim", `${formatWidgetTokens(snapshot.totalTokens)} tokens`));
844
+ if (snapshot.totalCost > 0)
845
+ stats.push(theme.fg("warning", `$${snapshot.totalCost.toFixed(2)}`));
846
+ if (typeof snapshot.cacheHitRate === "number") {
847
+ const hitColor = snapshot.cacheHitRate >= 70 ? "success" : snapshot.cacheHitRate >= 40 ? "warning" : "error";
848
+ stats.push(theme.fg(hitColor, `${Math.round(snapshot.cacheHitRate)}% cache hit`));
849
+ }
850
+ if (stats.length > 0) {
851
+ add(`${theme.fg("accent", "Run totals")} ${stats.join(theme.fg("dim", " · "))}`);
852
+ }
853
+ lines.push("");
854
+ const nextAction = snapshot.allMilestonesComplete
855
+ ? "Review the roll-up, then start a new milestone when ready."
856
+ : "Review the roll-up, inspect status, or continue to the next milestone.";
857
+ const commands = snapshot.allMilestonesComplete
858
+ ? ["/gsd status for overview", "/gsd visualize to inspect", "/gsd notifications for history", "/gsd start for new work"]
859
+ : ["/gsd status for overview", "/gsd visualize to inspect", "/gsd notifications for history", "/gsd auto for next milestone"];
860
+ add(`${theme.fg("success", "Next")} ${theme.fg("text", nextAction)}`);
861
+ add(theme.fg("dim", commands.join(" · ")));
862
+ const location = snapshot.basePath ? theme.fg("dim", snapshot.basePath) : "";
863
+ const reason = theme.fg("dim", snapshot.reason);
864
+ lines.push(rightAlign(`${pad}${truncateToWidth(location, Math.max(0, width - 32), "…")}`, reason, width));
865
+ lines.push(...ui.bar());
866
+ return lines;
867
+ },
868
+ invalidate() { },
869
+ dispose() { },
870
+ }));
871
+ }
872
+ export function setAutoOutcomeWidget(ctx, snapshot) {
873
+ if (!ctx.hasUI)
874
+ return;
875
+ ctx.ui.setWidget("gsd-outcome", (_tui, theme) => ({
876
+ render(width) {
877
+ const color = snapshot.status === "failed" || snapshot.status === "blocked"
878
+ ? "warning"
879
+ : snapshot.status === "complete"
880
+ ? "success"
881
+ : "borderAccent";
882
+ const icon = snapshot.status === "complete" ? "✓"
883
+ : snapshot.status === "failed" ? "x"
884
+ : snapshot.status === "blocked" ? "!"
885
+ : snapshot.status === "paused" ? "||"
886
+ : "●";
887
+ const innerWidth = Math.max(8, width - 4);
888
+ const maxLines = 7;
889
+ const lines = [];
890
+ const elapsed = snapshot.startedAt ? formatAutoElapsed(snapshot.startedAt) : "";
891
+ const heading = `${theme.fg(color, icon)} ${theme.fg("accent", theme.bold("GSD"))} ${theme.fg("text", snapshot.title)}`;
892
+ lines.push(rightAlign(heading, elapsed ? theme.fg("dim", elapsed) : "", innerWidth));
893
+ const commands = snapshot.commands?.filter(Boolean) ?? [];
894
+ const commandLine = commands.length > 0 ? theme.fg("dim", commands.join(" · ")) : null;
895
+ const addWrapped = (text, prefix = "") => {
896
+ const reserve = commandLine ? 1 : 0;
897
+ const remaining = Math.max(0, maxLines - reserve - lines.length);
898
+ if (remaining === 0)
899
+ return;
900
+ const available = Math.max(8, innerWidth - visibleWidth(prefix));
901
+ for (const [idx, line] of wrapVisibleText(text, available).slice(0, remaining).entries()) {
902
+ lines.push(`${idx === 0 ? prefix : " ".repeat(visibleWidth(prefix))}${line}`);
903
+ }
904
+ };
905
+ if (snapshot.detail) {
906
+ addWrapped(snapshot.detail, `${theme.fg("dim", "Reason")} `);
907
+ }
908
+ if (snapshot.unitLabel) {
909
+ addWrapped(snapshot.unitLabel, `${theme.fg("dim", "Last")} `);
910
+ }
911
+ addWrapped(snapshot.nextAction, `${theme.fg("success", "Next")} `);
912
+ if (commandLine && lines.length < maxLines) {
913
+ lines.push(commandLine);
914
+ }
915
+ return renderFrame(theme, lines, width, { borderColor: color, paddingX: 1 });
916
+ },
917
+ invalidate() { },
918
+ dispose() { },
919
+ }));
920
+ }
921
+ function normalizeRollupText(value) {
922
+ const clean = value
923
+ ?.replace(/\s+/g, " ")
924
+ .replace(/^[-*]\s+/, "")
925
+ .trim();
926
+ if (!clean || clean === "(none)" || clean === "None." || clean === "Not provided.")
927
+ return null;
928
+ return clean;
925
929
  }