gsd-pi 2.82.0-dev.ed17d078d → 3.0.0-dev.04f5ccf82

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 (653) 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/detect-stuck.js +1 -1
  11. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  12. package/dist/resources/extensions/gsd/auto/loop.js +122 -40
  13. package/dist/resources/extensions/gsd/auto/orchestrator.js +15 -4
  14. package/dist/resources/extensions/gsd/auto/phases.js +146 -49
  15. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  16. package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -1
  17. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  18. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  19. package/dist/resources/extensions/gsd/auto-budget.js +9 -0
  20. package/dist/resources/extensions/gsd/auto-dashboard.js +72 -5
  21. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  22. package/dist/resources/extensions/gsd/auto-dispatch.js +185 -30
  23. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  24. package/dist/resources/extensions/gsd/auto-post-unit.js +329 -137
  25. package/dist/resources/extensions/gsd/auto-prompts.js +36 -10
  26. package/dist/resources/extensions/gsd/auto-recovery.js +82 -16
  27. package/dist/resources/extensions/gsd/auto-start.js +99 -16
  28. package/dist/resources/extensions/gsd/auto-timers.js +11 -3
  29. package/dist/resources/extensions/gsd/auto-verification.js +146 -34
  30. package/dist/resources/extensions/gsd/auto-worktree.js +185 -26
  31. package/dist/resources/extensions/gsd/auto.js +135 -74
  32. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +65 -10
  33. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +13 -10
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +14 -4
  35. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +24 -9
  37. package/dist/resources/extensions/gsd/clean-root-preflight.js +267 -8
  38. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  39. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -0
  40. package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
  41. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  42. package/dist/resources/extensions/gsd/commands-handlers.js +2 -0
  43. package/dist/resources/extensions/gsd/commands-mcp-status.js +9 -0
  44. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -4
  45. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  46. package/dist/resources/extensions/gsd/crash-recovery.js +55 -7
  47. package/dist/resources/extensions/gsd/db/auto-workers.js +30 -0
  48. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  49. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  50. package/dist/resources/extensions/gsd/db-base-schema.js +2 -0
  51. package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
  52. package/dist/resources/extensions/gsd/db-task-slice-rows.js +2 -0
  53. package/dist/resources/extensions/gsd/dispatch-guard.js +46 -2
  54. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  55. package/dist/resources/extensions/gsd/doctor-git-checks.js +74 -3
  56. package/dist/resources/extensions/gsd/doctor-proactive.js +14 -2
  57. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  58. package/dist/resources/extensions/gsd/doctor.js +2 -28
  59. package/dist/resources/extensions/gsd/export-html.js +27 -425
  60. package/dist/resources/extensions/gsd/forensics.js +10 -3
  61. package/dist/resources/extensions/gsd/git-conflict-state.js +21 -0
  62. package/dist/resources/extensions/gsd/git-service.js +152 -15
  63. package/dist/resources/extensions/gsd/gsd-db.js +76 -33
  64. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  65. package/dist/resources/extensions/gsd/guided-flow.js +110 -117
  66. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  67. package/dist/resources/extensions/gsd/init-wizard.js +17 -2
  68. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -11
  69. package/dist/resources/extensions/gsd/mcp-filter.js +58 -0
  70. package/dist/resources/extensions/gsd/migrate/parsers.js +121 -2
  71. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  72. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  73. package/dist/resources/extensions/gsd/native-git-bridge.js +57 -14
  74. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -0
  75. package/dist/resources/extensions/gsd/paths.js +4 -0
  76. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  77. package/dist/resources/extensions/gsd/planning-path-scope.js +9 -3
  78. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -9
  79. package/dist/resources/extensions/gsd/pre-execution-checks.js +54 -19
  80. package/dist/resources/extensions/gsd/preferences-mcp.js +19 -0
  81. package/dist/resources/extensions/gsd/preferences-models.js +6 -4
  82. package/dist/resources/extensions/gsd/preferences-types.js +3 -0
  83. package/dist/resources/extensions/gsd/preferences-validation.js +147 -0
  84. package/dist/resources/extensions/gsd/preferences.js +35 -0
  85. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  86. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  89. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  90. package/dist/resources/extensions/gsd/prompts/forensics.md +3 -3
  91. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  92. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  93. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  94. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  95. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  96. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  97. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  98. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  99. package/dist/resources/extensions/gsd/repo-identity.js +39 -22
  100. package/dist/resources/extensions/gsd/repository-registry.js +44 -0
  101. package/dist/resources/extensions/gsd/safety/evidence-collector.js +2 -0
  102. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +42 -18
  103. package/dist/resources/extensions/gsd/session-lock.js +15 -2
  104. package/dist/resources/extensions/gsd/slice-parallel-conflict.js +2 -2
  105. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +84 -5
  106. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  107. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  108. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  109. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  110. package/dist/resources/extensions/gsd/state.js +28 -7
  111. package/dist/resources/extensions/gsd/status-guards.js +14 -2
  112. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  113. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  114. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  115. package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -9
  116. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -10
  117. package/dist/resources/extensions/gsd/tools/exec-tool.js +87 -5
  118. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  119. package/dist/resources/extensions/gsd/tools/plan-slice.js +151 -15
  120. package/dist/resources/extensions/gsd/tools/validate-milestone.js +32 -1
  121. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +185 -40
  122. package/dist/resources/extensions/gsd/tui/render-kit.js +33 -0
  123. package/dist/resources/extensions/gsd/unit-context-composer.js +2 -0
  124. package/dist/resources/extensions/gsd/unit-context-manifest.js +69 -17
  125. package/dist/resources/extensions/gsd/validation.js +23 -1
  126. package/dist/resources/extensions/gsd/verification-gate.js +142 -7
  127. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  128. package/dist/resources/extensions/gsd/watch/header-renderer.js +34 -25
  129. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
  130. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  131. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  132. package/dist/resources/extensions/gsd/worktree-lifecycle.js +86 -19
  133. package/dist/resources/extensions/gsd/worktree-manager.js +11 -2
  134. package/dist/resources/extensions/gsd/worktree-safety.js +43 -4
  135. package/dist/resources/extensions/gsd/worktree-state-projection.js +31 -0
  136. package/dist/resources/extensions/gsd/worktree-telemetry.js +32 -0
  137. package/dist/resources/extensions/shared/html-shell.js +388 -0
  138. package/dist/resources/extensions/shared/interview-ui.js +6 -4
  139. package/dist/resources/extensions/shared/next-action-ui.js +13 -5
  140. package/dist/resources/extensions/subagent/index.js +448 -78
  141. package/dist/resources/extensions/subagent/launch.js +77 -0
  142. package/dist/resources/extensions/subagent/run-store.js +148 -0
  143. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  144. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  145. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  146. package/dist/resources/extensions/visual-brief/index.js +5 -0
  147. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  148. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  149. package/dist/resources/skills/forensics/SKILL.md +1 -1
  150. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  151. package/dist/web/standalone/.next/BUILD_ID +1 -1
  152. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  153. package/dist/web/standalone/.next/build-manifest.json +3 -3
  154. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  155. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  156. package/dist/web/standalone/.next/required-server-files.json +1 -1
  157. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  159. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  163. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  164. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  167. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  170. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  171. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  172. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  174. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  177. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/index.html +1 -1
  180. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  181. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  182. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  183. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  184. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  185. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  186. package/dist/web/standalone/.next/server/app/page.js +2 -2
  187. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  190. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  191. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  195. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  196. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  197. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  198. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  199. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  200. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  201. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  202. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  203. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  204. package/dist/web/standalone/server.js +1 -1
  205. package/dist/welcome-screen.js +7 -8
  206. package/package.json +4 -4
  207. package/packages/contracts/dist/rpc.test.js +7 -0
  208. package/packages/contracts/dist/rpc.test.js.map +1 -1
  209. package/packages/contracts/dist/workflow.d.ts +21 -0
  210. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  211. package/packages/contracts/dist/workflow.js +24 -0
  212. package/packages/contracts/dist/workflow.js.map +1 -1
  213. package/packages/contracts/src/rpc.test.ts +8 -0
  214. package/packages/contracts/src/workflow.ts +24 -0
  215. package/packages/daemon/package.json +2 -2
  216. package/packages/mcp-server/README.md +13 -4
  217. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  218. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  219. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  220. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  221. package/packages/mcp-server/package.json +2 -2
  222. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  223. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  224. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  225. package/packages/native/package.json +1 -1
  226. package/packages/native/src/__tests__/stream-process.test.mjs +32 -12
  227. package/packages/native/tsconfig.json +2 -1
  228. package/packages/native/tsconfig.tsbuildinfo +1 -1
  229. package/packages/pi-agent-core/package.json +1 -1
  230. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  231. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  232. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  233. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  234. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  235. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  236. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  237. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  238. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  239. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  240. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  241. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  242. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  243. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  244. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  245. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  247. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  248. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  249. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  250. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  251. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  252. package/packages/pi-ai/package.json +1 -1
  253. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  254. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  255. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  256. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  257. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  258. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  259. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  260. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  261. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  262. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  263. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  264. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  265. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  267. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +6 -1
  269. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +7 -2
  271. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +14 -1
  273. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  275. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +8 -2
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +3 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +16 -0
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +82 -97
  290. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -7
  292. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +11 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  300. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/packages/pi-coding-agent/package.json +1 -1
  302. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  303. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  304. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  305. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +23 -1
  306. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +7 -2
  307. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  308. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +17 -1
  309. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +20 -0
  310. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +3 -0
  311. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  312. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -1
  313. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +91 -102
  314. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +15 -1
  315. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +9 -9
  316. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  317. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  318. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  319. package/packages/pi-tui/dist/__tests__/loader.test.d.ts +2 -0
  320. package/packages/pi-tui/dist/__tests__/loader.test.d.ts.map +1 -0
  321. package/packages/pi-tui/dist/__tests__/loader.test.js +24 -0
  322. package/packages/pi-tui/dist/__tests__/loader.test.js.map +1 -0
  323. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  324. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  325. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  326. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  327. package/packages/pi-tui/dist/__tests__/tui.test.js +72 -4
  328. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  329. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  330. package/packages/pi-tui/dist/components/loader.js +3 -0
  331. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  332. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  333. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  334. package/packages/pi-tui/dist/terminal.js +12 -0
  335. package/packages/pi-tui/dist/terminal.js.map +1 -1
  336. package/packages/pi-tui/dist/tui.d.ts +1 -0
  337. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  338. package/packages/pi-tui/dist/tui.js +117 -33
  339. package/packages/pi-tui/dist/tui.js.map +1 -1
  340. package/packages/pi-tui/package.json +1 -1
  341. package/packages/pi-tui/src/__tests__/loader.test.ts +30 -0
  342. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  343. package/packages/pi-tui/src/__tests__/tui.test.ts +90 -4
  344. package/packages/pi-tui/src/components/loader.ts +3 -0
  345. package/packages/pi-tui/src/terminal.ts +11 -0
  346. package/packages/pi-tui/src/tui.ts +116 -33
  347. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  348. package/packages/rpc-client/package.json +1 -1
  349. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  350. package/pkg/package.json +1 -1
  351. package/src/resources/GSD-WORKFLOW.md +10 -1
  352. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  353. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +52 -6
  354. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  355. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +49 -2
  356. package/src/resources/extensions/cmux/index.ts +6 -0
  357. package/src/resources/extensions/gsd/auto/contracts.ts +19 -6
  358. package/src/resources/extensions/gsd/auto/detect-stuck.ts +1 -0
  359. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  360. package/src/resources/extensions/gsd/auto/loop.ts +123 -40
  361. package/src/resources/extensions/gsd/auto/orchestrator.ts +15 -4
  362. package/src/resources/extensions/gsd/auto/phases.ts +172 -60
  363. package/src/resources/extensions/gsd/auto/session.ts +16 -0
  364. package/src/resources/extensions/gsd/auto/types.ts +3 -0
  365. package/src/resources/extensions/gsd/auto/unit-runner-events.ts +6 -2
  366. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  367. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  368. package/src/resources/extensions/gsd/auto-budget.ts +11 -0
  369. package/src/resources/extensions/gsd/auto-dashboard.ts +78 -5
  370. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  371. package/src/resources/extensions/gsd/auto-dispatch.ts +208 -29
  372. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  373. package/src/resources/extensions/gsd/auto-post-unit.ts +369 -148
  374. package/src/resources/extensions/gsd/auto-prompts.ts +36 -13
  375. package/src/resources/extensions/gsd/auto-recovery.ts +86 -13
  376. package/src/resources/extensions/gsd/auto-start.ts +109 -14
  377. package/src/resources/extensions/gsd/auto-timers.ts +10 -3
  378. package/src/resources/extensions/gsd/auto-verification.ts +174 -42
  379. package/src/resources/extensions/gsd/auto-worktree.ts +202 -30
  380. package/src/resources/extensions/gsd/auto.ts +172 -81
  381. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +66 -10
  382. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -10
  383. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +13 -4
  384. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  385. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +27 -10
  386. package/src/resources/extensions/gsd/clean-root-preflight.ts +284 -8
  387. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  388. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -0
  389. package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
  390. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  391. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  392. package/src/resources/extensions/gsd/commands-mcp-status.ts +8 -0
  393. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +17 -4
  394. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  395. package/src/resources/extensions/gsd/crash-recovery.ts +55 -6
  396. package/src/resources/extensions/gsd/db/auto-workers.ts +37 -0
  397. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  398. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  399. package/src/resources/extensions/gsd/db-base-schema.ts +2 -0
  400. package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
  401. package/src/resources/extensions/gsd/db-task-slice-rows.ts +4 -0
  402. package/src/resources/extensions/gsd/dispatch-guard.ts +60 -2
  403. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  404. package/src/resources/extensions/gsd/doctor-git-checks.ts +73 -3
  405. package/src/resources/extensions/gsd/doctor-proactive.ts +18 -2
  406. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  407. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  408. package/src/resources/extensions/gsd/doctor.ts +2 -27
  409. package/src/resources/extensions/gsd/export-html.ts +27 -427
  410. package/src/resources/extensions/gsd/forensics.ts +9 -3
  411. package/src/resources/extensions/gsd/git-conflict-state.ts +23 -0
  412. package/src/resources/extensions/gsd/git-service.ts +182 -16
  413. package/src/resources/extensions/gsd/gsd-db.ts +80 -31
  414. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  415. package/src/resources/extensions/gsd/guided-flow.ts +142 -134
  416. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  417. package/src/resources/extensions/gsd/init-wizard.ts +17 -2
  418. package/src/resources/extensions/gsd/journal.ts +8 -1
  419. package/src/resources/extensions/gsd/markdown-renderer.ts +14 -11
  420. package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
  421. package/src/resources/extensions/gsd/migrate/parsers.ts +139 -2
  422. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  423. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  424. package/src/resources/extensions/gsd/native-git-bridge.ts +63 -14
  425. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -0
  426. package/src/resources/extensions/gsd/paths.ts +5 -0
  427. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  428. package/src/resources/extensions/gsd/planning-path-scope.ts +10 -2
  429. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -12
  430. package/src/resources/extensions/gsd/pre-execution-checks.ts +67 -19
  431. package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
  432. package/src/resources/extensions/gsd/preferences-models.ts +6 -4
  433. package/src/resources/extensions/gsd/preferences-types.ts +35 -0
  434. package/src/resources/extensions/gsd/preferences-validation.ts +154 -0
  435. package/src/resources/extensions/gsd/preferences.ts +39 -0
  436. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  437. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  438. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  439. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  440. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  441. package/src/resources/extensions/gsd/prompts/forensics.md +3 -3
  442. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  443. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  444. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  445. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  446. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  447. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  448. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  449. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  450. package/src/resources/extensions/gsd/repo-identity.ts +45 -25
  451. package/src/resources/extensions/gsd/repository-registry.ts +77 -0
  452. package/src/resources/extensions/gsd/safety/evidence-collector.ts +2 -0
  453. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +54 -19
  454. package/src/resources/extensions/gsd/session-lock.ts +15 -2
  455. package/src/resources/extensions/gsd/slice-parallel-conflict.ts +2 -2
  456. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +75 -3
  457. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  458. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  459. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  460. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  461. package/src/resources/extensions/gsd/state.ts +33 -7
  462. package/src/resources/extensions/gsd/status-guards.ts +16 -2
  463. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  464. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  465. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  466. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  467. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +10 -1
  468. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  469. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  470. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +775 -34
  471. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +245 -28
  472. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  473. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  474. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +136 -13
  476. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
  477. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
  478. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  479. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  480. package/src/resources/extensions/gsd/tests/auto-workers.test.ts +29 -0
  481. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  482. package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +21 -0
  483. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  484. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  485. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +170 -3
  486. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +32 -4
  487. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  488. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  489. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +55 -2
  490. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +60 -9
  491. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  492. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +104 -2
  493. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  494. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  495. package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +61 -2
  497. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +139 -1
  498. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +68 -1
  499. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +140 -1
  500. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  501. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
  502. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +97 -0
  503. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +99 -1
  504. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +15 -1
  505. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  506. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +28 -0
  507. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  508. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  509. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  510. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  511. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  512. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  513. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  514. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  515. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  516. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  517. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +22 -0
  518. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +36 -1
  519. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +33 -1
  520. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  521. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +226 -2
  522. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +5 -21
  523. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +15 -0
  524. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  525. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +40 -0
  526. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +49 -3
  527. package/src/resources/extensions/gsd/tests/journal.test.ts +32 -0
  528. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
  529. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +11 -0
  530. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  531. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +21 -40
  532. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +59 -1
  533. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  534. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +60 -0
  535. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +80 -2
  536. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  537. package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +55 -0
  538. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  539. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  540. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  541. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  542. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  543. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +343 -3
  544. package/src/resources/extensions/gsd/tests/plan-task.test.ts +18 -1
  545. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  546. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +105 -3
  547. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +8 -1
  548. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  549. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +147 -0
  550. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +54 -0
  551. package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
  552. package/src/resources/extensions/gsd/tests/preferences.test.ts +75 -0
  553. package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +148 -0
  554. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +79 -0
  555. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +42 -1
  556. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  557. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  558. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  559. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  560. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  561. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +28 -1
  562. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +52 -0
  563. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  564. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +59 -1
  566. package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +2 -2
  567. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +112 -1
  568. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  569. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +94 -2
  570. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  571. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  572. package/src/resources/extensions/gsd/tests/status-guards.test.ts +17 -1
  573. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  574. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +2 -1
  575. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  576. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +22 -0
  577. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +1 -0
  578. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +131 -9
  579. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +111 -1
  580. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  581. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +68 -0
  582. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +42 -1
  583. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +188 -1
  584. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  585. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  586. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  587. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  588. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +153 -1
  589. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  590. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  591. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +73 -2
  592. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +25 -0
  593. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +90 -0
  594. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +95 -0
  595. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +16 -0
  596. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +27 -0
  597. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +59 -0
  598. package/src/resources/extensions/gsd/tools/complete-milestone.ts +18 -10
  599. package/src/resources/extensions/gsd/tools/complete-slice.ts +57 -10
  600. package/src/resources/extensions/gsd/tools/exec-tool.ts +98 -5
  601. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  602. package/src/resources/extensions/gsd/tools/plan-slice.ts +172 -12
  603. package/src/resources/extensions/gsd/tools/validate-milestone.ts +31 -0
  604. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +166 -17
  605. package/src/resources/extensions/gsd/tui/render-kit.ts +44 -0
  606. package/src/resources/extensions/gsd/types.ts +1 -1
  607. package/src/resources/extensions/gsd/unit-context-composer.ts +3 -0
  608. package/src/resources/extensions/gsd/unit-context-manifest.ts +86 -19
  609. package/src/resources/extensions/gsd/validation.ts +23 -1
  610. package/src/resources/extensions/gsd/verification-gate.ts +170 -6
  611. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  612. package/src/resources/extensions/gsd/watch/header-renderer.ts +35 -24
  613. package/src/resources/extensions/gsd/workflow-manifest.ts +2 -0
  614. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  615. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  616. package/src/resources/extensions/gsd/worktree-lifecycle.ts +98 -20
  617. package/src/resources/extensions/gsd/worktree-manager.ts +14 -2
  618. package/src/resources/extensions/gsd/worktree-safety.ts +57 -10
  619. package/src/resources/extensions/gsd/worktree-state-projection.ts +43 -0
  620. package/src/resources/extensions/gsd/worktree-telemetry.ts +39 -0
  621. package/src/resources/extensions/shared/html-shell.ts +412 -0
  622. package/src/resources/extensions/shared/interview-ui.ts +6 -4
  623. package/src/resources/extensions/shared/next-action-ui.ts +11 -5
  624. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +15 -0
  625. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +32 -0
  626. package/src/resources/extensions/subagent/index.ts +567 -103
  627. package/src/resources/extensions/subagent/launch.ts +131 -0
  628. package/src/resources/extensions/subagent/run-store.ts +218 -0
  629. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  630. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  631. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  632. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  633. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  634. package/src/resources/extensions/visual-brief/index.ts +8 -0
  635. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  636. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  637. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  638. package/src/resources/skills/forensics/SKILL.md +1 -1
  639. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  640. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  641. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  642. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  644. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  645. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  646. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  647. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  648. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  649. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  650. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  651. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  652. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → w_ikFkx_-OHxisG9xjz4u}/_buildManifest.js +0 -0
  653. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → w_ikFkx_-OHxisG9xjz4u}/_ssgManifest.js +0 -0
