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

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 (434) hide show
  1. package/README.md +4 -2
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +2 -2
  4. package/dist/resources/extensions/github-sync/templates.js +39 -8
  5. package/dist/resources/extensions/gsd/auto/loop.js +48 -10
  6. package/dist/resources/extensions/gsd/auto/phases.js +66 -45
  7. package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
  8. package/dist/resources/extensions/gsd/auto/run-unit.js +32 -16
  9. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
  12. package/dist/resources/extensions/gsd/auto-prompts.js +124 -2
  13. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  14. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  15. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  16. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  17. package/dist/resources/extensions/gsd/auto.js +75 -5
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +36 -3
  19. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
  21. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  22. package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
  23. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  24. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  25. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  26. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  27. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  28. package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
  29. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  30. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  31. package/dist/resources/extensions/gsd/detection.js +106 -0
  32. package/dist/resources/extensions/gsd/graph.js +9 -3
  33. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  34. package/dist/resources/extensions/gsd/guided-flow.js +82 -16
  35. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  36. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  37. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  38. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  39. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  40. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  41. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
  42. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  43. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  44. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  46. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  47. package/dist/resources/extensions/gsd/quick.js +34 -2
  48. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  49. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  50. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  51. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  52. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  53. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  54. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  55. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  56. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  57. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  58. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  59. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  60. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  61. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  62. package/dist/web/standalone/.next/BUILD_ID +1 -1
  63. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  64. package/dist/web/standalone/.next/build-manifest.json +3 -3
  65. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  66. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/index.html +1 -1
  85. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  92. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  93. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  96. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  97. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  98. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  99. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  100. package/package.json +12 -8
  101. package/packages/contracts/package.json +1 -1
  102. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  103. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  104. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  105. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  106. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  107. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  108. package/packages/native/tsconfig.tsbuildinfo +1 -1
  109. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  110. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  111. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  112. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  113. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  114. package/packages/pi-ai/dist/models/index.js +8 -0
  115. package/packages/pi-ai/dist/models/index.js.map +1 -1
  116. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  117. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  118. package/packages/pi-ai/dist/providers/fake.js +319 -0
  119. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  120. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  121. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  122. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  123. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  124. package/packages/pi-ai/src/models/index.ts +9 -0
  125. package/packages/pi-ai/src/providers/fake.ts +376 -0
  126. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  127. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  128. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  129. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  131. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
  132. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  134. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  136. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  138. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  140. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  141. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  142. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  143. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  144. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  145. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  146. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  147. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  148. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  149. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  150. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  151. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
  152. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/extensions/runner.js +17 -1
  154. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +99 -0
  156. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
  158. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  162. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  164. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  166. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  167. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  169. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  170. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  171. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  172. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  175. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  177. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  180. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  181. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  182. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  186. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  188. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  190. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  192. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  193. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  194. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  195. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  196. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  197. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  199. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  208. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  215. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  216. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  217. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  218. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  228. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  230. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  231. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  232. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  233. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  235. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  237. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  238. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  239. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  240. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  241. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  243. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  244. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  245. package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
  246. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  247. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  248. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  249. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  250. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  251. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +110 -0
  252. package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -1
  253. package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
  254. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  255. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  256. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  257. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  258. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  259. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  260. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  261. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  262. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  263. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  265. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  266. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  267. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  268. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  269. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  270. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  271. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  272. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  273. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  274. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  275. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  276. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  277. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  278. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  279. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  280. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  281. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  282. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  283. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  284. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  285. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  286. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  287. package/packages/pi-tui/dist/index.d.ts +1 -0
  288. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  289. package/packages/pi-tui/dist/index.js +2 -0
  290. package/packages/pi-tui/dist/index.js.map +1 -1
  291. package/packages/pi-tui/dist/style.d.ts +41 -0
  292. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  293. package/packages/pi-tui/dist/style.js +158 -0
  294. package/packages/pi-tui/dist/style.js.map +1 -0
  295. package/packages/pi-tui/dist/tui.d.ts +0 -1
  296. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  297. package/packages/pi-tui/dist/tui.js +21 -16
  298. package/packages/pi-tui/dist/tui.js.map +1 -1
  299. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  300. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  301. package/packages/pi-tui/src/index.ts +9 -0
  302. package/packages/pi-tui/src/style.ts +225 -0
  303. package/packages/pi-tui/src/tui.ts +23 -16
  304. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  305. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  306. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  307. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  308. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  309. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  310. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  311. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  312. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  313. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  314. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  315. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  316. package/src/resources/GSD-WORKFLOW.md +2 -2
  317. package/src/resources/extensions/github-sync/templates.ts +38 -8
  318. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  319. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  320. package/src/resources/extensions/gsd/auto/loop.ts +67 -18
  321. package/src/resources/extensions/gsd/auto/phases.ts +77 -48
  322. package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
  323. package/src/resources/extensions/gsd/auto/run-unit.ts +42 -15
  324. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  325. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
  326. package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
  327. package/src/resources/extensions/gsd/auto-prompts.ts +133 -2
  328. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  329. package/src/resources/extensions/gsd/auto-start.ts +7 -6
  330. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  331. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  332. package/src/resources/extensions/gsd/auto.ts +90 -4
  333. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -2
  334. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
  335. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -1
  336. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  337. package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
  338. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  339. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  340. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  341. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  342. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  343. package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
  344. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  345. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  346. package/src/resources/extensions/gsd/detection.ts +128 -0
  347. package/src/resources/extensions/gsd/graph.ts +12 -5
  348. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  349. package/src/resources/extensions/gsd/guided-flow.ts +98 -16
  350. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  351. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  352. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  353. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  354. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  355. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  356. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  357. package/src/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
  358. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  359. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  360. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  361. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  362. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  363. package/src/resources/extensions/gsd/quick.ts +37 -2
  364. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  365. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  366. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  367. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +155 -5
  368. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  369. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  370. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
  371. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  372. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  373. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  374. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  375. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  376. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
  377. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  378. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  379. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  380. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  381. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  382. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  383. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  384. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  385. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  386. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  387. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  388. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  389. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  390. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  391. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
  392. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  393. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  394. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  395. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  396. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  397. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  398. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  399. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  400. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  401. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  402. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  403. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  404. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  405. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  406. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  407. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  408. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  409. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  410. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  411. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
  412. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  413. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  414. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  415. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  416. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  417. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  418. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  419. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  420. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  421. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  422. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  423. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  424. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  425. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  426. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  427. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  428. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  429. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  430. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  431. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  432. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  433. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_buildManifest.js +0 -0
  434. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_ssgManifest.js +0 -0
