gsd-pi 2.82.0-dev.ed17d078d → 3.0.0-dev.2e8b124f7

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 (580) hide show
  1. package/README.md +93 -18
  2. package/dist/cli.js +20 -9
  3. package/dist/headless-ui.js +13 -6
  4. package/dist/headless.js +9 -2
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/GSD-WORKFLOW.md +10 -1
  7. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  8. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +44 -6
  9. package/dist/resources/extensions/cmux/index.js +5 -0
  10. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  11. package/dist/resources/extensions/gsd/auto/loop.js +110 -37
  12. package/dist/resources/extensions/gsd/auto/orchestrator.js +13 -2
  13. package/dist/resources/extensions/gsd/auto/phases.js +104 -38
  14. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  15. package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -1
  16. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  17. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  18. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  19. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  20. package/dist/resources/extensions/gsd/auto-dispatch.js +71 -20
  21. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  22. package/dist/resources/extensions/gsd/auto-post-unit.js +278 -137
  23. package/dist/resources/extensions/gsd/auto-prompts.js +36 -10
  24. package/dist/resources/extensions/gsd/auto-recovery.js +79 -14
  25. package/dist/resources/extensions/gsd/auto-start.js +90 -14
  26. package/dist/resources/extensions/gsd/auto-timers.js +11 -3
  27. package/dist/resources/extensions/gsd/auto-verification.js +102 -34
  28. package/dist/resources/extensions/gsd/auto-worktree.js +178 -11
  29. package/dist/resources/extensions/gsd/auto.js +107 -54
  30. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +5 -4
  33. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  34. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +24 -9
  35. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  36. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  37. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -0
  38. package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
  39. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  40. package/dist/resources/extensions/gsd/commands-handlers.js +2 -0
  41. package/dist/resources/extensions/gsd/commands-mcp-status.js +9 -0
  42. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -2
  43. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  44. package/dist/resources/extensions/gsd/crash-recovery.js +52 -7
  45. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  46. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  47. package/dist/resources/extensions/gsd/db-base-schema.js +2 -0
  48. package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
  49. package/dist/resources/extensions/gsd/db-task-slice-rows.js +2 -0
  50. package/dist/resources/extensions/gsd/dispatch-guard.js +46 -2
  51. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  52. package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
  53. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  54. package/dist/resources/extensions/gsd/doctor.js +2 -28
  55. package/dist/resources/extensions/gsd/export-html.js +27 -425
  56. package/dist/resources/extensions/gsd/forensics.js +10 -3
  57. package/dist/resources/extensions/gsd/git-service.js +138 -10
  58. package/dist/resources/extensions/gsd/gsd-db.js +76 -33
  59. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  60. package/dist/resources/extensions/gsd/guided-flow.js +110 -117
  61. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  62. package/dist/resources/extensions/gsd/init-wizard.js +17 -2
  63. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -11
  64. package/dist/resources/extensions/gsd/mcp-filter.js +58 -0
  65. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  66. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  67. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  68. package/dist/resources/extensions/gsd/native-git-bridge.js +57 -14
  69. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -0
  70. package/dist/resources/extensions/gsd/paths.js +4 -0
  71. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  72. package/dist/resources/extensions/gsd/planning-path-scope.js +9 -3
  73. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -9
  74. package/dist/resources/extensions/gsd/pre-execution-checks.js +38 -11
  75. package/dist/resources/extensions/gsd/preferences-mcp.js +19 -0
  76. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  77. package/dist/resources/extensions/gsd/preferences-validation.js +138 -0
  78. package/dist/resources/extensions/gsd/preferences.js +2 -0
  79. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  80. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  83. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  84. package/dist/resources/extensions/gsd/prompts/forensics.md +3 -3
  85. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  86. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  87. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  88. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  89. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  90. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  91. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  92. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  93. package/dist/resources/extensions/gsd/repository-registry.js +44 -0
  94. package/dist/resources/extensions/gsd/safety/evidence-collector.js +2 -0
  95. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +42 -18
  96. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +59 -2
  97. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  98. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  99. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  100. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  101. package/dist/resources/extensions/gsd/state.js +14 -4
  102. package/dist/resources/extensions/gsd/status-guards.js +14 -2
  103. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  104. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  105. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  106. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  107. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  108. package/dist/resources/extensions/gsd/tools/plan-slice.js +151 -15
  109. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  110. package/dist/resources/extensions/gsd/unit-context-composer.js +2 -0
  111. package/dist/resources/extensions/gsd/unit-context-manifest.js +69 -17
  112. package/dist/resources/extensions/gsd/validation.js +23 -1
  113. package/dist/resources/extensions/gsd/verification-gate.js +142 -7
  114. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  115. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
  116. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  117. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  118. package/dist/resources/extensions/gsd/worktree-lifecycle.js +83 -19
  119. package/dist/resources/extensions/gsd/worktree-manager.js +11 -2
  120. package/dist/resources/extensions/gsd/worktree-safety.js +33 -1
  121. package/dist/resources/extensions/gsd/worktree-state-projection.js +31 -0
  122. package/dist/resources/extensions/shared/html-shell.js +388 -0
  123. package/dist/resources/extensions/shared/interview-ui.js +6 -4
  124. package/dist/resources/extensions/subagent/index.js +448 -78
  125. package/dist/resources/extensions/subagent/launch.js +77 -0
  126. package/dist/resources/extensions/subagent/run-store.js +148 -0
  127. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  128. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  129. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  130. package/dist/resources/extensions/visual-brief/index.js +5 -0
  131. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  132. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  133. package/dist/resources/skills/forensics/SKILL.md +1 -1
  134. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  135. package/dist/web/standalone/.next/BUILD_ID +1 -1
  136. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  137. package/dist/web/standalone/.next/build-manifest.json +3 -3
  138. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  139. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  140. package/dist/web/standalone/.next/required-server-files.json +1 -1
  141. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  143. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  151. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  154. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  155. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  156. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  158. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  161. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/index.html +1 -1
  164. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  165. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  167. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  169. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  170. package/dist/web/standalone/.next/server/app/page.js +2 -2
  171. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  174. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  175. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  179. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  180. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  181. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  182. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  183. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  184. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  185. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  186. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  187. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  188. package/dist/web/standalone/server.js +1 -1
  189. package/package.json +4 -4
  190. package/packages/contracts/dist/rpc.test.js +7 -0
  191. package/packages/contracts/dist/rpc.test.js.map +1 -1
  192. package/packages/contracts/dist/workflow.d.ts +21 -0
  193. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  194. package/packages/contracts/dist/workflow.js +24 -0
  195. package/packages/contracts/dist/workflow.js.map +1 -1
  196. package/packages/contracts/src/rpc.test.ts +8 -0
  197. package/packages/contracts/src/workflow.ts +24 -0
  198. package/packages/daemon/package.json +2 -2
  199. package/packages/mcp-server/README.md +13 -4
  200. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  201. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  203. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  204. package/packages/mcp-server/package.json +2 -2
  205. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  206. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  207. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  208. package/packages/native/package.json +1 -1
  209. package/packages/native/tsconfig.json +2 -1
  210. package/packages/native/tsconfig.tsbuildinfo +1 -1
  211. package/packages/pi-agent-core/package.json +1 -1
  212. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  213. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  214. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  215. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  216. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  217. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  218. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  219. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  220. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  221. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  222. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  223. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  224. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  225. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  226. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  227. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  228. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  229. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  230. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  231. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  232. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  233. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  234. package/packages/pi-ai/package.json +1 -1
  235. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  236. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  237. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  238. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  239. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  240. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  241. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  242. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  243. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  244. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  245. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  246. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  247. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  249. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +6 -1
  251. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  252. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +7 -2
  253. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +14 -1
  255. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  257. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +8 -2
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
  267. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -7
  269. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +11 -0
  271. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  275. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  277. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  278. package/packages/pi-coding-agent/package.json +1 -1
  279. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  280. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  281. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  282. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +23 -1
  283. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +7 -2
  284. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  285. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +17 -1
  286. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  287. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -1
  288. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
  289. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +15 -1
  290. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +9 -9
  291. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  292. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  293. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  294. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  295. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  296. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  297. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  298. package/packages/pi-tui/dist/__tests__/tui.test.js +45 -2
  299. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  300. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  301. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  302. package/packages/pi-tui/dist/terminal.js +12 -0
  303. package/packages/pi-tui/dist/terminal.js.map +1 -1
  304. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  305. package/packages/pi-tui/dist/tui.js +106 -27
  306. package/packages/pi-tui/dist/tui.js.map +1 -1
  307. package/packages/pi-tui/package.json +1 -1
  308. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  309. package/packages/pi-tui/src/__tests__/tui.test.ts +59 -2
  310. package/packages/pi-tui/src/terminal.ts +11 -0
  311. package/packages/pi-tui/src/tui.ts +108 -27
  312. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  313. package/packages/rpc-client/package.json +1 -1
  314. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  315. package/pkg/package.json +1 -1
  316. package/src/resources/GSD-WORKFLOW.md +10 -1
  317. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  318. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +52 -6
  319. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  320. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +49 -2
  321. package/src/resources/extensions/cmux/index.ts +6 -0
  322. package/src/resources/extensions/gsd/auto/contracts.ts +17 -6
  323. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  324. package/src/resources/extensions/gsd/auto/loop.ts +111 -38
  325. package/src/resources/extensions/gsd/auto/orchestrator.ts +13 -2
  326. package/src/resources/extensions/gsd/auto/phases.ts +127 -49
  327. package/src/resources/extensions/gsd/auto/session.ts +16 -0
  328. package/src/resources/extensions/gsd/auto/types.ts +3 -0
  329. package/src/resources/extensions/gsd/auto/unit-runner-events.ts +6 -2
  330. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  331. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  332. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  333. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  334. package/src/resources/extensions/gsd/auto-dispatch.ts +74 -20
  335. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  336. package/src/resources/extensions/gsd/auto-post-unit.ts +312 -148
  337. package/src/resources/extensions/gsd/auto-prompts.ts +36 -13
  338. package/src/resources/extensions/gsd/auto-recovery.ts +83 -11
  339. package/src/resources/extensions/gsd/auto-start.ts +99 -12
  340. package/src/resources/extensions/gsd/auto-timers.ts +10 -3
  341. package/src/resources/extensions/gsd/auto-verification.ts +124 -42
  342. package/src/resources/extensions/gsd/auto-worktree.ts +195 -11
  343. package/src/resources/extensions/gsd/auto.ts +100 -42
  344. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
  345. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
  346. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +5 -4
  347. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  348. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +27 -10
  349. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  350. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  351. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -0
  352. package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
  353. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  354. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  355. package/src/resources/extensions/gsd/commands-mcp-status.ts +8 -0
  356. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +11 -3
  357. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  358. package/src/resources/extensions/gsd/crash-recovery.ts +52 -6
  359. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  360. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  361. package/src/resources/extensions/gsd/db-base-schema.ts +2 -0
  362. package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
  363. package/src/resources/extensions/gsd/db-task-slice-rows.ts +4 -0
  364. package/src/resources/extensions/gsd/dispatch-guard.ts +60 -2
  365. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  366. package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
  367. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  368. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  369. package/src/resources/extensions/gsd/doctor.ts +2 -27
  370. package/src/resources/extensions/gsd/export-html.ts +27 -427
  371. package/src/resources/extensions/gsd/forensics.ts +9 -3
  372. package/src/resources/extensions/gsd/git-service.ts +166 -11
  373. package/src/resources/extensions/gsd/gsd-db.ts +80 -31
  374. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  375. package/src/resources/extensions/gsd/guided-flow.ts +142 -134
  376. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  377. package/src/resources/extensions/gsd/init-wizard.ts +17 -2
  378. package/src/resources/extensions/gsd/journal.ts +8 -1
  379. package/src/resources/extensions/gsd/markdown-renderer.ts +14 -11
  380. package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
  381. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  382. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  383. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  384. package/src/resources/extensions/gsd/native-git-bridge.ts +63 -14
  385. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -0
  386. package/src/resources/extensions/gsd/paths.ts +5 -0
  387. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  388. package/src/resources/extensions/gsd/planning-path-scope.ts +10 -2
  389. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -12
  390. package/src/resources/extensions/gsd/pre-execution-checks.ts +49 -11
  391. package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
  392. package/src/resources/extensions/gsd/preferences-types.ts +33 -0
  393. package/src/resources/extensions/gsd/preferences-validation.ts +145 -0
  394. package/src/resources/extensions/gsd/preferences.ts +5 -0
  395. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  396. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  397. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  398. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  399. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  400. package/src/resources/extensions/gsd/prompts/forensics.md +3 -3
  401. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  402. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  403. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  404. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  405. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  406. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  407. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  408. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  409. package/src/resources/extensions/gsd/repository-registry.ts +77 -0
  410. package/src/resources/extensions/gsd/safety/evidence-collector.ts +2 -0
  411. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +54 -19
  412. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +52 -1
  413. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  414. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  415. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  416. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  417. package/src/resources/extensions/gsd/state.ts +15 -4
  418. package/src/resources/extensions/gsd/status-guards.ts +16 -2
  419. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  420. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  421. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +10 -1
  422. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  423. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  424. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +300 -1
  425. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +197 -11
  426. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  427. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  428. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  429. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +129 -6
  430. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
  431. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  432. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  433. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  434. package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +21 -0
  435. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  436. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  437. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  438. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +32 -4
  439. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  440. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  441. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  442. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  443. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  444. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +104 -2
  445. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  446. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  447. package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +1 -0
  448. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +61 -2
  449. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +111 -1
  450. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +68 -1
  451. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  452. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
  453. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +97 -0
  454. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  455. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +28 -0
  456. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  457. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  458. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  459. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  460. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  461. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  462. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  463. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  464. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  465. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  466. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +22 -0
  467. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  468. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +199 -2
  469. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  470. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +49 -3
  471. package/src/resources/extensions/gsd/tests/journal.test.ts +32 -0
  472. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
  473. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +11 -0
  474. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  475. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  476. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  477. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +80 -2
  478. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  479. package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +55 -0
  480. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  481. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  482. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  483. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  484. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  485. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +343 -3
  486. package/src/resources/extensions/gsd/tests/plan-task.test.ts +18 -1
  487. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  488. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +105 -3
  489. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  490. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  491. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +59 -0
  492. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +54 -0
  493. package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
  494. package/src/resources/extensions/gsd/tests/preferences.test.ts +75 -0
  495. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +78 -0
  496. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  497. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  498. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  499. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  500. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  501. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +52 -0
  502. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  503. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +21 -1
  504. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +72 -1
  505. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  506. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +86 -2
  507. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  508. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  509. package/src/resources/extensions/gsd/tests/status-guards.test.ts +17 -1
  510. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  511. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +2 -1
  512. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  513. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +1 -0
  514. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +131 -9
  515. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +111 -1
  516. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  517. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +42 -1
  518. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +173 -1
  519. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  520. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  521. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  522. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  523. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  524. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  525. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  526. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +57 -2
  527. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +25 -0
  528. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +46 -0
  529. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +95 -0
  530. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +27 -0
  531. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +59 -0
  532. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  533. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  534. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  535. package/src/resources/extensions/gsd/tools/plan-slice.ts +172 -12
  536. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  537. package/src/resources/extensions/gsd/types.ts +1 -1
  538. package/src/resources/extensions/gsd/unit-context-composer.ts +3 -0
  539. package/src/resources/extensions/gsd/unit-context-manifest.ts +86 -19
  540. package/src/resources/extensions/gsd/validation.ts +23 -1
  541. package/src/resources/extensions/gsd/verification-gate.ts +170 -6
  542. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  543. package/src/resources/extensions/gsd/workflow-manifest.ts +2 -0
  544. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  545. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  546. package/src/resources/extensions/gsd/worktree-lifecycle.ts +93 -20
  547. package/src/resources/extensions/gsd/worktree-manager.ts +14 -2
  548. package/src/resources/extensions/gsd/worktree-safety.ts +45 -6
  549. package/src/resources/extensions/gsd/worktree-state-projection.ts +43 -0
  550. package/src/resources/extensions/shared/html-shell.ts +412 -0
  551. package/src/resources/extensions/shared/interview-ui.ts +6 -4
  552. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +15 -0
  553. package/src/resources/extensions/subagent/index.ts +567 -103
  554. package/src/resources/extensions/subagent/launch.ts +131 -0
  555. package/src/resources/extensions/subagent/run-store.ts +218 -0
  556. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  557. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  558. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  559. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  560. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  561. package/src/resources/extensions/visual-brief/index.ts +8 -0
  562. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  563. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  564. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  565. package/src/resources/skills/forensics/SKILL.md +1 -1
  566. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  567. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  568. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  569. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  570. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  571. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  572. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  573. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  574. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  575. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  576. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  577. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  578. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  579. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → zCegwxH2e6vLp1vEZLLuZ}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → zCegwxH2e6vLp1vEZLLuZ}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-coding-agent",
