gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.e146beb20

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 (342) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/GSD-WORKFLOW.md +2 -2
  3. package/dist/resources/extensions/github-sync/templates.js +39 -8
  4. package/dist/resources/extensions/gsd/auto/loop.js +48 -10
  5. package/dist/resources/extensions/gsd/auto/phases.js +37 -30
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -15
  7. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
  9. package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
  10. package/dist/resources/extensions/gsd/auto-prompts.js +111 -1
  11. package/dist/resources/extensions/gsd/auto-recovery.js +154 -8
  12. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  13. package/dist/resources/extensions/gsd/auto.js +9 -1
  14. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +15 -1
  15. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -1
  16. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  17. package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
  18. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  19. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  20. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  21. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  22. package/dist/resources/extensions/gsd/db-base-schema.js +14 -0
  23. package/dist/resources/extensions/gsd/db-migration-steps.js +16 -0
  24. package/dist/resources/extensions/gsd/detection.js +106 -0
  25. package/dist/resources/extensions/gsd/graph.js +9 -3
  26. package/dist/resources/extensions/gsd/gsd-db.js +102 -2
  27. package/dist/resources/extensions/gsd/guided-flow.js +49 -12
  28. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  29. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  30. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
  31. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  32. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  33. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  34. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  35. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  36. package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
  37. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  38. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  39. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  40. package/dist/web/standalone/.next/BUILD_ID +1 -1
  41. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  42. package/dist/web/standalone/.next/build-manifest.json +3 -3
  43. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  44. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  45. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  46. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/index.html +1 -1
  63. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  70. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  71. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  74. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  75. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  76. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  77. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  78. package/package.json +10 -6
  79. package/packages/contracts/package.json +1 -1
  80. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  81. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  82. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  83. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  84. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  85. package/packages/pi-ai/dist/models/index.js +8 -0
  86. package/packages/pi-ai/dist/models/index.js.map +1 -1
  87. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  88. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  89. package/packages/pi-ai/dist/providers/fake.js +319 -0
  90. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  91. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  92. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  93. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  94. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  95. package/packages/pi-ai/src/models/index.ts +9 -0
  96. package/packages/pi-ai/src/providers/fake.ts +376 -0
  97. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  98. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  99. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +74 -0
  100. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  102. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  103. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  104. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  105. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  106. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  107. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  108. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  109. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  110. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/runner.js +14 -1
  112. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +97 -0
  114. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  117. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +4 -0
  119. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  120. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  121. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  122. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  124. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  126. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  128. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  130. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  131. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  132. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  133. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  134. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  135. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  136. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  137. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  138. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  141. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  143. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  144. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  145. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  146. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  147. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +16 -0
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +106 -17
  151. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  152. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +60 -1
  154. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +40 -1
  156. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  158. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  160. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  162. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +23 -0
  165. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  167. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  168. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  170. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  171. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  172. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  173. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  174. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  179. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  183. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  185. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  187. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  189. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  190. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  191. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  192. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  193. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  194. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  195. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  196. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  198. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  199. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +87 -0
  200. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  201. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  202. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +108 -0
  203. package/packages/pi-coding-agent/src/core/extensions/runner.ts +16 -1
  204. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  205. package/packages/pi-coding-agent/src/core/settings-manager.ts +12 -0
  206. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  207. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  208. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  209. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  210. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  211. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  212. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  213. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  214. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  215. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +118 -17
  216. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +43 -1
  217. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -1
  218. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  219. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  220. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +25 -0
  221. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  222. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  223. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  224. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  225. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  226. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  227. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  228. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  229. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  230. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  231. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  232. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  233. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  234. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  235. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  236. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  237. package/packages/pi-tui/dist/index.d.ts +1 -0
  238. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  239. package/packages/pi-tui/dist/index.js +2 -0
  240. package/packages/pi-tui/dist/index.js.map +1 -1
  241. package/packages/pi-tui/dist/style.d.ts +41 -0
  242. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  243. package/packages/pi-tui/dist/style.js +158 -0
  244. package/packages/pi-tui/dist/style.js.map +1 -0
  245. package/packages/pi-tui/dist/tui.d.ts +0 -1
  246. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/tui.js +3 -8
  248. package/packages/pi-tui/dist/tui.js.map +1 -1
  249. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  250. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  251. package/packages/pi-tui/src/index.ts +9 -0
  252. package/packages/pi-tui/src/style.ts +225 -0
  253. package/packages/pi-tui/src/tui.ts +3 -8
  254. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  255. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  256. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  257. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  258. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  259. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  260. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  261. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  262. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  263. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  264. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  265. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  266. package/src/resources/GSD-WORKFLOW.md +2 -2
  267. package/src/resources/extensions/github-sync/templates.ts +38 -8
  268. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  269. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  270. package/src/resources/extensions/gsd/auto/loop.ts +67 -18
  271. package/src/resources/extensions/gsd/auto/phases.ts +42 -28
  272. package/src/resources/extensions/gsd/auto/run-unit.ts +24 -14
  273. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  274. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
  275. package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
  276. package/src/resources/extensions/gsd/auto-prompts.ts +116 -1
  277. package/src/resources/extensions/gsd/auto-recovery.ts +153 -7
  278. package/src/resources/extensions/gsd/auto-start.ts +7 -6
  279. package/src/resources/extensions/gsd/auto.ts +12 -1
  280. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -1
  282. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  283. package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
  284. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  285. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  286. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  287. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  288. package/src/resources/extensions/gsd/db-base-schema.ts +15 -0
  289. package/src/resources/extensions/gsd/db-migration-steps.ts +17 -0
  290. package/src/resources/extensions/gsd/detection.ts +128 -0
  291. package/src/resources/extensions/gsd/graph.ts +12 -5
  292. package/src/resources/extensions/gsd/gsd-db.ts +119 -1
  293. package/src/resources/extensions/gsd/guided-flow.ts +49 -12
  294. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  295. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  296. package/src/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
  297. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  298. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  299. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  300. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  301. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  302. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +84 -5
  303. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +170 -1
  304. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
  305. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  306. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  307. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  308. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
  309. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  310. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  311. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  312. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  313. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  314. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  315. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  316. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  317. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  318. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  319. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  320. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  321. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  322. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  323. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  325. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  326. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  327. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +46 -2
  328. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +7 -0
  329. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  330. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  331. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  332. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  334. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  335. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  336. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  337. package/src/resources/extensions/gsd/unit-runtime.ts +14 -0
  338. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  339. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  340. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  341. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → y73quA-XdLo9n41nxphjW}/_buildManifest.js +0 -0
  342. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → y73quA-XdLo9n41nxphjW}/_ssgManifest.js +0 -0