@@ -102,6 +102,61 @@ describe("ExtensionRunner.emitToolCall", () => {
102
102
  assert.equal(errors[0].event, "tool_call");
103
103
  assert.equal(errors[0].extensionPath, "/test/throwing-ext");
104
104
  });
105
+
106
+ it("preserves shutdown in tool_call handler context", async (t) => {
107
+ const dir = mkdtempSync(join(tmpdir(), "runner-test-"));
108
+ t.after(() => {
109
+ rmSync(dir, { recursive: true, force: true });
110
+ });
111
+
112
+ const sessionManager = SessionManager.create(dir, dir);
113
+ const authStorage = AuthStorage.create();
114
+ const modelRegistry = new ModelRegistry(authStorage, join(dir, "models.json"));
115
+ const runtime = makeMinimalRuntime();
116
+ let shutdownCount = 0;
117
+ const handlers = new Map();
118
+ handlers.set("tool_call", [
119
+ async (_event: unknown, ctx: { shutdown: () => void }) => {
120
+ ctx.shutdown();
121
+ },
122
+ ]);
123
+ const extension = {
124
+ path: "/test/shutdown-on-tool-call",
125
+ handlers,
126
+ commands: new Map(),
127
+ shortcuts: new Map(),
128
+ tools: new Map(),
129
+ flags: new Map(),
130
+ diagnostics: [],
131
+ } as unknown as Extension;
132
+ const runner = new ExtensionRunner([extension], runtime, dir, sessionManager, modelRegistry);
133
+ runner.bindCore({} as any, {
134
+ getModel: () => undefined,
135
+ isIdle: () => true,
136
+ abort: () => {},
137
+ hasPendingMessages: () => false,
138
+ shutdown: () => {
139
+ shutdownCount += 1;
140
+ },
141
+ getContextUsage: () => undefined,
142
+ compact: () => {},
143
+ getSystemPrompt: () => "",
144
+ setCompactionThresholdOverride: () => {},
145
+ });
146
+
147
+ const errors: any[] = [];
148
+ runner.onError((err) => errors.push(err));
149
+
150
+ await runner.emitToolCall({
151
+ type: "tool_call",
152
+ toolCallId: "test-123",
153
+ toolName: "test_tool",
154
+ input: {},
155
+ } as ToolCallEvent);
156
+
157
+ assert.equal(shutdownCount, 1);
158
+ assert.equal(errors.length, 0);
159
+ });
105
160
  });
106
161
 
