@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0
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 +10 -10
- 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/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -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 +17 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +8 -24
- 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-timeout-recovery.js +3 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto.js +19 -10
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +48 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +15 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- 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/docs/preferences-reference.md +2 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +8 -2
- package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
- package/dist/resources/extensions/gsd/git-service.js +57 -0
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
- package/dist/resources/extensions/gsd/json-persistence.js +20 -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 +2 -7
- 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 +11 -2
- 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/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 +3 -3
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- 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/references/commands.md +1 -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 +28 -5
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-registry.js +11 -3
- 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/worktree-manager.js +44 -2
- 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 +10 -10
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- 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/middleware.js +3 -3
- 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/_not-found/page-49f565245e1e4afe.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-4ae2d68984392bbf.js → layout-b35cbfff38aaf4cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-90d1d8d5e5d2dc6b.js → main-app-590a74400e35f685.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +1 -0
- 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/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +6 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- 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/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 +258 -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 +23 -5
- 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/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/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- 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/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/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/gsd/artifact-verification.ts +464 -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 +17 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +7 -23
- 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-timeout-recovery.ts +3 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto.ts +23 -8
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +43 -18
- 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 +50 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -4
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- 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/docs/preferences-reference.md +2 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +3 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +7 -2
- package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
- package/src/resources/extensions/gsd/git-service.ts +64 -0
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
- package/src/resources/extensions/gsd/json-persistence.ts +20 -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 +2 -10
- 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 +8 -2
- 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/orphan-stash-audit.ts +108 -20
- 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 +3 -3
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- 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/references/commands.md +1 -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-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-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- 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-scope-db-unavailable.test.ts +239 -2
- 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 +37 -2
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -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/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/plan-slice-prompt.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- 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/register-hooks-loop-guard-auto.test.ts +103 -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 +56 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +140 -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/uok-gitops-turn-action.test.ts +38 -0
- 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 +6 -5
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -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 +30 -5
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-registry.ts +11 -3
- 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/worktree-manager.ts +41 -1
- 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/app/_not-found/page-a6fb1847f67f167c.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_ssgManifest.js +0 -0
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
// File Purpose: Memory FTS5 SQLite schema helpers for the GSD database facade.
|
|
3
3
|
|
|
4
4
|
import type { DbAdapter } from "./db-adapter.js";
|
|
5
|
+
import { createRuntimeKvTableV25 } from "./db-runtime-kv-schema.js";
|
|
6
|
+
|
|
7
|
+
export const MEMORIES_FTS_REBUILT_KEY = "memories_fts_rebuilt_at";
|
|
5
8
|
|
|
6
9
|
export interface MemoryFtsSchemaOptions {
|
|
7
10
|
onUnavailable?: (message: string) => void;
|
|
8
11
|
}
|
|
9
12
|
|
|
13
|
+
export interface MemoryFtsRebuildOptions {
|
|
14
|
+
onRebuildFailed?: (message: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
function formatFtsUnavailableError(err: unknown): string {
|
|
11
18
|
const message = err instanceof Error ? err.message : String(err);
|
|
12
19
|
return message.replace(/\bmoduel\s*:\s*/gi, "module: ");
|
|
@@ -64,3 +71,41 @@ export function isMemoriesFtsAvailableSchema(db: DbAdapter): boolean {
|
|
|
64
71
|
return false;
|
|
65
72
|
}
|
|
66
73
|
}
|
|
74
|
+
|
|
75
|
+
export function rebuildMemoriesFtsSchemaOnce(
|
|
76
|
+
db: DbAdapter,
|
|
77
|
+
options: MemoryFtsRebuildOptions = {},
|
|
78
|
+
): void {
|
|
79
|
+
if (!isMemoriesFtsAvailableSchema(db)) return;
|
|
80
|
+
|
|
81
|
+
createRuntimeKvTableV25(db);
|
|
82
|
+
const marker = db.prepare(
|
|
83
|
+
"SELECT 1 as present FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = :key",
|
|
84
|
+
).get({ ":key": MEMORIES_FTS_REBUILT_KEY });
|
|
85
|
+
if (marker) return;
|
|
86
|
+
|
|
87
|
+
const now = new Date().toISOString();
|
|
88
|
+
try {
|
|
89
|
+
db.exec("BEGIN");
|
|
90
|
+
db.exec("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
91
|
+
db.prepare(
|
|
92
|
+
`INSERT INTO runtime_kv (scope, scope_id, key, value_json, updated_at)
|
|
93
|
+
VALUES ('global', '', :key, :value_json, :updated_at)
|
|
94
|
+
ON CONFLICT (scope, scope_id, key) DO UPDATE SET
|
|
95
|
+
value_json = excluded.value_json,
|
|
96
|
+
updated_at = excluded.updated_at`,
|
|
97
|
+
).run({
|
|
98
|
+
":key": MEMORIES_FTS_REBUILT_KEY,
|
|
99
|
+
":value_json": JSON.stringify(now),
|
|
100
|
+
":updated_at": now,
|
|
101
|
+
});
|
|
102
|
+
db.exec("COMMIT");
|
|
103
|
+
} catch (err) {
|
|
104
|
+
try {
|
|
105
|
+
db.exec("ROLLBACK");
|
|
106
|
+
} catch {
|
|
107
|
+
// Best effort: leave startup alive and retry the rebuild on next open.
|
|
108
|
+
}
|
|
109
|
+
options.onRebuildFailed?.(`FTS5 rebuild failed: ${(err as Error).message}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// File Purpose: Workspace-facing Interface for opening and maintaining the workflow database.
|
|
3
3
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
|
-
import { dirname } from "node:path";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
6
|
|
|
7
7
|
import type { GsdWorkspace, MilestoneScope } from "./workspace.js";
|
|
8
8
|
import type { DbAdapter } from "./db-adapter.js";
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
vacuumDatabase,
|
|
25
25
|
wasDbOpenAttempted,
|
|
26
26
|
} from "./gsd-db.js";
|
|
27
|
-
import { resolveGsdPathContract } from "./paths.js";
|
|
28
|
-
import { setLogBasePath } from "./workflow-logger.js";
|
|
27
|
+
import { resolveGsdPathContract, gsdRoot } from "./paths.js";
|
|
28
|
+
import { logWarning, setLogBasePath } from "./workflow-logger.js";
|
|
29
29
|
|
|
30
30
|
export interface WorkflowDatabaseLocation {
|
|
31
31
|
projectRoot: string;
|
|
@@ -56,6 +56,20 @@ export type WorkflowDatabaseOpenResult =
|
|
|
56
56
|
export type WorkflowDatabaseStatus = ReturnType<typeof getDbStatus>;
|
|
57
57
|
export type WorkflowDatabaseProvider = ReturnType<typeof getDbProvider>;
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Global SQLite handle invariants:
|
|
61
|
+
*
|
|
62
|
+
* - `openWorkflowDatabase` / `openDatabase` switch the process-global handle consumed by
|
|
63
|
+
* deriveState, dispatch, reconciliation repairs, and domain writers. Only one active
|
|
64
|
+
* project database should own the global handle at a time.
|
|
65
|
+
* - `openWorkflowDatabaseIsolated` opens a caller-owned connection that does not clobber
|
|
66
|
+
* the global handle. Use for read-only observers (parallel monitor) and other background
|
|
67
|
+
* probes that must not disturb the active workflow session.
|
|
68
|
+
* - Reconciliation repairs that write markdown/DB state must use `ensureWorkflowDbForBase`
|
|
69
|
+
* so repairs target the correct project; those paths intentionally re-open the global handle.
|
|
70
|
+
* - Pair ad-hoc project switches with `closeWorkflowDatabase()` or restore via
|
|
71
|
+
* `ensureWorkflowDbForBase(..., { refresh: true })` before returning to derive/dispatch.
|
|
72
|
+
*/
|
|
59
73
|
export function resolveWorkflowDatabaseLocation(basePath: string): WorkflowDatabaseLocation {
|
|
60
74
|
const contract = resolveGsdPathContract(basePath);
|
|
61
75
|
return {
|
|
@@ -172,6 +186,50 @@ export function refreshWorkflowDatabaseFromDisk(): boolean {
|
|
|
172
186
|
return refreshOpenDatabaseFromDisk();
|
|
173
187
|
}
|
|
174
188
|
|
|
189
|
+
export function expectedWorkflowDbPathForBase(basePath: string): string {
|
|
190
|
+
return join(gsdRoot(basePath), "gsd.db");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface EnsureWorkflowDbOptions {
|
|
194
|
+
/** When true, refresh from disk before reopening if already open on the correct path. */
|
|
195
|
+
refresh?: boolean;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function ensureWorkflowDbAtPath(dbPath: string | null): boolean {
|
|
199
|
+
if (!dbPath || dbPath === ":memory:") return isDbAvailable();
|
|
200
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath) return true;
|
|
201
|
+
if (!existsSync(dbPath)) return false;
|
|
202
|
+
try {
|
|
203
|
+
return openWorkflowDatabasePath(dbPath);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
logWarning("reconcile", `ensureWorkflowDbAtPath could not reopen DB: ${(err as Error).message}`);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function ensureWorkflowDbForBase(
|
|
211
|
+
basePath: string,
|
|
212
|
+
options: EnsureWorkflowDbOptions = {},
|
|
213
|
+
): boolean {
|
|
214
|
+
const dbPath = expectedWorkflowDbPathForBase(basePath);
|
|
215
|
+
if (!existsSync(dbPath)) return false;
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
if (options.refresh) {
|
|
219
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath && refreshWorkflowDatabaseFromDisk()) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return openWorkflowDatabasePath(dbPath);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath) return true;
|
|
226
|
+
return openWorkflowDatabasePath(dbPath);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
logWarning("reconcile", `ensureWorkflowDbForBase could not reopen DB: ${(err as Error).message}`);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
175
233
|
export function checkpointWorkflowDatabase(): void {
|
|
176
234
|
checkpointDatabase();
|
|
177
235
|
}
|
|
@@ -121,7 +121,7 @@ const POLICY: Record<string, DelegationPolicyEntry> = {
|
|
|
121
121
|
toolName: "gsd_plan_task",
|
|
122
122
|
verdict: "no",
|
|
123
123
|
rationale:
|
|
124
|
-
"
|
|
124
|
+
"Incremental task planning mutates the active slice plan and re-renders projections; keep it ordered in the foreground plan-slice unit.",
|
|
125
125
|
},
|
|
126
126
|
};
|
|
127
127
|
|
|
@@ -273,10 +273,10 @@ This config sets a parent workspace with two child repositories. The implicit `p
|
|
|
273
273
|
- `audit_unified.enabled`: boolean — dual-write unified audit envelope events. Default: `true`.
|
|
274
274
|
- `plan_v2.enabled`: boolean — enable bounded clarify/research/draft/compile planning flow. Default: `true`.
|
|
275
275
|
|
|
276
|
-
- `context_management`: configures context hygiene for auto-mode sessions. Keys:
|
|
276
|
+
- `context_management`: configures context hygiene for auto-mode sessions. In step mode, the configurable threshold is a soft warning; automatic session re-rooting happens only at the fixed 90% hard context boundary. Keys:
|
|
277
277
|
- `observation_masking`: boolean — mask old tool results to reduce context bloat. Default: `true`.
|
|
278
278
|
- `observation_mask_turns`: number — keep this many recent turns verbatim (1-50). Default: `8`.
|
|
279
|
-
- `compaction_threshold_percent`: number —
|
|
279
|
+
- `compaction_threshold_percent`: number — show a soft context warning at this fraction of the context window (0.5-0.95). Lower values warn earlier so operators can compact manually before drift accumulates. Default: `0.60`.
|
|
280
280
|
- `tool_result_max_chars`: number — max chars per tool result in GSD sessions (200-10000). Default: `800`.
|
|
281
281
|
|
|
282
282
|
- `auto_visualize`: boolean — show a visualizer hint after each milestone completion in auto-mode. Default: `false`.
|
|
@@ -1,14 +1,148 @@
|
|
|
1
|
-
import { existsSync, statSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
3
3
|
|
|
4
4
|
import type { DoctorIssue } from "./doctor-types.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getAllMilestones,
|
|
7
|
+
getMilestoneSlices,
|
|
8
|
+
getSliceTasks,
|
|
9
|
+
isDbAvailable,
|
|
10
|
+
isMemoriesFtsAvailable,
|
|
11
|
+
_getAdapter,
|
|
12
|
+
} from "./gsd-db.js";
|
|
13
|
+
import { MEMORIES_FTS_REBUILT_KEY } from "./db-memory-fts-schema.js";
|
|
6
14
|
import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
|
|
7
|
-
import { resolveGsdPathContract, resolveMilestoneFile } from "./paths.js";
|
|
15
|
+
import { gsdProjectionRoot, gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "./paths.js";
|
|
8
16
|
import { deriveState } from "./state.js";
|
|
17
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
9
18
|
import { workflowEventLogPath } from "./workflow-event-ledger.js";
|
|
10
19
|
import { readEvents } from "./workflow-events.js";
|
|
11
20
|
import { flushWorkflowProjections } from "./projection-flush.js";
|
|
21
|
+
import { parseRoadmapSlices } from "./roadmap-slices.js";
|
|
22
|
+
import { parsePlan } from "./parsers-legacy.js";
|
|
23
|
+
|
|
24
|
+
function relativeFile(basePath: string, filePath: string): string {
|
|
25
|
+
return relative(basePath, filePath).split("\\").join("/");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function reportCheckboxDbStatusDivergence(
|
|
29
|
+
issues: DoctorIssue[],
|
|
30
|
+
basePath: string,
|
|
31
|
+
filePath: string,
|
|
32
|
+
scope: "slice" | "task",
|
|
33
|
+
unitId: string,
|
|
34
|
+
status: string,
|
|
35
|
+
checkboxDone: boolean,
|
|
36
|
+
): void {
|
|
37
|
+
const dbDone = isClosedStatus(status);
|
|
38
|
+
if (checkboxDone === dbDone) return;
|
|
39
|
+
|
|
40
|
+
issues.push({
|
|
41
|
+
severity: "error",
|
|
42
|
+
code: "checkbox_db_status_divergence",
|
|
43
|
+
scope,
|
|
44
|
+
unitId,
|
|
45
|
+
message: `${scope === "slice" ? "Slice" : "Task"} ${unitId} is ${dbDone ? "closed" : "open"} in the database (status: ${status}) but the markdown checkbox is ${checkboxDone ? "checked" : "unchecked"}.`,
|
|
46
|
+
file: relativeFile(basePath, filePath),
|
|
47
|
+
fixable: false,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function checkProjectionCheckboxDbStatus(basePath: string, milestoneIds: string[], issues: DoctorIssue[]): void {
|
|
52
|
+
for (const milestoneId of milestoneIds) {
|
|
53
|
+
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
54
|
+
const slices = getMilestoneSlices(milestoneId);
|
|
55
|
+
|
|
56
|
+
if (roadmapPath && existsSync(roadmapPath)) {
|
|
57
|
+
try {
|
|
58
|
+
const roadmap = readFileSync(roadmapPath, "utf-8");
|
|
59
|
+
const sliceDoneById = new Map(parseRoadmapSlices(roadmap).map((entry) => [entry.id, entry.done]));
|
|
60
|
+
for (const slice of slices) {
|
|
61
|
+
const checkboxDone = sliceDoneById.get(slice.id);
|
|
62
|
+
if (checkboxDone === undefined) continue;
|
|
63
|
+
reportCheckboxDbStatusDivergence(
|
|
64
|
+
issues,
|
|
65
|
+
basePath,
|
|
66
|
+
roadmapPath,
|
|
67
|
+
"slice",
|
|
68
|
+
`${milestoneId}/${slice.id}`,
|
|
69
|
+
slice.status,
|
|
70
|
+
checkboxDone,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
// Non-fatal — checkbox drift diagnostics must never block doctor.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const slice of slices) {
|
|
79
|
+
const planPath = resolveSliceFile(basePath, milestoneId, slice.id, "PLAN");
|
|
80
|
+
if (!planPath || !existsSync(planPath)) continue;
|
|
81
|
+
try {
|
|
82
|
+
const plan = readFileSync(planPath, "utf-8");
|
|
83
|
+
// parsePlan reads the authoritative task checkboxes (the flat-phase
|
|
84
|
+
// <tasks> block / ## Tasks section), so a stray task-style checkbox
|
|
85
|
+
// line elsewhere in PLAN.md (e.g. a Must-Haves or Verification bullet
|
|
86
|
+
// above <tasks>) can no longer hide real drift or fake a divergence.
|
|
87
|
+
const taskDoneById = new Map(parsePlan(plan).tasks.map((entry) => [entry.id, entry.done]));
|
|
88
|
+
for (const task of getSliceTasks(milestoneId, slice.id)) {
|
|
89
|
+
const checkboxDone = taskDoneById.get(task.id);
|
|
90
|
+
if (checkboxDone === undefined) continue;
|
|
91
|
+
reportCheckboxDbStatusDivergence(
|
|
92
|
+
issues,
|
|
93
|
+
basePath,
|
|
94
|
+
planPath,
|
|
95
|
+
"task",
|
|
96
|
+
`${milestoneId}/${slice.id}/${task.id}`,
|
|
97
|
+
task.status,
|
|
98
|
+
checkboxDone,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// Non-fatal — checkbox drift diagnostics must never block doctor.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isClearedByMilestoneShellProjectionFlush(
|
|
109
|
+
basePath: string,
|
|
110
|
+
issue: DoctorIssue,
|
|
111
|
+
reRenderedMilestoneIds: Set<string>,
|
|
112
|
+
): boolean {
|
|
113
|
+
if (issue.code !== "checkbox_db_status_divergence") return false;
|
|
114
|
+
if (issue.scope !== "slice") return false;
|
|
115
|
+
|
|
116
|
+
const milestoneId = issue.unitId.split("/")[0] ?? "";
|
|
117
|
+
if (!reRenderedMilestoneIds.has(milestoneId)) return false;
|
|
118
|
+
|
|
119
|
+
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
120
|
+
if (!roadmapPath || !issue.file) return false;
|
|
121
|
+
|
|
122
|
+
return issue.file === relativeFile(basePath, roadmapPath);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function artifactExistsOnDisk(basePath: string, artifactPath: string): boolean {
|
|
126
|
+
if (isAbsolute(artifactPath)) return existsSync(artifactPath);
|
|
127
|
+
return [
|
|
128
|
+
join(gsdProjectionRoot(basePath), artifactPath),
|
|
129
|
+
join(gsdRoot(basePath), artifactPath),
|
|
130
|
+
].some((candidate) => existsSync(candidate));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function artifactUnitId(row: { milestone_id: string | null; slice_id: string | null; task_id: string | null }): string {
|
|
134
|
+
if (!row.milestone_id) return "project";
|
|
135
|
+
if (row.slice_id && row.task_id) return `${row.milestone_id}/${row.slice_id}/${row.task_id}`;
|
|
136
|
+
if (row.slice_id) return `${row.milestone_id}/${row.slice_id}`;
|
|
137
|
+
return row.milestone_id;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function artifactScope(row: { milestone_id: string | null; slice_id: string | null; task_id: string | null }): DoctorIssue["scope"] {
|
|
141
|
+
if (row.task_id) return "task";
|
|
142
|
+
if (row.slice_id) return "slice";
|
|
143
|
+
if (row.milestone_id) return "milestone";
|
|
144
|
+
return "project";
|
|
145
|
+
}
|
|
12
146
|
|
|
13
147
|
export async function checkEngineHealth(
|
|
14
148
|
basePath: string,
|
|
@@ -34,6 +168,32 @@ export async function checkEngineHealth(
|
|
|
34
168
|
if (isDbAvailable()) {
|
|
35
169
|
const adapter = _getAdapter()!;
|
|
36
170
|
|
|
171
|
+
try {
|
|
172
|
+
if (isMemoriesFtsAvailable(adapter)) {
|
|
173
|
+
const runtimeKv = adapter
|
|
174
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='runtime_kv'")
|
|
175
|
+
.get();
|
|
176
|
+
const marker = runtimeKv
|
|
177
|
+
? adapter.prepare(
|
|
178
|
+
"SELECT 1 as present FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = :key",
|
|
179
|
+
).get({ ":key": MEMORIES_FTS_REBUILT_KEY })
|
|
180
|
+
: undefined;
|
|
181
|
+
if (!marker) {
|
|
182
|
+
issues.push({
|
|
183
|
+
severity: "warning",
|
|
184
|
+
code: "memories_fts_rebuild_missing",
|
|
185
|
+
scope: "project",
|
|
186
|
+
unitId: "project",
|
|
187
|
+
message: `Memory full-text index exists but runtime_kv has no ${MEMORIES_FTS_REBUILT_KEY} marker. The index may be stale or incomplete, so memory search can silently degrade to the LIKE fallback.`,
|
|
188
|
+
file: ".gsd/gsd.db",
|
|
189
|
+
fixable: false,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
// Non-fatal — memory FTS health check failed
|
|
195
|
+
}
|
|
196
|
+
|
|
37
197
|
// a. Orphaned tasks (task.slice_id points to non-existent slice)
|
|
38
198
|
try {
|
|
39
199
|
const orphanedTasks = adapter
|
|
@@ -196,7 +356,41 @@ export async function checkEngineHealth(
|
|
|
196
356
|
// Non-fatal — completed-milestone reopen check failed
|
|
197
357
|
}
|
|
198
358
|
|
|
199
|
-
// f.
|
|
359
|
+
// f. Artifact rows reference files that no longer exist on disk.
|
|
360
|
+
try {
|
|
361
|
+
const artifactRows = adapter
|
|
362
|
+
.prepare(
|
|
363
|
+
`SELECT path, artifact_type, milestone_id, slice_id, task_id
|
|
364
|
+
FROM artifacts
|
|
365
|
+
WHERE path != ''
|
|
366
|
+
ORDER BY path`,
|
|
367
|
+
)
|
|
368
|
+
.all() as Array<{
|
|
369
|
+
path: string;
|
|
370
|
+
artifact_type: string;
|
|
371
|
+
milestone_id: string | null;
|
|
372
|
+
slice_id: string | null;
|
|
373
|
+
task_id: string | null;
|
|
374
|
+
}>;
|
|
375
|
+
|
|
376
|
+
for (const row of artifactRows) {
|
|
377
|
+
if (artifactExistsOnDisk(basePath, row.path)) continue;
|
|
378
|
+
const unitId = artifactUnitId(row);
|
|
379
|
+
issues.push({
|
|
380
|
+
severity: "error",
|
|
381
|
+
code: "artifact_file_missing",
|
|
382
|
+
scope: artifactScope(row),
|
|
383
|
+
unitId,
|
|
384
|
+
message: `Artifact ${row.path} is recorded in the database as ${row.artifact_type || "UNKNOWN"} but no matching file exists on disk`,
|
|
385
|
+
file: row.path,
|
|
386
|
+
fixable: false,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
} catch {
|
|
390
|
+
// Non-fatal — artifact file existence check failed
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// g. Completion artifacts disagree with open DB hierarchy rows.
|
|
200
394
|
try {
|
|
201
395
|
const rows = adapter
|
|
202
396
|
.prepare(
|
|
@@ -225,6 +419,7 @@ export async function checkEngineHealth(
|
|
|
225
419
|
|
|
226
420
|
const seen = new Set<string>();
|
|
227
421
|
for (const row of rows) {
|
|
422
|
+
if (!artifactExistsOnDisk(basePath, row.path)) continue;
|
|
228
423
|
const reopenAt = latestExplicitReopenAt(basePath, row.milestone_id);
|
|
229
424
|
if (!isAfter(row.imported_at, reopenAt)) continue;
|
|
230
425
|
const isSliceSummary = row.slice_id && !row.task_id && row.slice_status && !["complete", "done", "skipped", "closed"].includes(row.slice_status);
|
|
@@ -256,9 +451,24 @@ export async function checkEngineHealth(
|
|
|
256
451
|
// Non-fatal — DB constraint checks failed entirely
|
|
257
452
|
}
|
|
258
453
|
|
|
454
|
+
// Checkbox-vs-DB divergence detection runs before projection drift auto-fix
|
|
455
|
+
// so stale re-renders cannot overwrite manually edited markdown first. Runs
|
|
456
|
+
// inside its own try/catch: getAllMilestones / getMilestoneSlices /
|
|
457
|
+
// getSliceTasks issue prepared queries that can throw on a corrupt or locked
|
|
458
|
+
// DB, and like every other DB-touching check here this diagnostic must never
|
|
459
|
+
// block doctor.
|
|
460
|
+
try {
|
|
461
|
+
if (isDbAvailable()) {
|
|
462
|
+
checkProjectionCheckboxDbStatus(basePath, getAllMilestones().map((milestone) => milestone.id), issues);
|
|
463
|
+
}
|
|
464
|
+
} catch {
|
|
465
|
+
// Non-fatal: checkbox-vs-DB divergence check must never block doctor
|
|
466
|
+
}
|
|
467
|
+
|
|
259
468
|
// ── Projection drift detection ──────────────────────────────────────────
|
|
260
469
|
// If the DB is available, check whether markdown projections are stale
|
|
261
470
|
// relative to the event log and re-render them.
|
|
471
|
+
const reRenderedMilestoneIds: string[] = [];
|
|
262
472
|
try {
|
|
263
473
|
if (isDbAvailable()) {
|
|
264
474
|
const eventLogPath = workflowEventLogPath(basePath);
|
|
@@ -273,6 +483,7 @@ export async function checkEngineHealth(
|
|
|
273
483
|
try {
|
|
274
484
|
await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
|
|
275
485
|
fixesApplied.push(`re-rendered missing projections for ${milestone.id}`);
|
|
486
|
+
reRenderedMilestoneIds.push(milestone.id);
|
|
276
487
|
} catch {
|
|
277
488
|
// Non-fatal — projection re-render failed
|
|
278
489
|
}
|
|
@@ -283,6 +494,7 @@ export async function checkEngineHealth(
|
|
|
283
494
|
try {
|
|
284
495
|
await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
|
|
285
496
|
fixesApplied.push(`re-rendered stale projections for ${milestone.id}`);
|
|
497
|
+
reRenderedMilestoneIds.push(milestone.id);
|
|
286
498
|
} catch {
|
|
287
499
|
// Non-fatal — projection re-render failed
|
|
288
500
|
}
|
|
@@ -293,4 +505,20 @@ export async function checkEngineHealth(
|
|
|
293
505
|
} catch {
|
|
294
506
|
// Non-fatal — projection drift check must never block doctor
|
|
295
507
|
}
|
|
508
|
+
|
|
509
|
+
if (reRenderedMilestoneIds.length > 0) {
|
|
510
|
+
const reRendered = new Set(reRenderedMilestoneIds);
|
|
511
|
+
for (let i = issues.length - 1; i >= 0; i--) {
|
|
512
|
+
const issue = issues[i]!;
|
|
513
|
+
// flushWorkflowProjections re-renders milestone shell projections (not
|
|
514
|
+
// slice PLAN.md files), so only clear stale ROADMAP checkbox diagnostics.
|
|
515
|
+
if (isClearedByMilestoneShellProjectionFlush(basePath, issue, reRendered)) {
|
|
516
|
+
issues.splice(i, 1);
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
if (issue.code === "artifact_file_missing" && issue.file && artifactExistsOnDisk(basePath, issue.file)) {
|
|
520
|
+
issues.splice(i, 1);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
296
524
|
}
|
|
@@ -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,10 +84,13 @@ export type DoctorIssueCode =
|
|
|
84
84
|
| "db_orphaned_task"
|
|
85
85
|
| "db_orphaned_slice"
|
|
86
86
|
| "db_done_task_no_summary"
|
|
87
|
+
| "artifact_file_missing"
|
|
87
88
|
| "artifact_db_status_divergence"
|
|
89
|
+
| "checkbox_db_status_divergence"
|
|
88
90
|
| "completed_milestone_reopened"
|
|
89
91
|
| "db_duplicate_id"
|
|
90
92
|
| "db_unavailable"
|
|
93
|
+
| "memories_fts_rebuild_missing"
|
|
91
94
|
| "projection_drift"
|
|
92
95
|
// Milestone filesystem/DB drift (#4996)
|
|
93
96
|
| "orphan_milestone_dir"
|
|
@@ -12,7 +12,7 @@ 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
16
|
|
|
17
17
|
export interface ExecSandboxRequest {
|
|
18
18
|
/** Interpreter to use. */
|
|
@@ -138,7 +138,12 @@ function clampTimeout(request: ExecSandboxRequest, opts: ExecSandboxOptions): nu
|
|
|
138
138
|
function resolveCommand(runtime: ExecSandboxRequest["runtime"]): { cmd: string; args: string[] } {
|
|
139
139
|
switch (runtime) {
|
|
140
140
|
case "bash":
|
|
141
|
-
|
|
141
|
+
try {
|
|
142
|
+
const { shell, args } = getShellConfig();
|
|
143
|
+
return { cmd: shell, args };
|
|
144
|
+
} catch {
|
|
145
|
+
return { cmd: "bash", args: ["-c"] };
|
|
146
|
+
}
|
|
142
147
|
case "node":
|
|
143
148
|
return { cmd: process.execPath, args: ["-e"] };
|
|
144
149
|
case "python":
|
|
@@ -70,6 +70,50 @@ export function needsFlatPhaseMigration(basePath: string): boolean {
|
|
|
70
70
|
return hasLegacyMilestoneSubdirs(legacyMigratingPath(basePath));
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/** Retention window before flat-phase migration backups are auto-pruned. */
|
|
74
|
+
export const FLAT_PHASE_BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Remove stale flat-phase migration backups after the retention window.
|
|
78
|
+
* Only runs when migration is complete (.gsd/phases/ exists, legacy layout gone).
|
|
79
|
+
* Returns the number of migrate-* directories removed.
|
|
80
|
+
*/
|
|
81
|
+
export function pruneStaleFlatPhaseBackups(basePath: string): number {
|
|
82
|
+
if (needsFlatPhaseMigration(basePath)) return 0;
|
|
83
|
+
|
|
84
|
+
const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
|
|
85
|
+
if (!existsSync(phasesPath)) return 0;
|
|
86
|
+
|
|
87
|
+
const backupRoot = join(basePath, ".gsd-backups");
|
|
88
|
+
if (!existsSync(backupRoot)) return 0;
|
|
89
|
+
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
let removed = 0;
|
|
92
|
+
for (const entry of readdirSync(backupRoot)) {
|
|
93
|
+
if (!entry.startsWith("migrate-")) continue;
|
|
94
|
+
const dirPath = join(backupRoot, entry);
|
|
95
|
+
try {
|
|
96
|
+
const st = statSync(dirPath);
|
|
97
|
+
if (!st.isDirectory()) continue;
|
|
98
|
+
if (now - st.mtimeMs < FLAT_PHASE_BACKUP_RETENTION_MS) continue;
|
|
99
|
+
rmSync(dirPath, { recursive: true, force: true });
|
|
100
|
+
removed++;
|
|
101
|
+
} catch {
|
|
102
|
+
// Non-fatal: leave backup for manual recovery.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
if (readdirSync(backupRoot).length === 0) {
|
|
108
|
+
rmSync(backupRoot, { recursive: true, force: true });
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
// Non-fatal.
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return removed;
|
|
115
|
+
}
|
|
116
|
+
|
|
73
117
|
/**
|
|
74
118
|
* Migrate from legacy nested .gsd/milestones/ to flat-phase .gsd/phases/.
|
|
75
119
|
*
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
15
|
+
import type { Dirent } from "node:fs";
|
|
15
16
|
import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
16
17
|
import { gsdRoot } from "./paths.js";
|
|
17
18
|
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
@@ -360,6 +361,7 @@ export interface PreMergeCheckResult {
|
|
|
360
361
|
*/
|
|
361
362
|
export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [
|
|
362
363
|
".gsd-worktrees/",
|
|
364
|
+
".gsd-backups/**",
|
|
363
365
|
".gsd/activity/",
|
|
364
366
|
".gsd/audit/",
|
|
365
367
|
".gsd/forensics/",
|
|
@@ -1268,6 +1270,7 @@ function collectRepositoryDirtyStatus(basePath: string): Record<string, boolean>
|
|
|
1268
1270
|
const preferences = loadEffectiveGSDPreferences(basePath)?.preferences;
|
|
1269
1271
|
const registry = createRepositoryRegistryFromPreferences(basePath, preferences);
|
|
1270
1272
|
const dirtyByRepository: Record<string, boolean> = {};
|
|
1273
|
+
const registeredRoots = new Set(registry.repositories.map((repo) => resolve(repo.root)));
|
|
1271
1274
|
for (const repo of registry.repositories) {
|
|
1272
1275
|
try {
|
|
1273
1276
|
dirtyByRepository[repo.id] = runGit(repo.root, ["status", "--porcelain"]).length > 0;
|
|
@@ -1276,9 +1279,70 @@ function collectRepositoryDirtyStatus(basePath: string): Record<string, boolean>
|
|
|
1276
1279
|
dirtyByRepository[repo.id] = nativeHasChanges(repo.root);
|
|
1277
1280
|
}
|
|
1278
1281
|
}
|
|
1282
|
+
for (const repoRoot of findUndeclaredNestedGitRepositories(registry.projectRoot, registeredRoots)) {
|
|
1283
|
+
let dirty = false;
|
|
1284
|
+
try {
|
|
1285
|
+
dirty = runGit(repoRoot, ["status", "--porcelain"]).length > 0;
|
|
1286
|
+
} catch {
|
|
1287
|
+
dirty = nativeHasChanges(repoRoot);
|
|
1288
|
+
}
|
|
1289
|
+
if (!dirty) continue;
|
|
1290
|
+
|
|
1291
|
+
const relPath = relative(registry.projectRoot, repoRoot).split(sep).join("/") || repoRoot;
|
|
1292
|
+
const label = `${relPath} (undeclared)`;
|
|
1293
|
+
dirtyByRepository[label] = true;
|
|
1294
|
+
logWarning(
|
|
1295
|
+
"engine",
|
|
1296
|
+
`undeclared dirty nested git repo ${relPath}; declare it under workspace.repositories or commit manually`,
|
|
1297
|
+
{ file: "git-service.ts" },
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1279
1300
|
return dirtyByRepository;
|
|
1280
1301
|
}
|
|
1281
1302
|
|
|
1303
|
+
const UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH = 4;
|
|
1304
|
+
const UNDECLARED_NESTED_REPO_SKIP_DIRS = new Set([
|
|
1305
|
+
".git",
|
|
1306
|
+
".gsd",
|
|
1307
|
+
".gsd-worktrees",
|
|
1308
|
+
"node_modules",
|
|
1309
|
+
"dist",
|
|
1310
|
+
"dist-test",
|
|
1311
|
+
]);
|
|
1312
|
+
|
|
1313
|
+
function findUndeclaredNestedGitRepositories(projectRoot: string, registeredRoots: ReadonlySet<string>): string[] {
|
|
1314
|
+
const found: string[] = [];
|
|
1315
|
+
|
|
1316
|
+
function visit(dir: string, depth: number): void {
|
|
1317
|
+
if (depth >= UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH) return;
|
|
1318
|
+
|
|
1319
|
+
let entries: Dirent[];
|
|
1320
|
+
try {
|
|
1321
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
1322
|
+
} catch {
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
for (const entry of entries) {
|
|
1327
|
+
if (!entry.isDirectory()) continue;
|
|
1328
|
+
if (UNDECLARED_NESTED_REPO_SKIP_DIRS.has(entry.name)) continue;
|
|
1329
|
+
|
|
1330
|
+
const child = join(dir, entry.name);
|
|
1331
|
+
const childRoot = resolve(child);
|
|
1332
|
+
const hasGitDir = existsSync(join(child, ".git"));
|
|
1333
|
+
const isRegistered = registeredRoots.has(childRoot);
|
|
1334
|
+
if (hasGitDir && !isRegistered) {
|
|
1335
|
+
found.push(childRoot);
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
1338
|
+
visit(child, depth + 1);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
visit(projectRoot, 0);
|
|
1343
|
+
return found;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1282
1346
|
function runPerRepositoryCommitAction(args: {
|
|
1283
1347
|
basePath: string;
|
|
1284
1348
|
unitType: string;
|