@@ -0,0 +1,121 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it, type TestContext } from "node:test";
3
+
4
+ import { ProcessTerminal } from "../terminal.js";
5
+
6
+ function replaceProcessProperty(
7
+ t: TestContext,
8
+ target: object,
9
+ key: string,
10
+ value: unknown
11
+ ): void {
12
+ const descriptor = Object.getOwnPropertyDescriptor(target, key);
13
+ Object.defineProperty(target, key, {
14
+ configurable: true,
15
+ writable: true,
16
+ value,
17
+ });
18
+ t.after(() => {
19
+ if (descriptor) {
20
+ Object.defineProperty(target, key, descriptor);
21
+ return;
22
+ }
23
+ delete (target as Record<string, unknown>)[key];
24
+ });
25
+ }
26
+
27
+ describe("ProcessTerminal", () => {
28
+ it("restores terminal state when the process exits without an explicit stop", (t) => {
29
+ t.mock.timers.enable({ apis: ["setTimeout"] });
30
+
31
+ const writes: string[] = [];
32
+ const rawModes: boolean[] = [];
33
+ const resizeHandlers = new Set<(...args: unknown[]) => void>();
34
+ const stdinHandlers = new Set<(data: string) => void>();
35
+ let resumed = false;
36
+ let paused = false;
37
+ let encoding = "";
38
+ let sigwinchSent = false;
39
+
40
+ replaceProcessProperty(t, process.stdout, "isTTY", true);
41
+ replaceProcessProperty(t, process.stdout, "write", (data: string) => {
42
+ writes.push(data);
43
+ return true;
44
+ });
45
+ replaceProcessProperty(t, process.stdout, "on", (event: string, handler: (...args: unknown[]) => void) => {
46
+ if (event === "resize") resizeHandlers.add(handler);
47
+ return process.stdout;
48
+ });
49
+ replaceProcessProperty(
50
+ t,
51
+ process.stdout,
52
+ "removeListener",
53
+ (event: string, handler: (...args: unknown[]) => void) => {
54
+ if (event === "resize") resizeHandlers.delete(handler);
55
+ return process.stdout;
56
+ }
57
+ );
58
+
59
+ replaceProcessProperty(t, process.stdin, "isRaw", false);
60
+ replaceProcessProperty(t, process.stdin, "setRawMode", (enabled: boolean) => {
61
+ rawModes.push(enabled);
62
+ return process.stdin;
63
+ });
64
+ replaceProcessProperty(t, process.stdin, "setEncoding", (nextEncoding: BufferEncoding) => {
65
+ encoding = nextEncoding;
66
+ return process.stdin;
67
+ });
68
+ replaceProcessProperty(t, process.stdin, "resume", () => {
69
+ resumed = true;
70
+ return process.stdin;
71
+ });
72
+ replaceProcessProperty(t, process.stdin, "pause", () => {
73
+ paused = true;
74
+ return process.stdin;
75
+ });
76
+ replaceProcessProperty(t, process.stdin, "on", (event: string, handler: (data: string) => void) => {
77
+ if (event === "data") stdinHandlers.add(handler);
78
+ return process.stdin;
79
+ });
80
+ replaceProcessProperty(t, process.stdin, "removeListener", (event: string, handler: (data: string) => void) => {
81
+ if (event === "data") stdinHandlers.delete(handler);
82
+ return process.stdin;
83
+ });
84
+ replaceProcessProperty(t, process, "kill", (pid: number, signal?: NodeJS.Signals | number) => {
85
+ assert.equal(pid, process.pid);
86
+ assert.equal(signal, "SIGWINCH");
87
+ sigwinchSent = true;
88
+ return true;
89
+ });
90
+
91
+ const terminal = new ProcessTerminal();
92
+ const exitListenersBeforeStart = process.listeners("exit");
93
+
94
+ terminal.start(() => {}, () => {});
95
+
96
+ const processExitHandler = process
97
+ .listeners("exit")
98
+ .find((listener) => !exitListenersBeforeStart.includes(listener));
99
+ assert.ok(processExitHandler);
100
+ assert.deepEqual(rawModes, [true]);
101
+ assert.equal(encoding, "utf8");
102
+ assert.equal(resumed, true);
103
+ assert.equal(sigwinchSent, process.platform !== "win32");
104
+ assert.equal(resizeHandlers.size, 1);
105
+ assert.equal(stdinHandlers.size, 1);
106
+ assert.deepEqual(writes, ["\x1b[?2004h", "\x1b[?u"]);
107
+
108
+ processExitHandler(0);
109
+
110
+ assert.deepEqual(rawModes, [true, false]);
111
+ assert.equal(paused, true);
112
+ assert.equal(resizeHandlers.size, 0);
113
+ assert.equal(stdinHandlers.size, 0);
114
+ assert.equal(process.listeners("exit").includes(processExitHandler), false);
115
+ assert.deepEqual(writes, ["\x1b[?2004h", "\x1b[?u", "\x1b[?2004l"]);
116
+
117
+ terminal.stop();
118
+
119
+ assert.deepEqual(writes, ["\x1b[?2004h", "\x1b[?u", "\x1b[?2004l"]);
120
+ });
121
+ });
@@ -7,11 +7,11 @@ import { Container, CURSOR_MARKER, TUI } from "../tui.js";
7
7
  import type { Component } from "../tui.js";