107
162
  describe("ExtensionRunner.createContext", () => {
@@ -127,6 +182,61 @@ describe("ExtensionRunner.createContext", () => {
127
182
  assert.equal(runner.createContext().cwd, realProjectDir);
128
183
  assert.equal(runner.createCommandContext().cwd, realProjectDir);
129
184
  });
185
+
186
+ it("does not let lifecycle event handlers close the TUI", async (t) => {
187
+ const dir = mkdtempSync(join(tmpdir(), "runner-test-"));
188
+ t.after(() => {
189
+ rmSync(dir, { recursive: true, force: true });
190
+ });
191
+
192
+ const sessionManager = SessionManager.create(dir, dir);
193
+ const authStorage = AuthStorage.create();
194
+ const modelRegistry = new ModelRegistry(authStorage, join(dir, "models.json"));
195
+ const runtime = makeMinimalRuntime();
196
+ let shutdownCount = 0;
197
+ const handlers = new Map();
198
+ handlers.set("agent_end", [
199
+ async (_event: unknown, ctx: { shutdown: () => void }) => {
200
+ ctx.shutdown();
201
+ },
202
+ ]);
203
+ const extension = {
204
+ path: "/test/shutdown-on-agent-end",
205
+ handlers,
206
+ commands: new Map(),
207
+ shortcuts: new Map(),
208
+ tools: new Map(),
209
+ flags: new Map(),
210
+ diagnostics: [],
211
+ } as unknown as Extension;
212
+ const runner = new ExtensionRunner([extension], runtime, dir, sessionManager, modelRegistry);
213
+ runner.bindCore({} as any, {
214
+ getModel: () => undefined,
215
+ isIdle: () => true,
216
+ abort: () => {},
217
+ hasPendingMessages: () => false,
218
+ shutdown: () => {
219
+ shutdownCount += 1;
220
+ },
221
+ getContextUsage: () => undefined,
222
+ compact: () => {},
223
+ getSystemPrompt: () => "",
224
+ setCompactionThresholdOverride: () => {},
225
+ });
226
+
227
+ const errors: any[] = [];
228
+ runner.onError((err) => errors.push(err));
229
+
230
+ await runner.emit({ type: "agent_end", messages: [] } as any);
231
+
232
+ assert.equal(shutdownCount, 0);
233
+ assert.equal(errors.length, 1);
234
+ assert.equal(errors[0].event, "agent_end");
235
+ assert.match(errors[0].error, /cannot request TUI shutdown/);
236
+
237
+ runner.createCommandContext().shutdown();
238
+ assert.equal(shutdownCount, 1);
239
+ });
130
240
  });
131
241
 
