@opengsd/gsd-pi 1.2.0-dev.b1abb545 → 1.2.0-dev.ddc97c10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +14 -34
- package/dist/mcp-server.js +2 -1
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +5 -2
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +122 -58
- package/dist/resources/extensions/gsd/auto/phases.js +54 -6
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
- package/dist/resources/extensions/gsd/auto-post-unit.js +43 -14
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
- package/dist/resources/extensions/gsd/auto-start.js +24 -26
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
- package/dist/resources/extensions/gsd/auto.js +45 -21
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +29 -8
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +229 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +319 -71
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +5 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +398 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -3
- package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-git-checks.js +6 -21
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +172 -2048
- package/dist/resources/extensions/gsd/guidance.js +158 -0
- package/dist/resources/extensions/gsd/guided-flow.js +57 -8
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/paths.js +37 -24
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/preferences.js +14 -0
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +6 -20
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +46 -55
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
- package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -8
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +13 -31
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +16 -35
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +42 -16
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +28 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +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.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.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -11
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- 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 +8 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- 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 +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +9 -1
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +26 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +145 -59
- 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/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/README.md +1 -0
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +192 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +166 -0
- 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 +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +5 -2
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +137 -61
- package/src/resources/extensions/gsd/auto/phases.ts +74 -26
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
- package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +52 -13
- package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
- package/src/resources/extensions/gsd/auto-start.ts +24 -29
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
- package/src/resources/extensions/gsd/auto.ts +64 -25
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -10
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +270 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +368 -78
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +5 -16
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +490 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +5 -22
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +176 -2375
- package/src/resources/extensions/gsd/guidance.ts +217 -0
- package/src/resources/extensions/gsd/guided-flow.ts +71 -31
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
- package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/paths.ts +42 -22
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/preferences.ts +18 -0
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +9 -21
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +275 -40
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +109 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +45 -70
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
- package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -8
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +13 -40
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +16 -44
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +62 -16
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +13 -9
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +29 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → McokybTayhff1xEVc-d3T}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → McokybTayhff1xEVc-d3T}/_ssgManifest.js +0 -0
|
@@ -15,8 +15,11 @@ import {
|
|
|
15
15
|
upsertRequirement,
|
|
16
16
|
getAllMilestones,
|
|
17
17
|
} from "../gsd-db.ts";
|
|
18
|
+
import { registerAutoWorker } from "../db/auto-workers.ts";
|
|
19
|
+
import { claimMilestoneLease, getMilestoneLease } from "../db/milestone-leases.ts";
|
|
18
20
|
import { deriveState, invalidateStateCache } from "../state.ts";
|
|
19
21
|
import { autoSession } from "../auto-runtime-state.ts";
|
|
22
|
+
import { normalizeRealPath } from "../paths.ts";
|
|
20
23
|
import { markApprovalGateVerified, markDepthVerified, clearDiscussionFlowState, loadWriteGateSnapshot, setPendingGate } from "../bootstrap/write-gate.ts";
|
|
21
24
|
import {
|
|
22
25
|
executeCompleteMilestone,
|
|
@@ -94,6 +97,28 @@ function seedMilestone(milestoneId: string, title: string, status = "active"): v
|
|
|
94
97
|
).run(milestoneId, title, status, new Date().toISOString());
|
|
95
98
|
}
|
|
96
99
|
|
|
100
|
+
function validMilestonePlan(milestoneId = "M001"): Parameters<typeof executePlanMilestone>[0] {
|
|
101
|
+
return {
|
|
102
|
+
milestoneId,
|
|
103
|
+
title: "Workflow MCP planning",
|
|
104
|
+
vision: "Plan milestone over shared executors.",
|
|
105
|
+
slices: [
|
|
106
|
+
{
|
|
107
|
+
sliceId: "S01",
|
|
108
|
+
title: "Bridge planning",
|
|
109
|
+
risk: "medium",
|
|
110
|
+
depends: [],
|
|
111
|
+
demo: "Milestone plan persists through MCP.",
|
|
112
|
+
goal: "Persist roadmap state.",
|
|
113
|
+
successCriteria: "ROADMAP.md renders from DB.",
|
|
114
|
+
proofLevel: "integration",
|
|
115
|
+
integrationClosure: "Prompts and MCP call the same handler.",
|
|
116
|
+
observabilityImpact: "Executor tests cover output paths.",
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
97
122
|
function seedSlice(milestoneId: string, sliceId: string, status: string): void {
|
|
98
123
|
const db = _getAdapter();
|
|
99
124
|
if (!db) throw new Error("DB not open");
|
|
@@ -461,25 +486,7 @@ test("executePlanMilestone writes roadmap state and rendered roadmap path", asyn
|
|
|
461
486
|
try {
|
|
462
487
|
openTestDb(base);
|
|
463
488
|
|
|
464
|
-
const result = await inProjectDir(base, () => executePlanMilestone(
|
|
465
|
-
milestoneId: "M001",
|
|
466
|
-
title: "Workflow MCP planning",
|
|
467
|
-
vision: "Plan milestone over shared executors.",
|
|
468
|
-
slices: [
|
|
469
|
-
{
|
|
470
|
-
sliceId: "S01",
|
|
471
|
-
title: "Bridge planning",
|
|
472
|
-
risk: "medium",
|
|
473
|
-
depends: [],
|
|
474
|
-
demo: "Milestone plan persists through MCP.",
|
|
475
|
-
goal: "Persist roadmap state.",
|
|
476
|
-
successCriteria: "ROADMAP.md renders from DB.",
|
|
477
|
-
proofLevel: "integration",
|
|
478
|
-
integrationClosure: "Prompts and MCP call the same handler.",
|
|
479
|
-
observabilityImpact: "Executor tests cover output paths.",
|
|
480
|
-
},
|
|
481
|
-
],
|
|
482
|
-
}, base));
|
|
489
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan(), base));
|
|
483
490
|
|
|
484
491
|
assert.equal(result.details.operation, "plan_milestone");
|
|
485
492
|
assert.equal(result.details.milestoneId, "M001");
|
|
@@ -492,29 +499,257 @@ test("executePlanMilestone writes roadmap state and rendered roadmap path", asyn
|
|
|
492
499
|
}
|
|
493
500
|
});
|
|
494
501
|
|
|
502
|
+
test("executePlanMilestone refuses a same-milestone lease conflict", async () => {
|
|
503
|
+
const base = makeTmpBase();
|
|
504
|
+
try {
|
|
505
|
+
openTestDb(base);
|
|
506
|
+
seedMilestone("M001", "Existing holder");
|
|
507
|
+
const holder = registerAutoWorker({ projectRootRealpath: join(base, "other-project") });
|
|
508
|
+
const lease = claimMilestoneLease(holder, "M001");
|
|
509
|
+
assert.equal(lease.ok, true);
|
|
510
|
+
|
|
511
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M001"), base));
|
|
512
|
+
|
|
513
|
+
assert.equal(result.isError, true);
|
|
514
|
+
assert.equal(result.details.operation, "plan_milestone");
|
|
515
|
+
assert.equal(result.details.error, "milestone_lease_conflict");
|
|
516
|
+
assert.match(result.content[0].text, /Milestone M001 is currently leased/);
|
|
517
|
+
} finally {
|
|
518
|
+
closeDatabase();
|
|
519
|
+
cleanup(base);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
test("executePlanMilestone releases its one-shot milestone lease after planning", async () => {
|
|
524
|
+
const base = makeTmpBase();
|
|
525
|
+
try {
|
|
526
|
+
openTestDb(base);
|
|
527
|
+
seedMilestone("M001", "Existing milestone");
|
|
528
|
+
|
|
529
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M001"), base));
|
|
530
|
+
|
|
531
|
+
assert.equal(result.isError, undefined);
|
|
532
|
+
const lease = getMilestoneLease("M001");
|
|
533
|
+
assert.ok(lease, "planning should participate in milestone lease coordination");
|
|
534
|
+
assert.equal(lease.status, "released");
|
|
535
|
+
} finally {
|
|
536
|
+
closeDatabase();
|
|
537
|
+
cleanup(base);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
test("executePlanMilestone creates a fresh milestone without a one-shot lease", async () => {
|
|
542
|
+
const base = makeTmpBase();
|
|
543
|
+
try {
|
|
544
|
+
openTestDb(base);
|
|
545
|
+
|
|
546
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M042"), base));
|
|
547
|
+
|
|
548
|
+
assert.equal(result.isError, undefined);
|
|
549
|
+
assert.equal(result.details.operation, "plan_milestone");
|
|
550
|
+
assert.equal(result.details.milestoneId, "M042");
|
|
551
|
+
assert.equal(getMilestoneLease("M042"), null,
|
|
552
|
+
"fresh milestone creation must pass through without creating a lease row");
|
|
553
|
+
} finally {
|
|
554
|
+
closeDatabase();
|
|
555
|
+
cleanup(base);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
test("executePlanMilestone does not create a placeholder when fresh planning validation fails", async () => {
|
|
560
|
+
const base = makeTmpBase();
|
|
561
|
+
try {
|
|
562
|
+
openTestDb(base);
|
|
563
|
+
|
|
564
|
+
// handlePlanMilestone rejects empty slice arrays during validation. Fresh
|
|
565
|
+
// milestone creation must pass through without pre-inserting a leaseable
|
|
566
|
+
// placeholder row.
|
|
567
|
+
const invalid = { ...validMilestonePlan("M042"), slices: [] };
|
|
568
|
+
const result = await inProjectDir(base, () => executePlanMilestone(invalid, base));
|
|
569
|
+
|
|
570
|
+
assert.equal(result.isError, true);
|
|
571
|
+
assert.equal(result.details.operation, "plan_milestone");
|
|
572
|
+
const milestones = getAllMilestones();
|
|
573
|
+
assert.equal(milestones.find(m => m.id === "M042"), undefined,
|
|
574
|
+
"failed fresh planning must not leave a milestone row behind");
|
|
575
|
+
assert.equal(getMilestoneLease("M042"), null,
|
|
576
|
+
"failed fresh planning must not create a lease row");
|
|
577
|
+
} finally {
|
|
578
|
+
closeDatabase();
|
|
579
|
+
cleanup(base);
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
test("executePlanMilestone does not delete a peer worker's milestone row on lease conflict", async () => {
|
|
584
|
+
const base = makeTmpBase();
|
|
585
|
+
try {
|
|
586
|
+
openTestDb(base);
|
|
587
|
+
|
|
588
|
+
// Simulate a peer worker (different project_root) that has already
|
|
589
|
+
// created the milestone row and taken its lease. The one-shot executor
|
|
590
|
+
// must observe the active lease and refuse — without removing the peer's
|
|
591
|
+
// milestone row or lease. The pre-rollback bug was that
|
|
592
|
+
// INSERT OR IGNORE's silent no-op was treated as proof of authorship and
|
|
593
|
+
// the cleanup path then deleted the peer's row.
|
|
594
|
+
const peer = registerAutoWorker({ projectRootRealpath: join(base, "peer-project") });
|
|
595
|
+
seedMilestone("M050", "Peer-owned milestone");
|
|
596
|
+
const peerLease = claimMilestoneLease(peer, "M050");
|
|
597
|
+
assert.equal(peerLease.ok, true);
|
|
598
|
+
const peerLeaseToken = peerLease.ok ? peerLease.token : -1;
|
|
599
|
+
|
|
600
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M050"), base));
|
|
601
|
+
|
|
602
|
+
assert.equal(result.isError, true);
|
|
603
|
+
assert.equal(result.details.error, "milestone_lease_conflict");
|
|
604
|
+
const peerMilestone = getAllMilestones().find(m => m.id === "M050");
|
|
605
|
+
assert.ok(peerMilestone, "peer milestone row must survive the one-shot conflict path");
|
|
606
|
+
assert.equal(peerMilestone?.title, "Peer-owned milestone",
|
|
607
|
+
"peer milestone row must not be clobbered or recreated");
|
|
608
|
+
const surviving = getMilestoneLease("M050");
|
|
609
|
+
assert.ok(surviving, "peer lease row must survive");
|
|
610
|
+
assert.equal(surviving.status, "held", "peer must still hold the lease");
|
|
611
|
+
assert.equal(surviving.worker_id, peer);
|
|
612
|
+
assert.equal(surviving.fencing_token, peerLeaseToken,
|
|
613
|
+
"peer's fencing token must not be incremented by the rejected one-shot");
|
|
614
|
+
} finally {
|
|
615
|
+
closeDatabase();
|
|
616
|
+
cleanup(base);
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("executePlanMilestone refuses when a foreign active worker holds the lease even while in-process auto is active", async () => {
|
|
621
|
+
const base = makeTmpBase();
|
|
622
|
+
autoSession.reset();
|
|
623
|
+
try {
|
|
624
|
+
openTestDb(base);
|
|
625
|
+
seedMilestone("M060", "Foreign-held milestone");
|
|
626
|
+
|
|
627
|
+
// In-process auto must still reject a lease held by another worker.
|
|
628
|
+
const foreign = registerAutoWorker({ projectRootRealpath: join(base, "foreign-project") });
|
|
629
|
+
const foreignLease = claimMilestoneLease(foreign, "M060");
|
|
630
|
+
assert.equal(foreignLease.ok, true);
|
|
631
|
+
const foreignToken = foreignLease.ok ? foreignLease.token : -1;
|
|
632
|
+
|
|
633
|
+
const ownAutoWorker = registerAutoWorker({ projectRootRealpath: normalizeRealPath(base) });
|
|
634
|
+
autoSession.active = true;
|
|
635
|
+
autoSession.workerId = ownAutoWorker;
|
|
636
|
+
|
|
637
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M060"), base));
|
|
638
|
+
|
|
639
|
+
assert.equal(result.isError, true);
|
|
640
|
+
assert.equal(result.details.error, "milestone_lease_conflict",
|
|
641
|
+
"in-process auto must NOT skip lease checks when the lease is held by a different active worker");
|
|
642
|
+
const surviving = getMilestoneLease("M060");
|
|
643
|
+
assert.ok(surviving);
|
|
644
|
+
assert.equal(surviving.status, "held");
|
|
645
|
+
assert.equal(surviving.worker_id, foreign);
|
|
646
|
+
assert.equal(surviving.fencing_token, foreignToken,
|
|
647
|
+
"foreign worker's fencing token must not be incremented by the rejected call");
|
|
648
|
+
} finally {
|
|
649
|
+
autoSession.reset();
|
|
650
|
+
closeDatabase();
|
|
651
|
+
cleanup(base);
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
test("executePlanMilestone proceeds without re-claiming when in-process auto holds the lease itself", async () => {
|
|
656
|
+
const base = makeTmpBase();
|
|
657
|
+
autoSession.reset();
|
|
658
|
+
try {
|
|
659
|
+
openTestDb(base);
|
|
660
|
+
seedMilestone("M070", "Auto-held milestone");
|
|
661
|
+
|
|
662
|
+
// In-process auto should not re-claim its own lease and bump its token.
|
|
663
|
+
const ownAutoWorker = registerAutoWorker({ projectRootRealpath: normalizeRealPath(base) });
|
|
664
|
+
const heldLease = claimMilestoneLease(ownAutoWorker, "M070");
|
|
665
|
+
assert.equal(heldLease.ok, true);
|
|
666
|
+
const heldToken = heldLease.ok ? heldLease.token : -1;
|
|
667
|
+
autoSession.active = true;
|
|
668
|
+
autoSession.workerId = ownAutoWorker;
|
|
669
|
+
|
|
670
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M070"), base));
|
|
671
|
+
|
|
672
|
+
assert.equal(result.isError, undefined, `auto's own plan-milestone call should succeed: ${result.content?.[0]?.text}`);
|
|
673
|
+
const surviving = getMilestoneLease("M070");
|
|
674
|
+
assert.ok(surviving);
|
|
675
|
+
assert.equal(surviving.status, "held", "auto's lease must still be held after the planning call");
|
|
676
|
+
assert.equal(surviving.worker_id, ownAutoWorker);
|
|
677
|
+
assert.equal(surviving.fencing_token, heldToken,
|
|
678
|
+
"auto's fencing token must not be incremented by an in-process plan call");
|
|
679
|
+
} finally {
|
|
680
|
+
autoSession.reset();
|
|
681
|
+
closeDatabase();
|
|
682
|
+
cleanup(base);
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
test("executePlanMilestone refuses a same-process holder when active auto does not own it", async () => {
|
|
687
|
+
const base = makeTmpBase();
|
|
688
|
+
autoSession.reset();
|
|
689
|
+
try {
|
|
690
|
+
openTestDb(base);
|
|
691
|
+
seedMilestone("M080", "Same-process holder");
|
|
692
|
+
const staleWorker = registerAutoWorker({ projectRootRealpath: normalizeRealPath(base) });
|
|
693
|
+
const heldLease = claimMilestoneLease(staleWorker, "M080");
|
|
694
|
+
assert.equal(heldLease.ok, true);
|
|
695
|
+
const heldToken = heldLease.ok ? heldLease.token : -1;
|
|
696
|
+
|
|
697
|
+
autoSession.active = true;
|
|
698
|
+
autoSession.workerId = registerAutoWorker({ projectRootRealpath: normalizeRealPath(base) });
|
|
699
|
+
|
|
700
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M080"), base));
|
|
701
|
+
|
|
702
|
+
assert.equal(result.isError, true);
|
|
703
|
+
assert.equal(result.details?.error, "milestone_lease_conflict");
|
|
704
|
+
const surviving = getMilestoneLease("M080");
|
|
705
|
+
assert.ok(surviving, "same-process holder lease must remain after conflict");
|
|
706
|
+
assert.equal(surviving.worker_id, staleWorker);
|
|
707
|
+
assert.equal(surviving.fencing_token, heldToken);
|
|
708
|
+
assert.equal(surviving.status, "held");
|
|
709
|
+
} finally {
|
|
710
|
+
autoSession.reset();
|
|
711
|
+
closeDatabase();
|
|
712
|
+
cleanup(base);
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
test("executePlanMilestone takes over a stale same-process lease via reentry instead of waiting for TTL", async () => {
|
|
717
|
+
const base = makeTmpBase();
|
|
718
|
+
autoSession.reset();
|
|
719
|
+
try {
|
|
720
|
+
openTestDb(base);
|
|
721
|
+
seedMilestone("M080", "Stale-locked milestone");
|
|
722
|
+
|
|
723
|
+
// One-shot planning should reach claimMilestoneLease so its same-process
|
|
724
|
+
// reentry clause can recover stale worker rows.
|
|
725
|
+
const staleWorker = registerAutoWorker({ projectRootRealpath: normalizeRealPath(base) });
|
|
726
|
+
const staleLease = claimMilestoneLease(staleWorker, "M080");
|
|
727
|
+
assert.equal(staleLease.ok, true);
|
|
728
|
+
const staleToken = staleLease.ok ? staleLease.token : -1;
|
|
729
|
+
|
|
730
|
+
const result = await inProjectDir(base, () => executePlanMilestone(validMilestonePlan("M080"), base));
|
|
731
|
+
|
|
732
|
+
assert.equal(result.isError, undefined,
|
|
733
|
+
`same-process reentry takeover must succeed, not return milestone_lease_conflict: ${result.content?.[0]?.text}`);
|
|
734
|
+
const after = getMilestoneLease("M080");
|
|
735
|
+
assert.ok(after, "lease row must remain after takeover + release");
|
|
736
|
+
assert.equal(after.status, "released", "the executor releases its own claim before returning");
|
|
737
|
+
assert.notEqual(after.worker_id, staleWorker,
|
|
738
|
+
"lease must be owned by the new worker after takeover");
|
|
739
|
+
assert.ok(after.fencing_token > staleToken,
|
|
740
|
+
`fencing token must monotonically advance on takeover (was ${staleToken}, now ${after.fencing_token})`);
|
|
741
|
+
} finally {
|
|
742
|
+
autoSession.reset();
|
|
743
|
+
closeDatabase();
|
|
744
|
+
cleanup(base);
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
|
|
495
748
|
test("executePlanSlice writes task planning state and rendered plan artifacts", async () => {
|
|
496
749
|
const base = makeTmpBase();
|
|
497
750
|
try {
|
|
498
751
|
openTestDb(base);
|
|
499
|
-
await inProjectDir(base, () => executePlanMilestone(
|
|
500
|
-
milestoneId: "M001",
|
|
501
|
-
title: "Workflow MCP planning",
|
|
502
|
-
vision: "Plan milestone over shared executors.",
|
|
503
|
-
slices: [
|
|
504
|
-
{
|
|
505
|
-
sliceId: "S01",
|
|
506
|
-
title: "Bridge planning",
|
|
507
|
-
risk: "medium",
|
|
508
|
-
depends: [],
|
|
509
|
-
demo: "Milestone plan persists through MCP.",
|
|
510
|
-
goal: "Persist roadmap state.",
|
|
511
|
-
successCriteria: "ROADMAP.md renders from DB.",
|
|
512
|
-
proofLevel: "integration",
|
|
513
|
-
integrationClosure: "Prompts and MCP call the same handler.",
|
|
514
|
-
observabilityImpact: "Executor tests cover output paths.",
|
|
515
|
-
},
|
|
516
|
-
],
|
|
517
|
-
}, base));
|
|
752
|
+
await inProjectDir(base, () => executePlanMilestone(validMilestonePlan(), base));
|
|
518
753
|
|
|
519
754
|
const result = await inProjectDir(base, () => executePlanSlice({
|
|
520
755
|
milestoneId: "M001",
|
|
@@ -528,8 +763,8 @@ test("executePlanSlice writes task planning state and rendered plan artifacts",
|
|
|
528
763
|
estimate: "15m",
|
|
529
764
|
files: ["src/resources/extensions/gsd/tools/workflow-tool-executors.ts"],
|
|
530
765
|
verify: "node --test",
|
|
531
|
-
inputs: [
|
|
532
|
-
expectedOutput: ["
|
|
766
|
+
inputs: [],
|
|
767
|
+
expectedOutput: ["src/bridge-status.md"],
|
|
533
768
|
},
|
|
534
769
|
],
|
|
535
770
|
}, base));
|
|
@@ -161,13 +161,13 @@ test("enterMilestone returns ok:true mode:worktree on successful create", (t) =>
|
|
|
161
161
|
if (result.ok) {
|
|
162
162
|
assert.equal(result.mode, "worktree");
|
|
163
163
|
assert.ok(
|
|
164
|
-
result.path.endsWith("/.gsd
|
|
165
|
-
`expected path to end with /.gsd
|
|
164
|
+
result.path.endsWith("/.gsd-worktrees/M001"),
|
|
165
|
+
`expected path to end with /.gsd-worktrees/M001, got ${result.path}`,
|
|
166
166
|
);
|
|
167
167
|
}
|
|
168
168
|
assert.ok(
|
|
169
|
-
s.basePath.endsWith("/.gsd
|
|
170
|
-
`expected s.basePath to end with /.gsd
|
|
169
|
+
s.basePath.endsWith("/.gsd-worktrees/M001"),
|
|
170
|
+
`expected s.basePath to end with /.gsd-worktrees/M001, got ${s.basePath}`,
|
|
171
171
|
);
|
|
172
172
|
// After C3 (#5626) `invalidateAllCaches` is inlined; assertion against
|
|
173
173
|
// `deps.calls` for cache invalidation is no longer possible.
|
|
@@ -240,6 +240,43 @@ test("adoptStrandedMilestone forces branch recovery even when normal preferences
|
|
|
240
240
|
assert.equal(currentBranch, "milestone/M001");
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
+
test("enterMilestone honors stranded branch recovery instead of recreating the worktree", (t) => {
|
|
244
|
+
// Regression: after adoptStrandedMilestone checks out milestone/M001 in
|
|
245
|
+
// the project root, a plain enterMilestone under isolation:worktree used
|
|
246
|
+
// to attempt `git worktree add`, which git refuses ("branch is already in
|
|
247
|
+
// use by another worktree" — the root checkout IS the conflicting
|
|
248
|
+
// worktree), tripping a creation-failed warning and degrading isolation.
|
|
249
|
+
// The recovery override must keep re-entries in branch mode.
|
|
250
|
+
const previousCwd = process.cwd();
|
|
251
|
+
const base = makeGitRepoBase({ isolation: "worktree" });
|
|
252
|
+
t.after(() => cleanupRepoBase(base, previousCwd));
|
|
253
|
+
|
|
254
|
+
const s = makeSession({ basePath: base, originalBasePath: base });
|
|
255
|
+
const deps = makeDeps();
|
|
256
|
+
const ctx = makeCtx();
|
|
257
|
+
const lifecycle = new WorktreeLifecycle(s, deps);
|
|
258
|
+
|
|
259
|
+
const adopted = lifecycle.adoptStrandedMilestone("M001", base, ctx, {
|
|
260
|
+
mode: "branch",
|
|
261
|
+
});
|
|
262
|
+
assert.equal(adopted.ok, true, `expected adopt ok:true, got: ${JSON.stringify(adopted)}`);
|
|
263
|
+
|
|
264
|
+
const result = lifecycle.enterMilestone("M001", ctx);
|
|
265
|
+
|
|
266
|
+
assert.equal(result.ok, true, `expected ok:true, got: ${JSON.stringify(result)}`);
|
|
267
|
+
if (result.ok) {
|
|
268
|
+
assert.equal(result.mode, "branch");
|
|
269
|
+
assert.equal(result.path, base);
|
|
270
|
+
}
|
|
271
|
+
assert.equal(s.basePath, base);
|
|
272
|
+
assert.equal(s.isolationDegraded, false, "intentional branch adoption must not degrade isolation");
|
|
273
|
+
assert.equal(
|
|
274
|
+
ctx.messages.some((m) => m.msg.includes("creation for M001 failed")),
|
|
275
|
+
false,
|
|
276
|
+
"re-entry must not attempt (and fail) canonical worktree creation",
|
|
277
|
+
);
|
|
278
|
+
});
|
|
279
|
+
|
|
243
280
|
test("enterMilestone returns ok:false reason:isolation-degraded when session degraded", () => {
|
|
244
281
|
const s = makeSession({ isolationDegraded: true });
|
|
245
282
|
const deps = makeDeps({ getIsolationMode: () => "branch" });
|
|
@@ -142,6 +142,27 @@ describe("createWorktree", () => {
|
|
|
142
142
|
run("git rev-parse --git-dir", info.path);
|
|
143
143
|
assert.ok(!existsSync(join(info.path, "orphan.txt")), "stale file removed by recovery");
|
|
144
144
|
});
|
|
145
|
+
|
|
146
|
+
test("removes stale canonical directory when legacy orphan is cleaned and canonical target is stale", () => {
|
|
147
|
+
// Scenario: a stale .gsd-worktrees/M020 directory (no .git — aborted prior
|
|
148
|
+
// creation) coexists with an orphaned .gsd/worktrees/M020 dir (.git file not
|
|
149
|
+
// registered with git). worktreePathFor returns the legacy path (canonical has
|
|
150
|
+
// no .git marker), so only the legacy path was previously cleaned — the stale
|
|
151
|
+
// canonical blocked git worktree add. The fix ensures createWorktree also
|
|
152
|
+
// removes the stale canonical before calling git worktree add.
|
|
153
|
+
const canonicalDir = join(base, ".gsd-worktrees", "M020");
|
|
154
|
+
const legacyDir = join(base, ".gsd", "worktrees", "M020");
|
|
155
|
+
|
|
156
|
+
mkdirSync(canonicalDir, { recursive: true }); // stale canonical: exists, no .git
|
|
157
|
+
mkdirSync(legacyDir, { recursive: true });
|
|
158
|
+
writeFileSync(join(legacyDir, ".git"), "gitdir: ../../../../.git/worktrees/M020\n", "utf-8");
|
|
159
|
+
|
|
160
|
+
const info = createWorktree(base, "M020");
|
|
161
|
+
assert.strictEqual(info.name, "M020");
|
|
162
|
+
assert.ok(existsSync(info.path), "worktree path should exist after creation");
|
|
163
|
+
assert.ok(existsSync(join(info.path, ".git")), "new worktree has .git marker");
|
|
164
|
+
run("git rev-parse --git-dir", info.path);
|
|
165
|
+
});
|
|
145
166
|
});
|
|
146
167
|
|
|
147
168
|
describe("createWorktree — duplicate rejection", () => {
|
|
@@ -180,7 +201,7 @@ describe("createWorktree — branch cleanup on add failure", () => {
|
|
|
180
201
|
|
|
181
202
|
// Make the worktrees parent directory non-writable so `git worktree add`
|
|
182
203
|
// fails after the branch has already been force-reset.
|
|
183
|
-
const parentDir = join(base, ".gsd
|
|
204
|
+
const parentDir = join(base, ".gsd-worktrees");
|
|
184
205
|
mkdirSync(parentDir, { recursive: true });
|
|
185
206
|
run(`chmod 555 "${parentDir}"`, base);
|
|
186
207
|
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for worktreePathFor — the forward seam (project + name → path).
|
|
3
|
+
*
|
|
4
|
+
* Key invariant: a stale canonical directory (no .git marker) must NOT
|
|
5
|
+
* shadow a live legacy worktree (.gsd/worktrees/<name> with .git).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
|
|
15
|
+
import { worktreePathFor, canonicalWorktreesDir, legacyWorktreesDir } from "../worktree-placement.ts";
|
|
16
|
+
|
|
17
|
+
function makeTmpRoot(): string {
|
|
18
|
+
const root = join(tmpdir(), `gsd-placement-test-${randomUUID()}`);
|
|
19
|
+
mkdirSync(root, { recursive: true });
|
|
20
|
+
return root;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function cleanup(root: string): void {
|
|
24
|
+
try { rmSync(root, { recursive: true, force: true }); } catch { /* */ }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function makeCanonicalDir(root: string, name: string): string {
|
|
28
|
+
const p = join(canonicalWorktreesDir(root), name);
|
|
29
|
+
mkdirSync(p, { recursive: true });
|
|
30
|
+
return p;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function makeLiveCanonical(root: string, name: string): string {
|
|
34
|
+
const p = makeCanonicalDir(root, name);
|
|
35
|
+
writeFileSync(join(p, ".git"), `gitdir: ${join(root, ".git", "worktrees", name)}\n`);
|
|
36
|
+
return p;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function makeLiveLegacy(root: string, name: string): string {
|
|
40
|
+
const p = join(legacyWorktreesDir(root), name);
|
|
41
|
+
mkdirSync(p, { recursive: true });
|
|
42
|
+
writeFileSync(join(p, ".git"), `gitdir: ${join(root, ".git", "worktrees", name)}\n`);
|
|
43
|
+
return p;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test("returns canonical path when canonical has .git marker", () => {
|
|
47
|
+
const root = makeTmpRoot();
|
|
48
|
+
try {
|
|
49
|
+
const canonical = makeLiveCanonical(root, "M001");
|
|
50
|
+
assert.equal(worktreePathFor(root, "M001"), canonical);
|
|
51
|
+
} finally {
|
|
52
|
+
cleanup(root);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("returns legacy path when only legacy exists with .git marker", () => {
|
|
57
|
+
const root = makeTmpRoot();
|
|
58
|
+
try {
|
|
59
|
+
const legacy = makeLiveLegacy(root, "M001");
|
|
60
|
+
assert.equal(worktreePathFor(root, "M001"), legacy);
|
|
61
|
+
} finally {
|
|
62
|
+
cleanup(root);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("returns legacy path when canonical dir exists but has no .git (stale canonical)", () => {
|
|
67
|
+
const root = makeTmpRoot();
|
|
68
|
+
try {
|
|
69
|
+
makeCanonicalDir(root, "M001"); // stale: dir exists, no .git
|
|
70
|
+
const legacy = makeLiveLegacy(root, "M001");
|
|
71
|
+
assert.equal(
|
|
72
|
+
worktreePathFor(root, "M001"),
|
|
73
|
+
legacy,
|
|
74
|
+
"stale canonical must not shadow live legacy worktree",
|
|
75
|
+
);
|
|
76
|
+
} finally {
|
|
77
|
+
cleanup(root);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("returns canonical path for new-worktree creation when neither path exists", () => {
|
|
82
|
+
const root = makeTmpRoot();
|
|
83
|
+
try {
|
|
84
|
+
const expected = join(canonicalWorktreesDir(root), "M001");
|
|
85
|
+
assert.equal(worktreePathFor(root, "M001"), expected);
|
|
86
|
+
} finally {
|
|
87
|
+
cleanup(root);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("prefers live canonical over live legacy when both exist", () => {
|
|
92
|
+
const root = makeTmpRoot();
|
|
93
|
+
try {
|
|
94
|
+
const canonical = makeLiveCanonical(root, "M001");
|
|
95
|
+
makeLiveLegacy(root, "M001");
|
|
96
|
+
assert.equal(worktreePathFor(root, "M001"), canonical);
|
|
97
|
+
} finally {
|
|
98
|
+
cleanup(root);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("returns legacy when canonical is stale and legacy has no .git (both stale)", () => {
|
|
103
|
+
const root = makeTmpRoot();
|
|
104
|
+
try {
|
|
105
|
+
makeCanonicalDir(root, "M001"); // stale canonical
|
|
106
|
+
const legacy = join(legacyWorktreesDir(root), "M001");
|
|
107
|
+
mkdirSync(legacy, { recursive: true }); // stale legacy (no .git)
|
|
108
|
+
// Falls through to legacy existsSync since canonical has no .git
|
|
109
|
+
assert.equal(worktreePathFor(root, "M001"), legacy);
|
|
110
|
+
} finally {
|
|
111
|
+
cleanup(root);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
@@ -65,7 +65,7 @@ describe("reenterActiveWorktreeIfNeeded", () => {
|
|
|
65
65
|
const entered = await reenterActiveWorktreeIfNeeded(dir);
|
|
66
66
|
assert.ok(entered, "re-entry returned a worktree path");
|
|
67
67
|
assert.strictEqual(realpathSync(process.cwd()), realpathSync(entered!), "cwd moved into the worktree");
|
|
68
|
-
assert.strictEqual(entered, join(dir, ".gsd
|
|
68
|
+
assert.strictEqual(entered, join(dir, ".gsd-worktrees", "M001"));
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
test("no-op when already inside a worktree", async (t) => {
|
|
@@ -126,7 +126,9 @@ describe("Worktree Safety module", () => {
|
|
|
126
126
|
assert.equal(result.ok, false);
|
|
127
127
|
assert.equal(result.kind, "invalid-root");
|
|
128
128
|
assert.equal(result.details?.unitRoot, outsideRoot);
|
|
129
|
-
|
|
129
|
+
// The reported expected root is the canonical container; the legacy
|
|
130
|
+
// .gsd/worktrees/ location is also accepted but not surfaced here.
|
|
131
|
+
assert.equal(result.details?.expectedRoot, join(projectRoot, ".gsd-worktrees", "M001"));
|
|
130
132
|
});
|
|
131
133
|
|
|
132
134
|
test("accepts project root for source-writing Unit when isolation mode is none", () => {
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Fix: removeWorktree should query `git worktree list` to find the actual
|
|
10
10
|
* registered path when the computed path doesn't match.
|
|
11
|
+
*
|
|
12
|
+
* New worktrees are created at the canonical `.gsd-worktrees/` sibling and
|
|
13
|
+
* never cross the symlink, so this scenario only applies to LEGACY worktrees
|
|
14
|
+
* (created under `.gsd/worktrees/` by older versions). The test creates the
|
|
15
|
+
* worktree at the legacy location directly to keep that coverage.
|
|
11
16
|
*/
|
|
12
17
|
import { mkdtempSync, mkdirSync, rmSync, symlinkSync, unlinkSync, writeFileSync, existsSync, realpathSync } from "node:fs";
|
|
13
18
|
import { join } from "node:path";
|
|
@@ -15,7 +20,6 @@ import { tmpdir } from "node:os";
|
|
|
15
20
|
import { execSync } from "node:child_process";
|
|
16
21
|
|
|
17
22
|
import {
|
|
18
|
-
createWorktree,
|
|
19
23
|
removeWorktree,
|
|
20
24
|
listWorktrees,
|
|
21
25
|
worktreePath,
|
|
@@ -64,13 +68,15 @@ test('worktree-symlink-removal removes the git-registered symlink target safely'
|
|
|
64
68
|
run("git add .", base);
|
|
65
69
|
run('git commit -m "init"', base);
|
|
66
70
|
|
|
67
|
-
// Create a worktree
|
|
68
|
-
// the worktree at the external path
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
// Create a LEGACY worktree through the symlinked .gsd path — git resolves
|
|
72
|
+
// the symlink and registers the worktree at the external path. (Current
|
|
73
|
+
// createWorktree() uses the canonical .gsd-worktrees/ sibling instead.)
|
|
74
|
+
const legacyPath = join(base, ".gsd", "worktrees", "M002");
|
|
75
|
+
run(`git worktree add -b milestone/M002 "${legacyPath}"`, base);
|
|
76
|
+
assert.ok(existsSync(legacyPath), "worktree created");
|
|
71
77
|
|
|
72
78
|
// Verify worktree was created at the resolved (external) path
|
|
73
|
-
const realWtPath = realpathSync(
|
|
79
|
+
const realWtPath = realpathSync(legacyPath);
|
|
74
80
|
assert.ok(
|
|
75
81
|
realWtPath.startsWith(externalState),
|
|
76
82
|
`worktree real path (${realWtPath}) is under external state dir`,
|
|
@@ -116,8 +116,8 @@ describe("worktree-teardown-safety", () => {
|
|
|
116
116
|
|
|
117
117
|
const wtPathResult = worktreePath(tempDir, "anything");
|
|
118
118
|
assertTrue(
|
|
119
|
-
wtPathResult.startsWith(join(tempDir, ".gsd
|
|
120
|
-
"worktreePath returns path under .gsd
|
|
119
|
+
wtPathResult.startsWith(join(tempDir, ".gsd-worktrees")),
|
|
120
|
+
"worktreePath returns path under the canonical .gsd-worktrees/ container",
|
|
121
121
|
);
|
|
122
122
|
});
|
|
123
123
|
|