3
- "version": "2.82.0",
3
+ "version": "3.0.0",
4
4
  "description": "Coding agent CLI (vendored from pi-mono)",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -0,0 +1,79 @@
1
+ // Regression test for #5102: disabling thinking on one reasoning-capable
2
+ // model must not silently persist "off" as the global default.
3
+
4
+ import assert from "node:assert/strict";
5
+ import { mkdtempSync, rmSync } from "node:fs";
6
+ import { tmpdir } from "node:os";
7
+ import { join } from "node:path";
8
+ import { afterEach, beforeEach, describe, it } from "node:test";
9
+
10
+ import { Agent } from "@gsd/pi-agent-core";
11
+ import { getModel } from "@gsd/pi-ai";
12
+ import { AgentSession } from "./agent-session.js";
13
+ import { AuthStorage } from "./auth-storage.js";
14
+ import { ModelRegistry } from "./model-registry.js";
15
+ import { DefaultResourceLoader } from "./resource-loader.js";
16
+ import { SessionManager } from "./session-manager.js";
17
+ import { SettingsManager } from "./settings-manager.js";
18
+
19
+ let testDir: string;
20
+
21
+ async function createSession(): Promise<{ session: AgentSession; settingsManager: SettingsManager }> {
22
+ const agentDir = join(testDir, "agent-home");
23
+ const authStorage = AuthStorage.inMemory({});
24
+ const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
25
+ const settingsManager = SettingsManager.inMemory({ defaultThinkingLevel: "high" });
26
+ const resourceLoader = new DefaultResourceLoader({
27
+ cwd: testDir,
28
+ agentDir,
29
+ settingsManager,
30
+ noExtensions: true,
31
+ noPromptTemplates: true,
32
+ noThemes: true,
33
+ });
34
+ await resourceLoader.reload();
35
+
36
+ const session = new AgentSession({
37
+ agent: new Agent({
38
+ initialState: {
39
+ model: getModel("zai", "glm-5.1" as any),
40
+ thinkingLevel: "high",
41
+ },
42
+ }),
43
+ sessionManager: SessionManager.inMemory(testDir),
44
+ settingsManager,
45
+ cwd: testDir,
46
+ resourceLoader,
47
+ modelRegistry,
48
+ });
49
+
50
+ return { session, settingsManager };
51
+ }
52
+
53
+ describe("AgentSession thinking level persistence", () => {
54
+ beforeEach(() => {
55
+ testDir = mkdtempSync(join(tmpdir(), "agent-session-thinking-level-"));
56
+ });
57
+
58
+ afterEach(() => {
59
+ rmSync(testDir, { recursive: true, force: true });
60
+ });
61
+
62
+ it("does not persist off as the global default for reasoning-capable models", async () => {
63
+ const { session, settingsManager } = await createSession();
64
+
65
+ session.setThinkingLevel("off");
66
+
67
+ assert.equal(session.thinkingLevel, "off");
68
+ assert.equal(settingsManager.getDefaultThinkingLevel(), "high");
69
+ });
70
+
71
+ it("still persists non-off thinking levels as the global default", async () => {
72
+ const { session, settingsManager } = await createSession();
73
+
74
+ session.setThinkingLevel("low");
75
+
76
+ assert.equal(session.thinkingLevel, "low");
77
+ assert.equal(settingsManager.getDefaultThinkingLevel(), "low");
78
+ });
79
+ });
@@ -1945,7 +1945,7 @@ export class AgentSession {
1945
1945
 
1946
1946
  if (isChanging) {
1947
1947
  this.sessionManager.appendThinkingLevelChange(effectiveLevel);
1948
- if (this.supportsThinking() || effectiveLevel !== "off") {
1948
+ if (effectiveLevel !== "off") {
1949
1949
  this.settingsManager.setDefaultThinkingLevel(effectiveLevel);
1950
1950
  }
1951
1951
  this._emitSessionStateChanged("set_thinking_level");
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Regression tests for streamed interactive chat ordering.
1
3
  import assert from "node:assert/strict";
2
4
  import { test } from "node:test";
3
5
 
@@ -97,9 +99,7 @@ function createHost() {
97
99
  return host;
98
100
  }
99
101
 
100
- test("chat-controller renders content blocks in content[] index order (tool-first stream)", async () => {
101
- // ToolExecutionComponent uses the global theme singleton.
102
- // Install a minimal no-op theme implementation for this unit test.
102
+ function installTheme() {
103
103
  (globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
104
104
  fg: (_key: string, text: string) => text,
105
105
  bg: (_key: string, text: string) => text,
@@ -107,6 +107,12 @@ test("chat-controller renders content blocks in content[] index order (tool-firs
107
107
  italic: (text: string) => text,
108
108
  truncate: (text: string) => text,
109
109
  };
110
+ }
111
+
112
+ test("chat-controller renders content blocks in content[] index order (tool-first stream)", async () => {
113
+ // ToolExecutionComponent uses the global theme singleton.
114
+ // Install a minimal no-op theme implementation for this unit test.
115
+ installTheme();
110
116
 
111
117
  const host = createHost();
112
118
  const toolId = "mcp-tool-1";
@@ -168,6 +174,50 @@ test("chat-controller renders content blocks in content[] index order (tool-firs
168
174
  assert.equal(host.chatContainer.children[1]?.constructor?.name, "AssistantMessageComponent");
169
175
  });
170
176
 
177
+ test("chat-controller skips empty GPT reasoning blocks before tool-only turns", async () => {
178
+ installTheme();
179
+
180
+ const host = createHost();
181
+ host.getMarkdownThemeWithSettings = () => ({});
182
+ const toolId = "gpt-tool-1";
183
+ const toolCall = {
184
+ type: "toolCall",
185
+ id: toolId,
186
+ name: "read",
187
+ arguments: { filePath: "todo.js" },
188
+ };
189
+ const content = [
190
+ { type: "thinking", thinking: "", thinkingSignature: "encrypted" },
191
+ toolCall,
192
+ ];
193
+
194
+ await handleAgentEvent(host, { type: "message_start", message: makeAssistant([]) } as any);
195
+
196
+ await handleAgentEvent(
197
+ host,
198
+ {
199
+ type: "message_update",
200
+ message: makeAssistant(content),
201
+ assistantMessageEvent: {
202
+ type: "toolcall_end",
203
+ contentIndex: 1,
204
+ toolCall: {
205
+ ...toolCall,
206
+ externalResult: {
207
+ content: [{ type: "text", text: "todo contents" }],
208
+ details: {},
209
+ isError: false,
210
+ },
211
+ },
212
+ partial: makeAssistant(content),
213
+ },
214
+ } as any,
215
+ );
216
+
217
+ assert.equal(host.chatContainer.children.length, 1, "empty reasoning should not create a blank assistant block");
218
+ assert.equal(host.chatContainer.children[0]?.constructor?.name, "ToolExecutionComponent");
219
+ });
220
+
171
221
  test("chat-controller renders serverToolUse before trailing text matching content[] index order", async () => {
172
222
  (globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
173
223
  fg: (_key: string, text: string) => text,
@@ -9,7 +9,14 @@ import { describe, it, mock } from "node:test";
9
9
  import type { AgentMessage } from "@gsd/pi-agent-core";
10
10
  import type { Model, AssistantMessage } from "@gsd/pi-ai";
11
11
 
12
- import { generateSummary, estimateTokens, chunkMessages, isDegenerateSummary, CompactionProducedNoSummaryError } from "./compaction.js";
12
+ import {
13
+ generateSummary,
14
+ estimateTokens,
15
+ chunkMessages,
16
+ isDegenerateSummary,
17
+ CompactionProducedNoSummaryError,
18
+ calculateContextTokens,
19
+ } from "./compaction.js";
13
20
  import { estimateSerializedTokens } from "./utils.js";
14
21
 
15
22
  // ---------------------------------------------------------------------------
@@ -187,6 +194,21 @@ describe("chunkMessages", () => {
187
194
  });
188
195
  });
189
196
 
197
+ describe("calculateContextTokens", () => {
198
+ it("uses prompt-relevant usage only (input + cacheRead + cacheWrite)", () => {
199
+ const usage = {
200
+ input: 65,
201
+ output: 39_846,
202
+ cacheRead: 2_945_563,
203
+ cacheWrite: 243_452,
204
+ totalTokens: 3_228_926,
205
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
206
+ };
207
+
208
+ assert.equal(calculateContextTokens(usage), 3_189_080);
209
+ });
210
+ });
211
+
190
212
  // ---------------------------------------------------------------------------
191
213
  // generateSummary chunked fallback tests
192
214
  // ---------------------------------------------------------------------------
@@ -107,10 +107,15 @@ export const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {
107
107
 
108
108
  /**
109
109
  * Calculate total context tokens from usage.
110
- * Uses the native totalTokens field when available, falls back to computing from components.
110
+ * Uses prompt-relevant components only:
111
+ * - input: current user/tool payload sent to model
112
+ * - cacheRead/cacheWrite: context replay + newly cached context
113
+ *
114
+ * Excludes output because output tokens are not part of the current prompt size.
115
+ * Excludes totalTokens because some providers report cumulative loop/session totals.
111
116
  */
112
117
  export function calculateContextTokens(usage: Usage): number {
113
- return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
118
+ return usage.input + usage.cacheRead + usage.cacheWrite;
114
119
  }
115
120
 
116
121
  /**
@@ -573,7 +573,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
573
573
  const removed = modelRegistry.authStorage.removeLegacyOAuthCredential(resolvedProvider);
574
574
  if (removed) {
575
575
  console.warn(
576
- `[auth] Removed unsupported Anthropic OAuth credential from auth.json (#3952).`,
576
+ `[auth] Removed unsupported Anthropic OAuth credential from auth.json.`,
577
577
  );
578
578
  }
579
579
  if (isClaudeCodeBinaryInPath()) {
@@ -39,6 +39,7 @@ function renderToolCollapsed(
39
39
  details?: Record<string, unknown>;
40
40
  },
41
41
  toolDefinition?: { label?: string; renderCall?: (...args: any[]) => any; renderResult?: (...args: any[]) => any },
42
+ width = 120,
42
43
  ): string {
43
44
  const component = new ToolExecutionComponent(
44
45
  toolName,
@@ -48,7 +49,7 @@ function renderToolCollapsed(
48
49
  { requestRender() {} } as any,
49
50
  );
50
51
  if (result) component.updateResult(result);
51
- return stripAnsi(component.render(120).join("\n"));
52
+ return stripAnsi(component.render(width).join("\n"));
52
53
  }
53
54
 
54
55
  describe("ToolExecutionComponent", () => {
@@ -294,6 +295,21 @@ describe("ToolExecutionComponent", () => {
294
295
  assert.doesNotMatch(rendered, /\bok\b/);
295
296
  });
296
297
 
298
+ test("uses available row width for compact bash command text", () => {
299
+ const rendered = renderToolCollapsed(
300
+ "bash",
301
+ {
302
+ command:
303
+ 'grep -n "expanded\\|toolOutputExpanded\\|setExpanded\\|defaultExpanded" /tmp/project/src/tool-execution.ts',
304
+ },
305
+ { content: [{ type: "text", text: "ok" }], isError: false, details: { cwd: "/tmp/project" } },
306
+ undefined,
307
+ 200,
308
+ );
309
+
310
+ assert.match(rendered, /defaultExpanded/);
311
+ });
312
+
297
313
  test("keeps failed tools expanded and error visible", () => {
298
314
  const rendered = renderToolCollapsed(
299
315
  "edit",
@@ -20,6 +20,17 @@ function sanitizeStatusText(text: string): string {
20
20
  .trim();
21
21
  }
22
22
 
23
+ function truncateFooterPath(text: string, width: number): string {
24
+ if (visibleWidth(text) <= width) return text;
25
+ const tailMatch = text.match(/( \([^)]+\)(?: • .*)?)$/);
26
+ if (!tailMatch) return truncateToWidth(text, width, "...");
27
+ const tail = tailMatch[1];
28
+ const tailWidth = visibleWidth(tail);
29
+ if (tailWidth >= width - 4) return truncateToWidth(text, width, "...");
30
+ const head = text.slice(0, -tail.length);
31
+ return `${truncateToWidth(head, width - tailWidth, "...")}${tail}`;
32
+ }
33
+
23
34
  /**
24
35
  * Format token counts (similar to web-ui)
25
36
  */
@@ -222,10 +233,6 @@ export class FooterComponent implements Component {
222
233
  }
223
234
  }
224
235
 
225
- // Apply dim to the stats group before handing it to the shared footer strip.
226
- // statsLeft may contain color codes for context %, so keep coloring local to the group.
227
- const dimStatsLeft = theme.fg("dim", statsLeft);
228
-
229
236
  // Extension statuses right-aligned on the pwd line (sorted by key).
230
237
  // Keeps the footer compact by avoiding a dedicated row when the content
231
238
  // fits alongside pwd. Falls back to pwd-only if the combined line would
@@ -239,12 +246,21 @@ export class FooterComponent implements Component {
239
246
  .join(" ")
240
247
  : "";
241
248
 
249
+ const footerRight = [rightSide, extStatusText].filter(Boolean).join(" ");
250
+ const gsdSegment = theme.fg("accent", "● GSD");
251
+ const dimStatsLeft = theme.fg("dim", statsLeft);
252
+ const innerWidth = Math.max(1, width - 2);
253
+ const rightWidth = visibleWidth(footerRight);
254
+ const leftBudget = footerRight ? Math.max(1, innerWidth - rightWidth - 3) : innerWidth;
255
+ const sepWidth = visibleWidth(" │ ");
256
+ const pwdBudget = Math.max(1, leftBudget - visibleWidth(gsdSegment) - visibleWidth(dimStatsLeft) - sepWidth * 2);
257
+ const pwdSegment = theme.fg("dim", truncateFooterPath(pwd, pwdBudget));
258
+
242
259
  const leftSegments = [
243
- theme.fg("accent", "● GSD"),
244
- theme.fg("dim", pwd),
260
+ gsdSegment,
261
+ pwdSegment,
245
262
  dimStatsLeft,
246
263
  ];
247
- const footerRight = [rightSide, extStatusText].filter(Boolean).join(" ");
248
264
  return renderFooterStrip(leftSegments, footerRight, width);
249
265
  }
250
266
  }
@@ -117,7 +117,7 @@ function formatElapsed(ms: number): string {
117
117
  }
118
118
 
119
119
  function formatCommandPreview(command: string): string {
120
- return truncateToWidth(command.replace(/\s+/g, " ").trim(), 64, "");
120
+ return command.replace(/\s+/g, " ").trim();
121
121
  }
122
122
 
123
123
  function appendLineOrRange(displayPath: string | undefined, target: ToolTargetMetadata): string | undefined {
@@ -1,4 +1,5 @@
1
- // GSD-2 Interactive Chat Controller
1
+ // Project/App: GSD-2
2
+ // File Purpose: Interactive TUI chat stream controller.
2
3
  import { Loader, Markdown, Spacer, Text } from "@gsd/pi-tui";
3
4
 
4
5
  import type { InteractiveModeEvent, InteractiveModeStateHost } from "../interactive-mode-state.js";
@@ -31,18 +32,77 @@ type RenderedSegment =
31
32
  | { kind: "tool"; contentIndex: number; component: ToolExecutionComponent }
32
33
  | { kind: "tool-summary"; component: ToolPhaseSummaryComponent; phases: ToolExecutionPhase[] };
33
34
 
35
+ type DesiredSegment =
36
+ | { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
37
+ | { kind: "tool"; contentIndex: number; toolId: string };
38
+
34
39
  let renderedSegments: RenderedSegment[] = [];
35
40
  // When providers reuse one assistant lifecycle across internal sub-turns,
36
41
  // a content[] shrink resets renderedSegments. Keep the displaced segments so
37
42
  // claude-code MCP pruning can remove stale provisional text later.
38
43
  let orphanedSegments: RenderedSegment[] = [];
39
44
 
45
+ function getVisibleTextLikeBlockType(block: any): "text" | "thinking" | undefined {
46
+ if (block?.type === "text" && typeof block.text === "string" && block.text.trim().length > 0) return "text";
47
+ if (block?.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim().length > 0) return "thinking";
48
+ return undefined;
49
+ }
50
+
51
+ function buildDesiredSegments(
52
+ blocks: Array<any>,
53
+ options: { shouldSkipTextBlock?: (block: any, index: number) => boolean } = {},
54
+ ): DesiredSegment[] {
55
+ const desired: DesiredSegment[] = [];
56
+ let runStart = -1;
57
+ let runEnd = -1;
58
+ let runType: "text" | "thinking" | undefined;
59
+ const closeRun = () => {
60
+ if (runStart !== -1 && runType) {
61
+ desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
62
+ runStart = -1;
63
+ runEnd = -1;
64
+ runType = undefined;
65
+ }
66
+ };
67
+
68
+ for (let i = 0; i < blocks.length; i++) {
69
+ const block = blocks[i];
70
+ const blockType = getVisibleTextLikeBlockType(block);
71
+ const isInvisibleTextLike = blockType === undefined && (block?.type === "text" || block?.type === "thinking");
72
+ const isTool = block?.type === "toolCall" || block?.type === "serverToolUse";
73
+
74
+ if (blockType) {
75
+ if (options.shouldSkipTextBlock?.(block, i)) {
76
+ closeRun();
77
+ continue;
78
+ }
79
+ if (runStart === -1) {
80
+ runStart = i;
81
+ runEnd = i;
82
+ runType = blockType;
83
+ } else if (runType !== blockType) {
84
+ closeRun();
85
+ runStart = i;
86
+ runEnd = i;
87
+ runType = blockType;
88
+ } else {
89
+ runEnd = i;
90
+ }
91
+ } else {
92
+ if (isInvisibleTextLike) continue;
93
+ closeRun();
94
+ if (isTool) {
95
+ desired.push({ kind: "tool", contentIndex: i, toolId: block.id });
96
+ }
97
+ }
98
+ }
99
+ closeRun();
100
+
101
+ return desired;
102
+ }
103
+
40
104
  function hasVisibleAssistantContent(message: { content: Array<any> }): boolean {
41
- return message.content.some(
42
- (c) =>
43
- (c.type === "text" && typeof c.text === "string" && c.text.trim().length > 0)
44
- || (c.type === "thinking" && typeof c.thinking === "string" && c.thinking.trim().length > 0),
45
- );
105
+ return message.content.some((c) => getVisibleTextLikeBlockType(c) !== undefined);
46
106
  }
47
107
 
48
108
  function hasAssistantToolBlocks(message: { content: Array<any> }): boolean {
@@ -470,59 +530,14 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
470
530
  // Only prune provisional pre-tool prose after post-tool prose exists,
471
531
  // so MCP tool-only windows do not blank the assistant content.
472
532
  const shouldDropPreToolProse = isClaudeCodeProvider && hasMcpToolBlock && hasPostToolText;
473
- type DesiredSegment =
474
- | { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
475
- | { kind: "tool"; contentIndex: number; toolId: string };
476
- const desired: DesiredSegment[] = [];
477
- let runStart = -1;
478
- let runEnd = -1;
479
- let runType: "text" | "thinking" | undefined;
480
- const closeRun = () => {
481
- if (runStart !== -1 && runType) {
482
- desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
483
- runStart = -1;
484
- runEnd = -1;
485
- runType = undefined;
486
- }
487
- };
488
- for (let i = 0; i < blocks.length; i++) {
489
- const b = blocks[i];
490
- const blockType = b.type === "text" || b.type === "thinking" ? b.type : undefined;
491
- const isTextLike = blockType === "text" || blockType === "thinking";
492
- const isTool = b.type === "toolCall" || b.type === "serverToolUse";
493
- // For Claude Code MCP turns, prune only pre-tool prose, never thinking.
494
- const textValue = blockType === "text" && typeof b?.text === "string" ? b.text : "";
495
- const isLikelyQuestion = blockType === "text" && typeof textValue === "string" && /\?\s*$/.test(textValue.trim());
496
- const shouldSkipProse = shouldDropPreToolProse
497
- && firstToolIdx >= 0
498
- && i < firstToolIdx
499
- && blockType === "text"
500
- && !isLikelyQuestion;
501
- if (shouldSkipProse) {
502
- closeRun();
503
- continue;
504
- }
505
- if (isTextLike) {
506
- if (runStart === -1) {
507
- runStart = i;
508
- runEnd = i;
509
- runType = blockType;
510
- } else if (runType !== blockType) {
511
- closeRun();
512
- runStart = i;
513
- runEnd = i;
514
- runType = blockType;
515
- } else {
516
- runEnd = i;
517
- }
518
- } else {
519
- closeRun();
520
- if (isTool) {
521
- desired.push({ kind: "tool", contentIndex: i, toolId: b.id });
522
- }
523
- }
524
- }
525
- closeRun();
533
+ const desired = buildDesiredSegments(blocks, {
534
+ shouldSkipTextBlock: (block: any, index: number) => {
535
+ if (!shouldDropPreToolProse || firstToolIdx < 0 || index >= firstToolIdx) return false;
536
+ if (getVisibleTextLikeBlockType(block) !== "text") return false;
537
+ const textValue = typeof block?.text === "string" ? block.text : "";
538
+ return !/\?\s*$/.test(textValue.trim());
539
+ },
540
+ });
526
541
 
527
542
  // Claude Code MCP can emit provisional pre-tool prose that gets
528
543
  // superseded by post-tool output. Prune stale text-run segments so
@@ -742,49 +757,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
742
757
  // ranges/components don't keep stale partial indices.
743
758
  if (renderedSegments.length > 0) {
744
759
  const finalBlocks = host.streamingMessage.content;
745
- type DesiredSegment =
746
- | { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
747
- | { kind: "tool"; contentIndex: number; toolId: string };
748
- const desired: DesiredSegment[] = [];
749
- let runStart = -1;
750
- let runEnd = -1;
751
- let runType: "text" | "thinking" | undefined;
752
- const closeRun = () => {
753
- if (runStart !== -1 && runType) {
754
- desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
755
- runStart = -1;
756
- runEnd = -1;
757
- runType = undefined;
758
- }
759
- };
760
-
761
- for (let i = 0; i < finalBlocks.length; i++) {
762
- const block = finalBlocks[i] as any;
763
- const blockType = block?.type === "text" || block?.type === "thinking" ? block.type : undefined;
764
- const isTextLike = blockType === "text" || blockType === "thinking";
765
- const isTool = block?.type === "toolCall" || block?.type === "serverToolUse";
766
-
767
- if (isTextLike) {
768
- if (runStart === -1) {
769
- runStart = i;
770
- runEnd = i;
771
- runType = blockType;
772
- } else if (runType !== blockType) {
773
- closeRun();
774
- runStart = i;
775
- runEnd = i;
776
- runType = blockType;
777
- } else {
778
- runEnd = i;
779
- }
780
- } else {
781
- closeRun();
782
- if (isTool) {
783
- desired.push({ kind: "tool", contentIndex: i, toolId: block.id });
784
- }
785
- }
786
- }
787
- closeRun();
760
+ const desired = buildDesiredSegments(finalBlocks);
788
761
 
789
762
  const toolComponentsById = new Map<string, ToolExecutionComponent>();
790
763
  for (const [toolId, component] of host.pendingTools.entries()) {
@@ -45,7 +45,7 @@ function createMockHost() {
45
45
  toolOutputExpanded: false,
46
46
  hideThinkingBlock: false,
47
47
  isBashMode: false,
48
- onInputCallback: undefined,
48
+ onInputCallback: undefined as ((text: string) => void) | undefined,
49
49
  isInitialized: true,
50
50
  loadingAnimation: undefined,
51
51
  pendingWorkingMessage: undefined,
@@ -146,6 +146,20 @@ describe("input-controller pending images", () => {
146
146
  assert.equal(host.pendingImages.length, 0);
147
147
  assert.equal(promptCalls.length, 0); // bash commands don't go through prompt
148
148
  });
149
+
150
+ it("preserves pending images when using onInputCallback path", async () => {
151
+ let callbackText = "";
152
+ host.onInputCallback = (text: string) => {
153
+ callbackText = text;
154
+ };
155
+ host.pendingImages.push({ ...TEST_IMAGE });
156
+
157
+ await host.defaultEditor.onSubmit!("[Image #1] describe");
158
+
159
+ assert.equal(callbackText, "[Image #1] describe");
160
+ assert.equal(host.pendingImages.length, 1);
161
+ assert.equal(promptCalls.length, 0);
162
+ });
149
163
  });
150
164
 
151
165
  type HostOptions = {
@@ -71,9 +71,6 @@ export function setupEditorSubmitHandler(host: InteractiveModeStateHost & {
71
71
  }
72
72
  }
73
73
 
74
- // Consume pending images for prompt submissions
75
- const images = consumePendingImages(host);
76
-
77
74
  // Evaluate contextual tips before sending to agent
78
75
  const tip = host.contextualTips.evaluate({
79
76
  input: text,
@@ -85,6 +82,15 @@ export function setupEditorSubmitHandler(host: InteractiveModeStateHost & {
85
82
  host.showTip(tip);
86
83
  }
87
84
 
85
+ if (host.onInputCallback) {
86
+ host.onInputCallback(text);
87
+ host.editor.addToHistory?.(text);
88
+ return;
89
+ }
90
+
91
+ // Consume pending images for prompt submissions
92
+ const images = consumePendingImages(host);
93
+
88
94
  if (host.session.isCompacting) {
89
95
  if (host.isExtensionCommand(text)) {
90
96
  host.editor.addToHistory?.(text);
@@ -112,12 +118,6 @@ export function setupEditorSubmitHandler(host: InteractiveModeStateHost & {
112
118
 
113
119
  host.flushPendingBashComponents();
114
120
 
115
- if (host.onInputCallback) {
116
- host.onInputCallback(text);
117
- host.editor.addToHistory?.(text);
118
- return;
119
- }
120
-
121
121
  if (host.options?.submitPromptsDirectly) {
122
122
  host.editor.addToHistory?.(text);
123
123
  try {
@@ -1,7 +1,13 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Regression tests for interactive assistant replay ordering.
1
3
  import assert from "node:assert/strict";
2
4
  import { test } from "node:test";
5
+ import stripAnsi from "strip-ansi";
3
6
 
4
- import { buildAssistantReplaySegments } from "./interactive-mode.js";
7
+ import { buildAssistantReplaySegments, getToolExpansionStartupHint } from "./interactive-mode.js";
8
+ import { initTheme } from "./theme/theme.js";
9
+
10
+ initTheme("dark", false);
5
11
 
6
12
  test("buildAssistantReplaySegments preserves tool-first ordering", () => {
7
13
  const segments = buildAssistantReplaySegments([
@@ -42,3 +48,26 @@ test("buildAssistantReplaySegments ignores non-rendered non-tool blocks", () =>
42
48
  { kind: "assistant", startIndex: 2, endIndex: 2 },
43
49
  ]);
44
50
  });
51
+
52
+ test("buildAssistantReplaySegments skips empty GPT reasoning blocks before tools", () => {
53
+ const segments = buildAssistantReplaySegments([
54
+ { type: "thinking", thinking: "", thinkingSignature: "encrypted" },
55
+ { type: "text", text: " " },
56
+ { type: "toolCall", id: "t1", name: "read", arguments: { filePath: "todo.js" } },
57
+ ]);
58
+
59
+ assert.deepEqual(segments, [
60
+ { kind: "tool", contentIndex: 2 },
61
+ ]);
62
+ });
63
+
64
+ test("tool expansion startup hint reflects the default expansion state", () => {
65
+ const keybindings = {
66
+ getKeys(action: string) {
67
+ return action === "expandTools" ? ["ctrl+o"] : [];
68
+ },
69
+ } as any;
70
+
71
+ assert.match(stripAnsi(getToolExpansionStartupHint(true, keybindings)), /ctrl\+o.*collapse tools/);
72
+ assert.match(stripAnsi(getToolExpansionStartupHint(false, keybindings)), /ctrl\+o.*expand tools/);
73
+ });