gsd-pi 2.80.0-dev.3065f7bfa → 2.80.0-dev.488219eb6
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/dist/claude-cli-check.d.ts +30 -0
- package/dist/claude-cli-check.js +18 -7
- package/dist/cli.js +0 -19
- package/dist/headless-query.d.ts +10 -0
- package/dist/headless-query.js +6 -4
- package/dist/loader-entrypoint.d.ts +8 -0
- package/dist/loader-entrypoint.js +27 -0
- package/dist/loader.js +2 -11
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +6 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
- package/dist/resources/extensions/github-sync/sync.js +4 -1
- package/dist/resources/extensions/gsd/auto/loop.js +71 -8
- package/dist/resources/extensions/gsd/auto/phases.js +32 -8
- package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +81 -76
- package/dist/resources/extensions/gsd/auto-start.js +41 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +98 -80
- package/dist/resources/extensions/gsd/auto.js +84 -29
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +62 -13
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -26
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +29 -12
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -9
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -7
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -10
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -9
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +60 -26
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-config.js +1 -1
- package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
- package/dist/resources/extensions/gsd/git-service.js +37 -1
- package/dist/resources/extensions/gsd/guided-flow.js +14 -4
- package/dist/resources/extensions/gsd/init-wizard.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
- package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
- package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +22 -1
- package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- 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 +17 -17
- 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 +2 -2
- 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_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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +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 +17 -17
- 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/middleware.js +3 -3
- 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/8359.e059d86b255fce1c.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
- package/dist/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +9 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
- package/packages/pi-ai/src/providers/anthropic.ts +22 -9
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
- package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
- package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -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/tool-card-cleanup-and-success-runtime.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +153 -8
- 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 +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +23 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.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 +19 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +23 -5
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
- package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
- package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
- package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
- package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
- package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +177 -8
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +24 -5
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +21 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +25 -8
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
- package/src/resources/extensions/github-sync/sync.ts +8 -1
- package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
- package/src/resources/extensions/gsd/auto/loop.ts +84 -8
- package/src/resources/extensions/gsd/auto/phases.ts +43 -8
- package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +93 -78
- package/src/resources/extensions/gsd/auto-start.ts +56 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +118 -72
- package/src/resources/extensions/gsd/auto.ts +121 -29
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +76 -12
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -26
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +27 -12
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -9
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +4 -7
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +6 -10
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -9
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +64 -26
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
- package/src/resources/extensions/gsd/commands-config.ts +1 -1
- package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
- package/src/resources/extensions/gsd/git-service.ts +41 -2
- package/src/resources/extensions/gsd/guided-flow.ts +19 -4
- package/src/resources/extensions/gsd/init-wizard.ts +5 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
- package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +1 -217
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
- package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
- package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +35 -31
- package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
- package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -59
- package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -125
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -90
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -97
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +33 -47
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +6 -101
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
- package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +34 -1
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
- package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
- /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Auto-mode orchestration, session lifecycle, and stop handling.
|
|
1
3
|
/**
|
|
2
4
|
* GSD Auto Mode — Fresh Session Per Unit
|
|
3
5
|
*
|
|
@@ -354,6 +356,14 @@ function restoreProjectRootEnv(): void {
|
|
|
354
356
|
s.projectRootEnvCaptured = false;
|
|
355
357
|
}
|
|
356
358
|
|
|
359
|
+
export function _captureProjectRootEnvForTest(projectRoot: string): void {
|
|
360
|
+
captureProjectRootEnv(projectRoot);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function _restoreProjectRootEnvForTest(): void {
|
|
364
|
+
restoreProjectRootEnv();
|
|
365
|
+
}
|
|
366
|
+
|
|
357
367
|
function captureMilestoneLockEnv(milestoneId: string | null): void {
|
|
358
368
|
if (!s.milestoneLockEnvCaptured) {
|
|
359
369
|
s.hadMilestoneLockEnv = Object.prototype.hasOwnProperty.call(process.env, "GSD_MILESTONE_LOCK");
|
|
@@ -442,6 +452,16 @@ export function _synthesizePausedSessionRecoveryForTest(
|
|
|
442
452
|
return synthesizePausedSessionRecovery(basePath, unitType, unitId, sessionFile);
|
|
443
453
|
}
|
|
444
454
|
|
|
455
|
+
export function _resolvePausedResumeBasePathForTest(
|
|
456
|
+
basePath: string,
|
|
457
|
+
pausedWorktreePath: string | null | undefined,
|
|
458
|
+
pathExists: (path: string) => boolean = existsSync,
|
|
459
|
+
): string {
|
|
460
|
+
return pausedWorktreePath && pathExists(pausedWorktreePath)
|
|
461
|
+
? pausedWorktreePath
|
|
462
|
+
: basePath;
|
|
463
|
+
}
|
|
464
|
+
|
|
445
465
|
const DETACHED_AUTO_KEEPALIVE_INTERVAL_MS = 30_000;
|
|
446
466
|
|
|
447
467
|
function withDetachedAutoKeepalive<T>(run: Promise<T>): Promise<T> {
|
|
@@ -673,6 +693,30 @@ export function isAutoPaused(): boolean {
|
|
|
673
693
|
return s.paused;
|
|
674
694
|
}
|
|
675
695
|
|
|
696
|
+
export interface ResumeResourceRefreshDeps {
|
|
697
|
+
env?: NodeJS.ProcessEnv;
|
|
698
|
+
importModule?: (specifier: string) => Promise<any>;
|
|
699
|
+
openProjectDb?: (basePath: string) => Promise<void>;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export async function refreshResumeResourcesAndDb(
|
|
703
|
+
basePath: string,
|
|
704
|
+
deps: ResumeResourceRefreshDeps = {},
|
|
705
|
+
): Promise<void> {
|
|
706
|
+
const env = deps.env ?? process.env;
|
|
707
|
+
const importModule = deps.importModule ?? ((specifier: string) => import(specifier));
|
|
708
|
+
const agentDir = env.GSD_CODING_AGENT_DIR || join(gsdHome(), "agent");
|
|
709
|
+
const pkgRoot = env.GSD_PKG_ROOT;
|
|
710
|
+
const resourceLoaderPath = pkgRoot
|
|
711
|
+
? pathToFileURL(join(pkgRoot, "dist", "resource-loader.js")).href
|
|
712
|
+
: new URL("../../../resource-loader.js", import.meta.url).href;
|
|
713
|
+
const { initResources } = await importModule(resourceLoaderPath);
|
|
714
|
+
initResources(agentDir);
|
|
715
|
+
const { primeCache } = await importModule("./prompt-loader.js");
|
|
716
|
+
primeCache();
|
|
717
|
+
await (deps.openProjectDb ?? openProjectDbIfPresent)(basePath);
|
|
718
|
+
}
|
|
719
|
+
|
|
676
720
|
export function setActiveEngineId(id: string | null): void {
|
|
677
721
|
s.activeEngineId = id;
|
|
678
722
|
}
|
|
@@ -927,7 +971,23 @@ function handleLostSessionLock(
|
|
|
927
971
|
* the stale unit state, progress widget, status badge, and restores CWD so
|
|
928
972
|
* the dashboard does not show an orphaned timer and the shell is usable.
|
|
929
973
|
*/
|
|
930
|
-
function
|
|
974
|
+
export async function rerootCommandSession(
|
|
975
|
+
cmdCtx: Pick<ExtensionCommandContext, "newSession"> | null | undefined,
|
|
976
|
+
workspaceRoot: string,
|
|
977
|
+
): Promise<{ status: "skipped" | "ok" | "cancelled" | "failed"; error?: string }> {
|
|
978
|
+
if (!cmdCtx || !workspaceRoot) return { status: "skipped" };
|
|
979
|
+
try {
|
|
980
|
+
const result = await cmdCtx.newSession({ workspaceRoot });
|
|
981
|
+
return result.cancelled ? { status: "cancelled" } : { status: "ok" };
|
|
982
|
+
} catch (err) {
|
|
983
|
+
return {
|
|
984
|
+
status: "failed",
|
|
985
|
+
error: err instanceof Error ? err.message : String(err),
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
export async function cleanupAfterLoopExit(ctx: ExtensionContext): Promise<void> {
|
|
931
991
|
s.currentUnit = null;
|
|
932
992
|
s.active = false;
|
|
933
993
|
deactivateGSD();
|
|
@@ -965,6 +1025,34 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
|
|
|
965
1025
|
logWarning("engine", `chdir failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
966
1026
|
}
|
|
967
1027
|
}
|
|
1028
|
+
|
|
1029
|
+
if (s.originalBasePath && s.cmdCtx) {
|
|
1030
|
+
const result = await rerootCommandSession(s.cmdCtx, s.basePath);
|
|
1031
|
+
if (result.status === "cancelled") {
|
|
1032
|
+
logWarning("engine", "post-loop session re-root was cancelled", { file: "auto.ts", basePath: s.basePath });
|
|
1033
|
+
} else if (result.status === "failed") {
|
|
1034
|
+
logWarning("engine", `post-loop session re-root failed: ${result.error ?? "unknown"}`, { file: "auto.ts", basePath: s.basePath });
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
export function _cleanupAfterLoopExitForTest(ctx: ExtensionContext): Promise<void> {
|
|
1040
|
+
return cleanupAfterLoopExit(ctx);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
export type AutoWorktreeExitAction = "skip" | "merge" | "preserve";
|
|
1044
|
+
|
|
1045
|
+
export function _resolveAutoWorktreeExitActionForTest(
|
|
1046
|
+
currentMilestoneId: string | null | undefined,
|
|
1047
|
+
milestoneMergedInPhases: boolean,
|
|
1048
|
+
milestoneComplete: boolean,
|
|
1049
|
+
): AutoWorktreeExitAction {
|
|
1050
|
+
const action = _selectStopAutoWorktreeExit({
|
|
1051
|
+
currentMilestoneId: currentMilestoneId ?? null,
|
|
1052
|
+
milestoneComplete,
|
|
1053
|
+
milestoneMergedInPhases,
|
|
1054
|
+
});
|
|
1055
|
+
return action === "none" ? "skip" : action;
|
|
968
1056
|
}
|
|
969
1057
|
|
|
970
1058
|
export async function stopAuto(
|
|
@@ -1118,10 +1206,16 @@ export async function stopAuto(
|
|
|
1118
1206
|
logWarning("engine", `milestone summary check failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1119
1207
|
}
|
|
1120
1208
|
|
|
1121
|
-
|
|
1209
|
+
const exitAction = _selectStopAutoWorktreeExit({
|
|
1210
|
+
currentMilestoneId: s.currentMilestoneId,
|
|
1211
|
+
milestoneComplete,
|
|
1212
|
+
milestoneMergedInPhases: s.milestoneMergedInPhases,
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
if (exitAction === "merge") {
|
|
1122
1216
|
// Milestone is complete — merge worktree branch back to main
|
|
1123
1217
|
resolver.mergeAndExit(s.currentMilestoneId, notifyCtx);
|
|
1124
|
-
} else {
|
|
1218
|
+
} else if (exitAction === "preserve") {
|
|
1125
1219
|
// Milestone still in progress — preserve branch for later resumption
|
|
1126
1220
|
resolver.exitMilestone(s.currentMilestoneId, notifyCtx, {
|
|
1127
1221
|
preserveBranch: true,
|
|
@@ -1129,6 +1223,10 @@ export async function stopAuto(
|
|
|
1129
1223
|
}
|
|
1130
1224
|
}
|
|
1131
1225
|
} catch (e) {
|
|
1226
|
+
ctx?.ui.notify(
|
|
1227
|
+
`Worktree cleanup failed for ${s.currentMilestoneId ?? "current milestone"}: ${e instanceof Error ? e.message : String(e)}. Resolve the preserved branch/worktree and run /gsd auto to resume.`,
|
|
1228
|
+
"warning",
|
|
1229
|
+
);
|
|
1132
1230
|
debugLog("stop-cleanup-worktree", { error: e instanceof Error ? e.message : String(e) });
|
|
1133
1231
|
}
|
|
1134
1232
|
|
|
@@ -1179,13 +1277,11 @@ export async function stopAuto(
|
|
|
1179
1277
|
// its own cwd for tools and system prompt; refresh it before returning to the
|
|
1180
1278
|
// user so follow-up commands do not target a removed milestone worktree.
|
|
1181
1279
|
if (s.originalBasePath && ctx && s.cmdCtx) {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
}
|
|
1187
|
-
} catch (err) {
|
|
1188
|
-
logWarning("engine", `post-stop session re-root failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts", basePath: s.basePath });
|
|
1280
|
+
const result = await rerootCommandSession(s.cmdCtx, s.basePath);
|
|
1281
|
+
if (result.status === "cancelled") {
|
|
1282
|
+
logWarning("engine", "post-stop session re-root was cancelled", { file: "auto.ts", basePath: s.basePath });
|
|
1283
|
+
} else if (result.status === "failed") {
|
|
1284
|
+
logWarning("engine", `post-stop session re-root failed: ${result.error ?? "unknown"}`, { file: "auto.ts", basePath: s.basePath });
|
|
1189
1285
|
}
|
|
1190
1286
|
}
|
|
1191
1287
|
|
|
@@ -1317,6 +1413,17 @@ export async function stopAuto(
|
|
|
1317
1413
|
}
|
|
1318
1414
|
}
|
|
1319
1415
|
|
|
1416
|
+
export type StopAutoWorktreeExitAction = "none" | "merge" | "preserve";
|
|
1417
|
+
|
|
1418
|
+
export function _selectStopAutoWorktreeExit(args: {
|
|
1419
|
+
currentMilestoneId: string | null;
|
|
1420
|
+
milestoneComplete: boolean;
|
|
1421
|
+
milestoneMergedInPhases: boolean;
|
|
1422
|
+
}): StopAutoWorktreeExitAction {
|
|
1423
|
+
if (!args.currentMilestoneId || args.milestoneMergedInPhases) return "none";
|
|
1424
|
+
return args.milestoneComplete ? "merge" : "preserve";
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1320
1427
|
/**
|
|
1321
1428
|
* Pause auto-mode without destroying state. Context is preserved.
|
|
1322
1429
|
* The user can interact with the agent, then `/gsd auto` resumes
|
|
@@ -1995,9 +2102,7 @@ export async function startAuto(
|
|
|
1995
2102
|
{ file: "auto.ts", milestoneId: s.currentMilestoneId ?? "" },
|
|
1996
2103
|
);
|
|
1997
2104
|
}
|
|
1998
|
-
|
|
1999
|
-
s.basePath = resumeWorktreePath;
|
|
2000
|
-
}
|
|
2105
|
+
s.basePath = _resolvePausedResumeBasePathForTest(base, resumeWorktreePath);
|
|
2001
2106
|
// Rebuild scope now that s.basePath reflects the actual worktree (or project root).
|
|
2002
2107
|
rebuildScope(s.basePath, s.currentMilestoneId);
|
|
2003
2108
|
// Ensure the workflow-logger audit log is pinned to the project root
|
|
@@ -2049,20 +2154,7 @@ export async function startAuto(
|
|
|
2049
2154
|
// tree; deployed extensions live at ~/.gsd/agent/extensions/gsd/ where the
|
|
2050
2155
|
// relative path resolves to ~/.gsd/agent/resource-loader.js which doesn't exist.
|
|
2051
2156
|
// Using GSD_PKG_ROOT constructs a correct absolute path in both contexts (#3949).
|
|
2052
|
-
|
|
2053
|
-
const pkgRoot = process.env.GSD_PKG_ROOT;
|
|
2054
|
-
const resourceLoaderPath = pkgRoot
|
|
2055
|
-
? pathToFileURL(join(pkgRoot, "dist", "resource-loader.js")).href
|
|
2056
|
-
: new URL("../../../resource-loader.js", import.meta.url).href;
|
|
2057
|
-
const { initResources } = await import(resourceLoaderPath);
|
|
2058
|
-
initResources(agentDir);
|
|
2059
|
-
// initResources() uses synchronous fs APIs, so the prompt-template cache
|
|
2060
|
-
// can be primed immediately — no need for the legacy 1s setTimeout deferral.
|
|
2061
|
-
const { primeCache } = await import("./prompt-loader.js");
|
|
2062
|
-
primeCache();
|
|
2063
|
-
// Open the project DB before rebuild/derive so resume uses DB-backed
|
|
2064
|
-
// state instead of falling back to stale markdown parsing (#2940).
|
|
2065
|
-
await openProjectDbIfPresent(s.basePath);
|
|
2157
|
+
await refreshResumeResourcesAndDb(s.basePath);
|
|
2066
2158
|
try {
|
|
2067
2159
|
await rebuildState(s.basePath);
|
|
2068
2160
|
pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync" as const, preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, state: await deriveState(s.basePath) });
|
|
@@ -2134,7 +2226,7 @@ export async function startAuto(
|
|
|
2134
2226
|
runKernelLoop: runUokKernelLoop,
|
|
2135
2227
|
runLegacyLoop: runLegacyAutoLoop,
|
|
2136
2228
|
});
|
|
2137
|
-
cleanupAfterLoopExit(ctx);
|
|
2229
|
+
await cleanupAfterLoopExit(ctx);
|
|
2138
2230
|
return;
|
|
2139
2231
|
}
|
|
2140
2232
|
|
|
@@ -2194,7 +2286,7 @@ export async function startAuto(
|
|
|
2194
2286
|
runKernelLoop: runUokKernelLoop,
|
|
2195
2287
|
runLegacyLoop: runLegacyAutoLoop,
|
|
2196
2288
|
});
|
|
2197
|
-
cleanupAfterLoopExit(ctx);
|
|
2289
|
+
await cleanupAfterLoopExit(ctx);
|
|
2198
2290
|
}
|
|
2199
2291
|
|
|
2200
2292
|
// describeNextUnit is imported from auto-dashboard.ts and re-exported
|
|
@@ -15,7 +15,12 @@ import { clearPathCache } from "../paths.js";
|
|
|
15
15
|
import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
|
|
16
16
|
import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
|
|
17
17
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
isSessionSwitchAbortGraceActive,
|
|
20
|
+
isSessionSwitchInFlight,
|
|
21
|
+
resolveAgentEnd,
|
|
22
|
+
resolveAgentEndCancelled,
|
|
23
|
+
} from "../auto/resolve.js";
|
|
19
24
|
import { resolveModelId } from "../auto-model-selection.js";
|
|
20
25
|
import { resolveProjectRoot } from "../worktree.js";
|
|
21
26
|
import { clearDiscussionFlowState } from "./write-gate.js";
|
|
@@ -77,6 +82,42 @@ export function isUserInitiatedAbortMessage(message: string | undefined | null):
|
|
|
77
82
|
return /\b(?:claude code process aborted by user|request aborted by user|process aborted by user)\b/i.test(message);
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
function isBareClaudeCodeSessionSwitchAbortMarker(message: string | undefined | null): boolean {
|
|
86
|
+
if (!message) return false;
|
|
87
|
+
const normalized = message.trim().replace(/\s+/g, " ").toLowerCase();
|
|
88
|
+
return normalized === "claude code process aborted by user"
|
|
89
|
+
|| normalized === "request aborted by user"
|
|
90
|
+
|| normalized === "process aborted by user"
|
|
91
|
+
|| normalized === "claude code stream aborted by caller";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function readAssistantTextContent(content: unknown): string {
|
|
95
|
+
if (!Array.isArray(content)) return "";
|
|
96
|
+
return content
|
|
97
|
+
.map((block) => {
|
|
98
|
+
if (!block || typeof block !== "object") return "";
|
|
99
|
+
const text = (block as { text?: unknown }).text;
|
|
100
|
+
return typeof text === "string" ? text : "";
|
|
101
|
+
})
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function isClaudeCodeSessionSwitchAbortMessage(lastMsg: unknown): boolean {
|
|
107
|
+
if (!lastMsg || typeof lastMsg !== "object") return false;
|
|
108
|
+
const m = lastMsg as { stopReason?: unknown; errorMessage?: unknown; content?: unknown };
|
|
109
|
+
const carriers = [
|
|
110
|
+
m.errorMessage ? String(m.errorMessage) : "",
|
|
111
|
+
readAssistantTextContent(m.content),
|
|
112
|
+
].filter((value) => value.trim().length > 0);
|
|
113
|
+
|
|
114
|
+
if ((m.stopReason === "error" || m.stopReason === "aborted") && carriers.length > 0) {
|
|
115
|
+
return carriers.every(isBareClaudeCodeSessionSwitchAbortMarker);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
80
121
|
/**
|
|
81
122
|
* Resolve an agent_end event observed while a session switch is in flight.
|
|
82
123
|
*
|
|
@@ -89,10 +130,11 @@ export function isUserInitiatedAbortMessage(message: string | undefined | null):
|
|
|
89
130
|
* "Auto-mode stopped — Unit aborted: Claude Code process aborted by user"
|
|
90
131
|
* even though no user input occurred.
|
|
91
132
|
*
|
|
92
|
-
*
|
|
93
|
-
* the session-switch is in flight: the abort is the expected side-effect
|
|
94
|
-
* the transition, not a user signal. Other branches (genuine `stopReason
|
|
95
|
-
* "aborted"` with content/errorMessage) preserve the prior
|
|
133
|
+
* Claude Code abort markers are intentionally ignored when the abort fires
|
|
134
|
+
* while the session-switch is in flight: the abort is the expected side-effect
|
|
135
|
+
* of the transition, not a user signal. Other branches (genuine `stopReason
|
|
136
|
+
* === "aborted"` with diagnostic content/errorMessage) preserve the prior
|
|
137
|
+
* behavior.
|
|
96
138
|
*/
|
|
97
139
|
export function _handleSessionSwitchAgentEnd(
|
|
98
140
|
lastMsg: unknown,
|
|
@@ -101,9 +143,14 @@ export function _handleSessionSwitchAgentEnd(
|
|
|
101
143
|
if (!lastMsg || typeof lastMsg !== "object") return;
|
|
102
144
|
const m = lastMsg as { stopReason?: unknown; errorMessage?: unknown; content?: unknown };
|
|
103
145
|
|
|
146
|
+
if (isClaudeCodeSessionSwitchAbortMessage(m)) {
|
|
147
|
+
// Internal abort from in-flight session transition — drop on the floor.
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
104
151
|
if (m.stopReason === "error") {
|
|
105
152
|
const rawErrorMsg = m.errorMessage ? String(m.errorMessage) : "";
|
|
106
|
-
if (
|
|
153
|
+
if (isBareClaudeCodeSessionSwitchAbortMarker(rawErrorMsg)) {
|
|
107
154
|
// Internal abort from in-flight session transition — drop on the floor.
|
|
108
155
|
return;
|
|
109
156
|
}
|
|
@@ -120,6 +167,18 @@ export function _handleSessionSwitchAgentEnd(
|
|
|
120
167
|
}
|
|
121
168
|
}
|
|
122
169
|
|
|
170
|
+
export function resolveAgentEndErrorDisplay(
|
|
171
|
+
rawErrorMsg: string,
|
|
172
|
+
content: unknown,
|
|
173
|
+
): string {
|
|
174
|
+
const isUseless = !rawErrorMsg || /^(success|ok|true|error|unknown)$/i.test(rawErrorMsg.trim());
|
|
175
|
+
if (isUseless && Array.isArray(content)) {
|
|
176
|
+
const textBlock = content.find((b: any) => b.type === "text" && b.text);
|
|
177
|
+
if (textBlock) return (textBlock as any).text.slice(0, 300);
|
|
178
|
+
}
|
|
179
|
+
return rawErrorMsg;
|
|
180
|
+
}
|
|
181
|
+
|
|
123
182
|
async function pauseTransientWithBackoff(
|
|
124
183
|
cls: ErrorClass,
|
|
125
184
|
pi: ExtensionAPI,
|
|
@@ -204,6 +263,13 @@ export async function handleAgentEnd(
|
|
|
204
263
|
return;
|
|
205
264
|
}
|
|
206
265
|
|
|
266
|
+
if (isSessionSwitchAbortGraceActive() && isClaudeCodeSessionSwitchAbortMessage(lastMsg)) {
|
|
267
|
+
// Claude Code can report the abort from `newSession()` a few hundred ms
|
|
268
|
+
// after the guard drops. That event belongs to the old turn; do not let it
|
|
269
|
+
// cancel the freshly-dispatched unit.
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
207
273
|
if (lastMsg && "stopReason" in lastMsg && lastMsg.stopReason === "aborted") {
|
|
208
274
|
// Empty content with aborted stopReason is a non-fatal agent stop (the LLM
|
|
209
275
|
// chose to end without producing output). Only pause on genuine fatal aborts
|
|
@@ -243,15 +309,13 @@ export async function handleAgentEnd(
|
|
|
243
309
|
});
|
|
244
310
|
return;
|
|
245
311
|
}
|
|
246
|
-
const isUseless = !rawErrorMsg || /^(success|ok|true|error|unknown)$/i.test(rawErrorMsg.trim());
|
|
247
312
|
// #3588: When errorMessage is uninformative, extract the real error from
|
|
248
313
|
// the assistant message text content for display purposes only.
|
|
249
314
|
// Classification still uses rawErrorMsg to avoid false positives from prose.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
315
|
+
const displayMsg = resolveAgentEndErrorDisplay(
|
|
316
|
+
rawErrorMsg,
|
|
317
|
+
"content" in lastMsg ? lastMsg.content : undefined,
|
|
318
|
+
);
|
|
255
319
|
const errorDetail = displayMsg ? `: ${displayMsg}` : "";
|
|
256
320
|
const explicitRetryAfterMs = ("retryAfterMs" in lastMsg && typeof lastMsg.retryAfterMs === "number") ? lastMsg.retryAfterMs : undefined;
|
|
257
321
|
|
|
@@ -5,7 +5,7 @@ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
|
5
5
|
import { Text } from "@gsd/pi-tui";
|
|
6
6
|
|
|
7
7
|
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
8
|
-
import { ensureDbOpen } from "./dynamic-tools.js";
|
|
8
|
+
import { ensureDbOpen, resolveCtxCwd } from "./dynamic-tools.js";
|
|
9
9
|
import { loadWriteGateSnapshot, shouldBlockRootArtifactSaveInSnapshot } from "./write-gate.js";
|
|
10
10
|
import { StringEnum } from "@gsd/pi-ai";
|
|
11
11
|
import { logError } from "../workflow-logger.js";
|
|
@@ -16,12 +16,6 @@ async function loadWorkflowExecutors(): Promise<typeof import("../tools/workflow
|
|
|
16
16
|
return import("../tools/workflow-tool-executors.js");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function toolWorkspaceRoot(ctx: unknown): string {
|
|
20
|
-
if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
|
|
21
|
-
return (ctx as { cwd: string }).cwd;
|
|
22
|
-
}
|
|
23
|
-
return process.cwd();
|
|
24
|
-
}
|
|
25
19
|
|
|
26
20
|
/**
|
|
27
21
|
* Register an alias tool that shares the same execute function as its canonical counterpart.
|
|
@@ -72,7 +66,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
72
66
|
// ─── gsd_decision_save (formerly gsd_save_decision) ─────────────────────
|
|
73
67
|
|
|
74
68
|
const decisionSaveExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
75
|
-
const basePath =
|
|
69
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
76
70
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
77
71
|
if (!dbAvailable) {
|
|
78
72
|
return {
|
|
@@ -160,7 +154,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
160
154
|
// ─── gsd_requirement_update (formerly gsd_update_requirement) ───────────
|
|
161
155
|
|
|
162
156
|
const requirementUpdateExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
163
|
-
const basePath =
|
|
157
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
164
158
|
const gateBlock = requirementRootWriteGuard("update_requirement", basePath);
|
|
165
159
|
if (gateBlock) return gateBlock;
|
|
166
160
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
@@ -241,7 +235,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
241
235
|
// ─── gsd_requirement_save ─────────────────────────────────────────────
|
|
242
236
|
|
|
243
237
|
const requirementSaveExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
244
|
-
const basePath =
|
|
238
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
245
239
|
const gateBlock = requirementRootWriteGuard("save_requirement", basePath);
|
|
246
240
|
if (gateBlock) return gateBlock;
|
|
247
241
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
@@ -345,7 +339,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
345
339
|
|
|
346
340
|
const summarySaveExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
347
341
|
const { executeSummarySave } = await loadWorkflowExecutors();
|
|
348
|
-
return executeSummarySave(params,
|
|
342
|
+
return executeSummarySave(params, resolveCtxCwd(_ctx));
|
|
349
343
|
};
|
|
350
344
|
|
|
351
345
|
const summarySaveTool = {
|
|
@@ -396,7 +390,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
396
390
|
|
|
397
391
|
const milestoneGenerateIdExecute = async (_toolCallId: string, _params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
398
392
|
try {
|
|
399
|
-
const basePath =
|
|
393
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
400
394
|
// Claim a reserved ID if the guided-flow already previewed one to the user.
|
|
401
395
|
// This guarantees the ID shown in the UI matches the one materialised on disk.
|
|
402
396
|
const { claimReservedId, findMilestoneIds, getReservedMilestoneIds, nextMilestoneId } = await import("../guided-flow.js");
|
|
@@ -481,7 +475,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
481
475
|
|
|
482
476
|
const planMilestoneExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
483
477
|
const { executePlanMilestone } = await loadWorkflowExecutors();
|
|
484
|
-
return executePlanMilestone(params,
|
|
478
|
+
return executePlanMilestone(params, resolveCtxCwd(_ctx));
|
|
485
479
|
};
|
|
486
480
|
|
|
487
481
|
const planMilestoneTool = {
|
|
@@ -551,7 +545,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
551
545
|
|
|
552
546
|
const planSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
553
547
|
const { executePlanSlice } = await loadWorkflowExecutors();
|
|
554
|
-
return executePlanSlice(params,
|
|
548
|
+
return executePlanSlice(params, resolveCtxCwd(_ctx));
|
|
555
549
|
};
|
|
556
550
|
|
|
557
551
|
const planSliceTool = {
|
|
@@ -600,7 +594,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
600
594
|
// ─── gsd_plan_task (gsd_task_plan alias) ───────────────────────────────
|
|
601
595
|
|
|
602
596
|
const planTaskExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
603
|
-
const basePath =
|
|
597
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
604
598
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
605
599
|
if (!dbAvailable) {
|
|
606
600
|
return {
|
|
@@ -675,7 +669,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
675
669
|
|
|
676
670
|
const taskCompleteExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
677
671
|
const { executeTaskComplete } = await loadWorkflowExecutors();
|
|
678
|
-
return executeTaskComplete(params,
|
|
672
|
+
return executeTaskComplete(params, resolveCtxCwd(_ctx));
|
|
679
673
|
};
|
|
680
674
|
|
|
681
675
|
const taskCompleteTool = {
|
|
@@ -746,7 +740,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
746
740
|
|
|
747
741
|
const sliceCompleteExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
748
742
|
const { executeSliceComplete } = await loadWorkflowExecutors();
|
|
749
|
-
return executeSliceComplete(params,
|
|
743
|
+
return executeSliceComplete(params, resolveCtxCwd(_ctx));
|
|
750
744
|
};
|
|
751
745
|
|
|
752
746
|
const sliceCompleteTool = {
|
|
@@ -846,7 +840,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
846
840
|
// ─── gsd_skip_slice (#3477 / #3487) ───────────────────────────────────
|
|
847
841
|
|
|
848
842
|
const skipSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
849
|
-
const basePath =
|
|
843
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
850
844
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
851
845
|
if (!dbAvailable) {
|
|
852
846
|
return {
|
|
@@ -939,7 +933,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
939
933
|
|
|
940
934
|
const milestoneCompleteExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
941
935
|
const { executeCompleteMilestone } = await loadWorkflowExecutors();
|
|
942
|
-
return executeCompleteMilestone(params,
|
|
936
|
+
return executeCompleteMilestone(params, resolveCtxCwd(_ctx));
|
|
943
937
|
};
|
|
944
938
|
|
|
945
939
|
const milestoneCompleteTool = {
|
|
@@ -985,7 +979,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
985
979
|
|
|
986
980
|
const milestoneValidateExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
987
981
|
const { executeValidateMilestone } = await loadWorkflowExecutors();
|
|
988
|
-
return executeValidateMilestone(params,
|
|
982
|
+
return executeValidateMilestone(params, resolveCtxCwd(_ctx));
|
|
989
983
|
};
|
|
990
984
|
|
|
991
985
|
const milestoneValidateTool = {
|
|
@@ -1023,7 +1017,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1023
1017
|
|
|
1024
1018
|
const replanSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1025
1019
|
const { executeReplanSlice } = await loadWorkflowExecutors();
|
|
1026
|
-
return executeReplanSlice(params,
|
|
1020
|
+
return executeReplanSlice(params, resolveCtxCwd(_ctx));
|
|
1027
1021
|
};
|
|
1028
1022
|
|
|
1029
1023
|
const replanSliceTool = {
|
|
@@ -1074,7 +1068,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1074
1068
|
|
|
1075
1069
|
const reassessRoadmapExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1076
1070
|
const { executeReassessRoadmap } = await loadWorkflowExecutors();
|
|
1077
|
-
return executeReassessRoadmap(params,
|
|
1071
|
+
return executeReassessRoadmap(params, resolveCtxCwd(_ctx));
|
|
1078
1072
|
};
|
|
1079
1073
|
|
|
1080
1074
|
const reassessRoadmapTool = {
|
|
@@ -1133,7 +1127,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1133
1127
|
// Single-writer v3, Stream 3: reversibility tools for closed units.
|
|
1134
1128
|
|
|
1135
1129
|
const reopenTaskExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1136
|
-
const basePath =
|
|
1130
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
1137
1131
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
1138
1132
|
if (!dbAvailable) {
|
|
1139
1133
|
return {
|
|
@@ -1200,7 +1194,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1200
1194
|
// ─── gsd_slice_reopen (gsd_reopen_slice alias) ─────────────────────────
|
|
1201
1195
|
|
|
1202
1196
|
const reopenSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1203
|
-
const basePath =
|
|
1197
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
1204
1198
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
1205
1199
|
if (!dbAvailable) {
|
|
1206
1200
|
return {
|
|
@@ -1267,7 +1261,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1267
1261
|
// ─── gsd_milestone_reopen (gsd_reopen_milestone alias) ─────────────────
|
|
1268
1262
|
|
|
1269
1263
|
const reopenMilestoneExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1270
|
-
const basePath =
|
|
1264
|
+
const basePath = resolveCtxCwd(_ctx);
|
|
1271
1265
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
1272
1266
|
if (!dbAvailable) {
|
|
1273
1267
|
return {
|
|
@@ -1333,7 +1327,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1333
1327
|
|
|
1334
1328
|
const saveGateResultExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
|
|
1335
1329
|
const { executeSaveGateResult } = await loadWorkflowExecutors();
|
|
1336
|
-
return executeSaveGateResult(params,
|
|
1330
|
+
return executeSaveGateResult(params, resolveCtxCwd(_ctx));
|
|
1337
1331
|
};
|
|
1338
1332
|
|
|
1339
1333
|
const saveGateResultTool = {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Registers workspace-aware dynamic filesystem and shell tools.
|
|
1
3
|
import { existsSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
2
5
|
import { dirname } from "node:path";
|
|
3
6
|
|
|
4
7
|
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
@@ -8,11 +11,22 @@ import { DEFAULT_BASH_TIMEOUT_SECS } from "../constants.js";
|
|
|
8
11
|
import { setLogBasePath, logWarning } from "../workflow-logger.js";
|
|
9
12
|
import { resolveGsdPathContract } from "../paths.js";
|
|
10
13
|
|
|
11
|
-
function
|
|
14
|
+
export function safeWorkspaceCwd(): string {
|
|
15
|
+
try {
|
|
16
|
+
return process.cwd();
|
|
17
|
+
} catch {
|
|
18
|
+
const projectRoot = process.env.GSD_PROJECT_ROOT;
|
|
19
|
+
if (projectRoot && existsSync(projectRoot)) return projectRoot;
|
|
20
|
+
return homedir();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function resolveCtxCwd(ctx?: unknown): string {
|
|
12
25
|
if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
|
|
13
|
-
|
|
26
|
+
const cwd = (ctx as { cwd: string }).cwd;
|
|
27
|
+
if (existsSync(cwd)) return cwd;
|
|
14
28
|
}
|
|
15
|
-
return
|
|
29
|
+
return safeWorkspaceCwd();
|
|
16
30
|
}
|
|
17
31
|
|
|
18
32
|
/**
|
|
@@ -25,7 +39,7 @@ export function resolveProjectRootDbPath(basePath: string): string {
|
|
|
25
39
|
return resolveGsdPathContract(basePath).projectDb;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
export async function ensureDbOpen(basePath: string =
|
|
42
|
+
export async function ensureDbOpen(basePath: string = safeWorkspaceCwd()): Promise<boolean> {
|
|
29
43
|
try {
|
|
30
44
|
const db = await import("../gsd-db.js");
|
|
31
45
|
const contract = resolveGsdPathContract(basePath);
|
|
@@ -57,7 +71,8 @@ export async function ensureDbOpen(basePath: string = process.cwd()): Promise<bo
|
|
|
57
71
|
}
|
|
58
72
|
|
|
59
73
|
export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
60
|
-
const
|
|
74
|
+
const fallbackRoot = safeWorkspaceCwd();
|
|
75
|
+
const baseBash = createBashTool(fallbackRoot, {
|
|
61
76
|
spawnHook: (ctx) => ctx,
|
|
62
77
|
});
|
|
63
78
|
const dynamicBash = {
|
|
@@ -69,7 +84,7 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
|
69
84
|
onUpdate?: unknown,
|
|
70
85
|
ctx?: unknown,
|
|
71
86
|
) => {
|
|
72
|
-
const basePath =
|
|
87
|
+
const basePath = resolveCtxCwd(ctx);
|
|
73
88
|
const fresh = createBashTool(basePath, {
|
|
74
89
|
spawnHook: (spawnCtx) => ({ ...spawnCtx, cwd: basePath }),
|
|
75
90
|
});
|
|
@@ -82,7 +97,7 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
|
82
97
|
};
|
|
83
98
|
pi.registerTool(dynamicBash as any);
|
|
84
99
|
|
|
85
|
-
const baseWrite = createWriteTool(
|
|
100
|
+
const baseWrite = createWriteTool(fallbackRoot);
|
|
86
101
|
pi.registerTool({
|
|
87
102
|
...baseWrite,
|
|
88
103
|
execute: async (
|
|
@@ -92,12 +107,12 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
|
92
107
|
onUpdate?: unknown,
|
|
93
108
|
ctx?: unknown,
|
|
94
109
|
) => {
|
|
95
|
-
const fresh = createWriteTool(
|
|
110
|
+
const fresh = createWriteTool(resolveCtxCwd(ctx));
|
|
96
111
|
return (fresh as any).execute(toolCallId, params, signal, onUpdate, ctx);
|
|
97
112
|
},
|
|
98
113
|
} as any);
|
|
99
114
|
|
|
100
|
-
const baseRead = createReadTool(
|
|
115
|
+
const baseRead = createReadTool(fallbackRoot);
|
|
101
116
|
pi.registerTool({
|
|
102
117
|
...baseRead,
|
|
103
118
|
execute: async (
|
|
@@ -107,12 +122,12 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
|
107
122
|
onUpdate?: unknown,
|
|
108
123
|
ctx?: unknown,
|
|
109
124
|
) => {
|
|
110
|
-
const fresh = createReadTool(
|
|
125
|
+
const fresh = createReadTool(resolveCtxCwd(ctx));
|
|
111
126
|
return (fresh as any).execute(toolCallId, params, signal, onUpdate, ctx);
|
|
112
127
|
},
|
|
113
128
|
} as any);
|
|
114
129
|
|
|
115
|
-
const baseEdit = createEditTool(
|
|
130
|
+
const baseEdit = createEditTool(fallbackRoot);
|
|
116
131
|
pi.registerTool({
|
|
117
132
|
...baseEdit,
|
|
118
133
|
execute: async (
|
|
@@ -122,7 +137,7 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
|
|
|
122
137
|
onUpdate?: unknown,
|
|
123
138
|
ctx?: unknown,
|
|
124
139
|
) => {
|
|
125
|
-
const fresh = createEditTool(
|
|
140
|
+
const fresh = createEditTool(resolveCtxCwd(ctx));
|
|
126
141
|
return (fresh as any).execute(toolCallId, params, signal, onUpdate, ctx);
|
|
127
142
|
},
|
|
128
143
|
} as any);
|