@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0-dev.5fc22c6f
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 +11 -11
- package/dist/cli.js +17 -4
- package/dist/headless-answers.js +1 -1
- package/dist/headless-ui.d.ts +1 -1
- package/dist/headless-ui.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/onboarding.js +11 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +20 -25
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +61 -50
- package/dist/resources/extensions/cursor-cli/index.js +16 -0
- package/dist/resources/extensions/cursor-cli/models.js +63 -0
- package/dist/resources/extensions/cursor-cli/package.json +11 -0
- package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
- package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
- package/dist/resources/extensions/gsd/activity-log.js +4 -1
- package/dist/resources/extensions/gsd/artifact-verification.js +431 -0
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-budget.js +5 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +32 -11
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +83 -25
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-start.js +4 -3
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +38 -11
- package/dist/resources/extensions/gsd/auto.js +32 -10
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +147 -23
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +56 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +29 -5
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +154 -2
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +39 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
- package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +227 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/doctor.js +93 -3
- package/dist/resources/extensions/gsd/exec-sandbox.js +14 -4
- package/dist/resources/extensions/gsd/flat-phase-migration.js +119 -23
- package/dist/resources/extensions/gsd/git-service.js +61 -8
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guidance.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
- package/dist/resources/extensions/gsd/guided-flow.js +40 -2
- package/dist/resources/extensions/gsd/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/key-manager.js +1 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +27 -15
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +22 -5
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +25 -2
- package/dist/resources/extensions/gsd/preferences.js +29 -2
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
- package/dist/resources/extensions/gsd/repository-registry.js +6 -1
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safe-fs.js +23 -2
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
- package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
- package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +103 -12
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
- package/dist/resources/extensions/gsd/unit-registry.js +11 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
- package/dist/resources/extensions/gsd/verification-gate.js +7 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/workspace.js +26 -8
- package/dist/resources/extensions/gsd/worktree-manager.js +140 -5
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- 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/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/wizard.d.ts +8 -0
- package/dist/wizard.js +8 -1
- package/integrations/hermes/__init__.py +31 -0
- package/integrations/hermes/tests/test_directory_loader.py +37 -0
- package/package.json +8 -8
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
- package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-runtime.js +25 -1
- package/packages/daemon/dist/cloud-runtime.js.map +1 -1
- package/packages/daemon/dist/cloud-runtime.test.js +51 -0
- package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
- package/packages/daemon/dist/message-batcher.d.ts +7 -0
- package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
- package/packages/daemon/dist/message-batcher.js +13 -0
- package/packages/daemon/dist/message-batcher.js.map +1 -1
- package/packages/daemon/dist/message-batcher.test.js +48 -0
- package/packages/daemon/dist/message-batcher.test.js.map +1 -1
- package/packages/daemon/package.json +5 -5
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -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 +25 -11
- 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-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- 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 +26 -841
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +259 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -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 +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +24 -6
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.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 +18 -0
- 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/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +3 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +46 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +38 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -2
- 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/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/dist/rpc-client.js +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +14 -4
- package/src/resources/GSD-WORKFLOW.md +20 -25
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +67 -49
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +159 -0
- package/src/resources/extensions/cursor-cli/index.ts +18 -0
- package/src/resources/extensions/cursor-cli/models.ts +65 -0
- package/src/resources/extensions/cursor-cli/package.json +11 -0
- package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
- package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
- package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
- package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
- package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
- package/src/resources/extensions/gsd/activity-log.ts +4 -1
- package/src/resources/extensions/gsd/artifact-verification.ts +468 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-budget.ts +12 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +34 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +80 -25
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-start.ts +4 -3
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +7 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +50 -11
- package/src/resources/extensions/gsd/auto.ts +36 -8
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +171 -23
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +60 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -5
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +136 -2
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +40 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
- package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +275 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +8 -1
- package/src/resources/extensions/gsd/doctor.ts +95 -3
- package/src/resources/extensions/gsd/exec-sandbox.ts +13 -4
- package/src/resources/extensions/gsd/flat-phase-migration.ts +142 -22
- package/src/resources/extensions/gsd/git-service.ts +70 -9
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guidance.ts +2 -0
- package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
- package/src/resources/extensions/gsd/guided-flow.ts +45 -2
- package/src/resources/extensions/gsd/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/key-manager.ts +1 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +27 -17
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +17 -4
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/model-router.ts +4 -5
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -3
- package/src/resources/extensions/gsd/preferences-validation.ts +28 -2
- package/src/resources/extensions/gsd/preferences.ts +38 -4
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
- package/src/resources/extensions/gsd/repository-registry.ts +7 -1
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safe-fs.ts +22 -2
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
- package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +296 -2
- package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +74 -2
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +307 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
- package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +214 -6
- package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
- package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
- package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +135 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
- package/src/resources/extensions/gsd/unit-registry.ts +11 -3
- package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
- package/src/resources/extensions/gsd/verification-gate.ts +8 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/workspace.ts +42 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +183 -5
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_ssgManifest.js +0 -0
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
import { existsSync, readFileSync } from "node:fs";
|
|
15
15
|
import { access, readFile } from "node:fs/promises";
|
|
16
|
+
import { homedir } from "node:os";
|
|
16
17
|
import { delimiter, join } from "node:path";
|
|
17
18
|
import { AuthStorage } from "@gsd/pi-coding-agent";
|
|
18
19
|
import { getEnvApiKey } from "@gsd/pi-ai";
|
|
20
|
+
import { isCursorAgentReadyUncached } from "../cursor-cli/readiness.js";
|
|
19
21
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
20
22
|
import { getAuthPath, PROVIDER_REGISTRY, supportsBrowserOAuth, type ProviderCategory } from "./key-manager.js";
|
|
21
|
-
import { homedir } from "node:os";
|
|
22
23
|
|
|
23
24
|
// ── Types ──────────────────────────────────────────────────────────────────────
|
|
24
25
|
|
|
@@ -49,6 +50,7 @@ const CLI_AUTH_PROVIDERS = new Set([
|
|
|
49
50
|
"claude-code",
|
|
50
51
|
"google-gemini-cli",
|
|
51
52
|
"google-antigravity",
|
|
53
|
+
"cursor-agent",
|
|
52
54
|
]);
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -57,9 +59,9 @@ const CLI_AUTH_PROVIDERS = new Set([
|
|
|
57
59
|
* e.g. GitHub Copilot subscriptions can access Claude and GPT models.
|
|
58
60
|
*/
|
|
59
61
|
const PROVIDER_ROUTES: Record<string, string[]> = {
|
|
60
|
-
anthropic: ["github-copilot", "claude-code"],
|
|
61
|
-
openai: ["github-copilot", "openai-codex"],
|
|
62
|
-
google: ["google-antigravity", "google-gemini-cli"],
|
|
62
|
+
anthropic: ["github-copilot", "claude-code", "cursor-agent"],
|
|
63
|
+
openai: ["github-copilot", "openai-codex", "cursor-agent"],
|
|
64
|
+
google: ["google-antigravity", "google-gemini-cli", "cursor-agent"],
|
|
63
65
|
};
|
|
64
66
|
|
|
65
67
|
// ── Model → Provider ID mapping ───────────────────────────────────────────────
|
|
@@ -86,6 +88,7 @@ function modelToProviderId(model: string): string | null {
|
|
|
86
88
|
anthropic: "anthropic",
|
|
87
89
|
openai: "openai",
|
|
88
90
|
"github-copilot": "github-copilot",
|
|
91
|
+
"cursor-agent": "cursor-agent",
|
|
89
92
|
};
|
|
90
93
|
if (prefixMap[prefix]) return prefixMap[prefix];
|
|
91
94
|
return rawPrefix;
|
|
@@ -95,6 +98,7 @@ function modelToProviderId(model: string): string | null {
|
|
|
95
98
|
if (lower.startsWith("claude")) return "anthropic";
|
|
96
99
|
if (lower.startsWith("gpt-") || lower.startsWith("o1") || lower.startsWith("o3")) return "openai";
|
|
97
100
|
if (lower.startsWith("gemini")) return "google";
|
|
101
|
+
if (lower.startsWith("composer")) return "cursor-agent";
|
|
98
102
|
if (lower.startsWith("llama") || lower.startsWith("mixtral")) return "groq";
|
|
99
103
|
if (lower.startsWith("grok")) return "xai";
|
|
100
104
|
if (lower.startsWith("mistral") || lower.startsWith("codestral")) return "mistral";
|
|
@@ -160,11 +164,13 @@ const CLI_BINARY_MAP: Record<string, string[]> = {
|
|
|
160
164
|
"claude-code": ["claude", "claude-code"],
|
|
161
165
|
"google-gemini-cli": ["gemini"],
|
|
162
166
|
"google-antigravity": ["agy"],
|
|
167
|
+
"cursor-agent": ["cursor-agent"],
|
|
163
168
|
};
|
|
164
169
|
|
|
165
170
|
const CLI_AUTH_PATH_CHECK_PROVIDERS = new Set([
|
|
166
171
|
"google-gemini-cli",
|
|
167
172
|
"google-antigravity",
|
|
173
|
+
"cursor-agent",
|
|
168
174
|
]);
|
|
169
175
|
|
|
170
176
|
let asyncCliBinaryPathCache: Map<string, boolean> | null = null;
|
|
@@ -212,6 +218,18 @@ function isCliBinaryInPath(providerId: string): boolean {
|
|
|
212
218
|
return pathDirs.some(dir => executableNames.some(name => existsSync(join(dir, name))));
|
|
213
219
|
}
|
|
214
220
|
|
|
221
|
+
function isExternalCliProviderReady(providerId: string): boolean {
|
|
222
|
+
if (providerId === "cursor-agent") return isCursorAgentReadyUncached();
|
|
223
|
+
return isCliBinaryInPath(providerId);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function cursorAgentFailureDetail(): string {
|
|
227
|
+
if (!isCliBinaryInPath("cursor-agent")) {
|
|
228
|
+
return "Install Cursor Agent and ensure `cursor-agent` is on PATH";
|
|
229
|
+
}
|
|
230
|
+
return "Run `cursor-agent login` or set CURSOR_API_KEY";
|
|
231
|
+
}
|
|
232
|
+
|
|
215
233
|
async function isCliBinaryInPathAsync(providerId: string): Promise<boolean> {
|
|
216
234
|
const executableNames = cliExecutableNames(providerId);
|
|
217
235
|
if (executableNames.length === 0) return false;
|
|
@@ -345,6 +363,12 @@ function resolveKeyFromAuthOrEnv(providerId: string): KeyLookup | null {
|
|
|
345
363
|
}
|
|
346
364
|
|
|
347
365
|
function resolveKey(providerId: string): KeyLookup {
|
|
366
|
+
if (providerId === "cursor-agent") {
|
|
367
|
+
return isExternalCliProviderReady(providerId)
|
|
368
|
+
? { found: true, source: "env", backedOff: false }
|
|
369
|
+
: { found: false, source: "none", backedOff: false };
|
|
370
|
+
}
|
|
371
|
+
|
|
348
372
|
const direct = resolveKeyFromAuthOrEnv(providerId);
|
|
349
373
|
if (direct) return direct;
|
|
350
374
|
|
|
@@ -354,7 +378,7 @@ function resolveKey(providerId: string): KeyLookup {
|
|
|
354
378
|
|
|
355
379
|
// Cross-provider routes can use a local CLI when it is installed. Explicit
|
|
356
380
|
// external CLI provider selections are handled in checkLlmProviders() below.
|
|
357
|
-
if (CLI_AUTH_PROVIDERS.has(providerId) &&
|
|
381
|
+
if (CLI_AUTH_PROVIDERS.has(providerId) && isExternalCliProviderReady(providerId)) {
|
|
358
382
|
return { found: true, source: "env", backedOff: false };
|
|
359
383
|
}
|
|
360
384
|
|
|
@@ -373,17 +397,22 @@ function checkLlmProviders(): ProviderCheckResult[] {
|
|
|
373
397
|
if (CLI_AUTH_PROVIDERS.has(providerId)) {
|
|
374
398
|
const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
|
|
375
399
|
const label = info?.label ?? providerId;
|
|
376
|
-
if (CLI_AUTH_PATH_CHECK_PROVIDERS.has(providerId) && !
|
|
400
|
+
if (CLI_AUTH_PATH_CHECK_PROVIDERS.has(providerId) && !isExternalCliProviderReady(providerId)) {
|
|
377
401
|
const binaries = CLI_BINARY_MAP[providerId]?.map(binary => `\`${binary}\``).join(" or ");
|
|
402
|
+
const detail = providerId === "cursor-agent"
|
|
403
|
+
? cursorAgentFailureDetail()
|
|
404
|
+
: binaries
|
|
405
|
+
? `Install ${label} and ensure ${binaries} is on PATH`
|
|
406
|
+
: `Install ${label} and ensure its CLI is on PATH`;
|
|
378
407
|
results.push({
|
|
379
408
|
name: providerId,
|
|
380
409
|
label,
|
|
381
410
|
category: "llm",
|
|
382
411
|
status: "error",
|
|
383
|
-
message:
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
412
|
+
message: providerId === "cursor-agent" && isCliBinaryInPath(providerId)
|
|
413
|
+
? `${label} — CLI not authenticated`
|
|
414
|
+
: `${label} — CLI not found`,
|
|
415
|
+
detail,
|
|
387
416
|
required: true,
|
|
388
417
|
});
|
|
389
418
|
continue;
|
|
@@ -408,6 +408,9 @@ export async function checkRuntimeHealth(
|
|
|
408
408
|
if (!existingLines.has(".gsd-worktrees/") && !existingLines.has(".gsd-worktrees")) {
|
|
409
409
|
missing.push(".gsd-worktrees/");
|
|
410
410
|
}
|
|
411
|
+
if (!existingLines.has(".gsd-backups/") && !existingLines.has(".gsd-backups")) {
|
|
412
|
+
missing.push(".gsd-backups/");
|
|
413
|
+
}
|
|
411
414
|
if (!hasBlanketIgnore) {
|
|
412
415
|
missing.push(...criticalPatterns.filter(p => !existingLines.has(p)));
|
|
413
416
|
}
|
|
@@ -84,14 +84,21 @@ export type DoctorIssueCode =
|
|
|
84
84
|
| "db_orphaned_task"
|
|
85
85
|
| "db_orphaned_slice"
|
|
86
86
|
| "db_done_task_no_summary"
|
|
87
|
+
| "artifact_file_missing"
|
|
88
|
+
| "artifact_user_content_missing"
|
|
87
89
|
| "artifact_db_status_divergence"
|
|
90
|
+
| "checkbox_db_status_divergence"
|
|
88
91
|
| "completed_milestone_reopened"
|
|
89
92
|
| "db_duplicate_id"
|
|
90
93
|
| "db_unavailable"
|
|
94
|
+
| "memories_fts_rebuild_missing"
|
|
91
95
|
| "projection_drift"
|
|
92
96
|
// Milestone filesystem/DB drift (#4996)
|
|
93
97
|
| "orphan_milestone_dir"
|
|
94
|
-
| "orphan_milestone_db"
|
|
98
|
+
| "orphan_milestone_db"
|
|
99
|
+
// Parent-workspace declared repository checks (#818)
|
|
100
|
+
| "workspace_repo_path_missing"
|
|
101
|
+
| "workspace_repo_not_a_repo";
|
|
95
102
|
|
|
96
103
|
/**
|
|
97
104
|
* Issue codes that represent global or completion-critical state.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { existsSync, mkdirSync, lstatSync, readdirSync, readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
3
4
|
|
|
4
5
|
import { loadFile, parseSummary, saveFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
|
|
5
6
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
@@ -16,6 +17,8 @@ import { isClosedStatus } from "./status-guards.js";
|
|
|
16
17
|
import type { DoctorIssue, DoctorIssueCode, DoctorReport } from "./doctor-types.js";
|
|
17
18
|
import { GLOBAL_STATE_CODES } from "./doctor-types.js";
|
|
18
19
|
import type { RoadmapSliceEntry } from "./types.js";
|
|
20
|
+
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
21
|
+
import { createRepositoryRegistryFromPreferences } from "./repository-registry.js";
|
|
19
22
|
import { checkGitHealth, checkRuntimeHealth, checkGlobalHealth, checkEngineHealth } from "./doctor-checks.js";
|
|
20
23
|
import { checkEnvironmentHealth } from "./doctor-environment.js";
|
|
21
24
|
import { runProviderChecks } from "./doctor-providers.js";
|
|
@@ -308,6 +311,94 @@ export async function readDoctorHistory(basePath: string, lastN = 50): Promise<D
|
|
|
308
311
|
} catch { return []; }
|
|
309
312
|
}
|
|
310
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Resolve the git working-tree root for a path, or null if it is not a repo.
|
|
316
|
+
* Used by the workspace-repository probe to check that a declared child path is
|
|
317
|
+
* itself a git repository (not merely nested inside the parent's repo).
|
|
318
|
+
*/
|
|
319
|
+
function resolveGitToplevel(cwd: string): string | null {
|
|
320
|
+
try {
|
|
321
|
+
const out = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
322
|
+
cwd,
|
|
323
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
324
|
+
encoding: "utf-8",
|
|
325
|
+
env: GIT_NO_PROMPT_ENV,
|
|
326
|
+
}).trim();
|
|
327
|
+
return out ? resolve(out) : null;
|
|
328
|
+
} catch {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** realpath that falls back to the resolved path if the link cannot be read. */
|
|
334
|
+
function realpathSafe(p: string): string {
|
|
335
|
+
try {
|
|
336
|
+
return realpathSync(p);
|
|
337
|
+
} catch {
|
|
338
|
+
return resolve(p);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Parent-workspace probe (#818): validate that every declared child repository
|
|
344
|
+
* exists on disk and is a git repository at its own root. The registry only
|
|
345
|
+
* checks paths stay inside the project root; it never checks existence or
|
|
346
|
+
* git-ness, so a typo'd path (e.g. `frontned`) would otherwise build cleanly
|
|
347
|
+
* and silently produce "no problems found." No-op for single-repo projects.
|
|
348
|
+
*/
|
|
349
|
+
function checkWorkspaceRepositoryHealth(
|
|
350
|
+
basePath: string,
|
|
351
|
+
prefs: GSDPreferences | undefined,
|
|
352
|
+
issues: DoctorIssue[],
|
|
353
|
+
): void {
|
|
354
|
+
if (prefs?.workspace?.mode !== "parent") return;
|
|
355
|
+
let registry;
|
|
356
|
+
try {
|
|
357
|
+
registry = createRepositoryRegistryFromPreferences(basePath, prefs);
|
|
358
|
+
} catch (err) {
|
|
359
|
+
issues.push({
|
|
360
|
+
severity: "error",
|
|
361
|
+
code: "invalid_preferences",
|
|
362
|
+
scope: "project",
|
|
363
|
+
unitId: "workspace",
|
|
364
|
+
message: `workspace registry failed to build: ${err instanceof Error ? err.message : String(err)}`,
|
|
365
|
+
fixable: false,
|
|
366
|
+
});
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
for (const repo of registry.repositories) {
|
|
370
|
+
if (repo.id === "project") continue;
|
|
371
|
+
if (!existsSync(repo.root)) {
|
|
372
|
+
issues.push({
|
|
373
|
+
severity: "error",
|
|
374
|
+
code: "workspace_repo_path_missing",
|
|
375
|
+
scope: "project",
|
|
376
|
+
unitId: `workspace.repositories.${repo.id}`,
|
|
377
|
+
message: `declared repository "${repo.id}" path does not exist on disk: ${repo.root}`,
|
|
378
|
+
fixable: false,
|
|
379
|
+
});
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
// Must be a repo at its OWN root — a plain dir nested in the parent repo
|
|
383
|
+
// would otherwise pass a bare `nativeIsRepo` check via the enclosing
|
|
384
|
+
// parent's .git. Compare on realpath so symlinked temp roots (macOS
|
|
385
|
+
// /var vs /private/var) don't cause a false mismatch.
|
|
386
|
+
const toplevel = resolveGitToplevel(repo.root);
|
|
387
|
+
const declaredReal = realpathSafe(repo.root);
|
|
388
|
+
const toplevelReal = toplevel ? realpathSafe(toplevel) : null;
|
|
389
|
+
if (toplevelReal !== declaredReal) {
|
|
390
|
+
issues.push({
|
|
391
|
+
severity: "warning",
|
|
392
|
+
code: "workspace_repo_not_a_repo",
|
|
393
|
+
scope: "project",
|
|
394
|
+
unitId: `workspace.repositories.${repo.id}`,
|
|
395
|
+
message: `declared repository "${repo.id}" path is not a git repository at its own root: ${repo.root}`,
|
|
396
|
+
fixable: false,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
311
402
|
export async function runGSDDoctor(basePath: string, options?: { fix?: boolean; dryRun?: boolean; scope?: string; fixLevel?: "task" | "all"; isolationMode?: "none" | "worktree" | "branch"; includeBuild?: boolean; includeTests?: boolean }): Promise<DoctorReport> {
|
|
312
403
|
const issues: DoctorIssue[] = [];
|
|
313
404
|
const fixesApplied: string[] = [];
|
|
@@ -366,6 +457,7 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
|
|
|
366
457
|
(prefs?.preferences?.git?.isolation === "worktree" ? "worktree" :
|
|
367
458
|
prefs?.preferences?.git?.isolation === "branch" ? "branch" : "none");
|
|
368
459
|
await checkGitHealth(basePath, issues, fixesApplied, shouldFix, isolationMode, dryRun);
|
|
460
|
+
checkWorkspaceRepositoryHealth(basePath, prefs?.preferences, issues);
|
|
369
461
|
const gitMs = Date.now() - t0git;
|
|
370
462
|
|
|
371
463
|
// Runtime health checks — timed
|
|
@@ -386,7 +478,7 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
|
|
|
386
478
|
const envMs = Date.now() - t0env;
|
|
387
479
|
|
|
388
480
|
// Engine health checks — DB constraints and projection drift
|
|
389
|
-
await checkEngineHealth(basePath, issues, fixesApplied);
|
|
481
|
+
await checkEngineHealth(basePath, issues, fixesApplied, { repair: fix && !dryRun });
|
|
390
482
|
|
|
391
483
|
const milestonesPath = milestonesDir(basePath);
|
|
392
484
|
const legacyMilestonesPath2 = legacyMilestonesDir(basePath);
|
|
@@ -12,7 +12,8 @@ import { spawn } from "node:child_process";
|
|
|
12
12
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
import { resolve } from "node:path";
|
|
15
|
-
import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
|
|
15
|
+
import { getShellConfig, killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
|
|
16
|
+
import { redactSecrets } from "./redact-secrets.js";
|
|
16
17
|
|
|
17
18
|
export interface ExecSandboxRequest {
|
|
18
19
|
/** Interpreter to use. */
|
|
@@ -138,7 +139,12 @@ function clampTimeout(request: ExecSandboxRequest, opts: ExecSandboxOptions): nu
|
|
|
138
139
|
function resolveCommand(runtime: ExecSandboxRequest["runtime"]): { cmd: string; args: string[] } {
|
|
139
140
|
switch (runtime) {
|
|
140
141
|
case "bash":
|
|
141
|
-
|
|
142
|
+
try {
|
|
143
|
+
const { shell, args } = getShellConfig();
|
|
144
|
+
return { cmd: shell, args };
|
|
145
|
+
} catch {
|
|
146
|
+
return { cmd: "bash", args: ["-c"] };
|
|
147
|
+
}
|
|
142
148
|
case "node":
|
|
143
149
|
return { cmd: process.execPath, args: ["-e"] };
|
|
144
150
|
case "python":
|
|
@@ -310,8 +316,11 @@ export function runExecSandbox(
|
|
|
310
316
|
const stderrBuf = Buffer.concat(stderrChunks);
|
|
311
317
|
const stdoutSuffix = stdoutTruncated ? "\n[truncated: stdout cap reached]\n" : "";
|
|
312
318
|
const stderrSuffix = stderrTruncated ? "\n[truncated: stderr cap reached]\n" : "";
|
|
313
|
-
|
|
314
|
-
|
|
319
|
+
// Redact secret-shaped substrings before persisting to .gsd/exec/ (skipped by
|
|
320
|
+
// the secret scanner). The returned digest is derived from the raw buffer
|
|
321
|
+
// below and is redacted downstream when the session is written to activity/.
|
|
322
|
+
writeFileSync(stdoutPath, redactSecrets(Buffer.concat([stdoutBuf, Buffer.from(stdoutSuffix, "utf-8")]).toString("utf-8")));
|
|
323
|
+
writeFileSync(stderrPath, redactSecrets(Buffer.concat([stderrBuf, Buffer.from(stderrSuffix, "utf-8")]).toString("utf-8")));
|
|
315
324
|
|
|
316
325
|
const digestBody = tail(stdoutBuf, opts.digest_chars);
|
|
317
326
|
const digest =
|
|
@@ -11,18 +11,84 @@ import { migrateFromMarkdown } from "./md-importer.js";
|
|
|
11
11
|
import { countDbHierarchy } from "./migration-auto-check.js";
|
|
12
12
|
import { logWarning } from "./workflow-logger.js";
|
|
13
13
|
import { LAYOUT_SEGMENTS } from "./layout-policy.js";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
canonicalPhaseDirName,
|
|
16
|
+
dirIsContentBearingLegacyMilestone,
|
|
17
|
+
milestonesDir,
|
|
18
|
+
resolveMilestonePath,
|
|
19
|
+
} from "./paths.js";
|
|
15
20
|
|
|
16
21
|
const LEGACY_MIGRATING_SEGMENT = "milestones.migrating";
|
|
22
|
+
const RETRYABLE_FS_ERROR_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY"]);
|
|
23
|
+
const RM_RETRY_OPTIONS = { recursive: true, force: true, maxRetries: 5, retryDelay: 100 } as const;
|
|
24
|
+
|
|
25
|
+
type FlatPhaseMigrationFsOps = {
|
|
26
|
+
cpSync: typeof cpSync;
|
|
27
|
+
renameSync: typeof renameSync;
|
|
28
|
+
rmSync: typeof rmSync;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
let fsOps: FlatPhaseMigrationFsOps = { cpSync, renameSync, rmSync };
|
|
32
|
+
|
|
33
|
+
export function _setFlatPhaseMigrationFsOpsForTest(
|
|
34
|
+
overrides: Partial<FlatPhaseMigrationFsOps>,
|
|
35
|
+
): () => void {
|
|
36
|
+
const previous = fsOps;
|
|
37
|
+
fsOps = { ...fsOps, ...overrides };
|
|
38
|
+
return () => {
|
|
39
|
+
fsOps = previous;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
17
42
|
|
|
18
43
|
function legacyMigratingPath(basePath: string): string {
|
|
19
44
|
return join(basePath, ".gsd", LEGACY_MIGRATING_SEGMENT);
|
|
20
45
|
}
|
|
21
46
|
|
|
47
|
+
function removePathWithRetries(path: string): void {
|
|
48
|
+
fsOps.rmSync(path, { recursive: true, force: true, maxRetries: RM_RETRY_OPTIONS.maxRetries, retryDelay: RM_RETRY_OPTIONS.retryDelay });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isRetryableFsError(err: unknown): boolean {
|
|
52
|
+
const code = (err as { code?: unknown } | null)?.code;
|
|
53
|
+
return typeof code === "string" && RETRYABLE_FS_ERROR_CODES.has(code);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function movePathWithCopyDeleteFallback(src: string, dst: string): void {
|
|
57
|
+
try {
|
|
58
|
+
fsOps.renameSync(src, dst);
|
|
59
|
+
return;
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (!isRetryableFsError(err)) throw err;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
fsOps.cpSync(src, dst, { recursive: true, force: true });
|
|
66
|
+
removePathWithRetries(src);
|
|
67
|
+
} catch (fallbackErr) {
|
|
68
|
+
if (existsSync(src) && existsSync(dst)) {
|
|
69
|
+
try {
|
|
70
|
+
removePathWithRetries(dst);
|
|
71
|
+
} catch {
|
|
72
|
+
// Leave the original error intact; the next run can pre-clean dst.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
throw fallbackErr;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function expectedPhaseDirs(basePath: string): string[] {
|
|
80
|
+
return getAllMilestones().map((milestone) =>
|
|
81
|
+
resolveMilestonePath(basePath, milestone.id) ??
|
|
82
|
+
join(milestonesDir(basePath), canonicalPhaseDirName(milestone.id, milestone.title)),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
22
86
|
function hasLegacyMilestoneSubdirs(dirPath: string): boolean {
|
|
23
87
|
if (!existsSync(dirPath)) return false;
|
|
24
88
|
try {
|
|
25
|
-
return readdirSync(dirPath).some(
|
|
89
|
+
return readdirSync(dirPath).some(
|
|
90
|
+
(e) => statSync(join(dirPath, e)).isDirectory() && dirIsContentBearingLegacyMilestone(join(dirPath, e)),
|
|
91
|
+
);
|
|
26
92
|
} catch {
|
|
27
93
|
return false;
|
|
28
94
|
}
|
|
@@ -34,19 +100,26 @@ function rollbackPartialMigration(
|
|
|
34
100
|
migratingPath?: string,
|
|
35
101
|
): void {
|
|
36
102
|
// Remove the partially-written phases/ dir.
|
|
37
|
-
|
|
103
|
+
try {
|
|
104
|
+
removePathWithRetries(join(basePath, ".gsd", LAYOUT_SEGMENTS.level1));
|
|
105
|
+
} catch (removeErr) {
|
|
106
|
+
logWarning(
|
|
107
|
+
"migration",
|
|
108
|
+
`rollback: could not remove partial ${LAYOUT_SEGMENTS.level1}/: ${(removeErr as Error).message}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
38
111
|
// Restore milestones/ — prefer renaming the preserved migrating copy back.
|
|
39
112
|
const milestonesPath = join(basePath, ".gsd", "milestones");
|
|
40
113
|
try {
|
|
41
114
|
if (migratingPath && existsSync(migratingPath) && !existsSync(milestonesPath)) {
|
|
42
|
-
|
|
115
|
+
movePathWithCopyDeleteFallback(migratingPath, milestonesPath);
|
|
43
116
|
return;
|
|
44
117
|
}
|
|
45
118
|
if (existsSync(backupDir)) {
|
|
46
119
|
cpSync(backupDir, milestonesPath, { recursive: true });
|
|
47
120
|
}
|
|
48
121
|
if (migratingPath && existsSync(migratingPath)) {
|
|
49
|
-
|
|
122
|
+
removePathWithRetries(migratingPath);
|
|
50
123
|
}
|
|
51
124
|
} catch (restoreErr) {
|
|
52
125
|
logWarning(
|
|
@@ -70,6 +143,50 @@ export function needsFlatPhaseMigration(basePath: string): boolean {
|
|
|
70
143
|
return hasLegacyMilestoneSubdirs(legacyMigratingPath(basePath));
|
|
71
144
|
}
|
|
72
145
|
|
|
146
|
+
/** Retention window before flat-phase migration backups are auto-pruned. */
|
|
147
|
+
export const FLAT_PHASE_BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Remove stale flat-phase migration backups after the retention window.
|
|
151
|
+
* Only runs when migration is complete (.gsd/phases/ exists, legacy layout gone).
|
|
152
|
+
* Returns the number of migrate-* directories removed.
|
|
153
|
+
*/
|
|
154
|
+
export function pruneStaleFlatPhaseBackups(basePath: string): number {
|
|
155
|
+
if (needsFlatPhaseMigration(basePath)) return 0;
|
|
156
|
+
|
|
157
|
+
const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
|
|
158
|
+
if (!existsSync(phasesPath)) return 0;
|
|
159
|
+
|
|
160
|
+
const backupRoot = join(basePath, ".gsd-backups");
|
|
161
|
+
if (!existsSync(backupRoot)) return 0;
|
|
162
|
+
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
let removed = 0;
|
|
165
|
+
for (const entry of readdirSync(backupRoot)) {
|
|
166
|
+
if (!entry.startsWith("migrate-")) continue;
|
|
167
|
+
const dirPath = join(backupRoot, entry);
|
|
168
|
+
try {
|
|
169
|
+
const st = statSync(dirPath);
|
|
170
|
+
if (!st.isDirectory()) continue;
|
|
171
|
+
if (now - st.mtimeMs < FLAT_PHASE_BACKUP_RETENTION_MS) continue;
|
|
172
|
+
rmSync(dirPath, { recursive: true, force: true });
|
|
173
|
+
removed++;
|
|
174
|
+
} catch {
|
|
175
|
+
// Non-fatal: leave backup for manual recovery.
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
if (readdirSync(backupRoot).length === 0) {
|
|
181
|
+
rmSync(backupRoot, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
// Non-fatal.
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return removed;
|
|
188
|
+
}
|
|
189
|
+
|
|
73
190
|
/**
|
|
74
191
|
* Migrate from legacy nested .gsd/milestones/ to flat-phase .gsd/phases/.
|
|
75
192
|
*
|
|
@@ -118,18 +235,29 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
118
235
|
throw err;
|
|
119
236
|
}
|
|
120
237
|
|
|
238
|
+
if (existsSync(migratingPath)) {
|
|
239
|
+
removePathWithRetries(migratingPath);
|
|
240
|
+
}
|
|
241
|
+
|
|
121
242
|
// 3. Rename legacy tree aside before rendering so path resolvers target
|
|
122
243
|
// phases/ instead of writing back into the nested milestones/ layout.
|
|
123
244
|
// Keep the full tree on disk until render+verify succeed (unlike rmSync).
|
|
124
245
|
try {
|
|
125
|
-
|
|
246
|
+
movePathWithCopyDeleteFallback(milestonesPath, migratingPath);
|
|
126
247
|
} catch (err) {
|
|
127
248
|
logWarning("migration", `failed to rename legacy milestones/ before render: ${(err as Error).message}`);
|
|
128
249
|
throw err;
|
|
129
250
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Clear any stale or partially-rendered flat projection before this run
|
|
254
|
+
// writes. Verification below checks the current DB render, not leftovers.
|
|
255
|
+
try {
|
|
256
|
+
removePathWithRetries(phasesPath);
|
|
257
|
+
} catch (err) {
|
|
258
|
+
logWarning("migration", `failed to clear stale phases/ before render: ${(err as Error).message}`);
|
|
259
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
260
|
+
throw err;
|
|
133
261
|
}
|
|
134
262
|
|
|
135
263
|
// 4. Render flat-phase from DB
|
|
@@ -167,22 +295,14 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
167
295
|
}
|
|
168
296
|
|
|
169
297
|
const db = countDbHierarchy();
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// /^\d+-/ matches any numeric prefix (01-, 10-, 100-) so M100+ milestones
|
|
173
|
-
// whose dirs start with "100-slug" are counted correctly.
|
|
174
|
-
renderedDirCount = readdirSync(phasesPath, { withFileTypes: true })
|
|
175
|
-
.filter((entry) => entry.isDirectory() && /^\d+-/.test(entry.name)).length;
|
|
176
|
-
} catch {
|
|
177
|
-
// phases/ doesn't exist or is unreadable — same as zero dirs
|
|
178
|
-
}
|
|
179
|
-
if (db.milestones > 0 && renderedDirCount !== db.milestones) {
|
|
298
|
+
const missingPhaseDirs = expectedPhaseDirs(basePath).filter((phaseDir) => !existsSync(phaseDir));
|
|
299
|
+
if (db.milestones > 0 && missingPhaseDirs.length > 0) {
|
|
180
300
|
logWarning(
|
|
181
301
|
"migration",
|
|
182
|
-
`
|
|
302
|
+
`flat-phase migration missing ${missingPhaseDirs.length} expected phase dir(s): ${missingPhaseDirs.join(", ")}`,
|
|
183
303
|
);
|
|
184
304
|
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
185
|
-
throw new Error("flat-phase migration verification failed:
|
|
305
|
+
throw new Error("flat-phase migration verification failed: missing rendered phase directories");
|
|
186
306
|
}
|
|
187
307
|
if (db.slices > 0 && renderResult.rendered === 0) {
|
|
188
308
|
logWarning(
|
|
@@ -195,7 +315,7 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
195
315
|
|
|
196
316
|
// 6. Verified — remove the renamed legacy tree (backup already on disk).
|
|
197
317
|
try {
|
|
198
|
-
|
|
318
|
+
removePathWithRetries(migratingPath);
|
|
199
319
|
} catch (err) {
|
|
200
320
|
logWarning(
|
|
201
321
|
"migration",
|