gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.20138ae42
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 +50 -31
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +5 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +30 -1
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
- package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
- package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
- package/dist/resources/extensions/gsd/auto-start.js +85 -12
- package/dist/resources/extensions/gsd/auto-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +158 -55
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -1
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- 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/git-service.js +39 -1
- package/dist/resources/extensions/gsd/gsd-db.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow.js +93 -111
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- 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 +48 -12
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- 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/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/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- 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/status-guards.js +4 -0
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +8 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
- package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- 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/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/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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 +3 -3
- 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/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 +12 -12
- 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.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +6 -5
- 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 +14 -3
- 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-parity.test.ts +244 -0
- 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-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- 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/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- 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/src/providers/transform-messages.ts +24 -0
- 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/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.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/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- 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/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- 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/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +8 -5
- package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +36 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
- package/src/resources/extensions/gsd/auto-start.ts +92 -9
- package/src/resources/extensions/gsd/auto-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
- package/src/resources/extensions/gsd/auto.ts +167 -53
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -1
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/git-service.ts +45 -1
- package/src/resources/extensions/gsd/gsd-db.ts +3 -0
- package/src/resources/extensions/gsd/guided-flow.ts +126 -128
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- 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 +54 -12
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- 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/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/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- 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/status-guards.ts +5 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +8 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
- 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 +129 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
- 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 +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -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 +11 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- 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/integration/doctor-git.test.ts +44 -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 +103 -1
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -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 +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- 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/plan-milestone-sketch-render.test.ts +157 -0
- 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 +225 -1
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
- 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 +86 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -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/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -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 +1 -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 +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/shared/html-shell.ts +412 -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/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/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/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/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// GSD-2 — ADR-005 Phase 3b: ProviderSwitchObserver Tests
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { mkdtempSync, readFileSync, rmSync, existsSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
|
|
8
|
+
import { setProviderSwitchObserver, type ProviderSwitchReport } from "@gsd/pi-ai";
|
|
9
|
+
|
|
10
|
+
import { autoSession } from "../auto-runtime-state.ts";
|
|
11
|
+
import {
|
|
12
|
+
initNotificationStore,
|
|
13
|
+
readNotifications,
|
|
14
|
+
_resetNotificationStore,
|
|
15
|
+
} from "../notification-store.ts";
|
|
16
|
+
import {
|
|
17
|
+
_resetProviderSwitchStats,
|
|
18
|
+
getProviderSwitchStats,
|
|
19
|
+
installProviderSwitchObserver,
|
|
20
|
+
uninstallProviderSwitchObserver,
|
|
21
|
+
} from "../provider-switch-observer.ts";
|
|
22
|
+
|
|
23
|
+
function makeReport(overrides: Partial<ProviderSwitchReport> = {}): ProviderSwitchReport {
|
|
24
|
+
return {
|
|
25
|
+
fromApi: "anthropic-messages",
|
|
26
|
+
toApi: "openai-responses",
|
|
27
|
+
thinkingBlocksDropped: 0,
|
|
28
|
+
thinkingBlocksDowngraded: 0,
|
|
29
|
+
toolCallIdsRemapped: 0,
|
|
30
|
+
syntheticToolResultsInserted: 0,
|
|
31
|
+
thoughtSignaturesDropped: 0,
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function withTempBasePath(): { basePath: string; cleanup: () => void } {
|
|
37
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-provider-switch-"));
|
|
38
|
+
return {
|
|
39
|
+
basePath,
|
|
40
|
+
cleanup: () => rmSync(basePath, { recursive: true, force: true }),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test.beforeEach(() => {
|
|
45
|
+
_resetProviderSwitchStats();
|
|
46
|
+
_resetNotificationStore();
|
|
47
|
+
autoSession.currentTraceId = null;
|
|
48
|
+
autoSession.basePath = "";
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test.afterEach(() => {
|
|
52
|
+
uninstallProviderSwitchObserver();
|
|
53
|
+
_resetNotificationStore();
|
|
54
|
+
autoSession.currentTraceId = null;
|
|
55
|
+
autoSession.basePath = "";
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("installProviderSwitchObserver wires the pi-ai observer hook", () => {
|
|
59
|
+
installProviderSwitchObserver();
|
|
60
|
+
// Indirect: a second install is a no-op. We verify by checking the counter
|
|
61
|
+
// increments exactly once when we fire a single report directly into pi-ai's
|
|
62
|
+
// observer slot.
|
|
63
|
+
installProviderSwitchObserver();
|
|
64
|
+
|
|
65
|
+
// Drive the pi-ai observer directly. The install above pointed it at our
|
|
66
|
+
// handler; firing here exercises the same code path as a real transform.
|
|
67
|
+
// We can't reach the installed handler reference from here, so we re-install
|
|
68
|
+
// a sentinel and confirm setProviderSwitchObserver accepts undefined.
|
|
69
|
+
setProviderSwitchObserver(undefined);
|
|
70
|
+
assert.ok(true); // install/uninstall did not throw
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("non-empty report increments the in-memory counter", () => {
|
|
74
|
+
installProviderSwitchObserver();
|
|
75
|
+
|
|
76
|
+
// Reach into the installed handler via setProviderSwitchObserver re-binding.
|
|
77
|
+
// We snapshot the handler by re-installing, capturing nothing — instead we
|
|
78
|
+
// use the public API: drive a report through the observer hook directly by
|
|
79
|
+
// calling setProviderSwitchObserver with a wrapper that proxies into the
|
|
80
|
+
// installed handler. This is awkward without a separate seam, so we test
|
|
81
|
+
// the recordReport path end-to-end by firing through pi-ai's transform helper
|
|
82
|
+
// pattern in a sibling test below. Here we exercise install idempotency only.
|
|
83
|
+
|
|
84
|
+
// Fire by setting our own observer that forwards to the module API isn't
|
|
85
|
+
// possible without exporting handleReport. Instead, verify install state
|
|
86
|
+
// doesn't crash; the real fire path is covered by the integration test
|
|
87
|
+
// below that exercises transformMessagesWithReport.
|
|
88
|
+
assert.deepEqual(getProviderSwitchStats().totalSwitches, 0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("end-to-end: transformMessagesWithReport fires the observer and updates stats + notifications", async () => {
|
|
92
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
93
|
+
|
|
94
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
95
|
+
try {
|
|
96
|
+
initNotificationStore(basePath);
|
|
97
|
+
installProviderSwitchObserver();
|
|
98
|
+
|
|
99
|
+
// Construct a cross-API transform that will drop a redacted thinking block.
|
|
100
|
+
const targetModel = {
|
|
101
|
+
id: "gpt-5",
|
|
102
|
+
name: "GPT-5",
|
|
103
|
+
api: "openai-responses",
|
|
104
|
+
provider: "openai",
|
|
105
|
+
baseUrl: "",
|
|
106
|
+
reasoning: false,
|
|
107
|
+
input: ["text"],
|
|
108
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
109
|
+
contextWindow: 128000,
|
|
110
|
+
maxTokens: 8192,
|
|
111
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
112
|
+
|
|
113
|
+
const messages = [
|
|
114
|
+
{
|
|
115
|
+
role: "assistant" as const,
|
|
116
|
+
content: [
|
|
117
|
+
{ type: "thinking" as const, thinking: "", redacted: true },
|
|
118
|
+
{ type: "text" as const, text: "hi" },
|
|
119
|
+
],
|
|
120
|
+
api: "anthropic-messages",
|
|
121
|
+
provider: "anthropic",
|
|
122
|
+
model: "claude-sonnet-4-6",
|
|
123
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
124
|
+
stopReason: "stop" as const,
|
|
125
|
+
timestamp: Date.now(),
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
transformMessagesWithReport(messages as Parameters<typeof transformMessagesWithReport>[0], targetModel, undefined, "anthropic-messages");
|
|
130
|
+
|
|
131
|
+
const stats = getProviderSwitchStats();
|
|
132
|
+
assert.equal(stats.totalSwitches, 1, "non-empty report should bump the counter");
|
|
133
|
+
assert.ok(stats.totals.thinkingBlocksDropped >= 1, "thinking block drop should be tallied");
|
|
134
|
+
assert.ok(stats.lastReport, "last report should be retained");
|
|
135
|
+
assert.equal(stats.lastReport?.fromApi, "anthropic-messages");
|
|
136
|
+
assert.equal(stats.lastReport?.toApi, "openai-responses");
|
|
137
|
+
|
|
138
|
+
// Notification persistence — the observer is interactive (no traceId), so
|
|
139
|
+
// the byTrace key falls back to "interactive".
|
|
140
|
+
assert.ok("interactive" in stats.byTrace, "interactive trace bucket should exist");
|
|
141
|
+
assert.equal(stats.byTrace.interactive?.switches, 1);
|
|
142
|
+
|
|
143
|
+
const notifications = readNotifications(basePath);
|
|
144
|
+
const switchNotifs = notifications.filter((n) => n.message.includes("Provider switch"));
|
|
145
|
+
assert.ok(switchNotifs.length >= 1, "a provider-switch notification should be persisted");
|
|
146
|
+
assert.equal(switchNotifs[0]?.severity, "warning");
|
|
147
|
+
} finally {
|
|
148
|
+
cleanup();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("end-to-end: audit event is emitted when an auto trace is active", async () => {
|
|
153
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
154
|
+
|
|
155
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
156
|
+
try {
|
|
157
|
+
initNotificationStore(basePath);
|
|
158
|
+
installProviderSwitchObserver();
|
|
159
|
+
autoSession.basePath = basePath;
|
|
160
|
+
autoSession.currentTraceId = "trace-provider-switch-1";
|
|
161
|
+
|
|
162
|
+
const targetModel = {
|
|
163
|
+
id: "gpt-5",
|
|
164
|
+
name: "GPT-5",
|
|
165
|
+
api: "openai-responses",
|
|
166
|
+
provider: "openai",
|
|
167
|
+
baseUrl: "",
|
|
168
|
+
reasoning: false,
|
|
169
|
+
input: ["text"],
|
|
170
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
171
|
+
contextWindow: 128000,
|
|
172
|
+
maxTokens: 8192,
|
|
173
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
174
|
+
|
|
175
|
+
const messages = [
|
|
176
|
+
{
|
|
177
|
+
role: "assistant" as const,
|
|
178
|
+
content: [
|
|
179
|
+
{ type: "thinking" as const, thinking: "", redacted: true },
|
|
180
|
+
{ type: "text" as const, text: "hi" },
|
|
181
|
+
],
|
|
182
|
+
api: "anthropic-messages",
|
|
183
|
+
provider: "anthropic",
|
|
184
|
+
model: "claude-sonnet-4-6",
|
|
185
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
186
|
+
stopReason: "stop" as const,
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
transformMessagesWithReport(messages as Parameters<typeof transformMessagesWithReport>[0], targetModel, undefined, "anthropic-messages");
|
|
192
|
+
|
|
193
|
+
const auditLogPath = join(basePath, ".gsd", "audit", "events.jsonl");
|
|
194
|
+
assert.ok(existsSync(auditLogPath), "audit events file should be created");
|
|
195
|
+
const auditLines = readFileSync(auditLogPath, "utf-8")
|
|
196
|
+
.trim()
|
|
197
|
+
.split("\n")
|
|
198
|
+
.map((line) => JSON.parse(line) as { category: string; type: string; traceId: string; payload: Record<string, unknown> });
|
|
199
|
+
const switchEvent = auditLines.find((e) => e.category === "model-policy" && e.type === "provider-switch");
|
|
200
|
+
assert.ok(switchEvent, "a model-policy/provider-switch audit event should be present");
|
|
201
|
+
assert.equal(switchEvent?.traceId, "trace-provider-switch-1");
|
|
202
|
+
assert.equal(switchEvent?.payload.fromApi, "anthropic-messages");
|
|
203
|
+
assert.equal(switchEvent?.payload.toApi, "openai-responses");
|
|
204
|
+
|
|
205
|
+
const stats = getProviderSwitchStats();
|
|
206
|
+
assert.ok("trace-provider-switch-1" in stats.byTrace, "trace-keyed bucket should be populated");
|
|
207
|
+
assert.equal(stats.byTrace["trace-provider-switch-1"]?.switches, 1);
|
|
208
|
+
} finally {
|
|
209
|
+
cleanup();
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("empty report does not bump counter or emit a notification", async () => {
|
|
214
|
+
const { transformMessagesWithReport } = await import("@gsd/pi-ai");
|
|
215
|
+
|
|
216
|
+
const { basePath, cleanup } = withTempBasePath();
|
|
217
|
+
try {
|
|
218
|
+
initNotificationStore(basePath);
|
|
219
|
+
installProviderSwitchObserver();
|
|
220
|
+
|
|
221
|
+
// Same-API transform → no transformations → empty report.
|
|
222
|
+
const sameApiModel = {
|
|
223
|
+
id: "claude-sonnet-4-6",
|
|
224
|
+
name: "Claude Sonnet 4.6",
|
|
225
|
+
api: "anthropic-messages",
|
|
226
|
+
provider: "anthropic",
|
|
227
|
+
baseUrl: "",
|
|
228
|
+
reasoning: false,
|
|
229
|
+
input: ["text"],
|
|
230
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
231
|
+
contextWindow: 200000,
|
|
232
|
+
maxTokens: 8192,
|
|
233
|
+
} as Parameters<typeof transformMessagesWithReport>[1];
|
|
234
|
+
|
|
235
|
+
transformMessagesWithReport(
|
|
236
|
+
[
|
|
237
|
+
{
|
|
238
|
+
role: "user" as const,
|
|
239
|
+
content: "plain text — no transforms triggered",
|
|
240
|
+
},
|
|
241
|
+
] as Parameters<typeof transformMessagesWithReport>[0],
|
|
242
|
+
sameApiModel,
|
|
243
|
+
undefined,
|
|
244
|
+
"anthropic-messages",
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
assert.equal(getProviderSwitchStats().totalSwitches, 0);
|
|
248
|
+
assert.equal(readNotifications(basePath).length, 0);
|
|
249
|
+
} finally {
|
|
250
|
+
cleanup();
|
|
251
|
+
}
|
|
252
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Regression
|
|
3
|
-
* block completion when VALIDATION
|
|
2
|
+
* Regression tests for non-passing VALIDATION verdicts: completing-milestone
|
|
3
|
+
* dispatch must block completion when VALIDATION needs remediation or attention.
|
|
4
4
|
*
|
|
5
5
|
* Without this guard, needs-remediation + allSlicesDone causes a loop:
|
|
6
6
|
* complete-milestone dispatched → agent refuses (correct) → no SUMMARY
|
|
@@ -66,6 +66,50 @@ test("completing-milestone blocks when VALIDATION verdict is needs-remediation (
|
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
test("completing-milestone blocks when VALIDATION verdict is needs-attention (#5747)", async () => {
|
|
70
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-attention-"));
|
|
71
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
writeFileSync(
|
|
75
|
+
join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md"),
|
|
76
|
+
[
|
|
77
|
+
"---",
|
|
78
|
+
"verdict: needs-attention",
|
|
79
|
+
"remediation_round: 0",
|
|
80
|
+
"---",
|
|
81
|
+
"",
|
|
82
|
+
"# Validation Report",
|
|
83
|
+
"",
|
|
84
|
+
"Acceptance proof is incomplete and needs human attention.",
|
|
85
|
+
].join("\n"),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const ctx = {
|
|
89
|
+
mid: "M001",
|
|
90
|
+
midTitle: "Test Milestone",
|
|
91
|
+
basePath: base,
|
|
92
|
+
state: { phase: "completing-milestone" } as any,
|
|
93
|
+
prefs: {} as any,
|
|
94
|
+
session: undefined,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const result = await completingRule!.match(ctx);
|
|
98
|
+
|
|
99
|
+
assert.ok(result !== null, "rule should match");
|
|
100
|
+
assert.equal(result!.action, "stop", "should return stop action");
|
|
101
|
+
if (result!.action === "stop") {
|
|
102
|
+
assert.equal(result!.level, "warning", "should be warning level (pausable)");
|
|
103
|
+
assert.ok(
|
|
104
|
+
result!.reason.includes("needs-attention"),
|
|
105
|
+
"reason should mention needs-attention",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
rmSync(base, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
69
113
|
test("completing-milestone proceeds normally when VALIDATION verdict is pass (#2675 guard)", async () => {
|
|
70
114
|
const base = mkdtempSync(join(tmpdir(), "gsd-remediation-"));
|
|
71
115
|
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Verifies GSD session hook widget and footer lifecycle behavior.
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* session-start-footer.test.ts
|
|
3
|
-
*
|
|
4
5
|
* Verifies that register-hooks.ts suppresses the gsd-health widget (not the
|
|
5
|
-
* built-in footer) when isAutoActive() is true,
|
|
6
|
-
*
|
|
6
|
+
* built-in footer) when isAutoActive() is true, clears stale completion widgets
|
|
7
|
+
* on inactive session switches, and that setFooter is never called by the
|
|
8
|
+
* extension in either session_start or session_switch.
|
|
7
9
|
*
|
|
8
10
|
* Testing strategy:
|
|
9
11
|
* 1. Source-code regression guards: structural checks on register-hooks.ts.
|
|
@@ -139,6 +141,16 @@ test("session_switch toggles gsd-health from runtime auto state without touching
|
|
|
139
141
|
widgetCalls.length = 0;
|
|
140
142
|
autoSession.active = false;
|
|
141
143
|
await sessionSwitch!({ reason: "resume" }, ctx);
|
|
144
|
+
assert.deepEqual(
|
|
145
|
+
widgetCalls
|
|
146
|
+
.filter((call) => call.key === "gsd-progress" || call.key === "gsd-outcome")
|
|
147
|
+
.map((call) => [call.key, call.value]),
|
|
148
|
+
[
|
|
149
|
+
["gsd-progress", undefined],
|
|
150
|
+
["gsd-outcome", undefined],
|
|
151
|
+
],
|
|
152
|
+
"session_switch should clear stale GSD completion widgets when auto is inactive",
|
|
153
|
+
);
|
|
142
154
|
const healthWidgetValues = widgetCalls
|
|
143
155
|
.filter((call) => call.key === "gsd-health")
|
|
144
156
|
.map((call) => call.value);
|
|
@@ -5,6 +5,7 @@ import test from "node:test";
|
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
_hasEmptyAgentEndContent,
|
|
8
9
|
_handleSessionSwitchAgentEnd,
|
|
9
10
|
isBareClaudeCodeStreamAbortPlaceholder,
|
|
10
11
|
isClaudeCodeSessionSwitchAbortMessage,
|
|
@@ -188,6 +189,15 @@ test("empty-content aborted during session-switch is silently ignored", () => {
|
|
|
188
189
|
assert.equal(cancelledWith, null);
|
|
189
190
|
});
|
|
190
191
|
|
|
192
|
+
test("missing agent_end content is classified as empty abort content", () => {
|
|
193
|
+
// Providers may omit content entirely for a late aborted agent_end. That is
|
|
194
|
+
// equivalent to empty content and must not pause/cancel the next unit.
|
|
195
|
+
assert.equal(_hasEmptyAgentEndContent(undefined), true);
|
|
196
|
+
assert.equal(_hasEmptyAgentEndContent(null), true);
|
|
197
|
+
assert.equal(_hasEmptyAgentEndContent([]), true);
|
|
198
|
+
assert.equal(_hasEmptyAgentEndContent([{ type: "text", text: "partial" }]), false);
|
|
199
|
+
});
|
|
200
|
+
|
|
191
201
|
test("completed assistant content with aborted stopReason during session-switch is ignored", () => {
|
|
192
202
|
// newSession() can abort the just-finished provider stream while the last
|
|
193
203
|
// assistant message still carries the completed unit summary. That is a
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// GSD-2 — Smart entry routing behavior tests.
|
|
2
|
+
// Verifies guided wizard choices resolve to the correct execution path.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
resolveActiveTaskChoiceRoute,
|
|
9
|
+
resolveGuidedExecuteLaunchMode,
|
|
10
|
+
type ActiveTaskChoice,
|
|
11
|
+
type ActiveTaskRoute,
|
|
12
|
+
type SmartEntryIsolationMode,
|
|
13
|
+
} from "../smart-entry-routing.ts";
|
|
14
|
+
|
|
15
|
+
test("guided execute route enters auto step bootstrap only for worktree isolation", () => {
|
|
16
|
+
const cases: Array<{
|
|
17
|
+
isolationMode: SmartEntryIsolationMode;
|
|
18
|
+
expectedRoute: ActiveTaskRoute;
|
|
19
|
+
}> = [
|
|
20
|
+
{
|
|
21
|
+
isolationMode: "worktree",
|
|
22
|
+
expectedRoute: {
|
|
23
|
+
kind: "auto-bootstrap",
|
|
24
|
+
verboseMode: false,
|
|
25
|
+
options: {
|
|
26
|
+
step: true,
|
|
27
|
+
milestoneLock: "M001",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
isolationMode: "none",
|
|
33
|
+
expectedRoute: {
|
|
34
|
+
kind: "guided-dispatch",
|
|
35
|
+
unitType: "execute-task",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
isolationMode: "branch",
|
|
40
|
+
expectedRoute: {
|
|
41
|
+
kind: "guided-dispatch",
|
|
42
|
+
unitType: "execute-task",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (const testCase of cases) {
|
|
48
|
+
assert.deepEqual(
|
|
49
|
+
resolveActiveTaskChoiceRoute({
|
|
50
|
+
choice: "execute",
|
|
51
|
+
isolationMode: testCase.isolationMode,
|
|
52
|
+
milestoneId: "M001",
|
|
53
|
+
}),
|
|
54
|
+
testCase.expectedRoute,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("active task smart entry choices resolve to explicit routes", () => {
|
|
60
|
+
const cases: Array<{
|
|
61
|
+
choice: ActiveTaskChoice;
|
|
62
|
+
expectedRoute: ActiveTaskRoute;
|
|
63
|
+
}> = [
|
|
64
|
+
{
|
|
65
|
+
choice: "auto",
|
|
66
|
+
expectedRoute: {
|
|
67
|
+
kind: "auto-bootstrap",
|
|
68
|
+
verboseMode: false,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
choice: "status",
|
|
73
|
+
expectedRoute: {
|
|
74
|
+
kind: "status",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
choice: "milestone_actions",
|
|
79
|
+
expectedRoute: {
|
|
80
|
+
kind: "milestone-actions",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (const testCase of cases) {
|
|
86
|
+
assert.deepEqual(
|
|
87
|
+
resolveActiveTaskChoiceRoute({
|
|
88
|
+
choice: testCase.choice,
|
|
89
|
+
isolationMode: "worktree",
|
|
90
|
+
milestoneId: "M001",
|
|
91
|
+
}),
|
|
92
|
+
testCase.expectedRoute,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("active task route rejects invalid choices from untyped callers", () => {
|
|
98
|
+
assert.throws(
|
|
99
|
+
() =>
|
|
100
|
+
resolveActiveTaskChoiceRoute({
|
|
101
|
+
choice: "not_yet" as ActiveTaskChoice,
|
|
102
|
+
isolationMode: "worktree",
|
|
103
|
+
milestoneId: "M001",
|
|
104
|
+
}),
|
|
105
|
+
/Invalid ActiveTaskChoice: not_yet/,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("guided execute launch mode remains a small compatibility helper", () => {
|
|
110
|
+
assert.equal(resolveGuidedExecuteLaunchMode("worktree"), "auto-step");
|
|
111
|
+
assert.equal(resolveGuidedExecuteLaunchMode("none"), "guided-dispatch");
|
|
112
|
+
assert.equal(resolveGuidedExecuteLaunchMode("branch"), "guided-dispatch");
|
|
113
|
+
});
|
|
@@ -4,7 +4,10 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
|
|
6
6
|
import { _withDetachedAutoKeepaliveForTest } from "../auto.ts";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
_scheduleAutoStartAfterIdleForTest,
|
|
9
|
+
resolveGuidedExecuteLaunchMode,
|
|
10
|
+
} from "../guided-flow.ts";
|
|
8
11
|
|
|
9
12
|
const gsdDir = resolve(import.meta.dirname, "..");
|
|
10
13
|
|
|
@@ -64,6 +67,24 @@ test("bare /gsd stays in the foreground smart-entry flow (#5125 regression)", ()
|
|
|
64
67
|
);
|
|
65
68
|
});
|
|
66
69
|
|
|
70
|
+
test("guided execute uses auto step bootstrap when worktree isolation is enabled", () => {
|
|
71
|
+
assert.equal(
|
|
72
|
+
resolveGuidedExecuteLaunchMode("worktree"),
|
|
73
|
+
"auto-step",
|
|
74
|
+
"guided execute must enter auto bootstrap so the milestone worktree is created before execution",
|
|
75
|
+
);
|
|
76
|
+
assert.equal(
|
|
77
|
+
resolveGuidedExecuteLaunchMode("none"),
|
|
78
|
+
"guided-dispatch",
|
|
79
|
+
"non-isolated projects can keep the foreground guided dispatch path",
|
|
80
|
+
);
|
|
81
|
+
assert.equal(
|
|
82
|
+
resolveGuidedExecuteLaunchMode("branch"),
|
|
83
|
+
"guided-dispatch",
|
|
84
|
+
"this regression fix is scoped to worktree isolation",
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
67
88
|
test("auto bootstrap validates blocked directories before touching .gsd migration state", () => {
|
|
68
89
|
const autoSrc = readGsdFile("auto.ts");
|
|
69
90
|
const autoStartSrc = readGsdFile("auto-start.ts");
|
|
@@ -99,19 +120,49 @@ test("auto bootstrap validates blocked directories before touching .gsd migratio
|
|
|
99
120
|
|
|
100
121
|
test("fresh start registers the auto worker before bootstrap enters worktree flow (#5405)", () => {
|
|
101
122
|
const autoSrc = readGsdFile("auto.ts");
|
|
123
|
+
const autoStartSrc = readGsdFile("auto-start.ts");
|
|
102
124
|
const startAutoIdx = autoSrc.indexOf("export async function startAuto(");
|
|
103
125
|
const startAutoBody = autoSrc.slice(startAutoIdx);
|
|
126
|
+
const bootstrapIdx = autoStartSrc.indexOf("export async function bootstrapAutoSession(");
|
|
127
|
+
const bootstrapBody = autoStartSrc.slice(bootstrapIdx);
|
|
104
128
|
|
|
105
|
-
const preBootstrapRegisterIdx = startAutoBody.indexOf("registerAutoWorkerForSession(s, base);");
|
|
106
129
|
const bootstrapCallIdx = startAutoBody.indexOf("const ready = await bootstrapAutoSession(");
|
|
130
|
+
const preBootstrapBody = startAutoBody.slice(0, bootstrapCallIdx);
|
|
131
|
+
const preBootstrapRegisterIdx = preBootstrapBody.lastIndexOf("registerAutoWorkerForSession(s, base);");
|
|
132
|
+
const resumeSectionIdx = startAutoBody.indexOf("if (s.paused) {");
|
|
133
|
+
const freshStartSectionIdx = startAutoBody.indexOf("// ── Fresh start path — delegated to auto-start.ts ──");
|
|
134
|
+
const resumeBody = startAutoBody.slice(resumeSectionIdx, freshStartSectionIdx);
|
|
135
|
+
const resumeDbOpenIdx = resumeBody.indexOf("await openProjectDbIfPresent(base);");
|
|
136
|
+
const resumeRegisterIdx = resumeBody.indexOf("registerAutoWorkerForSession(s, base);");
|
|
137
|
+
const resumeEnterMilestoneIdx = resumeBody.indexOf("buildLifecycle().enterMilestone");
|
|
138
|
+
const dbOpenIdx = bootstrapBody.indexOf("await openProjectDbIfPresent(base);");
|
|
139
|
+
const bootstrapRegisterIdx = bootstrapBody.indexOf("registerAutoWorkerForSession(base);");
|
|
140
|
+
const enterMilestoneIdx = bootstrapBody.indexOf("buildLifecycle().enterMilestone");
|
|
107
141
|
|
|
108
142
|
assert.ok(startAutoIdx > -1, "startAuto should exist");
|
|
109
143
|
assert.ok(preBootstrapRegisterIdx > -1, "startAuto should register worker before bootstrap");
|
|
110
144
|
assert.ok(bootstrapCallIdx > -1, "startAuto should call bootstrapAutoSession");
|
|
145
|
+
assert.ok(resumeSectionIdx > -1, "startAuto should have resume milestone entry flow");
|
|
146
|
+
assert.ok(freshStartSectionIdx > resumeSectionIdx, "resume assertions should be scoped before fresh start");
|
|
147
|
+
assert.ok(resumeDbOpenIdx > -1, "resume should open DB before milestone entry");
|
|
148
|
+
assert.ok(resumeRegisterIdx > -1, "resume should register worker before milestone entry");
|
|
149
|
+
assert.ok(resumeEnterMilestoneIdx > -1, "resume should enter milestones through lifecycle");
|
|
150
|
+
assert.ok(bootstrapIdx > -1, "bootstrapAutoSession should exist");
|
|
151
|
+
assert.ok(dbOpenIdx > -1, "bootstrap should open the project DB");
|
|
152
|
+
assert.ok(bootstrapRegisterIdx > -1, "bootstrap should register worker after DB open");
|
|
153
|
+
assert.ok(enterMilestoneIdx > -1, "bootstrap should enter milestones through lifecycle");
|
|
111
154
|
assert.ok(
|
|
112
155
|
preBootstrapRegisterIdx < bootstrapCallIdx,
|
|
113
156
|
"worker registration must happen before bootstrap so enterMilestone can claim milestone leases on first entry",
|
|
114
157
|
);
|
|
158
|
+
assert.ok(
|
|
159
|
+
dbOpenIdx < bootstrapRegisterIdx && bootstrapRegisterIdx < enterMilestoneIdx,
|
|
160
|
+
"bootstrap must open DB and register worker before first enterMilestone",
|
|
161
|
+
);
|
|
162
|
+
assert.ok(
|
|
163
|
+
resumeDbOpenIdx < resumeRegisterIdx && resumeRegisterIdx < resumeEnterMilestoneIdx,
|
|
164
|
+
"resume must open DB and register worker before first enterMilestone",
|
|
165
|
+
);
|
|
115
166
|
});
|
|
116
167
|
|
|
117
168
|
test("startAutoDetached reports failures asynchronously (#3733)", () => {
|
|
@@ -271,6 +271,11 @@ describe("#2945 Bug 3: mergeAndExit must teardown worktree after successful merg
|
|
|
271
271
|
// a real git fixture and verify the worktree directory is removed
|
|
272
272
|
// from disk after the merge.
|
|
273
273
|
const tmpBase = realpathSync(mkdtempSync(join(tmpdir(), "gsd-2945-bug3-")));
|
|
274
|
+
// ADR-016 phase 3 (#5693): Lifecycle.restoreToProjectRoot now chdirs to
|
|
275
|
+
// s.originalBasePath. Save cwd before the test so we can restore it
|
|
276
|
+
// before rmSync removes tmpBase — otherwise the next test in this file
|
|
277
|
+
// inherits a deleted cwd and process.cwd() throws ENOENT (uv_cwd).
|
|
278
|
+
const prevCwd = process.cwd();
|
|
274
279
|
try {
|
|
275
280
|
const git = (args: string[]): void => {
|
|
276
281
|
execFileSync("git", args, { cwd: tmpBase, stdio: "pipe" });
|
|
@@ -325,6 +330,7 @@ describe("#2945 Bug 3: mergeAndExit must teardown worktree after successful merg
|
|
|
325
330
|
`teardownAutoWorktree must be called after successful merge — worktree directory at ${wt} should be removed`,
|
|
326
331
|
);
|
|
327
332
|
} finally {
|
|
333
|
+
try { process.chdir(prevCwd); } catch { /* noop */ }
|
|
328
334
|
try { rmSync(tmpBase, { recursive: true, force: true }); } catch { /* noop */ }
|
|
329
335
|
}
|
|
330
336
|
});
|