132
242
  describe("ExtensionRunner protected commands", () => {
@@ -235,6 +235,7 @@ export class ExtensionRunner {
235
235
  private getContextUsageFn: () => ContextUsage | undefined = () => undefined;
236
236
  private compactFn: (options?: CompactOptions) => void = () => {};
237
237
  private getSystemPromptFn: () => string = () => "";
238
+ private setCompactionThresholdOverrideFn: (percent: number | undefined) => void = () => {};
238
239
  private newSessionHandler: NewSessionHandler = async () => {
239
240
  throw new Error("Command context not yet bound: newSession is unavailable during early lifecycle");
240
241
  };
@@ -428,6 +429,7 @@ export class ExtensionRunner {
428
429
  this.getContextUsageFn = contextActions.getContextUsage;
429
430
  this.compactFn = contextActions.compact;
430
431
  this.getSystemPromptFn = contextActions.getSystemPrompt;
432
+ this.setCompactionThresholdOverrideFn = contextActions.setCompactionThresholdOverride;
431
433
 
432
434
  // Flush provider registrations queued during extension loading
433
435
  for (const { name, config } of this.runtime.pendingProviderRegistrations) {
@@ -714,9 +716,23 @@ export class ExtensionRunner {
714
716
  getContextUsage: () => this.getContextUsageFn(),
715
717
  compact: (options) => this.compactFn(options),
716
718
  getSystemPrompt: () => this.getSystemPromptFn(),
719
+ setCompactionThresholdOverride: (percent) => this.setCompactionThresholdOverrideFn(percent),
717
720
  };
718
721
  }
719
722
 
723
+ private createEventContext(eventType: string): ExtensionContext {
724
+ return {
725
+ ...this.createContext(),
726
+ shutdown: () => {
727
+ throw new Error(`Extension event '${eventType}' cannot request TUI shutdown`);
728
+ },
729
+ };
730
+ }
731
+
732
+ private isShutdownGuardedEvent(eventType: string): boolean {
733
+ return eventType === "agent_end" || eventType === "stop" || eventType === "session_end";
734
+ }
735
+
720
736
  createCommandContext(): ExtensionCommandContext {
721
737
  return {
722
738
  ...this.createContext(),
@@ -757,7 +773,9 @@ export class ExtensionRunner {
757
773
  getEvent: () => unknown,
758
774
  processResult: (handlerResult: unknown, extensionPath: string) => { done: boolean },
759
775
  ): Promise<void> {
760
- const ctx = this.createContext();
776
+ const ctx = this.isShutdownGuardedEvent(eventType)
777
+ ? this.createEventContext(eventType)
778
+ : this.createContext();
761
779
 
762
780
  for (const ext of this.extensions) {
763
781
  const handlers = ext.handlers.get(eventType);
@@ -289,6 +289,12 @@ export interface ExtensionContext {
289
289
  compact(options?: CompactOptions): void;
290
290
  /** Get the current effective system prompt. */
291
291
  getSystemPrompt(): string;
292
+ /**
293
+ * Set or clear an in-memory compaction threshold-percent override (0 < value < 1).
294
+ * Pass `undefined` to clear. The override is not persisted; host integrations
295
+ * are expected to re-apply on each session_start.
296
+ */
297
+ setCompactionThresholdOverride(percent: number | undefined): void;
292
298
  }
293
299
 
294
300
  /**
@@ -1741,6 +1747,7 @@ export interface ExtensionContextActions {
1741
1747
  getContextUsage: () => ContextUsage | undefined;
1742
1748
  compact: (options?: CompactOptions) => void;
1743
1749
  getSystemPrompt: () => string;
1750
+ setCompactionThresholdOverride: (percent: number | undefined) => void;
1744
1751
  }
1745
1752
 
1746
1753
  /**
@@ -578,6 +578,10 @@ export class ModelRegistry {
578
578
  * Defaults to "apiKey" for built-ins and providers without explicit mode.
579
579
  */
580
580
  getProviderAuthMode(provider: string): ProviderAuthMode {
581
+ // E2E-test-only: the fake provider is keyless. Sentinel is project-
582
+ // internal ("gsd-fake") so it cannot collide with a real provider.
583
+ // See packages/pi-ai/src/providers/fake.ts.
584
+ if (provider === "gsd-fake") return "none";
581
585
  const config = this.registeredProviders.get(provider);
582
586
  if (!config) return "apiKey";
583
587
  if (config.authMode) return config.authMode;
@@ -15,6 +15,13 @@ export interface CompactionSettings {
15
15
  enabled?: boolean; // default: true
16
16
  reserveTokens?: number; // default: 16384
17
17
  keepRecentTokens?: number; // default: 20000
18
+ /**
19
+ * Optional percent-of-context-window trigger (0 < value < 1). When set,
20
+ * compaction fires at `contextWindow * thresholdPercent` and overrides
21
+ * `reserveTokens`. Typically set as a runtime override by host integrations
22
+ * (see `setCompactionThresholdOverride`) and not persisted by users directly.
23
+ */
24
+ thresholdPercent?: number;
18
25
  }
19
26
 
20
27
  export interface BranchSummarySettings {
@@ -32,6 +39,7 @@ export interface RetrySettings {
32
39
  export interface TerminalSettings {
33
40
  showImages?: boolean; // default: true (only relevant if terminal supports images)
34
41
  clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
42
+ adaptiveMode?: AdaptiveTuiMode; // default: "auto"
35
43
  }
36
44
 
37
45
  export interface ImageSettings {
@@ -149,6 +157,7 @@ export interface HooksSettings {
149
157
  }
150
158
 
151
159
  export type TransportSetting = Transport;
160
+ export type AdaptiveTuiMode = "auto" | "chat" | "workflow" | "validation" | "debug" | "compact";
152
161
 
153
162
  /**
154
163
  * Package source for npm/git packages.
@@ -810,11 +819,42 @@ export class SettingsManager {
810
819
  return this.settings.compaction?.keepRecentTokens ?? COMPACTION_KEEP_RECENT_TOKENS;
811
820
  }
812
821
 
813
- getCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number } {
822
+ getCompactionThresholdPercent(): number | undefined {
823
+ return this.settings.compaction?.thresholdPercent;
824
+ }
825
+
826
+ /**
827
+ * Set or clear an in-memory compaction threshold-percent override.
828
+ *
829
+ * Applied to `this.settings` only; never persisted to disk. Pass `undefined`
830
+ * to clear a previously set override (necessary for idempotent re-sync from
831
+ * host integrations whose preference may have been removed).
832
+ *
833
+ * Direct mutation is used instead of `applyOverrides()` because deep-merge
834
+ * semantics skip `undefined` values, which would prevent clearing.
835
+ */
836
+ setCompactionThresholdOverride(percent: number | undefined): void {
837
+ if (!this.settings.compaction) {
838
+ this.settings.compaction = {};
839
+ }
840
+ if (percent === undefined) {
841
+ delete this.settings.compaction.thresholdPercent;
842
+ } else {
843
+ this.settings.compaction.thresholdPercent = percent;
844
+ }
845
+ }
846
+
847
+ getCompactionSettings(): {
848
+ enabled: boolean;
849
+ reserveTokens: number;
850
+ keepRecentTokens: number;
851
+ thresholdPercent?: number;
852
+ } {
814
853
  return {
815
854
  enabled: this.getCompactionEnabled(),
816
855
  reserveTokens: this.getCompactionReserveTokens(),
817
856
  keepRecentTokens: this.getCompactionKeepRecentTokens(),
857
+ thresholdPercent: this.getCompactionThresholdPercent(),
818
858
  };
819
859
  }
820
860
 
@@ -978,6 +1018,16 @@ export class SettingsManager {
978
1018
  this.setNestedGlobalSetting("terminal", "clearOnShrink", enabled);
979
1019
  }
980
1020
 
1021
+ getAdaptiveMode(): AdaptiveTuiMode {
1022
+ const mode = this.settings.terminal?.adaptiveMode;
1023
+ const valid: AdaptiveTuiMode[] = ["auto", "chat", "workflow", "validation", "debug", "compact"];
1024
+ return mode && valid.includes(mode) ? mode : "auto";
1025
+ }
1026
+
1027
+ setAdaptiveMode(mode: AdaptiveTuiMode): void {
1028
+ this.setNestedGlobalSetting("terminal", "adaptiveMode", mode);
1029
+ }
1030
+
981
1031
  getImageAutoResize(): boolean {
982
1032
  return this.settings.images?.autoResize ?? true;
983
1033
  }
@@ -38,5 +38,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
38
38
  { name: "thinking", description: "Set thinking level (off/minimal/low/medium/high/xhigh)" },
39
39
  { name: "edit-mode", description: "Toggle edit mode (standard/hashline)" },
40
40
  { name: "terminal", description: "Run a shell command directly (e.g. /terminal ping -c3 1.1.1.1)" },
41
+ { name: "tui", description: "Configure TUI layout mode (e.g. /tui mode workflow)" },
41
42
  { name: "quit", description: "Quit pi" },
42
43
  ];
@@ -1,3 +1,4 @@
1
+ // GSD2 TUI Tests - Chat frame card visual contract coverage.
1
2
  import { test, describe } from "node:test";
2
3
  import assert from "node:assert/strict";
3
4
  import stripAnsi from "strip-ansi";
@@ -8,12 +9,12 @@ initTheme("dark", false);
8
9
 
9
10
  // Regression tests for the "compaction" tone added to renderChatFrame.
10
11
  // The compaction notice shares the same visual frame as user / assistant
11
- // messages (top rule, `• label` header, `│ ` body prefix) but uses the
12
+ // messages (top rule, label header, `│ ` body prefix) but uses the
12
13
  // purple `customMessageLabel` color key so it is visually distinct from
13
14
  // conversation turns.
14
15
 
15
16
  describe("renderChatFrame — compaction tone", () => {
16
- test("produces a top rule, `• compaction` header row, and a │ body margin", () => {
17
+ test("produces a top rule, compaction header row, and a │ body margin", () => {
17
18
  const lines = renderChatFrame(
18
19
  ["Compacted from 1,224,262 tokens (ctrl+o to expand)"],
19
20
  60,
@@ -33,11 +34,12 @@ describe("renderChatFrame — compaction tone", () => {
33
34
  // Top rule is a solid horizontal bar
34
35
  assert.match(plain[0], /^─+$/, "first line should be the solid top rule");
35
36
 
36
- // Header row contains `• compaction`
37
+ // Header row contains `compaction`
37
38
  assert.ok(
38
- plain[1].includes("compaction"),
39
- `expected header to contain "compaction", got ${JSON.stringify(plain[1])}`,
39
+ plain[1].includes("compaction"),
40
+ `expected header to contain "compaction", got ${JSON.stringify(plain[1])}`,
40
41
  );
42
+ assert.ok(!plain[1].includes("•"), `header should not render a bullet prefix, got ${JSON.stringify(plain[1])}`);
41
43
 
42
44
  // Body line(s) start with `│ `
43
45
  assert.ok(
@@ -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
+ });