@opengsd/gsd-pi 1.0.2-dev.e9a1b49 → 1.0.2-dev.fb7ddf1
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 +63 -12
- package/dist/headless-answers.js +2 -1
- package/dist/headless-events.d.ts +1 -0
- package/dist/headless-events.js +8 -1
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +44 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +81 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +38 -1
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +36 -55
- package/dist/resources/extensions/gsd/auto.js +40 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +7 -2
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
- package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +3 -20
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repo-identity.js +36 -6
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/extensions/subagent/index.js +8 -15
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/resources/skills/agent-browser/SKILL.md +1 -1
- package/dist/resources/skills/api-design/SKILL.md +1 -1
- package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
- package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/dist/resources/skills/forensics/SKILL.md +2 -2
- package/dist/resources/skills/grill-me/SKILL.md +1 -1
- package/dist/resources/skills/handoff/SKILL.md +1 -1
- package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/dist/resources/skills/observability/SKILL.md +1 -1
- package/dist/resources/skills/security-review/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/dist/resources/skills/tdd/SKILL.md +1 -1
- package/dist/resources/skills/write-docs/SKILL.md +1 -1
- package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.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/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-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/node_modules/node-pty/build/Makefile +1 -1
- package/dist/worktree-cli.d.ts +0 -2
- package/dist/worktree-cli.js +21 -9
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
- package/packages/cloud-mcp-gateway/package.json +4 -3
- package/packages/contracts/dist/rpc.test.js +5 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +15 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/dist/workflow.test.js +1 -0
- package/packages/contracts/dist/workflow.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +7 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +47 -8
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +16 -14
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/bin/pi-ai.js +14 -0
- package/packages/pi-ai/dist/models.generated.d.ts +48 -206
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +73 -226
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -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/tests/tool-search-shim.test.js +29 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
- package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +96 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +47 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +47 -57
- package/src/resources/extensions/gsd/auto.ts +50 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +7 -2
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
- package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +3 -20
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repo-identity.ts +35 -7
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/extensions/subagent/index.ts +8 -15
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/src/resources/skills/agent-browser/SKILL.md +1 -1
- package/src/resources/skills/api-design/SKILL.md +1 -1
- package/src/resources/skills/code-optimizer/SKILL.md +6 -11
- package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/src/resources/skills/forensics/SKILL.md +2 -2
- package/src/resources/skills/grill-me/SKILL.md +1 -1
- package/src/resources/skills/handoff/SKILL.md +1 -1
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/src/resources/skills/observability/SKILL.md +1 -1
- package/src/resources/skills/security-review/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/src/resources/skills/tdd/SKILL.md +1 -1
- package/src/resources/skills/write-docs/SKILL.md +1 -1
- package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
|
@@ -21,7 +21,7 @@ import { invalidateAllCaches } from "./cache.js";
|
|
|
21
21
|
import { writeLock, clearLock, readCrashLock, isLockProcessAlive } from "./crash-recovery.js";
|
|
22
22
|
import { acquireSessionLock, releaseSessionLock, updateSessionLock, } from "./session-lock.js";
|
|
23
23
|
import { ensureGitignore, untrackRuntimeFiles } from "./gitignore.js";
|
|
24
|
-
import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit, nativeGetCurrentBranch, nativeDetectMainBranch, nativeBranchList, nativeBranchExists, nativeBranchListMerged, nativeBranchDelete, nativeWorktreeRemove, nativeCommitCountBetween, } from "./native-git-bridge.js";
|
|
24
|
+
import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit, nativeGetCurrentBranch, nativeDetectMainBranch, nativeBranchList, nativeBranchExists, nativeBranchListMerged, nativeBranchDelete, nativeWorktreeRemove, nativeCommitCountBetween, nativeHasChanges, } from "./native-git-bridge.js";
|
|
25
25
|
import { GitServiceImpl } from "./git-service.js";
|
|
26
26
|
import { captureIntegrationBranch, detectWorktreeName, setActiveMilestoneId, } from "./worktree.js";
|
|
27
27
|
import { getAutoWorktreePath, checkoutBranchWithStashGuard } from "./auto-worktree.js";
|
|
@@ -126,17 +126,68 @@ export function resolveSurvivorRecoveryIsolationMode(isolationMode, phase) {
|
|
|
126
126
|
return "branch";
|
|
127
127
|
return isolationMode;
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
function isBlockingStrandedWorkAction(action) {
|
|
130
|
+
return action.kind === "in-progress-stranded-work" && action.blocksAuto;
|
|
131
|
+
}
|
|
132
|
+
function detectWorktreeEvidence(basePath, milestoneId, hasChanges) {
|
|
133
|
+
const wtDir = getWorktreeDir(basePath, milestoneId);
|
|
134
|
+
const wtPath = getAutoWorktreePath(basePath, milestoneId);
|
|
135
|
+
let dirty = false;
|
|
136
|
+
if (wtPath) {
|
|
137
|
+
try {
|
|
138
|
+
dirty = hasChanges(wtPath);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
dirty = false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
path: wtPath,
|
|
146
|
+
dirExists: existsSync(wtDir),
|
|
147
|
+
dirty,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function strandedWorkMessage(args) {
|
|
151
|
+
const evidence = [];
|
|
152
|
+
if (args.branch && args.commitsAhead > 0) {
|
|
153
|
+
evidence.push(`branch ${args.branch} has ${args.commitsAhead} commit(s) ahead of ${args.mainBranch}`);
|
|
154
|
+
}
|
|
155
|
+
if (args.dirtyWorktree) {
|
|
156
|
+
evidence.push("the worktree has uncommitted changes");
|
|
157
|
+
}
|
|
158
|
+
if (evidence.length === 0) {
|
|
159
|
+
evidence.push("physical git evidence exists");
|
|
160
|
+
}
|
|
161
|
+
const wtSuffix = args.worktreeDirExists
|
|
162
|
+
? ` Worktree directory at .gsd/worktrees/${args.milestoneId}/ holds live work.`
|
|
163
|
+
: "";
|
|
164
|
+
const recovery = args.recoveryMode === "worktree"
|
|
165
|
+
? "Recovering will adopt the existing worktree."
|
|
166
|
+
: "Recovering will adopt the milestone branch.";
|
|
167
|
+
return (`Stranded work for in-progress milestone ${args.milestoneId}: ${evidence.join("; ")}.` +
|
|
168
|
+
wtSuffix +
|
|
169
|
+
` ${recovery} Park or discard explicitly if abandoning.`);
|
|
170
|
+
}
|
|
171
|
+
export function auditOrphanedMilestoneBranches(basePath, _isolationMode, gitDeps = {}) {
|
|
130
172
|
const recovered = [];
|
|
131
173
|
const warnings = [];
|
|
174
|
+
const actions = [];
|
|
132
175
|
const branchList = gitDeps.branchList ?? nativeBranchList;
|
|
133
176
|
const branchExists = gitDeps.branchExists ?? nativeBranchExists;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
177
|
+
const hasChanges = gitDeps.hasChanges ?? nativeHasChanges;
|
|
178
|
+
const pushAction = (action) => {
|
|
179
|
+
actions.push(action);
|
|
180
|
+
if (action.severity === "info") {
|
|
181
|
+
recovered.push(action.message);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
warnings.push(action.message);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
137
187
|
// Skip if DB not available — can't determine completion status
|
|
138
|
-
if (!isDbAvailable())
|
|
139
|
-
return { recovered, warnings };
|
|
188
|
+
if (!isDbAvailable()) {
|
|
189
|
+
return { recovered, warnings, actions, blockingStrandedWork: null };
|
|
190
|
+
}
|
|
140
191
|
let milestoneBranches;
|
|
141
192
|
let milestoneBranchListAvailable = true;
|
|
142
193
|
try {
|
|
@@ -170,6 +221,7 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
170
221
|
if (!milestone)
|
|
171
222
|
continue;
|
|
172
223
|
const isMerged = mergedBranches.has(branch);
|
|
224
|
+
const worktreeEvidence = detectWorktreeEvidence(basePath, milestoneId, hasChanges);
|
|
173
225
|
// #4762 — in-progress milestone branch with unmerged commits ahead of
|
|
174
226
|
// main. This is the pre-completion orphan case: auto-mode exited without
|
|
175
227
|
// completing the milestone (pause, stop, crash, merge error, blocker) and
|
|
@@ -181,32 +233,45 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
181
233
|
// Parked/other closed statuses go through the legacy complete/unmerged
|
|
182
234
|
// path below where appropriate.
|
|
183
235
|
if (!isClosedStatus(milestone.status)) {
|
|
184
|
-
if (isMerged)
|
|
185
|
-
continue; // nothing to recover
|
|
186
236
|
let commitsAhead = 0;
|
|
187
237
|
try {
|
|
188
238
|
commitsAhead = nativeCommitCountBetween(basePath, mainBranch, branch);
|
|
189
239
|
}
|
|
190
240
|
catch {
|
|
191
|
-
|
|
192
|
-
continue;
|
|
241
|
+
commitsAhead = 0;
|
|
193
242
|
}
|
|
194
|
-
if (commitsAhead === 0)
|
|
243
|
+
if ((isMerged || commitsAhead === 0) && !worktreeEvidence.dirty)
|
|
195
244
|
continue;
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
245
|
+
const recoveryMode = worktreeEvidence.path
|
|
246
|
+
? "worktree"
|
|
247
|
+
: "branch";
|
|
248
|
+
const message = strandedWorkMessage({
|
|
249
|
+
milestoneId,
|
|
250
|
+
branch,
|
|
251
|
+
commitsAhead,
|
|
252
|
+
mainBranch,
|
|
253
|
+
dirtyWorktree: worktreeEvidence.dirty,
|
|
254
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
255
|
+
recoveryMode,
|
|
256
|
+
});
|
|
257
|
+
pushAction({
|
|
258
|
+
kind: "in-progress-stranded-work",
|
|
259
|
+
milestoneId,
|
|
260
|
+
branch,
|
|
261
|
+
commitsAhead,
|
|
262
|
+
dirtyWorktree: worktreeEvidence.dirty,
|
|
263
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
264
|
+
recoveryMode,
|
|
265
|
+
message,
|
|
266
|
+
severity: "warning",
|
|
267
|
+
blocksAuto: true,
|
|
268
|
+
});
|
|
204
269
|
// #4764 telemetry
|
|
205
270
|
try {
|
|
206
271
|
emitWorktreeOrphaned(basePath, milestoneId, {
|
|
207
272
|
reason: "in-progress-unmerged",
|
|
208
273
|
commitsAhead,
|
|
209
|
-
worktreeDirExists:
|
|
274
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
210
275
|
});
|
|
211
276
|
}
|
|
212
277
|
catch (err) {
|
|
@@ -223,7 +288,14 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
223
288
|
// Branch is merged — safe to delete branch and clean up worktree dir
|
|
224
289
|
try {
|
|
225
290
|
nativeBranchDelete(basePath, branch, true);
|
|
226
|
-
|
|
291
|
+
pushAction({
|
|
292
|
+
kind: "complete-merged-branch",
|
|
293
|
+
milestoneId,
|
|
294
|
+
branch,
|
|
295
|
+
message: `Deleted merged branch ${branch} for completed milestone ${milestoneId}.`,
|
|
296
|
+
severity: "info",
|
|
297
|
+
blocksAuto: false,
|
|
298
|
+
});
|
|
227
299
|
}
|
|
228
300
|
catch (err) {
|
|
229
301
|
warnings.push(`Failed to delete merged branch ${branch}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -246,7 +318,15 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
246
318
|
if (isInsideWorktreesDir(basePath, wtDir)) {
|
|
247
319
|
try {
|
|
248
320
|
rmSync(wtDir, { recursive: true, force: true });
|
|
249
|
-
|
|
321
|
+
pushAction({
|
|
322
|
+
kind: "complete-merged-worktree",
|
|
323
|
+
milestoneId,
|
|
324
|
+
branch,
|
|
325
|
+
worktreeDirExists: true,
|
|
326
|
+
message: `Removed orphaned worktree directory for ${milestoneId}.`,
|
|
327
|
+
severity: "info",
|
|
328
|
+
blocksAuto: false,
|
|
329
|
+
});
|
|
250
330
|
}
|
|
251
331
|
catch (err2) {
|
|
252
332
|
warnings.push(`Failed to remove worktree directory for ${milestoneId}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
@@ -257,14 +337,30 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
257
337
|
}
|
|
258
338
|
}
|
|
259
339
|
else {
|
|
260
|
-
|
|
340
|
+
pushAction({
|
|
341
|
+
kind: "complete-merged-worktree",
|
|
342
|
+
milestoneId,
|
|
343
|
+
branch,
|
|
344
|
+
worktreeDirExists: true,
|
|
345
|
+
message: `Removed orphaned worktree directory for ${milestoneId}.`,
|
|
346
|
+
severity: "info",
|
|
347
|
+
blocksAuto: false,
|
|
348
|
+
});
|
|
261
349
|
}
|
|
262
350
|
}
|
|
263
351
|
}
|
|
264
352
|
else {
|
|
265
353
|
// Branch is NOT merged — preserve for safety, warn the user
|
|
266
|
-
|
|
267
|
-
|
|
354
|
+
pushAction({
|
|
355
|
+
kind: "complete-unmerged-branch",
|
|
356
|
+
milestoneId,
|
|
357
|
+
branch,
|
|
358
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
359
|
+
message: `Branch ${branch} exists for completed milestone ${milestoneId} but is NOT merged into ${mainBranch}. ` +
|
|
360
|
+
`This may contain unmerged work. Merge manually or run \`/gsd doctor fix\` to resolve.`,
|
|
361
|
+
severity: "warning",
|
|
362
|
+
blocksAuto: false,
|
|
363
|
+
});
|
|
268
364
|
// #4764 telemetry
|
|
269
365
|
try {
|
|
270
366
|
emitWorktreeOrphaned(basePath, milestoneId, {
|
|
@@ -300,6 +396,43 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
300
396
|
completedMilestones = [];
|
|
301
397
|
}
|
|
302
398
|
for (const m of completedMilestones) {
|
|
399
|
+
if (!isClosedStatus(m.status)) {
|
|
400
|
+
if (seenMilestoneIds.has(m.id))
|
|
401
|
+
continue;
|
|
402
|
+
const worktreeEvidence = detectWorktreeEvidence(basePath, m.id, hasChanges);
|
|
403
|
+
if (!worktreeEvidence.dirty)
|
|
404
|
+
continue;
|
|
405
|
+
const message = strandedWorkMessage({
|
|
406
|
+
milestoneId: m.id,
|
|
407
|
+
commitsAhead: 0,
|
|
408
|
+
mainBranch,
|
|
409
|
+
dirtyWorktree: true,
|
|
410
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
411
|
+
recoveryMode: "worktree",
|
|
412
|
+
});
|
|
413
|
+
pushAction({
|
|
414
|
+
kind: "in-progress-stranded-work",
|
|
415
|
+
milestoneId: m.id,
|
|
416
|
+
commitsAhead: 0,
|
|
417
|
+
dirtyWorktree: true,
|
|
418
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
419
|
+
recoveryMode: "worktree",
|
|
420
|
+
message,
|
|
421
|
+
severity: "warning",
|
|
422
|
+
blocksAuto: true,
|
|
423
|
+
});
|
|
424
|
+
try {
|
|
425
|
+
emitWorktreeOrphaned(basePath, m.id, {
|
|
426
|
+
reason: "in-progress-unmerged",
|
|
427
|
+
commitsAhead: 0,
|
|
428
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
catch (err) {
|
|
432
|
+
logWarning("engine", `worktree-orphaned telemetry failed for ${m.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
433
|
+
}
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
303
436
|
if (m.status !== "complete")
|
|
304
437
|
continue;
|
|
305
438
|
if (seenMilestoneIds.has(m.id))
|
|
@@ -332,17 +465,36 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode, gitDeps
|
|
|
332
465
|
if (existsSync(wtDir)) {
|
|
333
466
|
try {
|
|
334
467
|
rmSync(wtDir, { recursive: true, force: true });
|
|
335
|
-
|
|
468
|
+
pushAction({
|
|
469
|
+
kind: "complete-branchless-worktree",
|
|
470
|
+
milestoneId: m.id,
|
|
471
|
+
worktreeDirExists: true,
|
|
472
|
+
message: `Removed orphaned worktree directory for ${m.id} (branch already deleted).`,
|
|
473
|
+
severity: "info",
|
|
474
|
+
blocksAuto: false,
|
|
475
|
+
});
|
|
336
476
|
}
|
|
337
477
|
catch (err) {
|
|
338
478
|
warnings.push(`Failed to remove orphaned worktree directory for ${m.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
339
479
|
}
|
|
340
480
|
}
|
|
341
481
|
else {
|
|
342
|
-
|
|
482
|
+
pushAction({
|
|
483
|
+
kind: "complete-branchless-worktree",
|
|
484
|
+
milestoneId: m.id,
|
|
485
|
+
worktreeDirExists: true,
|
|
486
|
+
message: `Removed orphaned worktree directory for ${m.id} (branch already deleted).`,
|
|
487
|
+
severity: "info",
|
|
488
|
+
blocksAuto: false,
|
|
489
|
+
});
|
|
343
490
|
}
|
|
344
491
|
}
|
|
345
|
-
return {
|
|
492
|
+
return {
|
|
493
|
+
recovered,
|
|
494
|
+
warnings,
|
|
495
|
+
actions,
|
|
496
|
+
blockingStrandedWork: actions.find(isBlockingStrandedWorkAction) ?? null,
|
|
497
|
+
};
|
|
346
498
|
}
|
|
347
499
|
/**
|
|
348
500
|
* Pure decision function for picking which orphan milestone the auto-loop
|
|
@@ -679,17 +831,27 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
679
831
|
// was lost due to session ending between completion and teardown.
|
|
680
832
|
// Must run after DB open and before worktree entry.
|
|
681
833
|
let orphanAuditRecovered = false;
|
|
834
|
+
let strandedRecoveryActions = [];
|
|
835
|
+
let strandedRecoveryAction = null;
|
|
682
836
|
try {
|
|
683
837
|
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode(base));
|
|
838
|
+
strandedRecoveryActions = auditResult.actions.filter(isBlockingStrandedWorkAction);
|
|
839
|
+
strandedRecoveryAction = strandedRecoveryActions[0] ?? null;
|
|
684
840
|
for (const msg of auditResult.recovered) {
|
|
685
841
|
ctx.ui.notify(`Orphan audit: ${msg}`, "info");
|
|
686
842
|
}
|
|
687
843
|
for (const msg of auditResult.warnings) {
|
|
688
|
-
|
|
844
|
+
const prefix = msg.startsWith("Stranded work") ? "" : "Orphan audit: ";
|
|
845
|
+
ctx.ui.notify(`${prefix}${msg}`, "warning");
|
|
689
846
|
}
|
|
690
847
|
if (auditResult.recovered.length > 0) {
|
|
691
848
|
orphanAuditRecovered = true;
|
|
692
|
-
debugLog("orphan-audit", {
|
|
849
|
+
debugLog("orphan-audit", {
|
|
850
|
+
recovered: auditResult.recovered,
|
|
851
|
+
warnings: auditResult.warnings,
|
|
852
|
+
strandedRecoveryAction,
|
|
853
|
+
strandedRecoveryActions,
|
|
854
|
+
});
|
|
693
855
|
}
|
|
694
856
|
}
|
|
695
857
|
catch (err) {
|
|
@@ -724,13 +886,6 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
724
886
|
logWarning("bootstrap", `orphaned preflight-stash audit failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
725
887
|
}
|
|
726
888
|
let state = await deriveState(base);
|
|
727
|
-
if (process.env.GSD_HEADLESS === "1" &&
|
|
728
|
-
orphanAuditRecovered &&
|
|
729
|
-
!state.activeMilestone &&
|
|
730
|
-
state.phase === "complete") {
|
|
731
|
-
ctx.ui.notify("Auto-mode stopped (Recovered completed milestone cleanup; all milestones complete).", "info");
|
|
732
|
-
return releaseLockAndReturn();
|
|
733
|
-
}
|
|
734
889
|
// Stale worktree state recovery (#654)
|
|
735
890
|
if (state.activeMilestone &&
|
|
736
891
|
shouldUseWorktreeIsolation(base) &&
|
|
@@ -740,6 +895,28 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
740
895
|
state = await deriveState(wtPath);
|
|
741
896
|
}
|
|
742
897
|
}
|
|
898
|
+
const blockingStrandedRecoveryAction = state.activeMilestone
|
|
899
|
+
? strandedRecoveryActions.find((action) => action.milestoneId !== state.activeMilestone?.id) ?? strandedRecoveryAction
|
|
900
|
+
: strandedRecoveryAction;
|
|
901
|
+
if (blockingStrandedRecoveryAction) {
|
|
902
|
+
if (!state.activeMilestone) {
|
|
903
|
+
ctx.ui.notify(`Stranded work for ${blockingStrandedRecoveryAction.milestoneId} blocks auto-mode, but that milestone is not active in project state. Park or discard it explicitly before continuing.`, "error");
|
|
904
|
+
return releaseLockAndReturn();
|
|
905
|
+
}
|
|
906
|
+
if (state.activeMilestone.id !== blockingStrandedRecoveryAction.milestoneId) {
|
|
907
|
+
ctx.ui.notify(`Stranded work for ${blockingStrandedRecoveryAction.milestoneId} blocks auto-mode before ${state.activeMilestone.id}. Recover, park, or discard ${blockingStrandedRecoveryAction.milestoneId} explicitly before continuing.`, "error");
|
|
908
|
+
return releaseLockAndReturn();
|
|
909
|
+
}
|
|
910
|
+
strandedRecoveryAction = blockingStrandedRecoveryAction;
|
|
911
|
+
ctx.ui.notify(`Recovering stranded work for ${strandedRecoveryAction.milestoneId} before dispatching new units.`, "info");
|
|
912
|
+
}
|
|
913
|
+
if (process.env.GSD_HEADLESS === "1" &&
|
|
914
|
+
orphanAuditRecovered &&
|
|
915
|
+
!state.activeMilestone &&
|
|
916
|
+
state.phase === "complete") {
|
|
917
|
+
ctx.ui.notify("Auto-mode stopped (Recovered completed milestone cleanup; all milestones complete).", "info");
|
|
918
|
+
return releaseLockAndReturn();
|
|
919
|
+
}
|
|
743
920
|
// Milestone branch recovery (#601, #2358)
|
|
744
921
|
// Detect survivor milestone branches in both pre-planning and complete phases.
|
|
745
922
|
// In phase=complete, the milestone artifacts exist but finalization (merge,
|
|
@@ -768,7 +945,8 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
768
945
|
// The worktree/branch was created but the milestone only has CONTEXT-DRAFT.md.
|
|
769
946
|
// Route to the interactive discussion handler instead of falling through to
|
|
770
947
|
// auto-mode, which would immediately stop with "needs discussion".
|
|
771
|
-
if (
|
|
948
|
+
if (!strandedRecoveryAction &&
|
|
949
|
+
decideSurvivorAction(hasSurvivorBranch, state.phase) === "discuss") {
|
|
772
950
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
773
951
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
774
952
|
invalidateAllCaches();
|
|
@@ -848,14 +1026,14 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
848
1026
|
const effectivePrefs = loadEffectiveGSDPreferences(base)?.preferences;
|
|
849
1027
|
const { shouldRunDeepProjectSetup } = await import("./auto-dispatch.js");
|
|
850
1028
|
const deepProjectStagePending = shouldRunDeepProjectSetup(state, effectivePrefs, base, { hasSurvivorBranch });
|
|
851
|
-
if (deepProjectStagePending) {
|
|
1029
|
+
if (deepProjectStagePending && !strandedRecoveryAction) {
|
|
852
1030
|
// Deep project-level setup runs before the first milestone exists. Let
|
|
853
1031
|
// the auto loop dispatch workflow-preferences / project / requirements
|
|
854
1032
|
// units instead of recursing back through showSmartEntry while this
|
|
855
1033
|
// bootstrap still holds the session lock.
|
|
856
1034
|
s.currentMilestoneId = null;
|
|
857
1035
|
}
|
|
858
|
-
if (!hasSurvivorBranch && !deepProjectStagePending) {
|
|
1036
|
+
if (!hasSurvivorBranch && !deepProjectStagePending && !strandedRecoveryAction) {
|
|
859
1037
|
// No active work — start a new milestone via discuss flow
|
|
860
1038
|
if (!state.activeMilestone || state.phase === "complete") {
|
|
861
1039
|
// Guard against recursive dialog loop (#1348):
|
|
@@ -917,7 +1095,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
917
1095
|
}
|
|
918
1096
|
}
|
|
919
1097
|
// Unreachable safety check
|
|
920
|
-
if (!state.activeMilestone && !deepProjectStagePending) {
|
|
1098
|
+
if (!state.activeMilestone && !deepProjectStagePending && !strandedRecoveryAction) {
|
|
921
1099
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
922
1100
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
923
1101
|
return releaseLockAndReturn();
|
|
@@ -952,7 +1130,9 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
952
1130
|
s.resourceVersionOnStart = readResourceVersion();
|
|
953
1131
|
s.pendingQuickTasks = [];
|
|
954
1132
|
s.currentUnit = null;
|
|
955
|
-
s.currentMilestoneId ??=
|
|
1133
|
+
s.currentMilestoneId ??=
|
|
1134
|
+
strandedRecoveryAction?.milestoneId ??
|
|
1135
|
+
(deepProjectStagePending ? null : state.activeMilestone?.id ?? null);
|
|
956
1136
|
s.originalModelId = startModelSnapshot?.id ?? ctx.model?.id ?? null;
|
|
957
1137
|
s.originalModelProvider = startModelSnapshot?.provider ?? ctx.model?.provider ?? null;
|
|
958
1138
|
s.originalThinkingLevel = startThinkingSnapshot ?? null;
|
|
@@ -960,7 +1140,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
960
1140
|
registerSigtermHandler(base);
|
|
961
1141
|
// Capture integration branch
|
|
962
1142
|
if (s.currentMilestoneId) {
|
|
963
|
-
if (getIsolationMode(base) !== "none") {
|
|
1143
|
+
if (getIsolationMode(base) !== "none" || strandedRecoveryAction) {
|
|
964
1144
|
captureIntegrationBranch(base, s.currentMilestoneId);
|
|
965
1145
|
}
|
|
966
1146
|
setActiveMilestoneId(base, s.currentMilestoneId);
|
|
@@ -970,7 +1150,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
970
1150
|
// milestone/<MID>. Auto-checkout back to the integration branch.
|
|
971
1151
|
const isolationMode = getIsolationMode(base);
|
|
972
1152
|
const isRepo = nativeIsRepo(base);
|
|
973
|
-
if (isolationMode === "none" && isRepo) {
|
|
1153
|
+
if (isolationMode === "none" && isRepo && !strandedRecoveryAction) {
|
|
974
1154
|
try {
|
|
975
1155
|
const currentBranch = nativeGetCurrentBranch(base);
|
|
976
1156
|
const integrationBranch = nativeDetectMainBranch(base);
|
|
@@ -1001,12 +1181,15 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
1001
1181
|
return symlinkRe.test(p);
|
|
1002
1182
|
};
|
|
1003
1183
|
if (s.currentMilestoneId &&
|
|
1004
|
-
getIsolationMode(base) !== "none" &&
|
|
1184
|
+
(getIsolationMode(base) !== "none" || strandedRecoveryAction?.recoveryMode) &&
|
|
1005
1185
|
!detectWorktreeName(base) &&
|
|
1006
1186
|
!isUnderGsdWorktrees(base)) {
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1009
|
-
|
|
1187
|
+
const lifecycle = buildLifecycle();
|
|
1188
|
+
const enterResult = strandedRecoveryAction?.recoveryMode
|
|
1189
|
+
? lifecycle.adoptStrandedMilestone(s.currentMilestoneId, base, { notify: ctx.ui.notify.bind(ctx.ui) }, { mode: strandedRecoveryAction.recoveryMode })
|
|
1190
|
+
: lifecycle.enterMilestone(s.currentMilestoneId, {
|
|
1191
|
+
notify: ctx.ui.notify.bind(ctx.ui),
|
|
1192
|
+
});
|
|
1010
1193
|
if (!enterResult.ok) {
|
|
1011
1194
|
s.active = false;
|
|
1012
1195
|
if (enterResult.reason === "lease-conflict") {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Tracks which tool calls are currently executing so the idle watchdog
|
|
4
4
|
* can distinguish "waiting for tool completion" from "truly idle".
|
|
5
5
|
*/
|
|
6
|
+
import { stripMcpToolPrefix } from "@gsd/pi-ai";
|
|
6
7
|
const inFlightTools = new Map();
|
|
7
8
|
/**
|
|
8
9
|
* Tools that block waiting for human input by design.
|
|
@@ -17,7 +18,7 @@ const INTERACTIVE_TOOLS = new Set(["ask_user_questions", "secure_env_collect"]);
|
|
|
17
18
|
export function markToolStart(toolCallId, isActive, toolName) {
|
|
18
19
|
if (!isActive)
|
|
19
20
|
return;
|
|
20
|
-
inFlightTools.set(toolCallId, { startedAt: Date.now(), toolName: toolName ?? "unknown" });
|
|
21
|
+
inFlightTools.set(toolCallId, { startedAt: Date.now(), toolName: stripMcpToolPrefix(toolName ?? "unknown") });
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Mark a tool execution as completed.
|
|
@@ -470,6 +470,7 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
470
470
|
// ── Post-execution checks (run after main verification passes for execute-task units) ──
|
|
471
471
|
let postExecChecks;
|
|
472
472
|
let postExecBlockingFailure = false;
|
|
473
|
+
let postExecFailureSummary = null;
|
|
473
474
|
if (result.passed && mid && sid && tid) {
|
|
474
475
|
// Check preferences — respect enhanced_verification and enhanced_verification_post
|
|
475
476
|
const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
|
|
@@ -544,6 +545,11 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
544
545
|
if (postExecResult.status === "fail") {
|
|
545
546
|
postExecBlockingFailure = true;
|
|
546
547
|
const blockingCount = postExecResult.checks.filter((c) => !c.passed && c.blocking).length;
|
|
548
|
+
const firstBlockingFailure = postExecResult.checks.find((c) => !c.passed && c.blocking);
|
|
549
|
+
if (firstBlockingFailure) {
|
|
550
|
+
postExecFailureSummary =
|
|
551
|
+
`[${firstBlockingFailure.category}] ${firstBlockingFailure.target}: ${firstBlockingFailure.message}`;
|
|
552
|
+
}
|
|
547
553
|
ctx.ui.notify(`Post-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`, "error");
|
|
548
554
|
}
|
|
549
555
|
else if (postExecResult.status === "warn") {
|
|
@@ -551,6 +557,11 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
551
557
|
// Strict mode: treat warnings as blocking
|
|
552
558
|
if (prefs?.enhanced_verification_strict === true) {
|
|
553
559
|
postExecBlockingFailure = true;
|
|
560
|
+
const firstWarning = postExecResult.checks.find((c) => (!c.passed && !c.blocking) || (c.passed && c.category === "pattern"));
|
|
561
|
+
if (firstWarning) {
|
|
562
|
+
postExecFailureSummary =
|
|
563
|
+
`[${firstWarning.category}] ${firstWarning.target}: ${firstWarning.message}`;
|
|
564
|
+
}
|
|
554
565
|
}
|
|
555
566
|
}
|
|
556
567
|
}
|
|
@@ -643,9 +654,10 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
643
654
|
s.verificationRetryCount.delete(retryKey);
|
|
644
655
|
s.verificationRetryFailureHashes.delete(retryKey);
|
|
645
656
|
s.pendingVerificationRetry = null;
|
|
646
|
-
|
|
657
|
+
const failureDetail = postExecFailureSummary ?? "unknown post-execution check failure";
|
|
658
|
+
ctx.ui.notify(`Post-execution checks failed (${failureDetail}) — pausing for human review`, "error");
|
|
647
659
|
await pauseAuto(ctx, pi, {
|
|
648
|
-
message:
|
|
660
|
+
message: `Post-execution checks failed: ${failureDetail}.`,
|
|
649
661
|
category: "unknown",
|
|
650
662
|
});
|
|
651
663
|
return "pause";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* manages create, enter, detect, and teardown for auto-mode worktrees.
|
|
9
9
|
*/
|
|
10
10
|
import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync, rmSync, unlinkSync, lstatSync as lstatSyncFn, } from "node:fs";
|
|
11
|
-
import { isAbsolute, join, relative, resolve, sep as pathSep } from "node:path";
|
|
11
|
+
import { dirname, isAbsolute, join, relative, resolve, sep as pathSep } from "node:path";
|
|
12
12
|
import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
|
|
13
13
|
import { reconcileWorktreeDb, isDbAvailable, getMilestone, getMilestoneSlices, getSliceTasks, closeDatabase, openDatabase, getDbPath, } from "./gsd-db.js";
|
|
14
14
|
import { execFileSync } from "node:child_process";
|
|
@@ -23,6 +23,8 @@ import { debugLog } from "./debug-logger.js";
|
|
|
23
23
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
24
24
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
25
25
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
26
|
+
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
27
|
+
import { classifyProject } from "./detection.js";
|
|
26
28
|
import { nativeGetCurrentBranch, nativeDetectMainBranch, nativeWorkingTreeStatus, nativeAddAllWithExclusions, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeConflictFiles, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchForceReset, nativeBranchExists, nativeDiffNumstat, nativeUpdateRef, nativeIsAncestor, nativeMergeAbort, nativeWorktreeList, nativeLsFiles, } from "./native-git-bridge.js";
|
|
27
29
|
import { gsdHome } from "./gsd-home.js";
|
|
28
30
|
import { createWorkspace } from "./workspace.js";
|
|
@@ -189,6 +191,37 @@ export function _resolveAutoWorktreeStartPoint(integrationBranch, gitMainBranch,
|
|
|
189
191
|
? gitMainBranch
|
|
190
192
|
: undefined;
|
|
191
193
|
}
|
|
194
|
+
function importUntrackedProjectRootContentIntoEmptyWorktree(projectRoot, worktreeRoot, milestoneId) {
|
|
195
|
+
const worktreeClassification = classifyProject(worktreeRoot);
|
|
196
|
+
if (worktreeClassification.kind !== "greenfield")
|
|
197
|
+
return 0;
|
|
198
|
+
const projectRootClassification = classifyProject(projectRoot);
|
|
199
|
+
if (projectRootClassification.kind === "greenfield" ||
|
|
200
|
+
projectRootClassification.kind === "invalid-repo" ||
|
|
201
|
+
projectRootClassification.untrackedFiles.length === 0) {
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
204
|
+
let copied = 0;
|
|
205
|
+
for (const relPath of projectRootClassification.untrackedFiles) {
|
|
206
|
+
const src = join(projectRoot, relPath);
|
|
207
|
+
if (!existsSync(src))
|
|
208
|
+
continue;
|
|
209
|
+
const dst = join(worktreeRoot, relPath);
|
|
210
|
+
if (existsSync(dst))
|
|
211
|
+
continue;
|
|
212
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
213
|
+
cpSync(src, dst, { recursive: true, force: false });
|
|
214
|
+
copied++;
|
|
215
|
+
}
|
|
216
|
+
if (copied > 0) {
|
|
217
|
+
debugLog("createAutoWorktree", {
|
|
218
|
+
phase: "import-untracked-project-content",
|
|
219
|
+
milestoneId,
|
|
220
|
+
copied,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return copied;
|
|
224
|
+
}
|
|
192
225
|
export function _shouldReconcileWorktreeDb(worktreeDbPath, mainDbPath, pathExists = existsSync, samePath = isSamePath) {
|
|
193
226
|
return pathExists(worktreeDbPath) && !samePath(worktreeDbPath, mainDbPath);
|
|
194
227
|
}
|
|
@@ -796,60 +829,7 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
|
|
|
796
829
|
export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
|
|
797
830
|
return _finalizeProjectionForMergeImpl(mainBasePath, worktreePath, milestoneId);
|
|
798
831
|
}
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* Run the user-configured post-create hook script after worktree creation.
|
|
802
|
-
* The script receives SOURCE_DIR and WORKTREE_DIR as environment variables.
|
|
803
|
-
* Failure is non-fatal — returns the error message or null on success.
|
|
804
|
-
*
|
|
805
|
-
* Reads the hook path from git.worktree_post_create in preferences.
|
|
806
|
-
* Pass hookPath directly to bypass preference loading (useful for testing).
|
|
807
|
-
*/
|
|
808
|
-
export function runWorktreePostCreateHook(sourceDir, worktreeDir, hookPath) {
|
|
809
|
-
if (hookPath === undefined) {
|
|
810
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
811
|
-
hookPath = prefs?.worktree_post_create;
|
|
812
|
-
}
|
|
813
|
-
if (!hookPath)
|
|
814
|
-
return null;
|
|
815
|
-
// Resolve relative paths against the source project root.
|
|
816
|
-
// On Windows, convert 8.3 short paths (e.g. RUNNER~1) to long paths
|
|
817
|
-
// so execFileSync can locate the file correctly.
|
|
818
|
-
let resolved = isAbsolute(hookPath) ? hookPath : join(sourceDir, hookPath);
|
|
819
|
-
if (!existsSync(resolved)) {
|
|
820
|
-
return `Worktree post-create hook not found: ${resolved}`;
|
|
821
|
-
}
|
|
822
|
-
if (process.platform === "win32") {
|
|
823
|
-
try {
|
|
824
|
-
resolved = realpathSync.native(resolved);
|
|
825
|
-
}
|
|
826
|
-
catch (err) { /* keep original */
|
|
827
|
-
logWarning("worktree", `realpath failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
try {
|
|
831
|
-
// .bat/.cmd files on Windows require shell mode — execFileSync cannot
|
|
832
|
-
// spawn them directly (EINVAL).
|
|
833
|
-
const needsShell = process.platform === "win32" && /\.(bat|cmd)$/i.test(resolved);
|
|
834
|
-
execFileSync(resolved, [], {
|
|
835
|
-
cwd: worktreeDir,
|
|
836
|
-
env: {
|
|
837
|
-
...process.env,
|
|
838
|
-
SOURCE_DIR: sourceDir,
|
|
839
|
-
WORKTREE_DIR: worktreeDir,
|
|
840
|
-
},
|
|
841
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
842
|
-
encoding: "utf-8",
|
|
843
|
-
timeout: 30_000, // 30 second timeout
|
|
844
|
-
shell: needsShell,
|
|
845
|
-
});
|
|
846
|
-
return null;
|
|
847
|
-
}
|
|
848
|
-
catch (err) {
|
|
849
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
850
|
-
return `Worktree post-create hook failed: ${msg}`;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
832
|
+
export { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
853
833
|
// ─── Auto-Worktree Branch Naming ───────────────────────────────────────────
|
|
854
834
|
/** Returns the git branch name for a milestone worktree (`milestone/<MID>`). */
|
|
855
835
|
export function autoWorktreeBranch(milestoneId) {
|
|
@@ -1204,6 +1184,7 @@ export function createAutoWorktree(basePath, milestoneId) {
|
|
|
1204
1184
|
// .gsd/ — both reads and writes converge on the project-root .gsd/.
|
|
1205
1185
|
// The original concerns (#759, #778) no longer apply because there is
|
|
1206
1186
|
// no second copy to drift.
|
|
1187
|
+
importUntrackedProjectRootContentIntoEmptyWorktree(basePath, info.path, milestoneId);
|
|
1207
1188
|
// Run user-configured post-create hook (#597) — e.g. copy .env, symlink assets
|
|
1208
1189
|
const hookError = runWorktreePostCreateHook(basePath, info.path);
|
|
1209
1190
|
if (hookError) {
|