gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.0fdacd524
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 +8 -7
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +77 -38
- 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 +90 -46
- 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 +60 -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 +4 -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 +13 -13
- 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 +44 -4
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.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/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- 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/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/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -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 +92 -47
- 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 +82 -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/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-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 +4 -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/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/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_ssgManifest.js +0 -0
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { detectStuck } from "./detect-stuck.js";
|
|
27
27
|
import { runUnit } from "./run-unit.js";
|
|
28
28
|
import { debugLog } from "../debug-logger.js";
|
|
29
|
+
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
29
30
|
import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
|
|
30
31
|
import { MergeConflictError } from "../git-service.js";
|
|
31
32
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
@@ -81,11 +82,7 @@ export function resetSessionTimeoutState(): void {
|
|
|
81
82
|
* Exported for testing as _resolveReportBasePath.
|
|
82
83
|
*/
|
|
83
84
|
export function _resolveReportBasePath(s: Pick<AutoSession, "originalBasePath" | "basePath">): string {
|
|
84
|
-
|
|
85
|
-
// originalBasePath is falsy — prevents reports landing in the worktree (#3729).
|
|
86
|
-
const resolved = s.originalBasePath || s.basePath;
|
|
87
|
-
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
88
|
-
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
85
|
+
return resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
/**
|
|
@@ -96,12 +93,7 @@ export function _resolveReportBasePath(s: Pick<AutoSession, "originalBasePath" |
|
|
|
96
93
|
export function _resolveDispatchGuardBasePath(
|
|
97
94
|
s: Pick<AutoSession, "originalBasePath" | "basePath">,
|
|
98
95
|
): string {
|
|
99
|
-
|
|
100
|
-
// originalBasePath is falsy — prevents guard checks running against the
|
|
101
|
-
// worktree instead of the project root (#3729).
|
|
102
|
-
const resolved = s.originalBasePath || s.basePath;
|
|
103
|
-
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
104
|
-
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
96
|
+
return resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
|
|
105
97
|
}
|
|
106
98
|
|
|
107
99
|
const PLAN_V2_GATE_PHASES: ReadonlySet<Phase> = new Set([
|
|
@@ -1342,7 +1334,7 @@ export async function runUnitPhase(
|
|
|
1342
1334
|
iterData: IterationData,
|
|
1343
1335
|
loopState: LoopState,
|
|
1344
1336
|
sidecarItem?: SidecarItem,
|
|
1345
|
-
): Promise<PhaseResult<{ unitStartedAt
|
|
1337
|
+
): Promise<PhaseResult<{ unitStartedAt?: number; requestDispatchedAt?: number }>> {
|
|
1346
1338
|
const { ctx, pi, s, deps, prefs } = ic;
|
|
1347
1339
|
const { unitType, unitId, prompt, state, mid } = iterData;
|
|
1348
1340
|
|
|
@@ -1860,7 +1852,7 @@ export async function runUnitPhase(
|
|
|
1860
1852
|
);
|
|
1861
1853
|
// Fall through to next iteration where dispatch will re-derive
|
|
1862
1854
|
// and re-dispatch this unit.
|
|
1863
|
-
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
|
|
1855
|
+
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt, requestDispatchedAt: unitResult.requestDispatchedAt } };
|
|
1864
1856
|
}
|
|
1865
1857
|
}
|
|
1866
1858
|
}
|
|
@@ -1924,7 +1916,7 @@ export async function runUnitPhase(
|
|
|
1924
1916
|
s.checkpointSha = null;
|
|
1925
1917
|
}
|
|
1926
1918
|
|
|
1927
|
-
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
|
|
1919
|
+
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt, requestDispatchedAt: unitResult.requestDispatchedAt } };
|
|
1928
1920
|
}
|
|
1929
1921
|
|
|
1930
1922
|
// ─── runFinalize ──────────────────────────────────────────────────────────────
|
|
@@ -40,6 +40,29 @@ export async function runUnit(
|
|
|
40
40
|
): Promise<UnitResult> {
|
|
41
41
|
debugLog("runUnit", { phase: "start", unitType, unitId });
|
|
42
42
|
|
|
43
|
+
// Ensure cwd matches basePath BEFORE newSession() captures it. The new
|
|
44
|
+
// session reads process.cwd() during construction to anchor its tool
|
|
45
|
+
// runtime and system prompt; if cwd has drifted (async_bash, background
|
|
46
|
+
// jobs, prior unit cleanup), the session would otherwise be rooted to
|
|
47
|
+
// the wrong directory. Must be synchronous — no awaits between chdir
|
|
48
|
+
// and newSession (#1389, #4762 follow-up).
|
|
49
|
+
try {
|
|
50
|
+
if (process.cwd() !== s.basePath) {
|
|
51
|
+
process.chdir(s.basePath);
|
|
52
|
+
}
|
|
53
|
+
} catch (e) {
|
|
54
|
+
const msg = `Failed to chdir to basePath before newSession (basePath: ${s.basePath}): ${String(e)}`;
|
|
55
|
+
logWarning("engine", msg, { basePath: s.basePath, error: String(e) });
|
|
56
|
+
return {
|
|
57
|
+
status: "cancelled",
|
|
58
|
+
errorContext: {
|
|
59
|
+
message: msg,
|
|
60
|
+
category: "session-failed",
|
|
61
|
+
isTransient: true,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
43
66
|
// ── Session creation with timeout ──
|
|
44
67
|
debugLog("runUnit", { phase: "session-create", unitType, unitId });
|
|
45
68
|
|
|
@@ -120,17 +143,6 @@ export async function runUnit(
|
|
|
120
143
|
_setCurrentResolve(resolve);
|
|
121
144
|
});
|
|
122
145
|
|
|
123
|
-
// Ensure cwd matches basePath before dispatch (#1389).
|
|
124
|
-
// async_bash and background jobs can drift cwd away from the worktree.
|
|
125
|
-
// Realigning here prevents commits from landing on the wrong branch.
|
|
126
|
-
try {
|
|
127
|
-
if (process.cwd() !== s.basePath) {
|
|
128
|
-
process.chdir(s.basePath);
|
|
129
|
-
}
|
|
130
|
-
} catch (e) {
|
|
131
|
-
logWarning("engine", "Failed to chdir to basePath before dispatch", { basePath: s.basePath, error: String(e) });
|
|
132
|
-
}
|
|
133
|
-
|
|
134
146
|
// ── Provider request-readiness pre-check (#4555) ──
|
|
135
147
|
// Verify the provider can accept requests before dispatching. If the token
|
|
136
148
|
// has expired since bootstrap, return cancelled immediately so the unit is
|
|
@@ -171,6 +183,7 @@ export async function runUnit(
|
|
|
171
183
|
// ── Send the prompt ──
|
|
172
184
|
debugLog("runUnit", { phase: "send-message", unitType, unitId });
|
|
173
185
|
|
|
186
|
+
const requestDispatchedAt = Date.now();
|
|
174
187
|
pi.sendMessage(
|
|
175
188
|
{ customType: "gsd-auto", content: prompt, display: s.verbose },
|
|
176
189
|
{ triggerTurn: true },
|
|
@@ -201,6 +214,7 @@ export async function runUnit(
|
|
|
201
214
|
unitId,
|
|
202
215
|
status: result.status,
|
|
203
216
|
});
|
|
217
|
+
const finalResult: UnitResult = { ...result, requestDispatchedAt };
|
|
204
218
|
|
|
205
219
|
// Discard trailing follow-up messages (e.g. async_job_result notifications)
|
|
206
220
|
// from the completed unit. Without this, queued follow-ups trigger wasteful
|
|
@@ -216,5 +230,5 @@ export async function runUnit(
|
|
|
216
230
|
logWarning("engine", "clearQueue failed after unit completion", { error: String(e) });
|
|
217
231
|
}
|
|
218
232
|
|
|
219
|
-
return
|
|
233
|
+
return finalResult;
|
|
220
234
|
}
|
|
@@ -21,6 +21,7 @@ import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent
|
|
|
21
21
|
import type { GitServiceImpl } from "../git-service.js";
|
|
22
22
|
import type { CaptureEntry } from "../captures.js";
|
|
23
23
|
import type { BudgetAlertLevel } from "../auto-budget.js";
|
|
24
|
+
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
24
25
|
|
|
25
26
|
// ─── Exported Types ──────────────────────────────────────────────────────────
|
|
26
27
|
|
|
@@ -193,6 +194,8 @@ export class AutoSession {
|
|
|
193
194
|
lastPromptCharCount: number | undefined;
|
|
194
195
|
lastBaselineCharCount: number | undefined;
|
|
195
196
|
pendingQuickTasks: CaptureEntry[] = [];
|
|
197
|
+
/** Timestamp of the last LLM request dispatch (ms since epoch). Used for proactive rate limiting. */
|
|
198
|
+
lastRequestTimestamp = 0;
|
|
196
199
|
|
|
197
200
|
// ── Safety harness ───────────────────────────────────────────────────────
|
|
198
201
|
/** SHA of the pre-unit git checkpoint ref. Cleared on success or rollback. */
|
|
@@ -224,12 +227,7 @@ export class AutoSession {
|
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
get lockBasePath(): string {
|
|
227
|
-
|
|
228
|
-
// Strip /.gsd/worktrees/ suffix if basePath is itself a worktree path
|
|
229
|
-
// to avoid reading/writing the lock inside the worktree (#3729).
|
|
230
|
-
const resolved = this.originalBasePath || this.basePath;
|
|
231
|
-
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
232
|
-
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
230
|
+
return resolveWorktreeProjectRoot(this.basePath, this.originalBasePath);
|
|
233
231
|
}
|
|
234
232
|
|
|
235
233
|
reset(): void {
|
|
@@ -294,6 +292,7 @@ export class AutoSession {
|
|
|
294
292
|
this.lastPromptCharCount = undefined;
|
|
295
293
|
this.lastBaselineCharCount = undefined;
|
|
296
294
|
this.pendingQuickTasks = [];
|
|
295
|
+
this.lastRequestTimestamp = 0;
|
|
297
296
|
this.sidecarQueue = [];
|
|
298
297
|
this.rewriteAttemptCount = 0;
|
|
299
298
|
this.consecutiveCompleteBootstraps = 0;
|
|
@@ -19,6 +19,7 @@ import { getActiveHook } from "./post-unit-hooks.js";
|
|
|
19
19
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
20
20
|
import { getErrorMessage } from "./error-utils.js";
|
|
21
21
|
import { nativeIsRepo } from "./native-git-bridge.js";
|
|
22
|
+
import { getHomeDir } from "./home-dir.js";
|
|
22
23
|
import {
|
|
23
24
|
resolveMilestoneFile,
|
|
24
25
|
resolveSliceFile,
|
|
@@ -582,8 +583,8 @@ export function updateProgressWidget(
|
|
|
582
583
|
let widgetPwd: string;
|
|
583
584
|
{
|
|
584
585
|
let fullPwd = process.cwd();
|
|
585
|
-
const widgetHome =
|
|
586
|
-
if (widgetHome && fullPwd.startsWith(widgetHome)) {
|
|
586
|
+
const widgetHome = getHomeDir();
|
|
587
|
+
if (widgetHome && (fullPwd === widgetHome || fullPwd.startsWith(widgetHome + "/") || fullPwd.startsWith(widgetHome + "\\"))) {
|
|
587
588
|
fullPwd = `~${fullPwd.slice(widgetHome.length)}`;
|
|
588
589
|
}
|
|
589
590
|
const parts = fullPwd.split("/");
|
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
31
31
|
import type { MinimalModelRegistry } from "./context-budget.js";
|
|
32
32
|
import { pauseAuto } from "./auto.js";
|
|
33
|
+
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
34
|
+
import { logWarning } from "./workflow-logger.js";
|
|
33
35
|
import {
|
|
34
36
|
getWorkflowTransportSupportError,
|
|
35
37
|
getRequiredWorkflowToolsForAutoUnit,
|
|
@@ -50,6 +52,14 @@ export async function dispatchDirectPhase(
|
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
const projectRoot = base;
|
|
56
|
+
|
|
57
|
+
// Switch the dispatch base to the canonical milestone worktree if one
|
|
58
|
+
// exists. Without this, /gsd dispatch invoked from the project root would
|
|
59
|
+
// build prompts and create a session anchored to the project root even
|
|
60
|
+
// though the milestone's actual code lives in the worktree.
|
|
61
|
+
const dispatchBase = resolveCanonicalMilestoneRoot(base, mid);
|
|
62
|
+
|
|
53
63
|
const normalized = phase.toLowerCase();
|
|
54
64
|
let unitType: string;
|
|
55
65
|
let unitId: string;
|
|
@@ -70,7 +80,7 @@ export async function dispatchDirectPhase(
|
|
|
70
80
|
|
|
71
81
|
// When require_slice_discussion is enabled, pause auto-mode before
|
|
72
82
|
// each new slice so the user can discuss requirements first (#789).
|
|
73
|
-
const sliceContextFile = resolveSliceFile(
|
|
83
|
+
const sliceContextFile = resolveSliceFile(dispatchBase, mid, sid, "CONTEXT");
|
|
74
84
|
const requireDiscussion = loadEffectiveGSDPreferences()?.preferences?.phases?.require_slice_discussion;
|
|
75
85
|
if (requireDiscussion && !sliceContextFile) {
|
|
76
86
|
ctx.ui.notify(
|
|
@@ -83,11 +93,11 @@ export async function dispatchDirectPhase(
|
|
|
83
93
|
|
|
84
94
|
unitType = "research-slice";
|
|
85
95
|
unitId = `${mid}/${sid}`;
|
|
86
|
-
prompt = await buildResearchSlicePrompt(mid, midTitle, sid, sTitle,
|
|
96
|
+
prompt = await buildResearchSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
87
97
|
} else {
|
|
88
98
|
unitType = "research-milestone";
|
|
89
99
|
unitId = mid;
|
|
90
|
-
prompt = await buildResearchMilestonePrompt(mid, midTitle,
|
|
100
|
+
prompt = await buildResearchMilestonePrompt(mid, midTitle, dispatchBase);
|
|
91
101
|
}
|
|
92
102
|
break;
|
|
93
103
|
}
|
|
@@ -106,7 +116,7 @@ export async function dispatchDirectPhase(
|
|
|
106
116
|
unitType = "plan-slice";
|
|
107
117
|
unitId = `${mid}/${sid}`;
|
|
108
118
|
prompt = await buildPlanSlicePrompt(
|
|
109
|
-
mid, midTitle, sid, sTitle,
|
|
119
|
+
mid, midTitle, sid, sTitle, dispatchBase, undefined,
|
|
110
120
|
{
|
|
111
121
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
112
122
|
modelRegistry: ctx.modelRegistry as MinimalModelRegistry | undefined,
|
|
@@ -115,7 +125,7 @@ export async function dispatchDirectPhase(
|
|
|
115
125
|
} else {
|
|
116
126
|
unitType = "plan-milestone";
|
|
117
127
|
unitId = mid;
|
|
118
|
-
prompt = await buildPlanMilestonePrompt(mid, midTitle,
|
|
128
|
+
prompt = await buildPlanMilestonePrompt(mid, midTitle, dispatchBase);
|
|
119
129
|
}
|
|
120
130
|
break;
|
|
121
131
|
}
|
|
@@ -137,7 +147,7 @@ export async function dispatchDirectPhase(
|
|
|
137
147
|
unitType = "execute-task";
|
|
138
148
|
unitId = `${mid}/${sid}/${tid}`;
|
|
139
149
|
prompt = await buildExecuteTaskPrompt(
|
|
140
|
-
mid, sid, sTitle, tid, tTitle,
|
|
150
|
+
mid, sid, sTitle, tid, tTitle, dispatchBase,
|
|
141
151
|
{
|
|
142
152
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
143
153
|
modelRegistry: ctx.modelRegistry as MinimalModelRegistry | undefined,
|
|
@@ -159,11 +169,11 @@ export async function dispatchDirectPhase(
|
|
|
159
169
|
}
|
|
160
170
|
unitType = "complete-slice";
|
|
161
171
|
unitId = `${mid}/${sid}`;
|
|
162
|
-
prompt = await buildCompleteSlicePrompt(mid, midTitle, sid, sTitle,
|
|
172
|
+
prompt = await buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
163
173
|
} else {
|
|
164
174
|
unitType = "complete-milestone";
|
|
165
175
|
unitId = mid;
|
|
166
|
-
prompt = await buildCompleteMilestonePrompt(mid, midTitle,
|
|
176
|
+
prompt = await buildCompleteMilestonePrompt(mid, midTitle, dispatchBase);
|
|
167
177
|
}
|
|
168
178
|
break;
|
|
169
179
|
}
|
|
@@ -177,7 +187,7 @@ export async function dispatchDirectPhase(
|
|
|
177
187
|
}
|
|
178
188
|
if (completedSliceIds.length === 0) {
|
|
179
189
|
// File-based fallback: parse roadmap checkboxes
|
|
180
|
-
const roadmapPath = resolveMilestoneFile(
|
|
190
|
+
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
181
191
|
if (roadmapPath) {
|
|
182
192
|
const roadmapContent = await loadFile(roadmapPath);
|
|
183
193
|
if (roadmapContent) {
|
|
@@ -192,7 +202,7 @@ export async function dispatchDirectPhase(
|
|
|
192
202
|
const completedSliceId = completedSliceIds[completedSliceIds.length - 1];
|
|
193
203
|
unitType = "reassess-roadmap";
|
|
194
204
|
unitId = `${mid}/${completedSliceId}`;
|
|
195
|
-
prompt = await buildReassessRoadmapPrompt(mid, midTitle, completedSliceId,
|
|
205
|
+
prompt = await buildReassessRoadmapPrompt(mid, midTitle, completedSliceId, dispatchBase);
|
|
196
206
|
break;
|
|
197
207
|
}
|
|
198
208
|
|
|
@@ -208,7 +218,7 @@ export async function dispatchDirectPhase(
|
|
|
208
218
|
}
|
|
209
219
|
if (uatCompletedSliceIds.length === 0) {
|
|
210
220
|
// File-based fallback: parse roadmap checkboxes
|
|
211
|
-
const roadmapPath = resolveMilestoneFile(
|
|
221
|
+
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
212
222
|
if (roadmapPath) {
|
|
213
223
|
const roadmapContent = await loadFile(roadmapPath);
|
|
214
224
|
if (roadmapContent) {
|
|
@@ -221,7 +231,7 @@ export async function dispatchDirectPhase(
|
|
|
221
231
|
return;
|
|
222
232
|
}
|
|
223
233
|
const sid = uatCompletedSliceIds[uatCompletedSliceIds.length - 1];
|
|
224
|
-
const uatFile = resolveSliceFile(
|
|
234
|
+
const uatFile = resolveSliceFile(dispatchBase, mid, sid, "UAT");
|
|
225
235
|
if (!uatFile) {
|
|
226
236
|
ctx.ui.notify("Cannot dispatch run-uat: no UAT file found.", "warning");
|
|
227
237
|
return;
|
|
@@ -231,10 +241,10 @@ export async function dispatchDirectPhase(
|
|
|
231
241
|
ctx.ui.notify("Cannot dispatch run-uat: UAT file is empty.", "warning");
|
|
232
242
|
return;
|
|
233
243
|
}
|
|
234
|
-
const uatPath = relSliceFile(
|
|
244
|
+
const uatPath = relSliceFile(dispatchBase, mid, sid, "UAT");
|
|
235
245
|
unitType = "run-uat";
|
|
236
246
|
unitId = `${mid}/${sid}`;
|
|
237
|
-
prompt = await buildRunUatPrompt(mid, sid, uatPath, uatContent,
|
|
247
|
+
prompt = await buildRunUatPrompt(mid, sid, uatPath, uatContent, dispatchBase);
|
|
238
248
|
break;
|
|
239
249
|
}
|
|
240
250
|
|
|
@@ -248,7 +258,7 @@ export async function dispatchDirectPhase(
|
|
|
248
258
|
}
|
|
249
259
|
unitType = "replan-slice";
|
|
250
260
|
unitId = `${mid}/${sid}`;
|
|
251
|
-
prompt = await buildReplanSlicePrompt(mid, midTitle, sid, sTitle,
|
|
261
|
+
prompt = await buildReplanSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
252
262
|
break;
|
|
253
263
|
}
|
|
254
264
|
|
|
@@ -264,7 +274,7 @@ export async function dispatchDirectPhase(
|
|
|
264
274
|
ctx.model?.provider,
|
|
265
275
|
getRequiredWorkflowToolsForAutoUnit(unitType),
|
|
266
276
|
{
|
|
267
|
-
projectRoot
|
|
277
|
+
projectRoot,
|
|
268
278
|
surface: "direct phase dispatch",
|
|
269
279
|
unitType,
|
|
270
280
|
authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
|
|
@@ -277,13 +287,39 @@ export async function dispatchDirectPhase(
|
|
|
277
287
|
}
|
|
278
288
|
|
|
279
289
|
ctx.ui.notify(`Dispatching ${unitType} for ${unitId}...`, "info");
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
290
|
+
|
|
291
|
+
const originalCwd = process.cwd();
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
// Ensure cwd matches dispatchBase BEFORE newSession() captures it. Synchronous —
|
|
295
|
+
// no awaits between chdir and newSession.
|
|
296
|
+
try {
|
|
297
|
+
if (process.cwd() !== dispatchBase) {
|
|
298
|
+
process.chdir(dispatchBase);
|
|
299
|
+
}
|
|
300
|
+
} catch (err) {
|
|
301
|
+
const msg = `Failed to chdir before direct-dispatch newSession (basePath: ${dispatchBase}): ${err instanceof Error ? err.message : String(err)}`;
|
|
302
|
+
logWarning("engine", msg, { file: "auto-direct-dispatch.ts", basePath: dispatchBase, error: err instanceof Error ? err.message : String(err) });
|
|
303
|
+
ctx.ui.notify(`${msg}. Cancelling dispatch to avoid running in the wrong directory.`, "error");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const result = await ctx.newSession();
|
|
308
|
+
if (result.cancelled) {
|
|
309
|
+
ctx.ui.notify("Session creation cancelled.", "warning");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
pi.sendMessage(
|
|
313
|
+
{ customType: "gsd-dispatch", content: prompt, display: false },
|
|
314
|
+
{ triggerTurn: true },
|
|
315
|
+
);
|
|
316
|
+
} finally {
|
|
317
|
+
try {
|
|
318
|
+
if (process.cwd() !== originalCwd) {
|
|
319
|
+
process.chdir(originalCwd);
|
|
320
|
+
}
|
|
321
|
+
} catch (err) {
|
|
322
|
+
logWarning("engine", `Failed to restore cwd after direct dispatch: ${err instanceof Error ? err.message : String(err)}`, { file: "auto-direct-dispatch.ts", basePath: originalCwd });
|
|
323
|
+
}
|
|
284
324
|
}
|
|
285
|
-
pi.sendMessage(
|
|
286
|
-
{ customType: "gsd-dispatch", content: prompt, display: false },
|
|
287
|
-
{ triggerTurn: true },
|
|
288
|
-
);
|
|
289
325
|
}
|
|
@@ -797,14 +797,25 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
797
797
|
if (state.phase !== "executing" || !state.activeTask) return null;
|
|
798
798
|
if (!state.activeSlice) return null; // fall through
|
|
799
799
|
|
|
800
|
-
//
|
|
800
|
+
// Reactive dispatch is on by default when there are enough ready tasks to
|
|
801
|
+
// benefit from parallelism. Users opt out explicitly via
|
|
802
|
+
// `reactive_execution.enabled: false`. The downstream safety checks
|
|
803
|
+
// (graph ambiguity, ready-task count, conflict-free selection) still gate
|
|
804
|
+
// every actual dispatch, so the worst-case "default-on" outcome is the
|
|
805
|
+
// same fall-through to sequential execution as before.
|
|
801
806
|
const reactiveConfig = prefs?.reactive_execution;
|
|
802
|
-
if (
|
|
807
|
+
if (reactiveConfig?.enabled === false) return null;
|
|
803
808
|
|
|
804
809
|
const sid = state.activeSlice.id;
|
|
805
810
|
const sTitle = state.activeSlice.title;
|
|
806
|
-
const maxParallel = reactiveConfig
|
|
807
|
-
const subagentModel = reactiveConfig
|
|
811
|
+
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
812
|
+
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
813
|
+
// Default-on safety threshold: only activate reactive dispatch when at
|
|
814
|
+
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
815
|
+
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
816
|
+
// better than none" intent). Default-on installs require >=3 to avoid
|
|
817
|
+
// surprising users with parallelism on small slices.
|
|
818
|
+
const minReadyTasksForReactive = reactiveConfig?.enabled === true ? 2 : 3;
|
|
808
819
|
|
|
809
820
|
// Dry-run mode: max_parallel=1 means graph is derived and logged but
|
|
810
821
|
// execution remains sequential
|
|
@@ -831,8 +842,9 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
831
842
|
const completed = new Set(graph.filter((n) => n.done).map((n) => n.id));
|
|
832
843
|
const readyIds = getReadyTasks(graph, completed, new Set());
|
|
833
844
|
|
|
834
|
-
// Only activate reactive dispatch when
|
|
835
|
-
|
|
845
|
+
// Only activate reactive dispatch when enough tasks are ready.
|
|
846
|
+
// Threshold is 2 when explicitly opted in, 3 when default-on.
|
|
847
|
+
if (readyIds.length < minReadyTasksForReactive) return null;
|
|
836
848
|
|
|
837
849
|
const uokFlags = resolveUokFlags(prefs);
|
|
838
850
|
const selected = uokFlags.executionGraph
|
|
@@ -37,7 +37,7 @@ import { composeInlinedContext, type ArtifactResolver } from "./unit-context-com
|
|
|
37
37
|
import { logWarning } from "./workflow-logger.js";
|
|
38
38
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
39
39
|
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
40
|
-
import { warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
40
|
+
import { resolveSkillManifest, warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
41
41
|
|
|
42
42
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
43
43
|
|
|
@@ -776,6 +776,25 @@ function formatSkillActivationBlock(skillNames: string[]): string {
|
|
|
776
776
|
return `<skill_activation>${calls}.</skill_activation>`;
|
|
777
777
|
}
|
|
778
778
|
|
|
779
|
+
/**
|
|
780
|
+
* Manifest-driven recommendations block — informational only, does NOT
|
|
781
|
+
* auto-invoke. Lists per-unit-type skills that are installed but not already
|
|
782
|
+
* activated by explicit user intent (always_use_skills / prefer_skills /
|
|
783
|
+
* skill_rules / task-plan skills_used). Surfaces relevant skills to the
|
|
784
|
+
* model so they can be invoked when the model judges them useful.
|
|
785
|
+
*
|
|
786
|
+
* This is the additive complement to the existing activation directive:
|
|
787
|
+
* activation force-invokes (explicit intent), recommendations remind
|
|
788
|
+
* (manifest defaults). User intent is preserved as the stronger signal
|
|
789
|
+
* (RFC #4779 design principle); this block only adds visibility.
|
|
790
|
+
*/
|
|
791
|
+
function formatSkillRecommendationsBlock(unitType: string | undefined, skillNames: string[]): string {
|
|
792
|
+
if (!unitType) return "";
|
|
793
|
+
const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
|
|
794
|
+
if (safe.length === 0) return "";
|
|
795
|
+
return `<skill_recommendations unit="${unitType}">For this unit type, also consider invoking: ${safe.join(", ")}. Use Skill({ skill: 'name' }) when relevant — these are recommendations, not requirements.</skill_recommendations>`;
|
|
796
|
+
}
|
|
797
|
+
|
|
779
798
|
export function buildSkillActivationBlock(params: {
|
|
780
799
|
base: string;
|
|
781
800
|
milestoneId: string;
|
|
@@ -846,10 +865,49 @@ export function buildSkillActivationBlock(params: {
|
|
|
846
865
|
}
|
|
847
866
|
}
|
|
848
867
|
|
|
868
|
+
// Heuristic auto-match (gated on skill_discovery: "auto").
|
|
869
|
+
// For each installed skill, check if its name or description appears in the
|
|
870
|
+
// unit's context tokens (milestone/slice/task titles). Only consider skills
|
|
871
|
+
// already on the unit-type manifest allowlist — this keeps the heuristic
|
|
872
|
+
// narrow and avoids wildly off-topic activations.
|
|
873
|
+
// Users who set `skill_discovery: "off"` or "suggest" do not get
|
|
874
|
+
// auto-matched skills (the recommendations block still surfaces manifest
|
|
875
|
+
// skills passively); only "auto" actually adds them to the activation
|
|
876
|
+
// directive set. Default `skill_discovery` is "suggest", so this is opt-in.
|
|
877
|
+
if ((prefs?.skill_discovery ?? "suggest") === "auto") {
|
|
878
|
+
const manifestAllow = resolveSkillManifest(params.unitType);
|
|
879
|
+
const allowSet = manifestAllow ? new Set(manifestAllow) : null;
|
|
880
|
+
for (const skill of visibleSkills) {
|
|
881
|
+
const normalized = normalizeSkillReference(skill.name);
|
|
882
|
+
if (matched.has(normalized) || avoided.has(normalized)) continue;
|
|
883
|
+
// Respect the manifest allowlist when present; wildcard (null) lets all
|
|
884
|
+
// installed skills compete for keyword match.
|
|
885
|
+
if (allowSet && !allowSet.has(normalized)) continue;
|
|
886
|
+
if (skillMatchesContext(skill, contextTokens)) {
|
|
887
|
+
matched.add(normalized);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
849
892
|
const ordered = [...matched]
|
|
850
893
|
.filter(name => installedNames.has(name) && !avoided.has(name))
|
|
851
894
|
.sort();
|
|
852
|
-
|
|
895
|
+
const activationBlock = formatSkillActivationBlock(ordered);
|
|
896
|
+
|
|
897
|
+
// Manifest-driven recommendations (additive, does not override explicit intent).
|
|
898
|
+
// Only surface skills the manifest declares for this unit type that are
|
|
899
|
+
// installed and not already in matched/avoided.
|
|
900
|
+
const matchedSet = new Set(ordered);
|
|
901
|
+
const manifestList = resolveSkillManifest(params.unitType);
|
|
902
|
+
const recommendations = (manifestList ?? [])
|
|
903
|
+
.filter(name => installedNames.has(name) && !avoided.has(name) && !matchedSet.has(name))
|
|
904
|
+
.sort();
|
|
905
|
+
const recommendationsBlock = formatSkillRecommendationsBlock(params.unitType, recommendations);
|
|
906
|
+
|
|
907
|
+
if (!activationBlock && !recommendationsBlock) return "";
|
|
908
|
+
if (!activationBlock) return recommendationsBlock;
|
|
909
|
+
if (!recommendationsBlock) return activationBlock;
|
|
910
|
+
return `${activationBlock}\n${recommendationsBlock}`;
|
|
853
911
|
}
|
|
854
912
|
|
|
855
913
|
/**
|
|
@@ -1209,6 +1267,7 @@ export async function buildDiscussMilestonePrompt(
|
|
|
1209
1267
|
const discussTemplates = inlineTemplate("context", "Context");
|
|
1210
1268
|
|
|
1211
1269
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1270
|
+
workingDirectory: base,
|
|
1212
1271
|
milestoneId: mid,
|
|
1213
1272
|
milestoneTitle: midTitle,
|
|
1214
1273
|
inlinedTemplates: discussTemplates,
|
|
@@ -2587,6 +2646,7 @@ export async function buildParallelResearchSlicesPrompt(
|
|
|
2587
2646
|
}
|
|
2588
2647
|
|
|
2589
2648
|
return loadPrompt("parallel-research-slices", {
|
|
2649
|
+
workingDirectory: basePath,
|
|
2590
2650
|
mid,
|
|
2591
2651
|
midTitle,
|
|
2592
2652
|
sliceCount: String(slices.length),
|
|
@@ -2623,6 +2683,7 @@ export async function buildGateEvaluatePrompt(
|
|
|
2623
2683
|
|
|
2624
2684
|
const subagentSections: string[] = [];
|
|
2625
2685
|
const gateListLines: string[] = [];
|
|
2686
|
+
const normalizedBase = base.replaceAll("\\", "/");
|
|
2626
2687
|
|
|
2627
2688
|
for (const def of gateDefs) {
|
|
2628
2689
|
gateListLines.push(`- **${def.id}**: ${def.question}`);
|
|
@@ -2630,6 +2691,8 @@ export async function buildGateEvaluatePrompt(
|
|
|
2630
2691
|
const subPrompt = [
|
|
2631
2692
|
`You are evaluating quality gate **${def.id}** for slice ${sid} (${sTitle}).`,
|
|
2632
2693
|
"",
|
|
2694
|
+
`**Working directory:** \`${normalizedBase}\`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT \`cd\` to any other directory.`,
|
|
2695
|
+
"",
|
|
2633
2696
|
`## Question: ${def.question}`,
|
|
2634
2697
|
"",
|
|
2635
2698
|
def.guidance,
|
|
@@ -2746,6 +2809,7 @@ export async function buildRewriteDocsPrompt(
|
|
|
2746
2809
|
const documentList = docList.length > 0 ? docList.join("\n") : "- No active plan documents found.";
|
|
2747
2810
|
|
|
2748
2811
|
return loadPrompt("rewrite-docs", {
|
|
2812
|
+
workingDirectory: base,
|
|
2749
2813
|
milestoneId: mid,
|
|
2750
2814
|
milestoneTitle: midTitle,
|
|
2751
2815
|
sliceId: sid ?? "none",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
11
11
|
import { parseUnitId } from "./unit-id.js";
|
|
12
|
+
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
12
13
|
import { appendEvent } from "./workflow-events.js";
|
|
13
14
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
14
15
|
import { clearParseCache } from "./files.js";
|
|
@@ -213,13 +214,40 @@ function getChangedFilesSinceBranch(basePath: string, targetBranch: string): { o
|
|
|
213
214
|
function getChangedFilesFromMilestoneTaggedCommits(
|
|
214
215
|
basePath: string,
|
|
215
216
|
milestoneId: string,
|
|
217
|
+
): { ok: boolean; matched: boolean; files: string[] } {
|
|
218
|
+
// Primary: path-scoped log against .gsd/milestones/<id>. Fast and unbounded
|
|
219
|
+
// by depth when .gsd/ is tracked in git.
|
|
220
|
+
const scoped = scanGsdTaggedCommits(basePath, milestoneId, [
|
|
221
|
+
"log", "--format=%H%x1f%B%x1e", "HEAD", "--", `.gsd/milestones/${milestoneId}`,
|
|
222
|
+
]);
|
|
223
|
+
if (!scoped.ok) return scoped;
|
|
224
|
+
if (scoped.matched) return scoped;
|
|
225
|
+
|
|
226
|
+
// Fallback (#5033): when .gsd/ is gitignored / external / untracked, the
|
|
227
|
+
// path-scoped scan matches no commits even though GSD-tagged commits
|
|
228
|
+
// referencing the milestone exist on the integration branch. Re-scan all
|
|
229
|
+
// of HEAD's history and rely on commitMatchesMilestone to bind by
|
|
230
|
+
// explicit milestone mention in the message body.
|
|
231
|
+
//
|
|
232
|
+
// Intentionally unbounded — symmetric with the primary scan, and avoids
|
|
233
|
+
// reintroducing the rolling-depth failure class removed in #4699 where
|
|
234
|
+
// milestone evidence aged out behind unrelated activity.
|
|
235
|
+
return scanGsdTaggedCommits(basePath, milestoneId, [
|
|
236
|
+
"log", "--format=%H%x1f%B%x1e", "HEAD",
|
|
237
|
+
]);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function scanGsdTaggedCommits(
|
|
241
|
+
basePath: string,
|
|
242
|
+
milestoneId: string,
|
|
243
|
+
gitArgs: readonly string[],
|
|
216
244
|
): { ok: boolean; matched: boolean; files: string[] } {
|
|
217
245
|
try {
|
|
218
|
-
const logOutput = execFileSync(
|
|
219
|
-
|
|
220
|
-
["
|
|
221
|
-
|
|
222
|
-
);
|
|
246
|
+
const logOutput = execFileSync("git", [...gitArgs], {
|
|
247
|
+
cwd: basePath,
|
|
248
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
249
|
+
encoding: "utf-8",
|
|
250
|
+
});
|
|
223
251
|
const records = logOutput
|
|
224
252
|
.split("\x1e")
|
|
225
253
|
.map((record) => record.trim())
|
|
@@ -270,15 +298,25 @@ function commitMatchesMilestone(message: string, milestoneId: string, files: rea
|
|
|
270
298
|
if (commitTrailerStartsWithMilestone(message, milestoneId)) return true;
|
|
271
299
|
|
|
272
300
|
// Meaningful execute-task commits currently store task scope as Sxx/Tyy
|
|
273
|
-
// rather than Mxx/Sxx/Tyy. Bind those commits back to the milestone
|
|
274
|
-
//
|
|
301
|
+
// rather than Mxx/Sxx/Tyy. Bind those commits back to the milestone when
|
|
302
|
+
// either the commit touched this milestone's artifacts, or — for projects
|
|
303
|
+
// where .gsd/ is gitignored/external (#5033) — the message explicitly
|
|
304
|
+
// names the milestone.
|
|
275
305
|
if (/^GSD-Task:\s*S[^/\s]+\/T\S+/m.test(message)) {
|
|
276
|
-
|
|
306
|
+
if (files.some((file) => isMilestoneArtifactPath(file, milestoneId))) return true;
|
|
307
|
+
if (commitMessageMentionsMilestone(message, milestoneId)) return true;
|
|
277
308
|
}
|
|
278
309
|
|
|
279
310
|
return false;
|
|
280
311
|
}
|
|
281
312
|
|
|
313
|
+
function commitMessageMentionsMilestone(message: string, milestoneId: string): boolean {
|
|
314
|
+
if (!MILESTONE_ID_RE.test(milestoneId)) return false;
|
|
315
|
+
|
|
316
|
+
const escapedMilestone = milestoneId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
317
|
+
return new RegExp(`\\b${escapedMilestone}\\b`).test(message);
|
|
318
|
+
}
|
|
319
|
+
|
|
282
320
|
function commitTrailerStartsWithMilestone(message: string, milestoneId: string): boolean {
|
|
283
321
|
const escapedMilestone = milestoneId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
284
322
|
const trailerPattern = new RegExp(
|