@@ -1,7 +1,8 @@
1
+ // GSD-2 Interactive Tool Execution Rendering Tests
1
2
  import { describe, test } from "node:test";
2
3
  import assert from "node:assert/strict";
3
4
  import stripAnsi from "strip-ansi";
4
- import { ToolExecutionComponent } from "../tool-execution.js";
5
+ import { ToolExecutionComponent, ToolPhaseSummaryComponent, type ToolExecutionPhase } from "../tool-execution.js";
5
6
  import { initTheme } from "../../theme/theme.js";
6
7
 
7
8
  initTheme("dark", false);
@@ -50,25 +51,85 @@ function renderToolCollapsed(
50
51
  }
51
52
 
52
53
  describe("ToolExecutionComponent", () => {
53
- test("renders framed header with Running status while tool is partial", () => {
54
+ test("renders framed header with running status while tool is partial", () => {
54
55
  const rendered = renderToolCollapsed("mcp__demo__do_thing", { ok: true });
55
56
 
56
- assert.match(rendered, /Tool demo\u00b7do_thing/);
57
- assert.match(rendered, /Running/);
57
+ assert.match(rendered, /demo\u00b7do_thing/);
58
+ assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
59
+ assert.match(rendered, /running/);
60
+ assert.match(rendered, /running · \d+(ms|s)/);
58
61
  });
59
62
 
60
- test("renders framed header with Error status for failed tool result", () => {
63
+ test("renders framed header with failed status for failed tool result", () => {
61
64
  const rendered = renderTool(
62
65
  "mcp__demo__do_thing",
63
66
  { ok: true },
64
67
  { content: [{ type: "text", text: "boom" }], isError: true },
65
68
  );
66
69
 
67
- assert.match(rendered, /Tool demo\u00b7do_thing/);
68
- assert.match(rendered, /Error/);
70
+ assert.match(rendered, /demo\u00b7do_thing/);
71
+ assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
72
+ assert.match(rendered, /failed/);
73
+ assert.match(rendered, /failed · \d+(ms|s)/);
69
74
  assert.match(rendered, /boom/);
70
75
  });
71
76
 
77
+ test("collapses successful low-signal tool cards by default", () => {
78
+ const rendered = renderToolCollapsed(
79
+ "mcp__demo__noop",
80
+ { ok: true },
81
+ { content: [], isError: false },
82
+ );
83
+
84
+ assert.match(rendered, /success · \d+(ms|s)/);
85
+ assert.match(rendered, /demo\u00b7noop/);
86
+ assert.doesNotMatch(rendered, /Completed/);
87
+ assert.doesNotMatch(rendered, /ok=true/);
88
+ });
89
+
90
+ test("exposes phase metadata for successful low-signal tool rows", () => {
91
+ const component = new ToolExecutionComponent(
92
+ "gsd_requirement_update",
93
+ { id: "R001" },
94
+ {},
95
+ { label: "Update Requirement" } as any,
96
+ { requestRender() {} } as any,
97
+ );
98
+ component.updateResult({ content: [], isError: false });
99
+
100
+ assert.deepEqual(component.getRollupPhase()?.label, "Requirement writes");
101
+ });
102
+
103
+ test("exposes phase metadata for collapsed output-bearing generic tools", () => {
104
+ const component = new ToolExecutionComponent(
105
+ "mcp__demo__do_thing",
106
+ { ok: true },
107
+ {},
108
+ undefined,
109
+ { requestRender() {} } as any,
110
+ );
111
+ component.updateResult({ content: [{ type: "text", text: "important output" }], isError: false });
112
+
113
+ assert.deepEqual(component.getRollupPhase()?.label, "Other tool actions");
114
+ });
115
+
116
+ test("renders phase-based summaries for rolled-up tool executions", () => {
117
+ const phases: ToolExecutionPhase[] = [
118
+ { label: "Setup / shell", count: 6, durationMs: 12 },
119
+ { label: "Context reads", count: 4, durationMs: 6 },
120
+ { label: "Requirement writes", count: 4, durationMs: 4 },
121
+ { label: "Memory lookups", count: 4, durationMs: 4 },
122
+ { label: "Finalization", count: 1, durationMs: 1 },
123
+ ];
124
+ const rendered = stripAnsi(new ToolPhaseSummaryComponent(phases).render(120).join("\n"));
125
+
126
+ assert.match(rendered, /Setup \/ shell 6 actions\s+success · 12ms/);
127
+ assert.match(rendered, /Context reads 4 actions\s+success · 6ms/);
128
+ assert.match(rendered, /Requirement writes 4 actions\s+success · 4ms/);
129
+ assert.match(rendered, /Memory lookups 4 actions\s+success · 4ms/);
130
+ assert.match(rendered, /Finalization 1 action\s+success · 1ms/);
131
+ });
132
+
72
133
  test("passes failed result status to custom result renderers", () => {
73
134
  const rendered = renderTool(
74
135
  "gsd_requirement_save",
@@ -85,7 +146,7 @@ describe("ToolExecutionComponent", () => {
85
146
  },
86
147
  );
87
148
 
88
- assert.match(rendered, /Error/);
149
+ assert.match(rendered, /failed/);
89
150
  assert.match(rendered, /custom saw error/);
90
151
  assert.doesNotMatch(rendered, /custom saw success/);
91
152
  });
@@ -148,14 +209,16 @@ describe("ToolExecutionComponent", () => {
148
209
  { label: "Complete Slice" },
149
210
  );
150
211
 
151
- assert.match(rendered, /Tool Complete Slice/);
212
+ assert.match(rendered, /Complete Slice/);
213
+ assert.doesNotMatch(rendered, /Tool Complete Slice/);
152
214
  assert.doesNotMatch(rendered, /gsd_slice_complete/);
153
215
  });
154
216
 
155
217
  test("frame header strips gsd_ prefix and title-cases when no label is registered", () => {
156
218
  const rendered = renderToolCollapsed("gsd_requirement_update", { id: "R005" });
157
219
 
158
- assert.match(rendered, /Tool Requirement Update/);
220
+ assert.match(rendered, /Requirement Update/);
221
+ assert.doesNotMatch(rendered, /Tool Requirement Update/);
159
222
  assert.doesNotMatch(rendered, /gsd_requirement_update/);
160
223
  });
161
224
 
@@ -184,7 +247,7 @@ describe("ToolExecutionComponent", () => {
184
247
  assert.doesNotMatch(rendered, /…/);
185
248
  });
186
249
 
187
- test("generic fallback truncates long output when collapsed", () => {
250
+ test("generic fallback collapses successful output rows until expanded", () => {
188
251
  const longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join("\n");
189
252
  const rendered = renderToolCollapsed(
190
253
  "mcp__demo__do_thing",
@@ -192,10 +255,10 @@ describe("ToolExecutionComponent", () => {
192
255
  { content: [{ type: "text", text: longOutput }], isError: false },
193
256
  );
194
257
 
195
- assert.match(rendered, /line 1\b/);
196
- assert.match(rendered, /line 10\b/);
197
- assert.doesNotMatch(rendered, /line 20\b/);
198
- assert.match(rendered, /\(15 more lines/);
258
+ assert.match(rendered, /demo\u00b7do_thing/);
259
+ assert.match(rendered, /success · \d+(ms|s)/);
260
+ assert.doesNotMatch(rendered, /line 1\b/);
261
+ assert.doesNotMatch(rendered, /\(15 more lines/);
199
262
  });
200
263
 
201
264
  test("generic fallback falls back to truncated JSON for complex args", () => {
@@ -0,0 +1,59 @@
1
+ // GSD2 - Runtime tests for adaptive terminal layout rendering
2
+
3
+ import assert from "node:assert/strict";
4
+ import { describe, it, before } from "node:test";
5
+ import stripAnsi from "strip-ansi";
6
+ import { AdaptiveLayoutComponent } from "./adaptive-layout.js";
7
+ import { initTheme } from "../theme/theme.js";
8
+
9
+ before(() => {
10
+ initTheme("dark", false);
11
+ });
12
+
13
+ function render(component: AdaptiveLayoutComponent, width: number): string {
14
+ return component.render(width).map(stripAnsi).join("\n");
15
+ }
16
+
17
+ describe("AdaptiveLayoutComponent", () => {
18
+ it("renders workflow command center and inspector on wide terminals", () => {
19
+ const component = new AdaptiveLayoutComponent(() => ({
20
+ override: "workflow",
21
+ activeToolCount: 2,
22
+ gsdPhase: "executing milestone M001",
23
+ sessionName: "demo",
24
+ cwd: "/tmp/demo",
25
+ }));
26
+
27
+ const output = render(component, 132);
28
+ assert.match(output, /GSD Command Center/);
29
+ assert.match(output, /signals/);
30
+ assert.match(output, /2 running/);
31
+ });
32
+
33
+ it("falls back to a single compact row for narrow workflow terminals", () => {
34
+ const component = new AdaptiveLayoutComponent(() => ({
35
+ override: "workflow",
36
+ activeToolCount: 1,
37
+ gsdPhase: "executing milestone M001",
38
+ cwd: "/tmp/demo",
39
+ }));
40
+
41
+ const output = render(component, 68);
42
+ assert.match(output, /GSD compact/);
43
+ assert.doesNotMatch(output, /signals/);
44
+ });
45
+
46
+ it("renders blocking failure context in debug mode", () => {
47
+ const component = new AdaptiveLayoutComponent(() => ({
48
+ override: "auto",
49
+ activeToolCount: 0,
50
+ lastError: "Cannot find module @gsd/native",
51
+ cwd: "/tmp/demo",
52
+ }));
53
+
54
+ const output = render(component, 120);
55
+ assert.match(output, /blocking failure/);
56
+ assert.match(output, /Cannot find module/);
57
+ assert.match(output, /inspect the failed output/);
58
+ });
59
+ });
@@ -0,0 +1,160 @@
1
+ // GSD2 - Adaptive terminal mode dashboard for the interactive TUI
2
+
3
+ import { style, truncateToWidth, visibleWidth, type Component } from "@gsd/pi-tui";
4
+ import type { TuiAdaptiveMode, TuiMode } from "../tui-mode.js";
5
+ import { resolveTuiMode } from "../tui-mode.js";
6
+ import { theme, type ThemeColor } from "../theme/theme.js";
7
+
8
+ export interface AdaptiveLayoutState {
9
+ override: TuiAdaptiveMode;
10
+ activeToolCount: number;
11
+ gsdPhase?: string;
12
+ lastError?: string;
13
+ sessionName?: string;
14
+ cwd: string;
15
+ }
16
+
17
+ export class AdaptiveLayoutComponent implements Component {
18
+ constructor(private readonly getState: () => AdaptiveLayoutState) {}
19
+
20
+ invalidate(): void {}
21
+
22
+ render(width: number): string[] {
23
+ const state = this.getState();
24
+ const mode = resolveTuiMode({
25
+ terminalWidth: width,
26
+ override: state.override,
27
+ activeToolCount: state.activeToolCount,
28
+ gsdPhase: state.gsdPhase,
29
+ hasBlockingError: !!state.lastError,
30
+ });
31
+
32
+ if (state.override === "auto" && mode === "chat" && !state.gsdPhase && !state.lastError && state.activeToolCount === 0) {
33
+ return [];
34
+ }
35
+
36
+ if (mode === "compact" || width < 72) return this.renderCompact(width, mode, state);
37
+ if (mode === "debug") return this.renderDebug(width, state);
38
+ if (mode === "validation") return this.renderValidation(width, state);
39
+ if (mode === "workflow") return this.renderWorkflow(width, state);
40
+ return this.renderChat(width, state);
41
+ }
42
+
43
+ private renderWorkflow(width: number, state: AdaptiveLayoutState): string[] {
44
+ if (width < 112) return this.renderCompact(width, "workflow", state);
45
+
46
+ const leftWidth = Math.max(44, Math.floor(width * 0.56));
47
+ const rightWidth = Math.max(32, width - leftWidth - 2);
48
+ const phase = state.gsdPhase ?? "Ready";
49
+ const left = this.frame(
50
+ [
51
+ this.metric("Active", phase, "modeWorkflow"),
52
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} running` : "idle", "toolRunning"),
53
+ this.metric("Mode", state.override === "auto" ? "auto workflow" : state.override, "modeWorkflow"),
54
+ ],
55
+ leftWidth,
56
+ "GSD Command Center",
57
+ "workflow",
58
+ "modeWorkflow",
59
+ );
60
+ const right = this.frame(
61
+ [
62
+ `Session ${state.sessionName ?? "current"}`,
63
+ `Path ${this.basename(state.cwd)}`,
64
+ `Next ${state.activeToolCount > 0 ? "watch tool output" : "continue from prompt"}`,
65
+ ],
66
+ rightWidth,
67
+ "signals",
68
+ "inspector",
69
+ "surfaceAccent",
70
+ );
71
+ return this.columns(left, right, leftWidth);
72
+ }
73
+
74
+ private renderValidation(width: number, state: AdaptiveLayoutState): string[] {
75
+ const phase = state.gsdPhase ?? "Validation pending";
76
+ return this.frame(
77
+ [
78
+ this.metric("Focus", phase, "modeValidation"),
79
+ this.metric("Checks", state.activeToolCount > 0 ? `${state.activeToolCount} active` : "waiting", "toolRunning"),
80
+ this.metric("Timeline", state.lastError ? "blocked" : "ready for completion evidence", state.lastError ? "toolError" : "toolSuccess"),
81
+ ],
82
+ width,
83
+ "validation",
84
+ state.override === "auto" ? "auto" : state.override,
85
+ "modeValidation",
86
+ );
87
+ }
88
+
89
+ private renderDebug(width: number, state: AdaptiveLayoutState): string[] {
90
+ const error = state.lastError ?? "Blocking error detected";
91
+ return this.frame(
92
+ [
93
+ this.metric("Failure", truncateToWidth(error, Math.max(20, width - 20), ""), "toolError"),
94
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} still running` : "none running", "toolRunning"),
95
+ this.metric("Next", "inspect the failed output, then retry the smallest step", "modeDebug"),
96
+ ],
97
+ width,
98
+ "blocking failure",
99
+ "debug",
100
+ "modeDebug",
101
+ );
102
+ }
103
+
104
+ private renderChat(width: number, state: AdaptiveLayoutState): string[] {
105
+ return this.frame(
106
+ [
107
+ this.metric("Mode", state.override === "auto" ? "auto chat" : state.override, "surfaceAccent"),
108
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} active` : "compact rows", "toolMuted"),
109
+ ],
110
+ width,
111
+ "chat",
112
+ state.sessionName ?? "conversation",
113
+ "surfaceAccent",
114
+ );
115
+ }
116
+
117
+ private renderCompact(width: number, mode: TuiMode, state: AdaptiveLayoutState): string[] {
118
+ const phase = state.lastError ?? state.gsdPhase ?? (state.activeToolCount > 0 ? `${state.activeToolCount} tools` : "ready");
119
+ const line = `${theme.fg("modeCompact", "GSD compact")} ${theme.fg("surfaceMuted", `${mode} · ${phase}`)}`;
120
+ return style()
121
+ .border("minimal")
122
+ .borderColor((text) => theme.fg("surfaceBorder", text))
123
+ .bodyGutter(" ")
124
+ .render([line], width);
125
+ }
126
+
127
+ private frame(lines: string[], width: number, title: string, rightTitle: string, accent: ThemeColor): string[] {
128
+ return style()
129
+ .border("rule")
130
+ .density("compact")
131
+ .toneColor((text) => theme.fg("surfaceMuted", text))
132
+ .borderColor((text) => theme.fg("surfaceBorder", text))
133
+ .title(theme.fg("surfaceTitle", title))
134
+ .rightTitle(theme.fg(accent, rightTitle))
135
+ .bodyGutter(theme.fg(accent, "│ "))
136
+ .render(lines, width);
137
+ }
138
+
139
+ private metric(label: string, value: string, color: ThemeColor): string {
140
+ return `${theme.fg("surfaceMuted", `${label.padEnd(8)} `)}${theme.fg(color, value)}`;
141
+ }
142
+
143
+ private columns(left: string[], right: string[], leftWidth: number): string[] {
144
+ const rows = Math.max(left.length, right.length);
145
+ const output: string[] = [];
146
+ for (let i = 0; i < rows; i++) {
147
+ const leftLine = left[i] ?? "";
148
+ const rightLine = right[i] ?? "";
149
+ const gap = " ".repeat(Math.max(2, leftWidth - visibleWidth(leftLine) + 2));
150
+ output.push(`${leftLine}${gap}${rightLine}`);
151
+ }
152
+ return output;
153
+ }
154
+
155
+ private basename(cwd: string): string {
156
+ const trimmed = cwd.replace(/\/+$/, "");
157
+ const slash = trimmed.lastIndexOf("/");
158
+ return slash === -1 ? trimmed : trimmed.slice(slash + 1);
159
+ }
160
+ }
@@ -1,3 +1,4 @@
1
+ // GSD2 TUI - Assistant message card renderer for interactive terminal sessions.
1
2
  import type { AssistantMessage } from "@gsd/pi-ai";
2
3
  import { Container, Markdown, type MarkdownTheme, Spacer, Text } from "@gsd/pi-tui";
3
4
  import { getMarkdownTheme, theme } from "../theme/theme.js";
@@ -1,4 +1,5 @@
1
- import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
1
+ // GSD2 TUI - Shared chat frame renderer for assistant, user, and system cards.
2
+ import { style, truncateToWidth, visibleWidth } from "@gsd/pi-tui";
2
3
  import { theme } from "../theme/theme.js";
3
4
  import { formatTimestamp, type TimestampFormat } from "./timestamp.js";
4
5
 
@@ -34,7 +35,7 @@ export function renderChatFrame(
34
35
  : "borderAccent";
35
36
  const borderMuted = isPurple ? "customMessageLabel" : "borderMuted";
36
37
  const border = (s: string) => theme.fg(borderColor, s);
37
- const leftRaw = `• ${opts.label}`;
38
+ const leftRaw = opts.label;
38
39
  const rightRaw =
39
40
  opts.showTimestamp === false || !opts.timestamp
40
41
  ? ""
@@ -67,21 +68,21 @@ export function renderChatFrame(
67
68
  const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
68
69
  const headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));
69
70
 
70
- const sourceLines = trimOuterBlankLines(contentLines);
71
71
  const bodyColor =
72
72
  opts.tone === "user"
73
73
  ? "userMessageText"
74
74
  : isPurple
75
75
  ? "customMessageText"
76
76
  : "assistantMessageText";
77
+ const sourceLines = trimOuterBlankLines(contentLines);
77
78
  const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
78
79
  const clipped = truncateToWidth(line, contentWidth, "");
79
- return border("│ ") + theme.fg(bodyColor, clipped);
80
+ return theme.fg(bodyColor, clipped);
80
81
  });
81
82
 
82
- return [
83
- theme.fg(borderMuted, "".repeat(outerWidth)),
84
- headerRow + " ".repeat(headerPad),
85
- ...bodyLines,
86
- ];
83
+ return style()
84
+ .border("rule")
85
+ .borderColor((line) => (line.startsWith("─") ? theme.fg(borderMuted, line) : border(line)))
86
+ .title(headerRow + " ".repeat(headerPad))
87
+ .render(bodyLines, outerWidth);
87
88
  }
@@ -1,5 +1,6 @@
1
1
  import type { ThinkingLevel } from "@gsd/pi-agent-core";
2
2
  import type { Transport } from "@gsd/pi-ai";
3
+ import type { AdaptiveTuiMode } from "../../../core/settings-manager.js";
3
4
  import {
4
5
  Container,
5
6
  getCapabilities,
@@ -46,6 +47,7 @@ export interface SettingsConfig {
46
47
  quietStartup: boolean;
47
48
  clearOnShrink: boolean;
48
49
  timestampFormat: "date-time-iso" | "date-time-us";
50
+ adaptiveMode: AdaptiveTuiMode;
49
51
  }
50
52
 
51
53
  export interface SettingsCallbacks {
@@ -71,6 +73,7 @@ export interface SettingsCallbacks {
71
73
  onQuietStartupChange: (enabled: boolean) => void;
72
74
  onClearOnShrinkChange: (enabled: boolean) => void;
73
75
  onTimestampFormatChange: (format: "date-time-iso" | "date-time-us") => void;
76
+ onAdaptiveModeChange: (mode: AdaptiveTuiMode) => void;
74
77
  onCancel: () => void;
75
78
  }
76
79
 
@@ -367,6 +370,15 @@ export class SettingsSelectorComponent extends Container {
367
370
  values: ["date-time-iso", "date-time-us"],
368
371
  });
369
372
 
373
+ const timestampIndex = items.findIndex((item) => item.id === "timestamp-format");
374
+ items.splice(timestampIndex + 1, 0, {
375
+ id: "adaptive-mode",
376
+ label: "TUI adaptive mode",
377
+ description: "Auto-select or force the terminal layout mode",
378
+ currentValue: config.adaptiveMode,
379
+ values: ["auto", "chat", "workflow", "validation", "debug", "compact"],
380
+ });
381
+
370
382
  // Add borders
371
383
  this.addChild(new DynamicBorder());
372
384
 
@@ -435,6 +447,9 @@ export class SettingsSelectorComponent extends Container {
435
447
  case "timestamp-format":
436
448
  callbacks.onTimestampFormatChange(newValue as "date-time-iso" | "date-time-us");
437
449
  break;
450
+ case "adaptive-mode":
451
+ callbacks.onAdaptiveModeChange(newValue as AdaptiveTuiMode);
452
+ break;
438
453
  }
439
454
  },
440
455
  callbacks.onCancel,
@@ -1,3 +1,4 @@
1
+ // GSD2 TUI Tests - Runtime coverage for tool-card cleanup and success notification rendering.
1
2
  // Runtime regression tests for the post-compaction tool-card cleanup and the
2
3
  // green-bordered success-notification rendering. Replaces the source-grep
3
4
  // `src/tests/tui-running-and-success-box.test.ts` that was deleted in #4875
@@ -74,7 +75,7 @@ function makeMockTUI(): MockTui {
74
75
  // ─── Bug 1: tool cards stuck in "Running" after compaction ──────────────
75
76
 
76
77
  describe("ToolExecutionComponent post-compaction cleanup", () => {
77
- it("renders 'Running' status while the tool call has no result", () => {
78
+ it("renders 'running' status while the tool call has no result", () => {
78
79
  // Baseline: a freshly-constructed component (mid-stream) must show
79
80
  // the running badge — this is the state we need to flip OUT of when
80
81
  // compaction removes the result message.
@@ -88,12 +89,12 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
88
89
  );
89
90
  const rendered = c.render(60).map(stripAnsi).join("\n");
90
91
  assert.ok(
91
- rendered.includes("Running"),
92
- "freshly constructed component should render 'Running' badge",
92
+ rendered.includes("running"),
93
+ "freshly constructed component should render 'running' badge",
93
94
  );
94
95
  });
95
96
 
96
- it("markHistoricalNoResult flips a stuck tool card OUT of 'Running'", () => {
97
+ it("markHistoricalNoResult flips a stuck tool card OUT of 'running'", () => {
97
98
  // Real bug: after session-history replay (post-compaction or session
98
99
  // switch), tool calls without matching tool_result messages stay in
99
100
  // isPartial = true forever. markHistoricalNoResult must produce a
@@ -111,13 +112,13 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
111
112
 
112
113
  const rendered = c.render(60).map(stripAnsi).join("\n");
113
114
  assert.ok(
114
- !rendered.includes("Running"),
115
- "after markHistoricalNoResult, the tool card must NOT render 'Running' got:\n" +
115
+ !rendered.includes("running"),
116
+ "after markHistoricalNoResult, the tool card must NOT render 'running' -- got:\n" +
116
117
  rendered,
117
118
  );
118
119
  assert.ok(
119
- rendered.includes("Done"),
120
- "flipped card should render 'Done' status (no-result success)",
120
+ rendered.includes("success"),
121
+ "flipped card should render 'success' status (no-result success)",
121
122
  );
122
123
  });
123
124
 
@@ -145,7 +146,7 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
145
146
  );
146
147
 
147
148
  const before = c.render(60).map(stripAnsi).join("\n");
148
- assert.ok(before.includes("Done"), "after complete(), card shows 'Done'");
149
+ assert.ok(before.includes("success"), "after complete(), card shows 'success'");
149
150
 
150
151
  c.markHistoricalNoResult(); // must early-return
151
152
  const after = c.render(60).map(stripAnsi).join("\n");