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.
- package/README.md +93 -18
- package/dist/cli.js +20 -9
- package/dist/headless-ui.js +13 -6
- package/dist/headless.js +9 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +44 -6
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +1 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +122 -40
- package/dist/resources/extensions/gsd/auto/orchestrator.js +15 -4
- package/dist/resources/extensions/gsd/auto/phases.js +146 -49
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -1
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-budget.js +9 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +72 -5
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +185 -30
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +329 -137
- package/dist/resources/extensions/gsd/auto-prompts.js +36 -10
- package/dist/resources/extensions/gsd/auto-recovery.js +82 -16
- package/dist/resources/extensions/gsd/auto-start.js +99 -16
- package/dist/resources/extensions/gsd/auto-timers.js +11 -3
- package/dist/resources/extensions/gsd/auto-verification.js +146 -34
- package/dist/resources/extensions/gsd/auto-worktree.js +185 -26
- package/dist/resources/extensions/gsd/auto.js +135 -74
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +65 -10
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +13 -10
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +14 -4
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +24 -9
- package/dist/resources/extensions/gsd/clean-root-preflight.js +267 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +2 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +9 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -4
- package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +55 -7
- package/dist/resources/extensions/gsd/db/auto-workers.js +30 -0
- package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/db-base-schema.js +2 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
- package/dist/resources/extensions/gsd/db-task-slice-rows.js +2 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +46 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +74 -3
- package/dist/resources/extensions/gsd/doctor-proactive.js +14 -2
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/forensics.js +10 -3
- package/dist/resources/extensions/gsd/git-conflict-state.js +21 -0
- package/dist/resources/extensions/gsd/git-service.js +152 -15
- package/dist/resources/extensions/gsd/gsd-db.js +76 -33
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
- package/dist/resources/extensions/gsd/guided-flow.js +110 -117
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/init-wizard.js +17 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +14 -11
- package/dist/resources/extensions/gsd/mcp-filter.js +58 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +121 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +57 -14
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -0
- package/dist/resources/extensions/gsd/paths.js +4 -0
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +9 -3
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -9
- package/dist/resources/extensions/gsd/pre-execution-checks.js +54 -19
- package/dist/resources/extensions/gsd/preferences-mcp.js +19 -0
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- package/dist/resources/extensions/gsd/preferences-types.js +3 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +147 -0
- package/dist/resources/extensions/gsd/preferences.js +35 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/forensics.md +3 -3
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
- package/dist/resources/extensions/gsd/repo-identity.js +39 -22
- package/dist/resources/extensions/gsd/repository-registry.js +44 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +2 -0
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +42 -18
- package/dist/resources/extensions/gsd/session-lock.js +15 -2
- package/dist/resources/extensions/gsd/slice-parallel-conflict.js +2 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +84 -5
- package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/state.js +28 -7
- package/dist/resources/extensions/gsd/status-guards.js +14 -2
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/templates/plan.md +9 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -9
- package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -10
- package/dist/resources/extensions/gsd/tools/exec-tool.js +87 -5
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +151 -15
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +32 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +185 -40
- package/dist/resources/extensions/gsd/tui/render-kit.js +33 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +2 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +69 -17
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +142 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/watch/header-renderer.js +34 -25
- package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +86 -19
- package/dist/resources/extensions/gsd/worktree-manager.js +11 -2
- package/dist/resources/extensions/gsd/worktree-safety.js +43 -4
- package/dist/resources/extensions/gsd/worktree-state-projection.js +31 -0
- package/dist/resources/extensions/gsd/worktree-telemetry.js +32 -0
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/shared/interview-ui.js +6 -4
- package/dist/resources/extensions/shared/next-action-ui.js +13 -5
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -0
- package/dist/resources/skills/forensics/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
- package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +7 -8
- package/package.json +4 -4
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +13 -4
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/src/__tests__/stream-process.test.mjs +32 -12
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +5 -6
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +6 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +7 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +14 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +8 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +16 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +82 -97
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -7
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +23 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +7 -2
- package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +91 -102
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +15 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +9 -9
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js +24 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +72 -4
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +3 -0
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +12 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +117 -33
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/loader.test.ts +30 -0
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +90 -4
- package/packages/pi-tui/src/components/loader.ts +3 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/src/tui.ts +116 -33
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +52 -6
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +49 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +19 -6
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +1 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +123 -40
- package/src/resources/extensions/gsd/auto/orchestrator.ts +15 -4
- package/src/resources/extensions/gsd/auto/phases.ts +172 -60
- package/src/resources/extensions/gsd/auto/session.ts +16 -0
- package/src/resources/extensions/gsd/auto/types.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-runner-events.ts +6 -2
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-budget.ts +11 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +78 -5
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +208 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +369 -148
- package/src/resources/extensions/gsd/auto-prompts.ts +36 -13
- package/src/resources/extensions/gsd/auto-recovery.ts +86 -13
- package/src/resources/extensions/gsd/auto-start.ts +109 -14
- package/src/resources/extensions/gsd/auto-timers.ts +10 -3
- package/src/resources/extensions/gsd/auto-verification.ts +174 -42
- package/src/resources/extensions/gsd/auto-worktree.ts +202 -30
- package/src/resources/extensions/gsd/auto.ts +172 -81
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +66 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -10
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +13 -4
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +27 -10
- package/src/resources/extensions/gsd/clean-root-preflight.ts +284 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +8 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +17 -4
- package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +55 -6
- package/src/resources/extensions/gsd/db/auto-workers.ts +37 -0
- package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/db-base-schema.ts +2 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
- package/src/resources/extensions/gsd/db-task-slice-rows.ts +4 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +60 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +73 -3
- package/src/resources/extensions/gsd/doctor-proactive.ts +18 -2
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/forensics.ts +9 -3
- package/src/resources/extensions/gsd/git-conflict-state.ts +23 -0
- package/src/resources/extensions/gsd/git-service.ts +182 -16
- package/src/resources/extensions/gsd/gsd-db.ts +80 -31
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +142 -134
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/init-wizard.ts +17 -2
- package/src/resources/extensions/gsd/journal.ts +8 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +14 -11
- package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +139 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +63 -14
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -0
- package/src/resources/extensions/gsd/paths.ts +5 -0
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +10 -2
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -12
- package/src/resources/extensions/gsd/pre-execution-checks.ts +67 -19
- package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -4
- package/src/resources/extensions/gsd/preferences-types.ts +35 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +154 -0
- package/src/resources/extensions/gsd/preferences.ts +39 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/forensics.md +3 -3
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
- package/src/resources/extensions/gsd/repo-identity.ts +45 -25
- package/src/resources/extensions/gsd/repository-registry.ts +77 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +2 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +54 -19
- package/src/resources/extensions/gsd/session-lock.ts +15 -2
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +2 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +75 -3
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/state.ts +33 -7
- package/src/resources/extensions/gsd/status-guards.ts +16 -2
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/templates/plan.md +9 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +775 -34
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +245 -28
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +136 -13
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-workers.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +170 -3
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +32 -4
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +55 -2
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +60 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +104 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +61 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +139 -1
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +68 -1
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +140 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +99 -1
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +36 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +226 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +5 -21
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +49 -3
- package/src/resources/extensions/gsd/tests/journal.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +21 -40
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +80 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +343 -3
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +105 -3
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +42 -1
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
- package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +94 -2
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +17 -1
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +131 -9
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +42 -1
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +188 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +153 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +73 -2
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +59 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +18 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +57 -10
- package/src/resources/extensions/gsd/tools/exec-tool.ts +98 -5
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +172 -12
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +31 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +166 -17
- package/src/resources/extensions/gsd/tui/render-kit.ts +44 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +3 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +86 -19
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +170 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +35 -24
- package/src/resources/extensions/gsd/workflow-manifest.ts +2 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +98 -20
- package/src/resources/extensions/gsd/worktree-manager.ts +14 -2
- package/src/resources/extensions/gsd/worktree-safety.ts +57 -10
- package/src/resources/extensions/gsd/worktree-state-projection.ts +43 -0
- package/src/resources/extensions/gsd/worktree-telemetry.ts +39 -0
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/shared/interview-ui.ts +6 -4
- package/src/resources/extensions/shared/next-action-ui.ts +11 -5
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +15 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +32 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/src/resources/skills/forensics/SKILL.md +1 -1
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → w_ikFkx_-OHxisG9xjz4u}/_buildManifest.js +0 -0
- /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
|
|
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
|
-
|
|
71
|
-
assert.ok(
|
|
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
|
|
738
|
+
newLines.length < this.previousLines.length &&
|
|
737
739
|
(newLines.length <= height || this.previousLines.length <= height)
|
|
738
740
|
) {
|
|
739
|
-
logRedraw(`bottom-anchored short block
|
|
741
|
+
logRedraw(`bottom-anchored short block shrunk (${this.previousLines.length} -> ${newLines.length})`);
|
|
740
742
|
fullRender(true);
|
|
741
743
|
return;
|
|
742
744
|
}
|
|
743
745
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
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
|
-
|
|
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
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
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
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
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
|
-
|
|
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
|