8
8
  import type { Terminal } from "../terminal.js";
9
9
 
10
- function makeTerminal(writes?: string[]): Terminal {
10
+ function makeTerminal(writes?: string[], rows = 24): Terminal {
11
11
  return {
12
12
  isTTY: true,
13
13
  columns: 80,
14
- rows: 24,
14
+ rows,
15
15
  kittyProtocolActive: false,
16
16
  start() {},
17
17
  stop() {},
@@ -67,8 +67,94 @@ describe("TUI", () => {
67
67
  anyTui.doRender();
68
68
 
69
69
  const renderWrite = writes[writeCountAfterFirstRender];
70
- assert.ok(renderWrite.startsWith("\x1b[?2026h\r"), "editor diff should start at the current cursor row");
71
- assert.ok(!renderWrite.startsWith("\x1b[?2026h\x1b[1A\r"), "editor diff must not move above the cursor row");
70
+ const withoutSyncWrapper = renderWrite.replace(/^\x1b\[\?2026h/, "");
71
+ assert.ok(withoutSyncWrapper.startsWith("\r"), "editor diff should start at the current cursor row");
72
+ assert.ok(!withoutSyncWrapper.startsWith("\x1b[1A\r"), "editor diff must not move above the cursor row");
73
+ });
74
+
75
+ it("omits synchronized-output wrappers when PI_DISABLE_SYNC_OUTPUT is enabled", () => {
76
+ const previous = process.env.PI_DISABLE_SYNC_OUTPUT;
77
+ process.env.PI_DISABLE_SYNC_OUTPUT = "1";
78
+ try {
79
+ const writes: string[] = [];
80
+ const tui = new TUI(makeTerminal(writes));
81
+ tui.addChild({
82
+ render: () => ["content"],
83
+ invalidate() {},
84
+ });
85
+
86
+ (tui as any).doRender();
87
+
88
+ const rendered = writes.join("");
89
+ assert.ok(rendered.includes("content"), "render should still write component output");
90
+ assert.ok(
91
+ !rendered.includes("\x1b[?2026h") && !rendered.includes("\x1b[?2026l"),
92
+ "PI_DISABLE_SYNC_OUTPUT=1 must suppress synchronized-output escape sequences",
93
+ );
94
+ } finally {
95
+ if (previous === undefined) {
96
+ delete process.env.PI_DISABLE_SYNC_OUTPUT;
97
+ } else {
98
+ process.env.PI_DISABLE_SYNC_OUTPUT = previous;
99
+ }
100
+ }
101
+ });
102
+
103
+ it("does not full-clear when a tall buffer shrinks (flicker regression #6130)", () => {
104
+ // Tall-buffer-shrink path: both prev and new exceed viewport height. The fix
105
+ // falls through to differential render instead of emitting \x1b[2J, which used
106
+ // to cause the bottom panel to flash on every shrink.
107
+ const writes: string[] = [];
108
+ const terminal = makeTerminal(writes, 10);
109
+ const tui = new TUI(terminal);
110
+ let lines = Array.from({ length: 20 }, (_, i) => `line-${i}`);
111
+ tui.addChild({
112
+ render: () => lines,
113
+ invalidate() {},
114
+ });
115
+ const anyTui = tui as any;
116
+
117
+ anyTui.doRender();
118
+ const writeCountAfterFirstRender = writes.length;
119
+
120
+ // Shrink: still taller than viewport, but smaller than before.
121
+ lines = Array.from({ length: 15 }, (_, i) => `line-${i}`);
122
+ anyTui.doRender();
123
+
124
+ const shrinkWrites = writes.slice(writeCountAfterFirstRender).join("");
125
+ assert.ok(
126
+ !shrinkWrites.includes("\x1b[2J"),
127
+ "tall buffer shrink must not emit \\x1b[2J — that causes the bottom panel to flash",
128
+ );
129
+ });
130
+
131
+ it("does not full-clear when firstChanged is above the viewport (flicker regression #6130)", () => {
132
+ // firstChanged-above-viewport path: a line above the current viewport changes.
133
+ // The fix clamps firstChanged to the viewport top and repaints in place instead
134
+ // of emitting \x1b[2J + full repaint, which used to cause a bottom-panel flash.
135
+ const writes: string[] = [];
136
+ const terminal = makeTerminal(writes, 10);
137
+ const tui = new TUI(terminal);
138
+ let lines = Array.from({ length: 20 }, (_, i) => `line-${i}`);
139
+ tui.addChild({
140
+ render: () => lines,
141
+ invalidate() {},
142
+ });
143
+ const anyTui = tui as any;
144
+
145
+ anyTui.doRender();
146
+ const writeCountAfterFirstRender = writes.length;
147
+
148
+ // Change a line above the viewport (viewportTop = 20 - 10 = 10, so line 0 is above).
149
+ lines = lines.slice();
150
+ lines[0] = "changed-above-viewport";
151
+ anyTui.doRender();
152
+
153
+ const clampWrites = writes.slice(writeCountAfterFirstRender).join("");
154
+ assert.ok(
155
+ !clampWrites.includes("\x1b[2J"),
156
+ "firstChanged-above-viewport must not emit \\x1b[2J — that causes the bottom panel to flash",
157
+ );
72
158
  });
73
159
 
74
160
  it("does not swallow a bare Escape keypress while waiting for the cell-size response", () => {
@@ -53,6 +53,9 @@ export class Loader extends Text {
53
53
  this.ui.requestRender();
54
54
  }
55
55
  }, 80);
56
+ // The loader animation is purely cosmetic — it must never keep the Node
57
+ // event loop alive on its own (otherwise a process can hang on exit).
58
+ this.intervalId.unref?.();
56
59
  // Trigger initial render
57
60
  if (this.ui) {
58
61
  this.ui.requestRender();
@@ -58,6 +58,10 @@ export interface Terminal {
58
58
  export class ProcessTerminal implements Terminal {
59
59
  private static _vtHandles: { GetConsoleMode: any; SetConsoleMode: any; handle: any } | null = null;
60
60
  private wasRaw = false;
61
+ private started = false;
62
+ private readonly processExitHandler = () => {
63
+ this.stop();
64
+ };
61
65
  private inputHandler?: (data: string) => void;
62
66
  private resizeHandler?: () => void;
63
67
  private _kittyProtocolActive = false;
@@ -81,6 +85,8 @@ export class ProcessTerminal implements Terminal {
81
85
  if (!this.isTTY) {
82
86
  return;
83
87
  }
88
+ if (this.started) return;
89
+ this.started = true;
84
90
 
85
91
  this.inputHandler = onInput;
86
92
  this.resizeHandler = onResize;
@@ -115,6 +121,7 @@ export class ProcessTerminal implements Terminal {
115
121
  // The query handler intercepts input temporarily, then installs the user's handler
116
122
  // See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
117
123
  this.queryAndEnableKittyProtocol();
124
+ process.once("exit", this.processExitHandler);
118
125
  }
119
126
 
120
127
  /**
@@ -267,6 +274,10 @@ export class ProcessTerminal implements Terminal {
267
274
  }
268
275
 
269
276
  stop(): void {
277
+ if (!this.started) return;
278
+ this.started = false;
279
+ process.removeListener("exit", this.processExitHandler);
280
+
270
281
  // Disable bracketed paste mode
271
282
  process.stdout.write("\x1b[?2004l");
272
283
 
@@ -261,6 +261,8 @@ export class TUI extends Container {
261
261
  private previousViewportTop = 0; // Track previous viewport top for resize-aware cursor moves
262
262
  private fullRedrawCount = 0;
263
263
  private stopped = false;
264
+ private readonly useSynchronizedOutput =
265
+ process.platform !== "win32" && process.env.PI_DISABLE_SYNC_OUTPUT !== "1";
264
266
  private _lastRenderedComponents: string[] | null = null;
265
267
 
266
268
  // Overlay stack for modal components rendered on top of base content
@@ -673,7 +675,7 @@ export class TUI extends Container {
673
675
  // Helper to clear scrollback and viewport and render all new lines
674
676
  const fullRender = (clear: boolean): void => {
675
677
  this.fullRedrawCount += 1;
676
- let buffer = "\x1b[?2026h"; // Begin synchronized output
678
+ let buffer = this.useSynchronizedOutput ? "\x1b[?2026h" : ""; // Begin synchronized output
677
679
  const startRow = Math.max(1, height - Math.max(1, newLines.length) + 1);
678
680
  if (clear) {
679
681
  // Clear viewport (scrollback preserved) and anchor the rendered
@@ -693,7 +695,7 @@ export class TUI extends Container {
693
695
  }
694
696
  buffer += line;
695
697
  }
696
- buffer += "\x1b[?2026l"; // End synchronized output
698
+ if (this.useSynchronizedOutput) buffer += "\x1b[?2026l"; // End synchronized output
697
699
  this.terminal.write(buffer);
698
700
  this.cursorRow = Math.max(0, newLines.length - 1);
699
701
  this.hardwareCursorRow = this.cursorRow;
@@ -733,17 +735,60 @@ export class TUI extends Container {
733
735
  }
734
736
 
735
737
  if (
736
- newLines.length !== this.previousLines.length &&
738
+ newLines.length < this.previousLines.length &&
737
739
  (newLines.length <= height || this.previousLines.length <= height)
738
740
  ) {
739
- logRedraw(`bottom-anchored short block resized (${this.previousLines.length} -> ${newLines.length})`);
741
+ logRedraw(`bottom-anchored short block shrunk (${this.previousLines.length} -> ${newLines.length})`);
740
742
  fullRender(true);
741
743
  return;
742
744
  }
743
745
 
744
- if (newLines.length < this.previousLines.length && newLines.length > height) {
745
- logRedraw(`bottom-anchored tall block shrunk (${this.previousLines.length} -> ${newLines.length})`);
746
- fullRender(true);
746
+ // Tall→tall shrink with viewport baseline shift. Both buffers fill the
747
+ // viewport, but newLines is shorter, so the viewport baseline must move
748
+ // from (previousLines.length - height) down to (newLines.length - height).
749
+ // The differential render below would see no diff in the overlapping
750
+ // indices (content[20..39] is identical between frames) and would leave
751
+ // the screen showing stale rows from the old viewport.
752
+ //
753
+ // Repaint the visible viewport in place without \x1b[2J — the four-pass
754
+ // flicker fix exists exactly to avoid that full-screen clear — then reset
755
+ // maxLinesRendered and previousViewportTop so subsequent diffs anchor
756
+ // against the new baseline.
757
+ if (
758
+ this.previousLines.length > height &&
759
+ newLines.length > height &&
760
+ newLines.length < this.previousLines.length &&
761
+ this.overlayStack.length === 0
762
+ ) {
763
+ logRedraw(`tall→tall shrink viewport realign (${this.previousLines.length} -> ${newLines.length})`);
764
+ const newViewportTop = getViewportTop(newLines.length);
765
+ const currentScreenRow = Math.max(0, hardwareCursorRow - prevViewportTop);
766
+ let buffer = this.useSynchronizedOutput ? "\x1b[?2026h" : "";
767
+ if (currentScreenRow > 0) {
768
+ buffer += `\x1b[${currentScreenRow}A`;
769
+ }
770
+ buffer += "\r";
771
+ for (let i = 0; i < height; i++) {
772
+ const idx = newViewportTop + i;
773
+ if (i > 0) buffer += "\r\n";
774
+ buffer += "\x1b[2K";
775
+ let line = newLines[idx] ?? "";
776
+ if (!isImageLine(line) && visibleWidth(line) > width) {
777
+ line = truncateToWidth(line, width);
778
+ }
779
+ buffer += line;
780
+ }
781
+ if (this.useSynchronizedOutput) buffer += "\x1b[?2026l";
782
+ this.terminal.write(buffer);
783
+ this.cursorRow = newLines.length - 1;
784
+ this.hardwareCursorRow = newLines.length - 1;
785
+ this.maxLinesRendered = newLines.length;
786
+ this.previousViewportTop = newViewportTop;
787
+ this.positionHardwareCursor(cursorPos, newLines.length);
788
+ this.previousLines = newLines;
789
+ this.previousWidth = width;
790
+ this.previousHeight = height;
791
+ this._shrinkDebounceActive = false;
747
792
  return;
748
793
  }
749
794
 
@@ -794,7 +839,7 @@ export class TUI extends Container {
794
839
  }
795
840
  lastChanged = newLines.length - 1;
796
841
  }
797
- const appendStart = appendedLines && firstChanged === this.previousLines.length && firstChanged > 0;
842
+ let appendStart = appendedLines && firstChanged === this.previousLines.length && firstChanged > 0;
798
843
 
799
844
  // No changes - but still need to update hardware cursor position if it moved
800
845
  if (firstChanged === -1) {
@@ -807,7 +852,7 @@ export class TUI extends Container {
807
852
  // All changes are in deleted lines (nothing to render, just clear)
808
853
  if (firstChanged >= newLines.length) {
809
854
  if (this.previousLines.length > newLines.length) {
810
- let buffer = "\x1b[?2026h";
855
+ let buffer = this.useSynchronizedOutput ? "\x1b[?2026h" : "";
811
856
  // Move to end of new content (clamp to 0 for empty content)
812
857
  const targetRow = Math.max(0, newLines.length - 1);
813
858
  const lineDiff = computeLineDiff(targetRow);
@@ -831,7 +876,7 @@ export class TUI extends Container {
831
876
  if (extraLines > 0) {
832
877
  buffer += `\x1b[${extraLines}A`;
833
878
  }
834
- buffer += "\x1b[?2026l";
879
+ if (this.useSynchronizedOutput) buffer += "\x1b[?2026l";
835
880
  this.terminal.write(buffer);
836
881
  this.cursorRow = targetRow;
837
882
  this.hardwareCursorRow = targetRow;
@@ -844,19 +889,34 @@ export class TUI extends Container {
844
889
  return;
845
890
  }
846
891
 
847
- // Check if firstChanged is above what was previously visible
848
- // Use previousLines.length (not maxLinesRendered) to avoid false positives after content shrinks
892
+ // Check if firstChanged is above what was previously visible.
893
+ // Use previousLines.length (not maxLinesRendered) to avoid false positives after content shrinks.
849
894
  const previousContentViewportTop = getViewportTop(this.previousLines.length);
895
+ let clampedToViewport = false;
850
896
  if (firstChanged < previousContentViewportTop) {
851
- // First change is above previous viewport - need full re-render
852
- logRedraw(`firstChanged < viewportTop (${firstChanged} < ${previousContentViewportTop})`);
853
- fullRender(true);
854
- return;
897
+ // First change is above the viewport. Avoid a full screen clear (\x1b[2J)
898
+ // which causes the bottom panel to flicker. Instead redraw from the actual
899
+ // viewport top down through the bottom of new content so every visible row
900
+ // gets the correct line, even if the viewport shifted (content shrank).
901
+ //
902
+ // Pick the smaller of the two viewport tops so any row currently on screen
903
+ // is covered. Force lastChanged to the end of new content so the render loop
904
+ // repaints the bottom rows that may now hold stale content from the previous
905
+ // frame (the case that caused "empty screen until next tick" after the clamp).
906
+ const newViewportTop = getViewportTop(newLines.length);
907
+ const clampedFirst = Math.max(0, Math.min(previousContentViewportTop, newViewportTop));
908
+ logRedraw(
909
+ `firstChanged < viewportTop (${firstChanged} < ${previousContentViewportTop}) — repaint from ${clampedFirst}`,
910
+ );
911
+ firstChanged = clampedFirst;
912
+ lastChanged = Math.max(lastChanged, newLines.length - 1);
913
+ appendStart = false;
914
+ clampedToViewport = true;
855
915
  }
856
916
 
857
917
  // Render from first changed line to end
858
918
  // Build buffer with all updates wrapped in synchronized output
859
- let buffer = "\x1b[?2026h"; // Begin synchronized output
919
+ let buffer = this.useSynchronizedOutput ? "\x1b[?2026h" : ""; // Begin synchronized output
860
920
  const prevViewportBottom = prevViewportTop + height - 1;
861
921
  const moveTargetRow = appendStart ? firstChanged - 1 : firstChanged;
862
922
  if (moveTargetRow > prevViewportBottom) {
@@ -899,23 +959,38 @@ export class TUI extends Container {
899
959
  // Track where cursor ended up after rendering
900
960
  let finalCursorRow = renderEnd;
901
961
 
902
- // If we had more lines before, clear them and move cursor back
903
- if (this.previousLines.length > newLines.length) {
904
- // Move to end of new content first if we stopped before it
905
- if (renderEnd < newLines.length - 1) {
906
- const moveDown = newLines.length - 1 - renderEnd;
907
- buffer += `\x1b[${moveDown}B`;
908
- finalCursorRow = newLines.length - 1;
909
- }
910
- const extraLines = this.previousLines.length - newLines.length;
911
- for (let i = newLines.length; i < this.previousLines.length; i++) {
912
- buffer += "\r\n\x1b[2K";
962
+ // If we had more lines before, clear ghost lines but only when they are
963
+ // actually visible. For tall buffers (both counts > height) the viewport shifts
964
+ // up so the differential render already overwrites the old bottom rows; emitting
965
+ // \r\n at screen-bottom would cause spurious terminal scrolling.
966
+ //
967
+ // Also skip ghost clearing when the clamp-to-viewport path was taken: that path
968
+ // renders from clampedFirst through newLines.length-1, filling the entire visible
969
+ // viewport. There are no ghost lines below renderEnd, and the local `viewportTop`
970
+ // is based on the stale (larger) maxLinesRendered, so the renderEndScreenRow
971
+ // check below would compute a negative value and incorrectly fire the cleanup —
972
+ // which then emits \r\n past screen-bottom and scrolls correct lines into
973
+ // scrollback while filling the viewport with blanks.
974
+ if (this.previousLines.length > newLines.length && !clampedToViewport) {
975
+ const renderEndScreenRow = renderEnd - viewportTop;
976
+ const ghostLinesVisible = renderEndScreenRow < height - 1;
977
+ if (ghostLinesVisible) {
978
+ // Move to end of new content first if we stopped before it
979
+ if (renderEnd < newLines.length - 1) {
980
+ const moveDown = newLines.length - 1 - renderEnd;
981
+ buffer += `\x1b[${moveDown}B`;
982
+ finalCursorRow = newLines.length - 1;
983
+ }
984
+ const extraLines = this.previousLines.length - newLines.length;
985
+ for (let i = newLines.length; i < this.previousLines.length; i++) {
986
+ buffer += "\r\n\x1b[2K";
987
+ }
988
+ // Move cursor back to end of new content
989
+ buffer += `\x1b[${extraLines}A`;
913
990
  }
914
- // Move cursor back to end of new content
915
- buffer += `\x1b[${extraLines}A`;
916
991
  }
917
992
 
918
- buffer += "\x1b[?2026l"; // End synchronized output
993
+ if (this.useSynchronizedOutput) buffer += "\x1b[?2026l"; // End synchronized output
919
994
 
920
995
  if (process.env.PI_TUI_DEBUG === "1") {
921
996
  const debugDir = path.join(os.tmpdir(), "tui");
@@ -954,8 +1029,16 @@ export class TUI extends Container {
954
1029
  // hardwareCursorRow tracks actual terminal cursor position (for movement)
955
1030
  this.cursorRow = Math.max(0, newLines.length - 1);
956
1031
  this.hardwareCursorRow = finalCursorRow;
957
- // Track terminal's working area (grows but doesn't shrink unless cleared)
958
- this.maxLinesRendered = Math.max(this.maxLinesRendered, newLines.length);
1032
+ // Track terminal's working area (grows but doesn't shrink unless cleared).
1033
+ // Exception: when the clamp-to-viewport path repainted shrunk content, the
1034
+ // visible viewport now anchors to newLines.length, so subsequent
1035
+ // computeLineDiff calls need viewportTop = newLines.length - height.
1036
+ // Without this reset, hardwareCursorRow's physical row goes negative.
1037
+ if (clampedToViewport && newLines.length < this.maxLinesRendered) {
1038
+ this.maxLinesRendered = newLines.length;
1039
+ } else {
1040
+ this.maxLinesRendered = Math.max(this.maxLinesRendered, newLines.length);
1041
+ }
959
1042
  this.previousViewportTop = getViewportTop(this.maxLinesRendered);
960
1043
 
961
1044
  // Position hardware cursor for IME