gsd-pi 2.78.0 → 2.78.1-dev.82bcf6b71
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 +60 -23
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +104 -33
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +43 -8
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +9 -13
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +30 -13
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +128 -32
- package/dist/resources/extensions/google-search/index.js +2 -6
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +5 -13
- package/dist/resources/extensions/gsd/auto/run-unit.js +26 -12
- package/dist/resources/extensions/gsd/auto/session.js +5 -6
- package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +55 -21
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +69 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +75 -13
- package/dist/resources/extensions/gsd/auto.js +39 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +112 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +45 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
- package/dist/resources/extensions/gsd/commands-config.js +3 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +309 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +10 -8
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +25 -24
- package/dist/resources/extensions/gsd/home-dir.js +16 -0
- package/dist/resources/extensions/gsd/key-manager.js +2 -1
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/migrate/command.js +3 -2
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +28 -13
- package/dist/resources/extensions/gsd/worktree-root.js +124 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/gsd/worktree.js +4 -115
- package/dist/resources/extensions/mcp-client/index.js +6 -9
- package/dist/resources/extensions/ollama/index.js +15 -2
- package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
- package/dist/resources/extensions/ollama/ollama-client.js +40 -4
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/extensions/subagent/index.js +324 -178
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/skills/lint/SKILL.md +4 -0
- package/dist/resources/skills/review/SKILL.md +4 -0
- package/dist/resources/skills/test/SKILL.md +3 -0
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -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 +19 -19
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +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_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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- 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 +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- 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/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/package.json +2 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +27 -1
- package/dist/worktree-cli.d.ts +1 -0
- package/dist/worktree-cli.js +9 -3
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -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/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
- package/src/resources/extensions/google-search/index.ts +2 -9
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +6 -14
- package/src/resources/extensions/gsd/auto/run-unit.ts +26 -12
- package/src/resources/extensions/gsd/auto/session.ts +5 -6
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +60 -24
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +66 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +97 -12
- package/src/resources/extensions/gsd/auto.ts +37 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +121 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- package/src/resources/extensions/gsd/commands-config.ts +3 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +12 -7
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +27 -26
- package/src/resources/extensions/gsd/home-dir.ts +19 -0
- package/src/resources/extensions/gsd/journal.ts +4 -1
- package/src/resources/extensions/gsd/key-manager.ts +2 -1
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +179 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +50 -27
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +25 -65
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +8 -2
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +235 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
- package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +28 -14
- package/src/resources/extensions/gsd/worktree-root.ts +144 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/gsd/worktree.ts +8 -119
- package/src/resources/extensions/mcp-client/index.ts +6 -10
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/ollama/index.ts +16 -2
- package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
- package/src/resources/extensions/ollama/ollama-client.ts +41 -4
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
- package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/extensions/subagent/index.ts +165 -7
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/src/resources/skills/lint/SKILL.md +4 -0
- package/src/resources/skills/review/SKILL.md +4 -0
- package/src/resources/skills/test/SKILL.md +3 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → hcvW7f3yv1JHzlWe7tIc6}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → hcvW7f3yv1JHzlWe7tIc6}/_ssgManifest.js +0 -0
|
@@ -107,6 +107,50 @@ test("profile: resolveProfileDefaults exists and handles all 4 tiers", () => {
|
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
+
test("profile: PROFILE_TIER_MAP defines tier intentions for all profiles", async () => {
|
|
111
|
+
const { getProfileTierMap } = await import("../preferences-models.ts");
|
|
112
|
+
const profileMaps = {
|
|
113
|
+
budget: getProfileTierMap("budget"),
|
|
114
|
+
balanced: getProfileTierMap("balanced"),
|
|
115
|
+
quality: getProfileTierMap("quality"),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
assert.deepEqual(
|
|
119
|
+
Object.keys(profileMaps).sort(),
|
|
120
|
+
["balanced", "budget", "quality"],
|
|
121
|
+
"PROFILE_TIER_MAP should include the profile default tiers",
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const expectedPhaseKeys = ["completion", "execution", "execution_simple", "planning", "research", "subagent"];
|
|
125
|
+
const validTiers = new Set(["light", "standard", "heavy"]);
|
|
126
|
+
for (const [profile, tierMap] of Object.entries(profileMaps)) {
|
|
127
|
+
assert.deepEqual(
|
|
128
|
+
Object.keys(tierMap).sort(),
|
|
129
|
+
expectedPhaseKeys,
|
|
130
|
+
`${profile} should define all model-bearing phases`,
|
|
131
|
+
);
|
|
132
|
+
for (const [phase, tier] of Object.entries(tierMap)) {
|
|
133
|
+
assert.ok(validTiers.has(tier), `${profile}.${phase} should be a tier name`);
|
|
134
|
+
assert.ok(!tier.includes("claude-"), `${profile}.${phase} should not be a model ID`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("profile: resolveProfileDefaults is provider-agnostic — picks OpenAI when only OpenAI is available", async () => {
|
|
140
|
+
// Behavioral check: with only OpenAI models in the available list, no slot
|
|
141
|
+
// should resolve to a claude-* model. Source-grep cannot prove this — only
|
|
142
|
+
// exercising the function with a controlled available-model list can.
|
|
143
|
+
const { resolveProfileDefaults } = await import("../preferences-models.ts");
|
|
144
|
+
const defaults = resolveProfileDefaults("balanced", ["gpt-4o", "gpt-4o-mini"]);
|
|
145
|
+
assert.ok(defaults.models, "balanced profile should populate models");
|
|
146
|
+
for (const [phase, modelId] of Object.entries(defaults.models!)) {
|
|
147
|
+
assert.ok(
|
|
148
|
+
typeof modelId === "string" && !String(modelId).startsWith("claude-"),
|
|
149
|
+
`${phase} resolved to ${modelId} but only OpenAI is available`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
110
154
|
test("profile: budget profile sets phase skips to true", () => {
|
|
111
155
|
// Extract the budget case block
|
|
112
156
|
const budgetIdx = preferencesSrc.indexOf('case "budget":');
|
|
@@ -222,11 +266,14 @@ test("merge: mergePreferences handles phases with spread", () => {
|
|
|
222
266
|
// Subagent Model Routing
|
|
223
267
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
224
268
|
|
|
225
|
-
test("subagent: budget profile
|
|
226
|
-
|
|
227
|
-
const
|
|
269
|
+
test("subagent: budget profile assigns light tier for subagent", () => {
|
|
270
|
+
// PROFILE_TIER_MAP.budget.subagent should be "light"
|
|
271
|
+
const tierMapIdx = preferencesSrc.indexOf("PROFILE_TIER_MAP");
|
|
272
|
+
const budgetIdx = preferencesSrc.indexOf("budget:", tierMapIdx);
|
|
273
|
+
const balancedIdx = preferencesSrc.indexOf("balanced:", tierMapIdx);
|
|
228
274
|
const budgetBlock = preferencesSrc.slice(budgetIdx, balancedIdx);
|
|
229
|
-
assert.ok(budgetBlock.includes("subagent:"), "budget profile should
|
|
275
|
+
assert.ok(budgetBlock.includes("subagent:"), "budget profile should define subagent tier");
|
|
276
|
+
assert.ok(budgetBlock.includes('"light"'), "budget subagent should use light tier");
|
|
230
277
|
});
|
|
231
278
|
|
|
232
279
|
test("subagent: resolveModelWithFallbacksForUnit handles subagent unit types", () => {
|
|
@@ -144,19 +144,10 @@ test("recoverTimedOutUnit: no top-level bumpTurnGeneration — steering branches
|
|
|
144
144
|
);
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
"utf-8",
|
|
155
|
-
);
|
|
156
|
-
const matches = src.match(/bumpAndResolveSynthetic\s*\(/g) ?? [];
|
|
157
|
-
assert.equal(
|
|
158
|
-
matches.length,
|
|
159
|
-
4,
|
|
160
|
-
`expected 4 advance-branch supersede sites (durableComplete, execute-task-exhausted, artifact-already-exists, non-execute-exhausted); found ${matches.length}`,
|
|
161
|
-
);
|
|
162
|
-
});
|
|
147
|
+
// Removed: source-grep count of `bumpAndResolveSynthetic\s*\(` occurrences.
|
|
148
|
+
// A literal 4 hardcodes the current branch shape, not behaviour. The
|
|
149
|
+
// behavioural invariant — "advance branches supersede atomically; non-advance
|
|
150
|
+
// branches do not bump" — is enforced by the previous test (no direct
|
|
151
|
+
// bumpTurnGeneration calls) plus the per-branch behavioural tests above
|
|
152
|
+
// (`recoverTimedOutUnit: …`). Refactors that split a branch into two would
|
|
153
|
+
// trip a count test without affecting correctness. Refs #4851.
|
|
@@ -199,8 +199,8 @@ test("#4934: every manifest declares a tools policy", () => {
|
|
|
199
199
|
}
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
test("#4934: tools.mode is one of the
|
|
203
|
-
const validModes = new Set(["all", "read-only", "planning", "docs"]);
|
|
202
|
+
test("#4934: tools.mode is one of the declared policies", () => {
|
|
203
|
+
const validModes = new Set(["all", "read-only", "planning", "planning-dispatch", "docs"]);
|
|
204
204
|
for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
|
|
205
205
|
const mode = (manifest as { tools: { mode: string } }).tools.mode;
|
|
206
206
|
assert.ok(
|
|
@@ -219,7 +219,42 @@ test('#4934: only execute-task and reactive-execute may use tools.mode "all" (fu
|
|
|
219
219
|
allowedAllUnits.has(unitType),
|
|
220
220
|
`manifest "${unitType}" declares tools.mode = "all" but is not on the execute-track. ` +
|
|
221
221
|
'Only execute-task and reactive-execute should have full source write access; ' +
|
|
222
|
-
'planning/discuss/research units must use "planning" (or "docs" for rewrite-docs).',
|
|
222
|
+
'planning/discuss/research units must use "planning" or "planning-dispatch" (or "docs" for rewrite-docs).',
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test('planning-dispatch mode is reserved for slice-level decomposition and completion units', () => {
|
|
229
|
+
const allowedDispatchUnits = new Set([
|
|
230
|
+
"plan-slice",
|
|
231
|
+
"refine-slice",
|
|
232
|
+
"complete-slice",
|
|
233
|
+
"complete-milestone",
|
|
234
|
+
]);
|
|
235
|
+
for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
|
|
236
|
+
const mode = (manifest as { tools: { mode: string } }).tools.mode;
|
|
237
|
+
if (mode === "planning-dispatch") {
|
|
238
|
+
assert.ok(
|
|
239
|
+
allowedDispatchUnits.has(unitType),
|
|
240
|
+
`manifest "${unitType}" declares tools.mode = "planning-dispatch" but is not on the dispatch-allowed allowlist. ` +
|
|
241
|
+
'planning-dispatch is intentionally narrow — extend the allowlist consciously when a new unit type genuinely benefits from subagent delegation.',
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('planning-dispatch manifests declare non-empty allowedSubagents lists', () => {
|
|
248
|
+
for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
|
|
249
|
+
if (manifest.tools.mode !== "planning-dispatch") continue;
|
|
250
|
+
assert.ok(
|
|
251
|
+
Array.isArray(manifest.tools.allowedSubagents) && manifest.tools.allowedSubagents.length > 0,
|
|
252
|
+
`manifest "${unitType}" has planning-dispatch policy but no allowedSubagents — explicit allowlist is required for runtime dispatch gating`,
|
|
253
|
+
);
|
|
254
|
+
for (const agent of manifest.tools.allowedSubagents) {
|
|
255
|
+
assert.ok(
|
|
256
|
+
typeof agent === "string" && agent.length > 0,
|
|
257
|
+
`manifest "${unitType}" has empty/invalid allowedSubagents entry: ${JSON.stringify(agent)}`,
|
|
223
258
|
);
|
|
224
259
|
}
|
|
225
260
|
}
|
|
@@ -76,13 +76,11 @@ describe("#3615 — structural: fallback exists with correct guards", () => {
|
|
|
76
76
|
);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
});
|
|
79
|
+
// Removed: source-grep count of `return null;` occurrences. The behaviour
|
|
80
|
+
// we care about ("function returns null only when no auto-dispatch /
|
|
81
|
+
// guided-resume / fallback path matches") is exercised by the behavioural
|
|
82
|
+
// tests below — counting literal `return null;` tokens encodes statement
|
|
83
|
+
// shape, not contract. Refs #4851.
|
|
86
84
|
});
|
|
87
85
|
|
|
88
86
|
// ── Behavioral tests: RESUME_INTENT_PATTERNS ────────────────────────
|
|
@@ -4,7 +4,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { execSync } from "node:child_process";
|
|
7
|
-
import { runTurnGitAction } from "../git-service.ts";
|
|
7
|
+
import { handleTurnGitActionError, runTurnGitAction } from "../git-service.ts";
|
|
8
8
|
|
|
9
9
|
function run(cmd: string, cwd: string): string {
|
|
10
10
|
return execSync(cmd, { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
|
|
@@ -83,3 +83,17 @@ test("uok gitops turn action commit creates commit with unit trailer", () => {
|
|
|
83
83
|
rmSync(repo, { recursive: true, force: true });
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
|
+
|
|
87
|
+
test("uok gitops turn action rethrows infrastructure failures", () => {
|
|
88
|
+
const err = Object.assign(new Error("ENFILE: file table overflow"), { code: "ENFILE" });
|
|
89
|
+
|
|
90
|
+
assert.throws(() => handleTurnGitActionError("commit", err), (thrown) => thrown === err);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("uok gitops turn action keeps non-infrastructure git failures recoverable", () => {
|
|
94
|
+
const result = handleTurnGitActionError("commit", new Error("nothing to commit"));
|
|
95
|
+
|
|
96
|
+
assert.equal(result.action, "commit");
|
|
97
|
+
assert.equal(result.status, "failed");
|
|
98
|
+
assert.equal(result.error, "nothing to commit");
|
|
99
|
+
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { test } from "node:test";
|
|
14
14
|
import assert from "node:assert/strict";
|
|
15
15
|
|
|
16
|
-
import { GSDVisualizerOverlay } from "../visualizer-overlay.ts";
|
|
16
|
+
import { GSDVisualizerOverlay, TAB_COUNT } from "../visualizer-overlay.ts";
|
|
17
17
|
|
|
18
18
|
function makeTui() {
|
|
19
19
|
const renders: number[] = [];
|
|
@@ -93,16 +93,16 @@ test("overlay switches tabs via 1–9,0 digit keys", (t) => {
|
|
|
93
93
|
|
|
94
94
|
test("overlay Tab key cycles forward and wraps around at TAB_COUNT", (t) => {
|
|
95
95
|
const { overlay } = makeOverlay(t);
|
|
96
|
-
overlay.activeTab =
|
|
96
|
+
overlay.activeTab = TAB_COUNT - 1;
|
|
97
97
|
overlay.handleInput("\t");
|
|
98
|
-
assert.equal(overlay.activeTab, 0,
|
|
98
|
+
assert.equal(overlay.activeTab, 0, `Tab wraps from ${TAB_COUNT - 1} back to 0`);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test("overlay Shift+Tab cycles backward and wraps", (t) => {
|
|
102
102
|
const { overlay } = makeOverlay(t);
|
|
103
103
|
overlay.activeTab = 0;
|
|
104
104
|
overlay.handleInput("\u001b[Z");
|
|
105
|
-
assert.equal(overlay.activeTab,
|
|
105
|
+
assert.equal(overlay.activeTab, TAB_COUNT - 1, `Shift+Tab wraps from 0 to ${TAB_COUNT - 1}`);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
// ─── Filter mode ─────────────────────────────────────────────────────────
|
|
@@ -331,9 +331,9 @@ test("overlay footer hint mentions tab navigation, filter, scroll, and help", (t
|
|
|
331
331
|
|
|
332
332
|
// ─── Scroll offsets array is sized to TAB_COUNT ──────────────────────────
|
|
333
333
|
|
|
334
|
-
test("overlay scrollOffsets array has one slot per tab
|
|
334
|
+
test("overlay scrollOffsets array has one slot per tab", (t) => {
|
|
335
335
|
const { overlay } = makeOverlay(t);
|
|
336
|
-
assert.equal(overlay.scrollOffsets.length,
|
|
336
|
+
assert.equal(overlay.scrollOffsets.length, TAB_COUNT, "scrollOffsets sized to TAB_COUNT");
|
|
337
337
|
assert.ok(overlay.scrollOffsets.every((n: number) => n === 0), "initialized to zero");
|
|
338
338
|
});
|
|
339
339
|
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import test, { after } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
7
|
+
const ownsGsdHome = process.env.GSD_HOME_TEST_OVERRIDE === undefined;
|
|
8
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
9
|
+
const synthesizedGsdHome = join(tmpdir(), `gsd-test-home-${process.pid}-${Date.now()}`);
|
|
10
|
+
process.env.GSD_HOME = process.env.GSD_HOME_TEST_OVERRIDE
|
|
11
|
+
?? synthesizedGsdHome;
|
|
12
|
+
|
|
13
|
+
after(() => {
|
|
14
|
+
if (ownsGsdHome) {
|
|
15
|
+
rmSync(synthesizedGsdHome, { recursive: true, force: true });
|
|
16
|
+
}
|
|
17
|
+
if (previousGsdHome === undefined) {
|
|
18
|
+
delete process.env.GSD_HOME;
|
|
19
|
+
} else {
|
|
20
|
+
process.env.GSD_HOME = previousGsdHome;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const { dispatchDirectPhase } = await import("../auto-direct-dispatch.ts");
|
|
25
|
+
const {
|
|
26
|
+
buildDiscussMilestonePrompt,
|
|
27
|
+
buildParallelResearchSlicesPrompt,
|
|
28
|
+
buildRewriteDocsPrompt,
|
|
29
|
+
} = await import("../auto-prompts.ts");
|
|
30
|
+
const { invalidateStateCache } = await import("../state.ts");
|
|
31
|
+
const { resolveAgentEnd, runUnit, _resetPendingResolve } = await import("../auto-loop.ts");
|
|
32
|
+
|
|
33
|
+
function writeMilestone(base: string, mid = "M001", title = "Worktree Path Injection"): void {
|
|
34
|
+
const milestoneDir = join(base, ".gsd", "milestones", mid);
|
|
35
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
36
|
+
writeFileSync(
|
|
37
|
+
join(milestoneDir, `${mid}-CONTEXT.md`),
|
|
38
|
+
`# ${mid}: ${title}\n\nContext.\n`,
|
|
39
|
+
"utf-8",
|
|
40
|
+
);
|
|
41
|
+
writeFileSync(
|
|
42
|
+
join(milestoneDir, `${mid}-ROADMAP.md`),
|
|
43
|
+
[
|
|
44
|
+
`# ${mid}: ${title}`,
|
|
45
|
+
"",
|
|
46
|
+
"## Slices",
|
|
47
|
+
"",
|
|
48
|
+
"- [ ] **S01: First slice** `risk:low` `depends:[]`",
|
|
49
|
+
"",
|
|
50
|
+
].join("\n"),
|
|
51
|
+
"utf-8",
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function makeLiveMilestoneWorktree(base: string, mid = "M001"): string {
|
|
56
|
+
const worktreeRoot = join(base, ".gsd", "worktrees", mid);
|
|
57
|
+
mkdirSync(worktreeRoot, { recursive: true });
|
|
58
|
+
writeFileSync(
|
|
59
|
+
join(worktreeRoot, ".git"),
|
|
60
|
+
`gitdir: ${join(base, ".git", "worktrees", mid)}\n`,
|
|
61
|
+
"utf-8",
|
|
62
|
+
);
|
|
63
|
+
writeMilestone(worktreeRoot, mid);
|
|
64
|
+
return worktreeRoot;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function waitFor(condition: () => boolean, label: string): Promise<void> {
|
|
68
|
+
const rawTimeout = process.env.READABLE_WAIT_TIMEOUT_MS;
|
|
69
|
+
const parsedTimeout = rawTimeout === undefined ? NaN : Number.parseInt(rawTimeout, 10);
|
|
70
|
+
const timeoutMs = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : 1000;
|
|
71
|
+
const deadline = Date.now() + timeoutMs;
|
|
72
|
+
|
|
73
|
+
while (Date.now() < deadline) {
|
|
74
|
+
if (condition()) return;
|
|
75
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
76
|
+
}
|
|
77
|
+
if (condition()) return;
|
|
78
|
+
assert.fail(`Timed out waiting for ${label} after ${timeoutMs}ms`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
test("runUnit changes cwd to basePath before creating a new session", async (t) => {
|
|
82
|
+
_resetPendingResolve();
|
|
83
|
+
|
|
84
|
+
const originalCwd = process.cwd();
|
|
85
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-rununit-base-")));
|
|
86
|
+
const drifted = realpathSync(mkdtempSync(join(tmpdir(), "gsd-rununit-drift-")));
|
|
87
|
+
t.after(() => {
|
|
88
|
+
process.chdir(originalCwd);
|
|
89
|
+
rmSync(base, { recursive: true, force: true });
|
|
90
|
+
rmSync(drifted, { recursive: true, force: true });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
process.chdir(drifted);
|
|
94
|
+
|
|
95
|
+
let cwdAtNewSession: string | undefined;
|
|
96
|
+
const session = {
|
|
97
|
+
active: true,
|
|
98
|
+
basePath: base,
|
|
99
|
+
verbose: false,
|
|
100
|
+
cmdCtx: {
|
|
101
|
+
newSession: () => {
|
|
102
|
+
cwdAtNewSession = process.cwd();
|
|
103
|
+
return Promise.resolve({ cancelled: false });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
} as any;
|
|
107
|
+
const pi = {
|
|
108
|
+
calls: [] as unknown[],
|
|
109
|
+
sendMessage(...args: unknown[]) {
|
|
110
|
+
this.calls.push(args);
|
|
111
|
+
},
|
|
112
|
+
} as any;
|
|
113
|
+
const ctx = { ui: { notify: () => {} }, model: { id: "test-model" } } as any;
|
|
114
|
+
|
|
115
|
+
const resultPromise = runUnit(ctx, pi, session, "task", "T01", "prompt");
|
|
116
|
+
await waitFor(() => pi.calls.length === 1, "runUnit dispatch");
|
|
117
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
118
|
+
|
|
119
|
+
const result = await resultPromise;
|
|
120
|
+
assert.equal(result.status, "completed");
|
|
121
|
+
assert.equal(cwdAtNewSession, base);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("runUnit cancels before creating a session when basePath chdir fails", async (t) => {
|
|
125
|
+
_resetPendingResolve();
|
|
126
|
+
|
|
127
|
+
const originalCwd = process.cwd();
|
|
128
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-rununit-missing-base-")));
|
|
129
|
+
const drifted = realpathSync(mkdtempSync(join(tmpdir(), "gsd-rununit-missing-drift-")));
|
|
130
|
+
rmSync(base, { recursive: true, force: true });
|
|
131
|
+
t.after(() => {
|
|
132
|
+
process.chdir(originalCwd);
|
|
133
|
+
rmSync(drifted, { recursive: true, force: true });
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
process.chdir(drifted);
|
|
137
|
+
|
|
138
|
+
let newSessionCalled = false;
|
|
139
|
+
const session = {
|
|
140
|
+
active: true,
|
|
141
|
+
basePath: base,
|
|
142
|
+
verbose: false,
|
|
143
|
+
cmdCtx: {
|
|
144
|
+
newSession: () => {
|
|
145
|
+
newSessionCalled = true;
|
|
146
|
+
return Promise.resolve({ cancelled: false });
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
} as any;
|
|
150
|
+
const pi = {
|
|
151
|
+
calls: [] as unknown[],
|
|
152
|
+
sendMessage(...args: unknown[]) {
|
|
153
|
+
this.calls.push(args);
|
|
154
|
+
},
|
|
155
|
+
} as any;
|
|
156
|
+
const ctx = { ui: { notify: () => {} }, model: { id: "test-model" } } as any;
|
|
157
|
+
|
|
158
|
+
const result = await runUnit(ctx, pi, session, "task", "T01", "prompt");
|
|
159
|
+
|
|
160
|
+
assert.equal(result.status, "cancelled");
|
|
161
|
+
assert.equal(result.errorContext?.category, "session-failed");
|
|
162
|
+
assert.equal(result.errorContext?.isTransient, true);
|
|
163
|
+
assert.match(result.errorContext?.message ?? "", /Failed to chdir to basePath before newSession/);
|
|
164
|
+
assert.ok(result.errorContext?.message.includes(base), "error should include the failed basePath");
|
|
165
|
+
assert.equal(newSessionCalled, false, "newSession must not run after chdir failure");
|
|
166
|
+
assert.equal(pi.calls.length, 0, "unit must not dispatch after chdir failure");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("direct dispatch redirects to the canonical milestone worktree before newSession", async (t) => {
|
|
170
|
+
invalidateStateCache();
|
|
171
|
+
|
|
172
|
+
const originalCwd = process.cwd();
|
|
173
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-direct-base-")));
|
|
174
|
+
const drifted = realpathSync(mkdtempSync(join(tmpdir(), "gsd-direct-drift-")));
|
|
175
|
+
writeMilestone(base);
|
|
176
|
+
const worktreeRoot = makeLiveMilestoneWorktree(base);
|
|
177
|
+
|
|
178
|
+
t.after(() => {
|
|
179
|
+
process.chdir(originalCwd);
|
|
180
|
+
rmSync(base, { recursive: true, force: true });
|
|
181
|
+
rmSync(drifted, { recursive: true, force: true });
|
|
182
|
+
invalidateStateCache();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
process.chdir(drifted);
|
|
186
|
+
|
|
187
|
+
let cwdAtNewSession: string | undefined;
|
|
188
|
+
let sentPrompt: string | undefined;
|
|
189
|
+
const ctx = {
|
|
190
|
+
ui: { notify: () => {} },
|
|
191
|
+
newSession: async () => {
|
|
192
|
+
cwdAtNewSession = process.cwd();
|
|
193
|
+
return { cancelled: false };
|
|
194
|
+
},
|
|
195
|
+
} as any;
|
|
196
|
+
const pi = {
|
|
197
|
+
sendMessage(message: { content: string }) {
|
|
198
|
+
sentPrompt = message.content;
|
|
199
|
+
},
|
|
200
|
+
} as any;
|
|
201
|
+
|
|
202
|
+
await dispatchDirectPhase(ctx, pi, "research-milestone", base);
|
|
203
|
+
|
|
204
|
+
assert.equal(cwdAtNewSession, worktreeRoot);
|
|
205
|
+
assert.equal(process.cwd(), drifted);
|
|
206
|
+
assert.ok(sentPrompt?.includes(worktreeRoot), "prompt should name the canonical worktree root");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("worktree-aware prompt builders include the explicit working directory", async (t) => {
|
|
210
|
+
const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-prompt-base-")));
|
|
211
|
+
writeMilestone(base);
|
|
212
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
213
|
+
|
|
214
|
+
const prompts = await Promise.all([
|
|
215
|
+
buildDiscussMilestonePrompt("M001", "Worktree Path Injection", base),
|
|
216
|
+
buildParallelResearchSlicesPrompt(
|
|
217
|
+
"M001",
|
|
218
|
+
"Worktree Path Injection",
|
|
219
|
+
[{ id: "S01", title: "First slice" }],
|
|
220
|
+
base,
|
|
221
|
+
),
|
|
222
|
+
buildRewriteDocsPrompt(
|
|
223
|
+
"M001",
|
|
224
|
+
"Worktree Path Injection",
|
|
225
|
+
null,
|
|
226
|
+
base,
|
|
227
|
+
[{ change: "Refresh docs", timestamp: "2026-04-27T00:00:00.000Z", appliedAt: "test" }] as any,
|
|
228
|
+
),
|
|
229
|
+
]);
|
|
230
|
+
|
|
231
|
+
for (const prompt of prompts) {
|
|
232
|
+
assert.match(prompt, /working directory/i);
|
|
233
|
+
assert.ok(prompt.includes(base), "prompt should include the provided working directory");
|
|
234
|
+
}
|
|
235
|
+
});
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, rmSync, mkdirSync, realpathSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
3
6
|
import {
|
|
4
7
|
WorktreeResolver,
|
|
5
8
|
type WorktreeResolverDeps,
|
|
@@ -1142,3 +1145,85 @@ test("mergeAndExit propagates non-MergeConflictError to caller (#4380)", () => {
|
|
|
1142
1145
|
"non-MergeConflictError must propagate to the caller, not be swallowed",
|
|
1143
1146
|
);
|
|
1144
1147
|
});
|
|
1148
|
+
|
|
1149
|
+
// ─── Regression: mergeAndExit anchors cwd at project root before merge work ─
|
|
1150
|
+
// (de73fb43d headless `gsd auto` exits-on-task regression)
|
|
1151
|
+
//
|
|
1152
|
+
// Background: the auto loop runs tasks inside the milestone worktree
|
|
1153
|
+
// (process.cwd() === worktreePath). When the milestone completes, the
|
|
1154
|
+
// worktree dir is torn down. If cwd was still inside it at that moment,
|
|
1155
|
+
// every subsequent process.cwd() throws ENOENT — and after de73fb43d
|
|
1156
|
+
// auto/run-unit.ts:50 turns that ENOENT into a session-failed cancel,
|
|
1157
|
+
// which in headless mode bubbles up to a "Auto-mode stopped" notify
|
|
1158
|
+
// and process.exit(0). mergeAndExit must therefore guarantee cwd is
|
|
1159
|
+
// anchored at the project root regardless of which merge path runs.
|
|
1160
|
+
|
|
1161
|
+
test("mergeAndExit chdirs to project root before merge work (regression: headless gsd auto exit)", () => {
|
|
1162
|
+
// Set up real dirs so process.chdir actually succeeds. realpathSync
|
|
1163
|
+
// canonicalizes the macOS /var → /private/var symlink so equality holds.
|
|
1164
|
+
const projectRoot = realpathSync(mkdtempSync(join(tmpdir(), "gsd-resolver-cwd-")));
|
|
1165
|
+
const worktreePath = join(projectRoot, ".gsd/worktrees/M001");
|
|
1166
|
+
mkdirSync(worktreePath, { recursive: true });
|
|
1167
|
+
const previousCwd = process.cwd();
|
|
1168
|
+
|
|
1169
|
+
try {
|
|
1170
|
+
process.chdir(worktreePath);
|
|
1171
|
+
assert.equal(process.cwd(), worktreePath, "precondition: cwd is in worktree");
|
|
1172
|
+
|
|
1173
|
+
const s = makeSession({
|
|
1174
|
+
basePath: worktreePath,
|
|
1175
|
+
originalBasePath: projectRoot,
|
|
1176
|
+
});
|
|
1177
|
+
const deps = makeDeps({
|
|
1178
|
+
isInAutoWorktree: () => true,
|
|
1179
|
+
getIsolationMode: () => "worktree",
|
|
1180
|
+
});
|
|
1181
|
+
const ctx = makeNotifyCtx();
|
|
1182
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
1183
|
+
|
|
1184
|
+
resolver.mergeAndExit("M001", ctx);
|
|
1185
|
+
|
|
1186
|
+
assert.equal(
|
|
1187
|
+
process.cwd(),
|
|
1188
|
+
projectRoot,
|
|
1189
|
+
"mergeAndExit must leave cwd at the project root, not the (about-to-be-removed) worktree",
|
|
1190
|
+
);
|
|
1191
|
+
} finally {
|
|
1192
|
+
try { process.chdir(previousCwd); } catch { /* best-effort */ }
|
|
1193
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
test("mergeAndExit anchors cwd even on isolation-degraded skip path", () => {
|
|
1198
|
+
// The skip paths (isolation-degraded, mode-none, missing-original-base)
|
|
1199
|
+
// bypass the per-mode merge helpers entirely. They must still leave cwd
|
|
1200
|
+
// at the project root so a subsequent worktree teardown elsewhere does
|
|
1201
|
+
// not strand cwd in a deleted dir.
|
|
1202
|
+
const projectRoot = realpathSync(mkdtempSync(join(tmpdir(), "gsd-resolver-cwd-degraded-")));
|
|
1203
|
+
const worktreePath = join(projectRoot, ".gsd/worktrees/M001");
|
|
1204
|
+
mkdirSync(worktreePath, { recursive: true });
|
|
1205
|
+
const previousCwd = process.cwd();
|
|
1206
|
+
|
|
1207
|
+
try {
|
|
1208
|
+
process.chdir(worktreePath);
|
|
1209
|
+
const s = makeSession({
|
|
1210
|
+
basePath: worktreePath,
|
|
1211
|
+
originalBasePath: projectRoot,
|
|
1212
|
+
});
|
|
1213
|
+
s.isolationDegraded = true;
|
|
1214
|
+
const deps = makeDeps({ getIsolationMode: () => "worktree" });
|
|
1215
|
+
const ctx = makeNotifyCtx();
|
|
1216
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
1217
|
+
|
|
1218
|
+
resolver.mergeAndExit("M001", ctx);
|
|
1219
|
+
|
|
1220
|
+
assert.equal(
|
|
1221
|
+
process.cwd(),
|
|
1222
|
+
projectRoot,
|
|
1223
|
+
"isolation-degraded skip must still anchor cwd at project root",
|
|
1224
|
+
);
|
|
1225
|
+
} finally {
|
|
1226
|
+
try { process.chdir(previousCwd); } catch { /* best-effort */ }
|
|
1227
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
listWorktrees,
|
|
21
21
|
worktreePath,
|
|
22
22
|
} from "../worktree-manager.ts";
|
|
23
|
-
import {
|
|
23
|
+
import { test } from 'node:test';
|
|
24
24
|
import assert from 'node:assert/strict';
|
|
25
25
|
|
|
26
26
|
|
|
@@ -28,37 +28,41 @@ function run(command: string, cwd: string): string {
|
|
|
28
28
|
return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Resolve tmpdir to handle macOS /tmp -> /private/var/... symlink.
|
|
34
|
-
const realTmp = realpathSync(tmpdir());
|
|
35
|
-
const base = mkdtempSync(join(realTmp, "gsd-wt-symlink-test-"));
|
|
36
|
-
const externalState = mkdtempSync(join(realTmp, "gsd-wt-symlink-ext-"));
|
|
37
|
-
|
|
38
|
-
run("git init -b main", base);
|
|
39
|
-
run('git config user.name "Test"', base);
|
|
40
|
-
run('git config user.email "test@example.com"', base);
|
|
41
|
-
|
|
42
|
-
// Create external state directory structure
|
|
43
|
-
mkdirSync(join(externalState, "worktrees"), { recursive: true });
|
|
44
|
-
|
|
45
|
-
// Create .gsd as a symlink to the external state directory
|
|
46
|
-
symlinkSync(externalState, join(base, ".gsd"));
|
|
47
|
-
|
|
48
|
-
// Verify the symlink is in place
|
|
49
|
-
assert.ok(existsSync(join(base, ".gsd")), ".gsd symlink exists");
|
|
50
|
-
assert.ok(
|
|
51
|
-
realpathSync(join(base, ".gsd")) === externalState,
|
|
52
|
-
".gsd resolves to external state dir",
|
|
53
|
-
);
|
|
31
|
+
test('worktree-symlink-removal removes the git-registered symlink target safely', (t) => {
|
|
32
|
+
console.log("\n=== #1852: removeWorktree with symlinked .gsd/ ===");
|
|
54
33
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
34
|
+
// Set up a test repo with .gsd/ as a symlink to an external directory,
|
|
35
|
+
// mimicking the external state directory layout (~/.gsd/projects/<hash>/).
|
|
36
|
+
// Resolve tmpdir to handle macOS /tmp -> /private/var/... symlink.
|
|
37
|
+
const realTmp = realpathSync(tmpdir());
|
|
38
|
+
const base = mkdtempSync(join(realTmp, "gsd-wt-symlink-test-"));
|
|
39
|
+
const externalState = mkdtempSync(join(realTmp, "gsd-wt-symlink-ext-"));
|
|
40
|
+
t.after(() => {
|
|
41
|
+
rmSync(base, { recursive: true, force: true });
|
|
42
|
+
rmSync(externalState, { recursive: true, force: true });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
run("git init -b main", base);
|
|
46
|
+
run('git config user.name "Test"', base);
|
|
47
|
+
run('git config user.email "test@example.com"', base);
|
|
48
|
+
|
|
49
|
+
// Create external state directory structure
|
|
50
|
+
mkdirSync(join(externalState, "worktrees"), { recursive: true });
|
|
51
|
+
|
|
52
|
+
// Create .gsd as a symlink to the external state directory
|
|
53
|
+
symlinkSync(externalState, join(base, ".gsd"));
|
|
54
|
+
|
|
55
|
+
// Verify the symlink is in place
|
|
56
|
+
assert.ok(existsSync(join(base, ".gsd")), ".gsd symlink exists");
|
|
57
|
+
assert.ok(
|
|
58
|
+
realpathSync(join(base, ".gsd")) === externalState,
|
|
59
|
+
".gsd resolves to external state dir",
|
|
60
|
+
);
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
// Create initial commit so we have a valid repo
|
|
63
|
+
writeFileSync(join(base, "README.md"), "# Test\n", "utf-8");
|
|
64
|
+
run("git add .", base);
|
|
65
|
+
run('git commit -m "init"', base);
|
|
62
66
|
|
|
63
67
|
// Create a worktree — git will resolve the symlink and register
|
|
64
68
|
// the worktree at the external path
|
|
@@ -127,7 +131,4 @@ describe('worktree-symlink-removal', async () => {
|
|
|
127
131
|
const listed = listWorktrees(base);
|
|
128
132
|
assert.deepStrictEqual(listed.length, 0, "no worktrees listed after removal");
|
|
129
133
|
|
|
130
|
-
// Cleanup
|
|
131
|
-
rmSync(base, { recursive: true, force: true });
|
|
132
|
-
rmSync(externalState, { recursive: true, force: true });
|
|
133
134
|
});
|