gsd-pi 2.82.0-dev.ed17d078d → 3.0.0-dev.1b44e695b
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 +134 -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 +66 -1
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +144 -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 +170 -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 +10 -2
- 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 +46 -1
- 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-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-types.js +3 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +147 -0
- package/dist/resources/extensions/gsd/preferences.js +6 -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/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/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 +7 -7
- 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 +7 -7
- 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/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/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/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/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__/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 +45 -2
- package/packages/pi-tui/dist/__tests__/tui.test.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.map +1 -1
- package/packages/pi-tui/dist/tui.js +106 -27
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +59 -2
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/src/tui.ts +108 -27
- 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 +160 -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 +72 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +164 -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 +174 -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 +11 -3
- 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 +45 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +1 -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-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-types.ts +35 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +154 -0
- package/src/resources/extensions/gsd/preferences.ts +9 -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 +107 -2
- 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 +111 -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-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/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-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/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/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/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 → Z8H5evS-hDo0qdP22XJPA}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → Z8H5evS-hDo0qdP22XJPA}/_ssgManifest.js +0 -0
|
@@ -427,22 +427,38 @@ function hasProjectState(externalPath: string): boolean {
|
|
|
427
427
|
*
|
|
428
428
|
* Returns the resolved external path (may differ from the computed identity).
|
|
429
429
|
*/
|
|
430
|
-
function resolveExternalPathWithRecovery(projectPath: string): string {
|
|
431
|
-
const
|
|
430
|
+
function resolveExternalPathWithRecovery(projectPath: string): { path: string; identity: string } {
|
|
431
|
+
const base = process.env.GSD_STATE_DIR || gsdHome();
|
|
432
432
|
const computedId = repoIdentity(projectPath);
|
|
433
|
+
const computedPath = join(base, "projects", computedId);
|
|
434
|
+
const computedHasState = hasProjectState(computedPath);
|
|
435
|
+
const markerId = readGsdIdMarker(projectPath);
|
|
436
|
+
const markerPath = markerId ? join(base, "projects", markerId) : null;
|
|
437
|
+
const markerHasState = markerPath ? hasProjectState(markerPath) : false;
|
|
438
|
+
|
|
439
|
+
// Split-brain guard: when marker and computed identities disagree and both
|
|
440
|
+
// directories contain state, prefer the marker-backed directory. This keeps
|
|
441
|
+
// all writers anchored to a single canonical project identity even if a
|
|
442
|
+
// transient identity computation produced a stale computed hash.
|
|
443
|
+
if (
|
|
444
|
+
markerId
|
|
445
|
+
&& markerPath
|
|
446
|
+
&& markerId !== computedId
|
|
447
|
+
&& markerHasState
|
|
448
|
+
&& computedHasState
|
|
449
|
+
) {
|
|
450
|
+
return { path: markerPath, identity: markerId };
|
|
451
|
+
}
|
|
433
452
|
|
|
434
453
|
// Check if computed path already has state — fast path, no recovery needed.
|
|
435
|
-
if (
|
|
436
|
-
return computedPath;
|
|
454
|
+
if (computedHasState) {
|
|
455
|
+
return { path: computedPath, identity: computedId };
|
|
437
456
|
}
|
|
438
457
|
|
|
439
458
|
// Check for .gsd-id marker from a previous location.
|
|
440
|
-
|
|
441
|
-
if (markerId && markerId !== computedId) {
|
|
459
|
+
if (markerId && markerPath && markerId !== computedId) {
|
|
442
460
|
// The marker points to a different identity — the repo was likely moved.
|
|
443
|
-
|
|
444
|
-
const markerPath = join(base, "projects", markerId);
|
|
445
|
-
if (hasProjectState(markerPath)) {
|
|
461
|
+
if (markerHasState) {
|
|
446
462
|
// Recover: use the old state directory and update the marker to the new identity.
|
|
447
463
|
// Move the state from the old hash dir to the new one so future lookups work
|
|
448
464
|
// without the marker.
|
|
@@ -465,12 +481,12 @@ function resolveExternalPathWithRecovery(projectPath: string): string {
|
|
|
465
481
|
try { rmSync(markerPath, { recursive: true, force: true }); } catch { /* non-fatal */ }
|
|
466
482
|
} catch {
|
|
467
483
|
// If migration fails, just point at the old directory.
|
|
468
|
-
return markerPath;
|
|
484
|
+
return { path: markerPath, identity: markerId };
|
|
469
485
|
}
|
|
470
486
|
}
|
|
471
487
|
}
|
|
472
488
|
|
|
473
|
-
return computedPath;
|
|
489
|
+
return { path: computedPath, identity: computedId };
|
|
474
490
|
}
|
|
475
491
|
|
|
476
492
|
// ─── Symlink Management ─────────────────────────────────────────────────────
|
|
@@ -489,20 +505,21 @@ function resolveExternalPathWithRecovery(projectPath: string): string {
|
|
|
489
505
|
* Returns the resolved external path.
|
|
490
506
|
*/
|
|
491
507
|
export function ensureGsdSymlink(projectPath: string): string {
|
|
492
|
-
const result = ensureGsdSymlinkCore(projectPath);
|
|
508
|
+
const { path: result, identity } = ensureGsdSymlinkCore(projectPath);
|
|
493
509
|
|
|
494
510
|
// Write .gsd-id marker so future relocations can recover this state (#2750).
|
|
495
511
|
// Only write for the project root (not subdirectories or worktrees that
|
|
496
512
|
// delegate to a parent .gsd).
|
|
497
513
|
if (!isInsideWorktree(projectPath)) {
|
|
498
|
-
writeGsdIdMarker(projectPath,
|
|
514
|
+
writeGsdIdMarker(projectPath, identity);
|
|
499
515
|
}
|
|
500
516
|
|
|
501
517
|
return result;
|
|
502
518
|
}
|
|
503
519
|
|
|
504
|
-
function ensureGsdSymlinkCore(projectPath: string): string {
|
|
505
|
-
const
|
|
520
|
+
function ensureGsdSymlinkCore(projectPath: string): { path: string; identity: string } {
|
|
521
|
+
const resolved = resolveExternalPathWithRecovery(projectPath);
|
|
522
|
+
const externalPath = resolved.path;
|
|
506
523
|
const localGsd = join(projectPath, ".gsd");
|
|
507
524
|
const inWorktree = isInsideWorktree(projectPath);
|
|
508
525
|
|
|
@@ -519,7 +536,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
519
536
|
const localGsdNormalized = normalizeForGuard(localGsd);
|
|
520
537
|
const gsdHomeNorm = normalizeForGuard(gsdHome());
|
|
521
538
|
if (localGsdNormalized === gsdHomeNorm) {
|
|
522
|
-
return localGsd;
|
|
539
|
+
return { path: localGsd, identity: resolved.identity };
|
|
523
540
|
}
|
|
524
541
|
|
|
525
542
|
// Guard: If projectPath is a plain subdirectory (not a worktree) of a git
|
|
@@ -538,7 +555,10 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
538
555
|
try {
|
|
539
556
|
const rootStat = lstatSync(rootGsd);
|
|
540
557
|
if (rootStat.isSymbolicLink() || rootStat.isDirectory()) {
|
|
541
|
-
return
|
|
558
|
+
return {
|
|
559
|
+
path: rootStat.isSymbolicLink() ? realpathSync(rootGsd) : rootGsd,
|
|
560
|
+
identity: resolved.identity,
|
|
561
|
+
};
|
|
542
562
|
}
|
|
543
563
|
} catch {
|
|
544
564
|
// Fall through to normal logic if we can't stat root .gsd
|
|
@@ -560,12 +580,12 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
560
580
|
// Write repo metadata once so cleanup commands can identify this directory later.
|
|
561
581
|
writeRepoMeta(externalPath, getRemoteUrl(projectPath), resolveGitRoot(projectPath));
|
|
562
582
|
|
|
563
|
-
const replaceWithSymlink = (): string => {
|
|
583
|
+
const replaceWithSymlink = (): { path: string; identity: string } => {
|
|
564
584
|
rmSync(localGsd, { recursive: true, force: true });
|
|
565
585
|
// Defensive: remove any residual entry (e.g. dangling symlink) before creating.
|
|
566
586
|
try { unlinkSync(localGsd); } catch { /* already gone */ }
|
|
567
587
|
symlinkSync(externalPath, localGsd, "junction");
|
|
568
|
-
return
|
|
588
|
+
return resolved;
|
|
569
589
|
};
|
|
570
590
|
|
|
571
591
|
// Check for dangling symlinks (e.g. after relocation recovery removed the old
|
|
@@ -585,7 +605,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
585
605
|
// Defensive: remove any residual entry to avoid EEXIST race (#2750).
|
|
586
606
|
try { unlinkSync(localGsd); } catch { /* nothing to remove */ }
|
|
587
607
|
symlinkSync(externalPath, localGsd, "junction");
|
|
588
|
-
return
|
|
608
|
+
return resolved;
|
|
589
609
|
}
|
|
590
610
|
|
|
591
611
|
try {
|
|
@@ -595,7 +615,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
595
615
|
// Already a symlink — verify it points to the right place
|
|
596
616
|
const target = realpathSync(localGsd);
|
|
597
617
|
if (target === externalPath) {
|
|
598
|
-
return
|
|
618
|
+
return resolved; // correct symlink, no-op
|
|
599
619
|
}
|
|
600
620
|
// In a worktree, mismatched symlinks are always stale. Heal them so
|
|
601
621
|
// the worktree points at the same external state dir as the main repo.
|
|
@@ -620,11 +640,11 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
620
640
|
return replaceWithSymlink();
|
|
621
641
|
} catch {
|
|
622
642
|
// Migration failed — preserve old symlink
|
|
623
|
-
return target;
|
|
643
|
+
return { path: target, identity: resolved.identity };
|
|
624
644
|
}
|
|
625
645
|
}
|
|
626
646
|
// Outside worktrees, preserve custom overrides or legacy symlinks.
|
|
627
|
-
return target;
|
|
647
|
+
return { path: target, identity: resolved.identity };
|
|
628
648
|
}
|
|
629
649
|
|
|
630
650
|
if (stat.isDirectory()) {
|
|
@@ -632,13 +652,13 @@ function ensureGsdSymlinkCore(projectPath: string): string {
|
|
|
632
652
|
// In worktrees, keep the directory in place and let syncGsdStateToWorktree
|
|
633
653
|
// refresh its contents. Replacing a git-tracked .gsd directory with a
|
|
634
654
|
// symlink makes git think tracked planning files were deleted.
|
|
635
|
-
return localGsd;
|
|
655
|
+
return { path: localGsd, identity: resolved.identity };
|
|
636
656
|
}
|
|
637
657
|
} catch {
|
|
638
658
|
// lstat failed — path exists but we can't stat it
|
|
639
659
|
}
|
|
640
660
|
|
|
641
|
-
return localGsd;
|
|
661
|
+
return { path: localGsd, identity: resolved.identity };
|
|
642
662
|
}
|
|
643
663
|
|
|
644
664
|
// ─── Worktree Detection ─────────────────────────────────────────────────────
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// GSD-2 + Repository registry seam for parent workspace multi-repo resolution.
|
|
2
|
+
|
|
3
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
4
|
+
import type { GSDPreferences, WorkspacePreferences, WorkspaceRepositoryPreference } from "./preferences-types.js";
|
|
5
|
+
import { resolveGsdPathContract } from "./paths.js";
|
|
6
|
+
|
|
7
|
+
export interface RegisteredRepository {
|
|
8
|
+
id: string;
|
|
9
|
+
root: string;
|
|
10
|
+
role?: string;
|
|
11
|
+
verification?: string[];
|
|
12
|
+
commitPolicy?: "auto" | "skip";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface RepositoryRegistry {
|
|
16
|
+
projectRoot: string;
|
|
17
|
+
mode: "project" | "parent";
|
|
18
|
+
repositories: RegisteredRepository[];
|
|
19
|
+
byId: ReadonlyMap<string, RegisteredRepository>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function assertInsideProjectRoot(projectRoot: string, candidateRoot: string, repoId: string): void {
|
|
23
|
+
const rel = relative(projectRoot, candidateRoot);
|
|
24
|
+
if (rel === "") return;
|
|
25
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
26
|
+
throw new Error(`workspace.repositories.${repoId}.path resolves outside project root: ${candidateRoot}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveRepositoryRoot(
|
|
31
|
+
projectRoot: string,
|
|
32
|
+
repoId: string,
|
|
33
|
+
repo: WorkspaceRepositoryPreference,
|
|
34
|
+
): RegisteredRepository {
|
|
35
|
+
const root = resolve(projectRoot, repo.path);
|
|
36
|
+
assertInsideProjectRoot(projectRoot, root, repoId);
|
|
37
|
+
return {
|
|
38
|
+
id: repoId,
|
|
39
|
+
root,
|
|
40
|
+
role: repo.role,
|
|
41
|
+
verification: repo.verification,
|
|
42
|
+
commitPolicy: repo.commit_policy,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createRepositoryRegistry(
|
|
47
|
+
basePath: string,
|
|
48
|
+
workspacePrefs?: WorkspacePreferences,
|
|
49
|
+
): RepositoryRegistry {
|
|
50
|
+
const contract = resolveGsdPathContract(basePath);
|
|
51
|
+
const projectRoot = contract.projectRoot;
|
|
52
|
+
const mode = workspacePrefs?.mode ?? "project";
|
|
53
|
+
const repoMap = new Map<string, RegisteredRepository>();
|
|
54
|
+
|
|
55
|
+
// Backward-compatible default for single-repo projects.
|
|
56
|
+
// Explicit workspacePrefs?.repositories entries can override "project"
|
|
57
|
+
// via resolveRepositoryRoot to customize role/verification/commit policy.
|
|
58
|
+
repoMap.set("project", { id: "project", root: projectRoot });
|
|
59
|
+
|
|
60
|
+
for (const [repoId, repoConfig] of Object.entries(workspacePrefs?.repositories ?? {})) {
|
|
61
|
+
repoMap.set(repoId, resolveRepositoryRoot(projectRoot, repoId, repoConfig));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
projectRoot,
|
|
66
|
+
mode,
|
|
67
|
+
repositories: Array.from(repoMap.values()),
|
|
68
|
+
byId: repoMap,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createRepositoryRegistryFromPreferences(
|
|
73
|
+
basePath: string,
|
|
74
|
+
preferences?: Pick<GSDPreferences, "workspace">,
|
|
75
|
+
): RepositoryRegistry {
|
|
76
|
+
return createRepositoryRegistry(basePath, preferences?.workspace);
|
|
77
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
/**
|
|
2
3
|
* Evidence cross-reference for auto-mode safety harness.
|
|
3
4
|
* Compares the LLM's claimed verification evidence (command + exitCode)
|
|
@@ -14,6 +15,7 @@ export interface ClaimedEvidence {
|
|
|
14
15
|
command: string;
|
|
15
16
|
exitCode: number;
|
|
16
17
|
verdict: string;
|
|
18
|
+
createdAt?: string;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export interface EvidenceMismatch {
|
|
@@ -40,7 +42,7 @@ export function crossReferenceEvidence(
|
|
|
40
42
|
);
|
|
41
43
|
const mismatches: EvidenceMismatch[] = [];
|
|
42
44
|
|
|
43
|
-
for (const claimed of claimedEvidence) {
|
|
45
|
+
for (const claimed of latestClaimBatch(claimedEvidence)) {
|
|
44
46
|
// Skip coerced entries — they're already flagged with exitCode: -1
|
|
45
47
|
// and verdict: "unknown (coerced from string)" by db-tools.ts
|
|
46
48
|
if (claimed.verdict?.includes("coerced from string")) continue;
|
|
@@ -49,10 +51,12 @@ export function crossReferenceEvidence(
|
|
|
49
51
|
// Skip entries with empty or generic commands
|
|
50
52
|
if (!claimed.command || claimed.command.length < 3) continue;
|
|
51
53
|
|
|
52
|
-
// Find matching bash
|
|
53
|
-
|
|
54
|
+
// Find matching bash calls by command similarity. A command may be retried
|
|
55
|
+
// after a failed first run; the newest matching execution is the one that
|
|
56
|
+
// supports or rejects a claimed pass.
|
|
57
|
+
const matches = findMatches(claimed.command, bashCalls);
|
|
54
58
|
|
|
55
|
-
if (
|
|
59
|
+
if (matches.length === 0) {
|
|
56
60
|
mismatches.push({
|
|
57
61
|
severity: "warning",
|
|
58
62
|
claimed,
|
|
@@ -63,6 +67,7 @@ export function crossReferenceEvidence(
|
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
// Exit code mismatch: LLM claims success but actual command failed
|
|
70
|
+
const match = latestMatch(matches);
|
|
66
71
|
if (claimed.exitCode === 0 && match.exitCode !== 0) {
|
|
67
72
|
mismatches.push({
|
|
68
73
|
severity: "error",
|
|
@@ -79,42 +84,72 @@ export function crossReferenceEvidence(
|
|
|
79
84
|
// ─── Internals ──────────────────────────────────────────────────────────────
|
|
80
85
|
|
|
81
86
|
/**
|
|
82
|
-
*
|
|
87
|
+
* Verification evidence rows are append-only across retries, but a task
|
|
88
|
+
* completion inserts one batch at a single created_at timestamp. When that
|
|
89
|
+
* timestamp is present, safety should judge the newest completion claim only.
|
|
90
|
+
*/
|
|
91
|
+
function latestClaimBatch(
|
|
92
|
+
claimedEvidence: readonly ClaimedEvidence[],
|
|
93
|
+
): readonly ClaimedEvidence[] {
|
|
94
|
+
const dated = claimedEvidence
|
|
95
|
+
.map((claim) => ({
|
|
96
|
+
claim,
|
|
97
|
+
time: typeof claim.createdAt === "string" ? Date.parse(claim.createdAt) : Number.NaN,
|
|
98
|
+
}))
|
|
99
|
+
.filter((entry) => Number.isFinite(entry.time));
|
|
100
|
+
|
|
101
|
+
if (dated.length === 0) return claimedEvidence;
|
|
102
|
+
|
|
103
|
+
const latestTime = Math.max(...dated.map((entry) => entry.time));
|
|
104
|
+
return claimedEvidence.filter((claim) => (
|
|
105
|
+
typeof claim.createdAt === "string" && Date.parse(claim.createdAt) === latestTime
|
|
106
|
+
));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Find bash evidence entries matching a claimed command.
|
|
83
111
|
* Uses substring matching — the claimed command may be a shortened version
|
|
84
112
|
* of the actual command, or vice versa.
|
|
85
113
|
*/
|
|
86
|
-
function
|
|
114
|
+
function findMatches(
|
|
87
115
|
claimedCommand: string,
|
|
88
116
|
bashCalls: readonly BashEvidence[],
|
|
89
|
-
): BashEvidence
|
|
117
|
+
): BashEvidence[] {
|
|
90
118
|
const normalized = claimedCommand.trim();
|
|
91
119
|
|
|
92
|
-
// Exact
|
|
93
|
-
const exact = bashCalls.
|
|
94
|
-
if (exact) return exact;
|
|
120
|
+
// Exact matches first
|
|
121
|
+
const exact = bashCalls.filter(b => b.command.trim() === normalized);
|
|
122
|
+
if (exact.length > 0) return exact;
|
|
95
123
|
|
|
96
124
|
// Substring match: claimed is contained in actual or actual in claimed
|
|
97
|
-
const substring = bashCalls.
|
|
125
|
+
const substring = bashCalls.filter(
|
|
98
126
|
b => b.command.includes(normalized) || normalized.includes(b.command),
|
|
99
127
|
);
|
|
100
|
-
if (substring) return substring;
|
|
128
|
+
if (substring.length > 0) return substring;
|
|
101
129
|
|
|
102
130
|
// Token match: split on whitespace and check significant overlap
|
|
103
131
|
const claimedTokens = normalized.split(/\s+/).filter(t => t.length > 2);
|
|
104
|
-
if (claimedTokens.length === 0) return
|
|
132
|
+
if (claimedTokens.length === 0) return [];
|
|
105
133
|
|
|
106
|
-
|
|
107
|
-
let bestScore = 0;
|
|
134
|
+
const scoredMatches: Array<{ call: BashEvidence; score: number }> = [];
|
|
108
135
|
|
|
109
136
|
for (const call of bashCalls) {
|
|
110
137
|
const callTokens = new Set(call.command.split(/\s+/));
|
|
111
138
|
const matchCount = claimedTokens.filter(t => callTokens.has(t)).length;
|
|
112
139
|
const score = matchCount / claimedTokens.length;
|
|
113
|
-
if (score
|
|
114
|
-
|
|
115
|
-
bestMatch = call;
|
|
140
|
+
if (score >= 0.5) {
|
|
141
|
+
scoredMatches.push({ call, score });
|
|
116
142
|
}
|
|
117
143
|
}
|
|
118
144
|
|
|
119
|
-
|
|
145
|
+
const bestScore = Math.max(0, ...scoredMatches.map((match) => match.score));
|
|
146
|
+
return scoredMatches
|
|
147
|
+
.filter((match) => match.score === bestScore)
|
|
148
|
+
.map((match) => match.call);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function latestMatch(matches: readonly BashEvidence[]): BashEvidence {
|
|
152
|
+
return matches.reduce((latest, match) => (
|
|
153
|
+
match.timestamp > latest.timestamp ? match : latest
|
|
154
|
+
));
|
|
120
155
|
}
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
import { createRequire } from "node:module";
|
|
20
20
|
import { existsSync, readFileSync, readdirSync, mkdirSync, unlinkSync, rmSync, statSync } from "node:fs";
|
|
21
21
|
import { join, dirname } from "node:path";
|
|
22
|
-
import { gsdRoot } from "./paths.js";
|
|
22
|
+
import { gsdRoot, normalizeRealPath } from "./paths.js";
|
|
23
23
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
24
|
+
import { markWorkerStoppingByPid } from "./db/auto-workers.js";
|
|
24
25
|
|
|
25
26
|
const _require = createRequire(import.meta.url);
|
|
26
27
|
|
|
@@ -281,6 +282,13 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
|
|
|
281
282
|
// Clean up numbered lock file variants from cloud sync conflicts (#1315)
|
|
282
283
|
cleanupStrayLockFiles(basePath);
|
|
283
284
|
|
|
285
|
+
// If lock metadata points to a dead PID, mark that worker row stopping so
|
|
286
|
+
// crash diagnostics do not keep surfacing it as active.
|
|
287
|
+
const existingPreflight = readExistingLockData(lp);
|
|
288
|
+
if (existingPreflight?.pid && !isPidAlive(existingPreflight.pid)) {
|
|
289
|
+
markWorkerStoppingByPid(normalizeRealPath(basePath), existingPreflight.pid);
|
|
290
|
+
}
|
|
291
|
+
|
|
284
292
|
// Write our lock data first (the content is informational; the OS lock is the real guard)
|
|
285
293
|
const lockData: SessionLockData = {
|
|
286
294
|
pid: process.pid,
|
|
@@ -308,7 +316,9 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
|
|
|
308
316
|
const lockDir = lockTarget + ".lock";
|
|
309
317
|
if (existsSync(lockDir)) {
|
|
310
318
|
const existingData = readExistingLockData(lp);
|
|
311
|
-
const
|
|
319
|
+
const deadPid = existingData?.pid && !isPidAlive(existingData.pid) ? existingData.pid : null;
|
|
320
|
+
if (deadPid) markWorkerStoppingByPid(normalizeRealPath(basePath), deadPid);
|
|
321
|
+
const isOrphan = !existingData || !!deadPid;
|
|
312
322
|
if (isOrphan) {
|
|
313
323
|
try { rmSync(lockDir, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
314
324
|
try { if (existsSync(lp)) unlinkSync(lp); } catch { /* best-effort */ }
|
|
@@ -344,6 +354,9 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
|
|
|
344
354
|
// Check: if auto.lock is gone and no process is alive, the lock dir is stale.
|
|
345
355
|
const existingData = readExistingLockData(lp);
|
|
346
356
|
const existingPid = existingData?.pid;
|
|
357
|
+
if (existingPid && !isPidAlive(existingPid)) {
|
|
358
|
+
markWorkerStoppingByPid(normalizeRealPath(basePath), existingPid);
|
|
359
|
+
}
|
|
347
360
|
|
|
348
361
|
// If no lock file or no alive process, try to clean up and re-acquire (#1245)
|
|
349
362
|
if (!existingData || (existingPid && !isPidAlive(existingPid))) {
|
|
@@ -55,8 +55,8 @@ export function hasFileConflict(
|
|
|
55
55
|
sliceA: string,
|
|
56
56
|
sliceB: string,
|
|
57
57
|
): boolean {
|
|
58
|
-
const planPathA = join(basePath, ".gsd", "milestones", mid, sliceA,
|
|
59
|
-
const planPathB = join(basePath, ".gsd", "milestones", mid, sliceB,
|
|
58
|
+
const planPathA = join(basePath, ".gsd", "milestones", mid, "slices", sliceA, `${sliceA}-PLAN.md`);
|
|
59
|
+
const planPathB = join(basePath, ".gsd", "milestones", mid, "slices", sliceB, `${sliceB}-PLAN.md`);
|
|
60
60
|
|
|
61
61
|
// Conservative: missing PLAN = block
|
|
62
62
|
if (!existsSync(planPathA) || !existsSync(planPathB)) {
|
|
@@ -18,13 +18,15 @@ import { randomUUID } from "node:crypto";
|
|
|
18
18
|
import {
|
|
19
19
|
appendFileSync,
|
|
20
20
|
existsSync,
|
|
21
|
+
lstatSync,
|
|
22
|
+
rmSync,
|
|
21
23
|
writeFileSync,
|
|
22
24
|
readFileSync,
|
|
23
25
|
mkdirSync,
|
|
24
26
|
renameSync,
|
|
25
27
|
unlinkSync,
|
|
26
28
|
} from "node:fs";
|
|
27
|
-
import { join, dirname } from "node:path";
|
|
29
|
+
import { isAbsolute, join, dirname, resolve } from "node:path";
|
|
28
30
|
import { fileURLToPath } from "node:url";
|
|
29
31
|
import { gsdRoot } from "./paths.js";
|
|
30
32
|
import { createWorktree, worktreePath, removeWorktree } from "./worktree-manager.js";
|
|
@@ -105,6 +107,37 @@ export function _buildSliceWorkerEnvForTest(
|
|
|
105
107
|
};
|
|
106
108
|
}
|
|
107
109
|
|
|
110
|
+
function isValidSliceWorktreePath(basePath: string, wtPath: string): boolean {
|
|
111
|
+
if (!existsSync(wtPath)) return false;
|
|
112
|
+
const gitPath = join(wtPath, ".git");
|
|
113
|
+
if (!existsSync(gitPath)) return false;
|
|
114
|
+
try {
|
|
115
|
+
if (!lstatSync(gitPath).isFile()) return false;
|
|
116
|
+
const content = readFileSync(gitPath, "utf8").trim();
|
|
117
|
+
if (!content.startsWith("gitdir: ")) return false;
|
|
118
|
+
const rawGitdir = content.slice("gitdir: ".length).trim();
|
|
119
|
+
if (!rawGitdir) return false;
|
|
120
|
+
const resolvedGitdir = isAbsolute(rawGitdir) ? rawGitdir : resolve(wtPath, rawGitdir);
|
|
121
|
+
const expectedPrefix = join(basePath, ".git", "worktrees").replaceAll("\\", "/");
|
|
122
|
+
const normalized = resolvedGitdir.replaceAll("\\", "/");
|
|
123
|
+
return normalized === expectedPrefix || normalized.startsWith(`${expectedPrefix}/`);
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isWorkerPidAlive(pid: number): boolean {
|
|
130
|
+
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
131
|
+
try {
|
|
132
|
+
process.kill(pid, 0);
|
|
133
|
+
return true;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
const code = (err as NodeJS.ErrnoException)?.code;
|
|
136
|
+
if (code === "ESRCH") return false;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
108
141
|
interface PersistedSliceWorker {
|
|
109
142
|
milestoneId: string;
|
|
110
143
|
sliceId: string;
|
|
@@ -334,7 +367,24 @@ export function restoreSliceState(basePath: string): PersistedSliceState | null
|
|
|
334
367
|
* crash followed by a fresh process is detectable. (Issue #4980 HIGH-8)
|
|
335
368
|
*/
|
|
336
369
|
export function isSliceParallelActive(basePath?: string): boolean {
|
|
337
|
-
|
|
370
|
+
const hasRunningWorkers = (): boolean => {
|
|
371
|
+
if (!sliceState) return false;
|
|
372
|
+
for (const worker of sliceState.workers.values()) {
|
|
373
|
+
if (worker.state === "running") {
|
|
374
|
+
if (worker.process) return true;
|
|
375
|
+
if (isRecoveredSliceWorkerAlive(worker)) return true;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return false;
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
if (sliceState?.active === true) {
|
|
382
|
+
if (hasRunningWorkers()) return true;
|
|
383
|
+
sliceState.active = false;
|
|
384
|
+
removeSliceStateFile(sliceState.basePath);
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
|
|
338
388
|
if (!basePath) return false;
|
|
339
389
|
const restored = restoreSliceState(basePath);
|
|
340
390
|
if (!restored || restored.workers.length === 0) return false;
|
|
@@ -365,7 +415,11 @@ export function isSliceParallelActive(basePath?: string): boolean {
|
|
|
365
415
|
cost: w.cost,
|
|
366
416
|
});
|
|
367
417
|
}
|
|
368
|
-
|
|
418
|
+
|
|
419
|
+
if (hasRunningWorkers()) return true;
|
|
420
|
+
sliceState.active = false;
|
|
421
|
+
removeSliceStateFile(sliceState.basePath);
|
|
422
|
+
return false;
|
|
369
423
|
}
|
|
370
424
|
|
|
371
425
|
/**
|
|
@@ -427,6 +481,9 @@ export async function startSliceParallel(
|
|
|
427
481
|
const wtName = `${milestoneId}-${slice.id}`;
|
|
428
482
|
const wtPath = worktreePath(basePath, wtName);
|
|
429
483
|
|
|
484
|
+
if (existsSync(wtPath) && !isValidSliceWorktreePath(basePath, wtPath)) {
|
|
485
|
+
rmSync(wtPath, { recursive: true, force: true });
|
|
486
|
+
}
|
|
430
487
|
if (!existsSync(wtPath)) {
|
|
431
488
|
createWorktree(basePath, wtName, { branch: wtBranch });
|
|
432
489
|
}
|
|
@@ -470,6 +527,21 @@ export async function startSliceParallel(
|
|
|
470
527
|
}
|
|
471
528
|
}
|
|
472
529
|
|
|
530
|
+
// Guard: if workers died immediately, treat as failed start so callers
|
|
531
|
+
// don't exit auto-mode and re-dispatch in a rapid loop.
|
|
532
|
+
for (let i = started.length - 1; i >= 0; i--) {
|
|
533
|
+
const sid = started[i];
|
|
534
|
+
const worker = sliceState.workers.get(sid);
|
|
535
|
+
if (worker && isWorkerPidAlive(worker.pid)) continue;
|
|
536
|
+
started.splice(i, 1);
|
|
537
|
+
errors.push({ sid, error: "Worker exited immediately after spawn" });
|
|
538
|
+
sliceState.workers.delete(sid);
|
|
539
|
+
const wtName = `${milestoneId}-${sid}`;
|
|
540
|
+
try {
|
|
541
|
+
removeWorktree(basePath, wtName, { deleteBranch: true, force: true });
|
|
542
|
+
} catch { /* ignore cleanup failures */ }
|
|
543
|
+
}
|
|
544
|
+
|
|
473
545
|
// If nothing started, deactivate
|
|
474
546
|
if (started.length === 0) {
|
|
475
547
|
sliceState.active = false;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// GSD-2 — Smart entry routing decisions.
|
|
2
|
+
// Pure route selection for /gsd guided wizard choices.
|
|
3
|
+
|
|
4
|
+
export type SmartEntryIsolationMode = "worktree" | "branch" | "none";
|
|
5
|
+
|
|
6
|
+
export type ActiveTaskChoice =
|
|
7
|
+
| "execute"
|
|
8
|
+
| "auto"
|
|
9
|
+
| "status"
|
|
10
|
+
| "milestone_actions";
|
|
11
|
+
|
|
12
|
+
export type ActiveTaskRoute =
|
|
13
|
+
| {
|
|
14
|
+
kind: "auto-bootstrap";
|
|
15
|
+
verboseMode: false;
|
|
16
|
+
options?: {
|
|
17
|
+
step?: true;
|
|
18
|
+
milestoneLock?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
| {
|
|
22
|
+
kind: "guided-dispatch";
|
|
23
|
+
unitType: "execute-task";
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
kind: "status";
|
|
27
|
+
}
|
|
28
|
+
| {
|
|
29
|
+
kind: "milestone-actions";
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function resolveGuidedExecuteLaunchMode(
|
|
33
|
+
isolationMode: SmartEntryIsolationMode,
|
|
34
|
+
): "auto-step" | "guided-dispatch" {
|
|
35
|
+
return isolationMode === "worktree" ? "auto-step" : "guided-dispatch";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function resolveActiveTaskChoiceRoute(input: {
|
|
39
|
+
choice: ActiveTaskChoice;
|
|
40
|
+
isolationMode: SmartEntryIsolationMode;
|
|
41
|
+
milestoneId: string;
|
|
42
|
+
}): ActiveTaskRoute {
|
|
43
|
+
if (input.choice === "auto") {
|
|
44
|
+
return {
|
|
45
|
+
kind: "auto-bootstrap",
|
|
46
|
+
verboseMode: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (input.choice === "execute") {
|
|
51
|
+
if (resolveGuidedExecuteLaunchMode(input.isolationMode) === "auto-step") {
|
|
52
|
+
return {
|
|
53
|
+
kind: "auto-bootstrap",
|
|
54
|
+
verboseMode: false,
|
|
55
|
+
options: {
|
|
56
|
+
step: true,
|
|
57
|
+
milestoneLock: input.milestoneId,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
kind: "guided-dispatch",
|
|
64
|
+
unitType: "execute-task",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (input.choice === "status") {
|
|
69
|
+
return { kind: "status" };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (input.choice === "milestone_actions") {
|
|
73
|
+
return { kind: "milestone-actions" };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
throw new Error(`Invalid ActiveTaskChoice: ${input.choice}`);
|
|
77
|
+
}
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "../../native-git-bridge.js";
|
|
24
24
|
import type { GSDState } from "../../types.js";
|
|
25
25
|
import { logError, logWarning } from "../../workflow-logger.js";
|
|
26
|
+
import { isGsdWorktreePath } from "../../worktree-root.js";
|
|
26
27
|
import type { DriftContext, DriftHandler, DriftRecord } from "../types.js";
|
|
27
28
|
|
|
28
29
|
export type MergeReconcileResult = "clean" | "reconciled" | "blocked";
|
|
@@ -46,7 +47,13 @@ function resolveGitDir(basePath: string): string {
|
|
|
46
47
|
return isAbsolute(gitDir) ? gitDir : resolve(basePath, gitDir);
|
|
47
48
|
}
|
|
48
49
|
} catch (err) {
|
|
49
|
-
|
|
50
|
+
const message = getErrorMessage(err);
|
|
51
|
+
logWarning("recovery", `gitdir resolution failed: ${message}`);
|
|
52
|
+
if (isGsdWorktreePath(basePath)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Worktree integrity failure: ${basePath} is not a valid git worktree (git rev-parse failed: ${message.split("\n")[0]}). Repair or recreate the worktree before retrying.`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
return join(basePath, ".git");
|