gsd-pi 2.80.0 → 2.81.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 +35 -59
- package/dist/claude-cli-check.d.ts +30 -0
- package/dist/claude-cli-check.js +18 -7
- package/dist/cli.js +0 -19
- package/dist/headless-query.d.ts +10 -0
- package/dist/headless-query.js +6 -4
- package/dist/loader-entrypoint.d.ts +8 -0
- package/dist/loader-entrypoint.js +27 -0
- package/dist/loader.js +2 -11
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +6 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +40 -3
- package/dist/resources/extensions/github-sync/sync.js +4 -1
- package/dist/resources/extensions/github-sync/templates.js +90 -74
- package/dist/resources/extensions/gsd/auto/contracts.js +2 -0
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +53 -0
- package/dist/resources/extensions/gsd/auto/loop.js +462 -525
- package/dist/resources/extensions/gsd/auto/orchestrator.js +48 -4
- package/dist/resources/extensions/gsd/auto/phases.js +311 -154
- package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +41 -45
- package/dist/resources/extensions/gsd/auto/session.js +9 -1
- package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.js +12 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-iteration.js +24 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.js +33 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-retry.js +49 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.js +25 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +80 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-ledger.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-iteration-completion.js +10 -0
- package/dist/resources/extensions/gsd/auto/workflow-journal-reporter.js +16 -0
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +263 -0
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +36 -0
- package/dist/resources/extensions/gsd/auto/workflow-phase-reporter.js +9 -0
- package/dist/resources/extensions/gsd/auto/workflow-session-lock.js +35 -0
- package/dist/resources/extensions/gsd/auto/workflow-sidecar-iteration.js +24 -0
- package/dist/resources/extensions/gsd/auto/workflow-sidecar-queue.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-turn-reporter.js +36 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +44 -0
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +23 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +72 -15
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +26 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +122 -88
- package/dist/resources/extensions/gsd/auto-prompts.js +382 -20
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
- package/dist/resources/extensions/gsd/auto-start.js +254 -17
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto-verification.js +2 -11
- package/dist/resources/extensions/gsd/auto-worktree.js +316 -374
- package/dist/resources/extensions/gsd/auto.js +273 -87
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +136 -11
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +54 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -10
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +30 -20
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -3
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +349 -57
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +147 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
- package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-config.js +1 -1
- package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/commands-ship.js +23 -46
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +12 -7
- package/dist/resources/extensions/gsd/component-loader.js +5 -11
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +25 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
- package/dist/resources/extensions/gsd/db-adapter.js +47 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +353 -0
- package/dist/resources/extensions/gsd/db-connection-cache.js +31 -0
- package/dist/resources/extensions/gsd/db-coordination-schema.js +104 -0
- package/dist/resources/extensions/gsd/db-decision-requirement-rows.js +71 -0
- package/dist/resources/extensions/gsd/db-gate-rows.js +16 -0
- package/dist/resources/extensions/gsd/db-lightweight-query-rows.js +29 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +56 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +22 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +416 -0
- package/dist/resources/extensions/gsd/db-milestone-artifact-rows.js +35 -0
- package/dist/resources/extensions/gsd/db-open-state.js +32 -0
- package/dist/resources/extensions/gsd/db-provider.js +108 -0
- package/dist/resources/extensions/gsd/db-runtime-kv-schema.js +27 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +23 -0
- package/dist/resources/extensions/gsd/db-task-slice-rows.js +86 -0
- package/dist/resources/extensions/gsd/db-transaction.js +63 -0
- package/dist/resources/extensions/gsd/db-verification-evidence-rows.js +3 -0
- package/dist/resources/extensions/gsd/db-verification-evidence-schema.js +19 -0
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/escalation.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +73 -5
- package/dist/resources/extensions/gsd/graph.js +9 -3
- package/dist/resources/extensions/gsd/gsd-db.js +331 -1535
- package/dist/resources/extensions/gsd/guided-flow.js +149 -48
- package/dist/resources/extensions/gsd/health-widget.js +3 -0
- package/dist/resources/extensions/gsd/init-wizard.js +4 -1
- package/dist/resources/extensions/gsd/legacy-telemetry.js +70 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -0
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/model-router.js +9 -6
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/notification-widget.js +21 -3
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +2 -0
- package/dist/resources/extensions/gsd/pr-evidence.js +117 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +24 -0
- package/dist/resources/extensions/gsd/process-task-path.js +61 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +37 -7
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +41 -35
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +23 -34
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
- package/dist/resources/extensions/gsd/prompts/discuss.md +81 -181
- package/dist/resources/extensions/gsd/prompts/execute-task.md +42 -67
- package/dist/resources/extensions/gsd/prompts/forensics.md +41 -84
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
- package/dist/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +47 -59
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +25 -87
- package/dist/resources/extensions/gsd/prompts/queue.md +46 -53
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +23 -23
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/research-slice.md +23 -23
- package/dist/resources/extensions/gsd/prompts/rethink.md +10 -10
- package/dist/resources/extensions/gsd/prompts/system.md +65 -107
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +15 -15
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
- package/dist/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/recovery-classification.js +94 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
- package/dist/resources/extensions/gsd/state-reconciliation.js +27 -0
- package/dist/resources/extensions/gsd/state.js +4 -0
- package/dist/resources/extensions/gsd/tool-contract.js +50 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +20 -16
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -1
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/uok/kernel.js +8 -3
- package/dist/resources/extensions/gsd/uok/plan-v2.js +2 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +13 -13
- package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -0
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/workflow-templates.js +9 -0
- package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +958 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- package/dist/resources/extensions/gsd/worktree-safety.js +119 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +317 -0
- package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +3 -3
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +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 +3 -3
- package/dist/web/standalone/.next/server/chunks/167.js +2 -0
- package/dist/web/standalone/.next/server/chunks/6897.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 +2 -2
- 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/static/chunks/8359.e059d86b255fce1c.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-ff639266d978f2a0.js → page-200592a7f3baf579.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-de742b64187e13fe.js} +1 -1
- package/dist/web/standalone/package.json +1 -0
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +20 -9
- package/packages/contracts/dist/index.d.ts +3 -0
- package/packages/contracts/dist/index.d.ts.map +1 -0
- package/packages/contracts/dist/index.js +5 -0
- package/packages/contracts/dist/index.js.map +1 -0
- package/packages/contracts/dist/rpc.d.ts +549 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.js +53 -0
- package/packages/contracts/dist/rpc.js.map +1 -0
- package/packages/contracts/dist/rpc.test.d.ts +2 -0
- package/packages/contracts/dist/rpc.test.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.test.js +47 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -0
- package/packages/contracts/dist/workflow.d.ts +180 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -0
- package/packages/contracts/dist/workflow.js +201 -0
- package/packages/contracts/dist/workflow.js.map +1 -0
- package/packages/contracts/package.json +39 -0
- package/packages/contracts/src/index.ts +5 -0
- package/packages/contracts/src/rpc.test.ts +72 -0
- package/packages/contracts/src/rpc.ts +286 -0
- package/packages/contracts/src/workflow.ts +213 -0
- package/packages/contracts/tsconfig.json +25 -0
- package/packages/daemon/package.json +3 -2
- package/packages/daemon/src/event-bridge.test.ts +2 -1
- package/packages/daemon/src/event-bridge.ts +1 -1
- package/packages/daemon/src/event-formatter.test.ts +1 -2
- package/packages/daemon/src/event-formatter.ts +1 -2
- package/packages/daemon/src/session-manager.ts +2 -2
- package/packages/daemon/src/types.ts +3 -18
- package/packages/mcp-server/dist/server.d.ts +13 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +77 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +1 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/types.d.ts +3 -11
- package/packages/mcp-server/dist/types.d.ts.map +1 -1
- package/packages/mcp-server/dist/types.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +24 -57
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -2
- package/packages/mcp-server/src/mcp-server.test.ts +138 -0
- package/packages/mcp-server/src/server.ts +99 -1
- package/packages/mcp-server/src/session-manager.ts +2 -2
- package/packages/mcp-server/src/types.ts +7 -18
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +32 -56
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +9 -2
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +43 -11
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +31 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +52 -11
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +26 -10
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
- package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/fake-model.js +27 -0
- package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/index.js +8 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +9 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
- package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/fake.js +319 -0
- package/packages/pi-ai/dist/providers/fake.js.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/models/fake-model.ts +30 -0
- package/packages/pi-ai/src/models/index.ts +9 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
- package/packages/pi-ai/src/providers/anthropic.ts +22 -9
- package/packages/pi-ai/src/providers/fake.ts +376 -0
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
- package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
- package/packages/pi-ai/src/types.ts +3 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +36 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +30 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +21 -2
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +94 -16
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +78 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +20 -7
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +102 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +60 -4
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +81 -4
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
- package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
- package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +154 -14
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +51 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +22 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +262 -20
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +86 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +111 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +77 -11
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -512
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js +3 -7
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +28 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/package.json +2 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +40 -1
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +40 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +102 -16
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +91 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +113 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +24 -6
- package/packages/pi-coding-agent/src/core/extensions/types.ts +63 -2
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +92 -4
- package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
- package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
- package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
- package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
- package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
- package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +217 -16
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +71 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +299 -20
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +118 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +108 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +101 -11
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +3 -336
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +31 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
- package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/index.d.ts +1 -0
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -0
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/style.d.ts +41 -0
- package/packages/pi-tui/dist/style.d.ts.map +1 -0
- package/packages/pi-tui/dist/style.js +158 -0
- package/packages/pi-tui/dist/style.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +19 -8
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
- package/packages/pi-tui/src/index.ts +9 -0
- package/packages/pi-tui/src/style.ts +225 -0
- package/packages/pi-tui/src/tui.ts +21 -8
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/README.md +10 -3
- package/packages/rpc-client/dist/index.d.ts +1 -1
- package/packages/rpc-client/dist/index.d.ts.map +1 -1
- package/packages/rpc-client/dist/index.js.map +1 -1
- package/packages/rpc-client/dist/rpc-client.d.ts +2 -6
- package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- package/packages/rpc-client/dist/rpc-types.d.ts +1 -565
- package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -1
- package/packages/rpc-client/dist/rpc-types.js +3 -11
- package/packages/rpc-client/dist/rpc-types.js.map +1 -1
- package/packages/rpc-client/package.json +4 -1
- package/packages/rpc-client/src/index.ts +1 -1
- package/packages/rpc-client/src/rpc-client.ts +3 -6
- package/packages/rpc-client/src/rpc-types.ts +3 -398
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +18 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +36 -27
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +42 -3
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +67 -0
- package/src/resources/extensions/github-sync/sync.ts +8 -1
- package/src/resources/extensions/github-sync/templates.ts +93 -88
- package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
- package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
- package/src/resources/extensions/github-sync/tests/templates.test.ts +10 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +19 -2
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +72 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +11 -11
- package/src/resources/extensions/gsd/auto/loop.ts +540 -602
- package/src/resources/extensions/gsd/auto/orchestrator.ts +52 -4
- package/src/resources/extensions/gsd/auto/phases.ts +427 -220
- package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +52 -44
- package/src/resources/extensions/gsd/auto/session.ts +9 -1
- package/src/resources/extensions/gsd/auto/types.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-runner-events.ts +15 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.ts +28 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-iteration.ts +52 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.ts +58 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.ts +71 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-retry.ts +90 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.ts +50 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +159 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-ledger.ts +45 -0
- package/src/resources/extensions/gsd/auto/workflow-iteration-completion.ts +26 -0
- package/src/resources/extensions/gsd/auto/workflow-journal-reporter.ts +33 -0
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +520 -0
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +58 -0
- package/src/resources/extensions/gsd/auto/workflow-phase-reporter.ts +22 -0
- package/src/resources/extensions/gsd/auto/workflow-session-lock.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-iteration.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-queue.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-turn-reporter.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +89 -0
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +51 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +81 -8
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +33 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +134 -90
- package/src/resources/extensions/gsd/auto-prompts.ts +398 -19
- package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
- package/src/resources/extensions/gsd/auto-start.ts +326 -25
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +344 -396
- package/src/resources/extensions/gsd/auto.ts +336 -89
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +162 -11
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +56 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +36 -10
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +32 -19
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +7 -4
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +6 -3
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +406 -57
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +153 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
- package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
- package/src/resources/extensions/gsd/commands-config.ts +1 -1
- package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/commands-ship.ts +24 -51
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +13 -0
- package/src/resources/extensions/gsd/component-loader.ts +5 -11
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +29 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
- package/src/resources/extensions/gsd/db-adapter.ts +75 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +385 -0
- package/src/resources/extensions/gsd/db-connection-cache.ts +45 -0
- package/src/resources/extensions/gsd/db-coordination-schema.ts +109 -0
- package/src/resources/extensions/gsd/db-decision-requirement-rows.ts +77 -0
- package/src/resources/extensions/gsd/db-gate-rows.ts +19 -0
- package/src/resources/extensions/gsd/db-lightweight-query-rows.ts +50 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +66 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +34 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +459 -0
- package/src/resources/extensions/gsd/db-milestone-artifact-rows.ts +70 -0
- package/src/resources/extensions/gsd/db-open-state.ts +47 -0
- package/src/resources/extensions/gsd/db-provider.ts +148 -0
- package/src/resources/extensions/gsd/db-runtime-kv-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +33 -0
- package/src/resources/extensions/gsd/db-task-slice-rows.ts +146 -0
- package/src/resources/extensions/gsd/db-transaction.ts +76 -0
- package/src/resources/extensions/gsd/db-verification-evidence-rows.ts +14 -0
- package/src/resources/extensions/gsd/db-verification-evidence-schema.ts +22 -0
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/escalation.ts +3 -1
- package/src/resources/extensions/gsd/git-service.ts +87 -10
- package/src/resources/extensions/gsd/graph.ts +12 -5
- package/src/resources/extensions/gsd/gsd-db.ts +399 -1677
- package/src/resources/extensions/gsd/guided-flow.ts +175 -55
- package/src/resources/extensions/gsd/health-widget.ts +3 -0
- package/src/resources/extensions/gsd/init-wizard.ts +5 -1
- package/src/resources/extensions/gsd/legacy-telemetry.ts +99 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +4 -1
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/model-router.ts +10 -6
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/notification-widget.ts +25 -4
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -1
- package/src/resources/extensions/gsd/pr-evidence.ts +182 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +27 -1
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/process-task-path.ts +81 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +36 -7
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +41 -35
- package/src/resources/extensions/gsd/prompts/complete-slice.md +23 -34
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
- package/src/resources/extensions/gsd/prompts/discuss.md +81 -181
- package/src/resources/extensions/gsd/prompts/execute-task.md +42 -67
- package/src/resources/extensions/gsd/prompts/forensics.md +41 -84
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
- package/src/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +47 -59
- package/src/resources/extensions/gsd/prompts/plan-slice.md +25 -87
- package/src/resources/extensions/gsd/prompts/queue.md +46 -53
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/refine-slice.md +23 -23
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/research-slice.md +23 -23
- package/src/resources/extensions/gsd/prompts/rethink.md +10 -10
- package/src/resources/extensions/gsd/prompts/system.md +65 -107
- package/src/resources/extensions/gsd/prompts/triage-captures.md +15 -15
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
- package/src/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/recovery-classification.ts +122 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
- package/src/resources/extensions/gsd/state-reconciliation.ts +57 -0
- package/src/resources/extensions/gsd/state.ts +6 -3
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +133 -9
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +660 -40
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +119 -2
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +175 -11
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -76
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +159 -213
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
- package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
- package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/commands-ship-eval-warn.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +159 -5
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +2 -9
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +90 -31
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +162 -10
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/db-base-schema.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/db-connection-cache.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/db-coordination-schema.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-decision-requirement-rows.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/db-gate-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-lightweight-query-rows.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
- package/src/resources/extensions/gsd/tests/db-migration-steps.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-milestone-artifact-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-open-state.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/db-provider.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-runtime-kv-schema.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/db-verification-evidence-schema.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +6 -11
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/discuss-headless-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-requirements-prompt-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -56
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +248 -10
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
- package/src/resources/extensions/gsd/tests/legacy-component-format-telemetry.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/legacy-telemetry.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +53 -43
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +37 -7
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +267 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +88 -98
- package/src/resources/extensions/gsd/tests/model-router.test.ts +33 -12
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +44 -9
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +95 -75
- package/src/resources/extensions/gsd/tests/plan-milestone-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +65 -16
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
- package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pr-evidence.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
- package/src/resources/extensions/gsd/tests/process-task-path.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -91
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
- package/src/resources/extensions/gsd/tests/queue-prompt-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -69
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +222 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -59
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -4
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +35 -40
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +32 -9
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +140 -8
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -99
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-dispatch-outcome.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-iteration.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile-outcome.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-retry.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-verify-outcome.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +300 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-ledger.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-iteration-completion.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/workflow-journal-reporter.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +607 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +20 -4
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/workflow-phase-reporter.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-session-lock.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-iteration.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-queue.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/workflow-turn-reporter.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/workflow-unit-dispatch.test.ts +160 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +38 -6
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +50 -31
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +434 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +373 -76
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +327 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +17 -33
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
- package/src/resources/extensions/gsd/tool-contract.ts +82 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +29 -24
- package/src/resources/extensions/gsd/tools/complete-task.ts +5 -2
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +7 -2
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/uok/kernel.ts +10 -3
- package/src/resources/extensions/gsd/uok/plan-v2.ts +5 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +13 -13
- package/src/resources/extensions/gsd/workflow-manifest.ts +6 -15
- package/src/resources/extensions/gsd/workflow-projections.ts +5 -1
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +11 -0
- package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +1255 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- package/src/resources/extensions/gsd/worktree-safety.ts +282 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +404 -0
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
- package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +0 -733
- package/dist/web/standalone/.next/server/chunks/6336.js +0 -1
- package/dist/web/standalone/.next/static/chunks/8336.6f6f30e410419aff.js +0 -10
- package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +0 -434
- package/src/resources/extensions/gsd/worktree-resolver.ts +0 -909
- /package/dist/web/standalone/.next/static/{V-3Ehy4B24f9FCGiLPWIM → drLMkgfHQ8lzS229_HWYR}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{V-3Ehy4B24f9FCGiLPWIM → drLMkgfHQ8lzS229_HWYR}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: GSD database facade, schema, migrations, and single-writer write API.
|
|
1
3
|
// GSD Database Abstraction Layer
|
|
2
4
|
// Provides a SQLite database with provider fallback chain:
|
|
3
5
|
// node:sqlite (built-in) → better-sqlite3 (npm) → null (unavailable)
|
|
@@ -20,269 +22,38 @@
|
|
|
20
22
|
// intentionally independent store for cross-worktree claim races and is
|
|
21
23
|
// excluded from this invariant.
|
|
22
24
|
import { createRequire } from "node:module";
|
|
25
|
+
import { createHash } from "node:crypto";
|
|
23
26
|
import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
24
27
|
import { dirname } from "node:path";
|
|
25
28
|
import { GSDError, GSD_STALE_STATE } from "./errors.js";
|
|
26
29
|
import { getGateIdsForTurn } from "./gate-registry.js";
|
|
27
30
|
import { logError, logWarning } from "./workflow-logger.js";
|
|
31
|
+
import { createDbAdapter } from "./db-adapter.js";
|
|
32
|
+
import { createBaseSchemaObjects } from "./db-base-schema.js";
|
|
33
|
+
import { createCoordinationTablesV24 } from "./db-coordination-schema.js";
|
|
34
|
+
import { createDbConnectionCache } from "./db-connection-cache.js";
|
|
35
|
+
import { emptyTaskStatusCounts, rowToActiveTaskSummary, rowToIdStatusSummary, rowToTaskStatusCounts, rowsToStringColumn, } from "./db-lightweight-query-rows.js";
|
|
36
|
+
import { rowToActiveDecision, rowToActiveRequirement, rowToDecision, rowToRequirement, rowsToRequirementCounts, } from "./db-decision-requirement-rows.js";
|
|
37
|
+
import { rowToGate } from "./db-gate-rows.js";
|
|
38
|
+
import { rowToArtifact, rowToMilestone } from "./db-milestone-artifact-rows.js";
|
|
39
|
+
import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
|
|
40
|
+
import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, applyMigrationV26MilestoneCommitAttributions, applyMigrationV27ArtifactHash, applyMigrationV28MemoryLastHitAt, } from "./db-migration-steps.js";
|
|
41
|
+
import { isMemoriesFtsAvailableSchema, tryCreateMemoriesFtsSchema } from "./db-memory-fts-schema.js";
|
|
42
|
+
import { createDbOpenState } from "./db-open-state.js";
|
|
43
|
+
import { createRuntimeKvTableV25 } from "./db-runtime-kv-schema.js";
|
|
44
|
+
import { getCurrentSchemaVersion, recordSchemaVersion } from "./db-schema-metadata.js";
|
|
45
|
+
import { rowToSlice, rowToTask } from "./db-task-slice-rows.js";
|
|
46
|
+
import { createDbTransactionRunner } from "./db-transaction.js";
|
|
47
|
+
import { ensureVerificationEvidenceDedupIndex } from "./db-verification-evidence-schema.js";
|
|
48
|
+
import { createSqliteProviderLoader, suppressSqliteWarning } from "./db-provider.js";
|
|
28
49
|
const _require = createRequire(import.meta.url);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
process.emit = function (event, ...args) {
|
|
37
|
-
if (event === "warning" &&
|
|
38
|
-
args[0] &&
|
|
39
|
-
typeof args[0] === "object" &&
|
|
40
|
-
"name" in args[0] &&
|
|
41
|
-
args[0].name === "ExperimentalWarning" &&
|
|
42
|
-
"message" in args[0] &&
|
|
43
|
-
typeof args[0].message === "string" &&
|
|
44
|
-
args[0].message.includes("SQLite")) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
return origEmit.apply(process, [event, ...args]);
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function loadProvider() {
|
|
51
|
-
if (loadAttempted)
|
|
52
|
-
return;
|
|
53
|
-
loadAttempted = true;
|
|
54
|
-
try {
|
|
55
|
-
suppressSqliteWarning();
|
|
56
|
-
const mod = _require("node:sqlite");
|
|
57
|
-
if (mod.DatabaseSync) {
|
|
58
|
-
providerModule = mod;
|
|
59
|
-
providerName = "node:sqlite";
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// unavailable
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
const mod = _require(BETTER_SQLITE3_PACKAGE);
|
|
68
|
-
if (typeof mod === "function" || (mod && mod.default)) {
|
|
69
|
-
providerModule = mod.default || mod;
|
|
70
|
-
providerName = "better-sqlite3";
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// unavailable
|
|
76
|
-
}
|
|
77
|
-
const nodeMajor = parseInt(process.versions.node.split(".")[0], 10);
|
|
78
|
-
const versionHint = nodeMajor < 22
|
|
79
|
-
? ` GSD requires Node >= 22.0.0 (current: v${process.versions.node}). Upgrade Node to fix this.`
|
|
80
|
-
: "";
|
|
81
|
-
process.stderr.write(`gsd-db: No SQLite provider available (tried node:sqlite, better-sqlite3).${versionHint}\n`);
|
|
82
|
-
}
|
|
83
|
-
function normalizeRow(row) {
|
|
84
|
-
if (row == null)
|
|
85
|
-
return undefined;
|
|
86
|
-
if (Object.getPrototypeOf(row) === null) {
|
|
87
|
-
return { ...row };
|
|
88
|
-
}
|
|
89
|
-
return row;
|
|
90
|
-
}
|
|
91
|
-
function normalizeRows(rows) {
|
|
92
|
-
return rows.map((r) => normalizeRow(r));
|
|
93
|
-
}
|
|
94
|
-
function createAdapter(rawDb) {
|
|
95
|
-
const db = rawDb;
|
|
96
|
-
const stmtCache = new Map();
|
|
97
|
-
function wrapStmt(raw) {
|
|
98
|
-
return {
|
|
99
|
-
run(...params) {
|
|
100
|
-
return raw.run(...params);
|
|
101
|
-
},
|
|
102
|
-
get(...params) {
|
|
103
|
-
return normalizeRow(raw.get(...params));
|
|
104
|
-
},
|
|
105
|
-
all(...params) {
|
|
106
|
-
return normalizeRows(raw.all(...params));
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
exec(sql) {
|
|
112
|
-
db.exec(sql);
|
|
113
|
-
},
|
|
114
|
-
prepare(sql) {
|
|
115
|
-
let cached = stmtCache.get(sql);
|
|
116
|
-
if (cached)
|
|
117
|
-
return cached;
|
|
118
|
-
cached = wrapStmt(db.prepare(sql));
|
|
119
|
-
stmtCache.set(sql, cached);
|
|
120
|
-
return cached;
|
|
121
|
-
},
|
|
122
|
-
close() {
|
|
123
|
-
stmtCache.clear();
|
|
124
|
-
db.close();
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
function openRawDb(path) {
|
|
129
|
-
loadProvider();
|
|
130
|
-
if (!providerModule || !providerName)
|
|
131
|
-
return null;
|
|
132
|
-
if (providerName === "node:sqlite") {
|
|
133
|
-
const { DatabaseSync } = providerModule;
|
|
134
|
-
return new DatabaseSync(path);
|
|
135
|
-
}
|
|
136
|
-
const Database = providerModule;
|
|
137
|
-
return new Database(path);
|
|
138
|
-
}
|
|
139
|
-
export const SCHEMA_VERSION = 25;
|
|
140
|
-
function indexExists(db, name) {
|
|
141
|
-
return !!db.prepare("SELECT 1 as present FROM sqlite_master WHERE type = 'index' AND name = ?").get(name);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Create the v24 coordination tables (workers, milestone_leases,
|
|
145
|
-
* unit_dispatches, cancellation_requests, command_queue) and their indexes.
|
|
146
|
-
*
|
|
147
|
-
* Idempotent — uses IF NOT EXISTS throughout. Called from both the
|
|
148
|
-
* fresh-install path and the v24 migration block in migrateSchema().
|
|
149
|
-
*
|
|
150
|
-
* Single-host invariant: these tables coordinate concurrent auto-mode
|
|
151
|
-
* workers via shared SQLite WAL on local disk only. NFS / network
|
|
152
|
-
* filesystems break the coordination semantics — multi-host execution
|
|
153
|
-
* needs a real coordinator (etcd, Postgres) and is out of scope.
|
|
154
|
-
*/
|
|
155
|
-
function createCoordinationTablesV24(db) {
|
|
156
|
-
const ddl = [
|
|
157
|
-
`CREATE TABLE IF NOT EXISTS workers (
|
|
158
|
-
worker_id TEXT PRIMARY KEY,
|
|
159
|
-
host TEXT NOT NULL,
|
|
160
|
-
pid INTEGER NOT NULL,
|
|
161
|
-
started_at TEXT NOT NULL,
|
|
162
|
-
version TEXT NOT NULL,
|
|
163
|
-
last_heartbeat_at TEXT NOT NULL,
|
|
164
|
-
status TEXT NOT NULL,
|
|
165
|
-
project_root_realpath TEXT NOT NULL
|
|
166
|
-
)`,
|
|
167
|
-
`CREATE TABLE IF NOT EXISTS milestone_leases (
|
|
168
|
-
milestone_id TEXT PRIMARY KEY,
|
|
169
|
-
worker_id TEXT NOT NULL,
|
|
170
|
-
fencing_token INTEGER NOT NULL,
|
|
171
|
-
acquired_at TEXT NOT NULL,
|
|
172
|
-
expires_at TEXT NOT NULL,
|
|
173
|
-
status TEXT NOT NULL,
|
|
174
|
-
FOREIGN KEY (worker_id) REFERENCES workers(worker_id),
|
|
175
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
176
|
-
)`,
|
|
177
|
-
`CREATE TABLE IF NOT EXISTS unit_dispatches (
|
|
178
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
179
|
-
trace_id TEXT NOT NULL,
|
|
180
|
-
turn_id TEXT,
|
|
181
|
-
worker_id TEXT NOT NULL,
|
|
182
|
-
milestone_lease_token INTEGER NOT NULL,
|
|
183
|
-
milestone_id TEXT NOT NULL,
|
|
184
|
-
slice_id TEXT,
|
|
185
|
-
task_id TEXT,
|
|
186
|
-
unit_type TEXT NOT NULL,
|
|
187
|
-
unit_id TEXT NOT NULL,
|
|
188
|
-
status TEXT NOT NULL,
|
|
189
|
-
attempt_n INTEGER NOT NULL DEFAULT 1,
|
|
190
|
-
started_at TEXT NOT NULL,
|
|
191
|
-
ended_at TEXT,
|
|
192
|
-
exit_reason TEXT,
|
|
193
|
-
error_summary TEXT,
|
|
194
|
-
verification_evidence_id INTEGER,
|
|
195
|
-
next_run_at TEXT,
|
|
196
|
-
retry_after_ms INTEGER,
|
|
197
|
-
max_attempts INTEGER NOT NULL DEFAULT 3,
|
|
198
|
-
last_error_code TEXT,
|
|
199
|
-
last_error_at TEXT,
|
|
200
|
-
FOREIGN KEY (worker_id) REFERENCES workers(worker_id),
|
|
201
|
-
FOREIGN KEY (verification_evidence_id) REFERENCES verification_evidence(id)
|
|
202
|
-
)`,
|
|
203
|
-
`CREATE TABLE IF NOT EXISTS cancellation_requests (
|
|
204
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
205
|
-
requested_at TEXT NOT NULL,
|
|
206
|
-
requested_by TEXT NOT NULL,
|
|
207
|
-
scope TEXT NOT NULL,
|
|
208
|
-
scope_id TEXT NOT NULL,
|
|
209
|
-
dispatch_id INTEGER,
|
|
210
|
-
reason TEXT NOT NULL,
|
|
211
|
-
status TEXT NOT NULL,
|
|
212
|
-
acked_at TEXT,
|
|
213
|
-
acked_worker_id TEXT,
|
|
214
|
-
FOREIGN KEY (dispatch_id) REFERENCES unit_dispatches(id),
|
|
215
|
-
FOREIGN KEY (acked_worker_id) REFERENCES workers(worker_id)
|
|
216
|
-
)`,
|
|
217
|
-
`CREATE TABLE IF NOT EXISTS command_queue (
|
|
218
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
219
|
-
target_worker TEXT,
|
|
220
|
-
command TEXT NOT NULL,
|
|
221
|
-
args_json TEXT NOT NULL DEFAULT '{}',
|
|
222
|
-
enqueued_at TEXT NOT NULL,
|
|
223
|
-
claimed_at TEXT,
|
|
224
|
-
claimed_by TEXT,
|
|
225
|
-
completed_at TEXT,
|
|
226
|
-
result_json TEXT
|
|
227
|
-
)`,
|
|
228
|
-
];
|
|
229
|
-
for (const stmt of ddl)
|
|
230
|
-
db.exec(stmt);
|
|
231
|
-
// Indexes — created here so both fresh-install and v24-migration paths
|
|
232
|
-
// produce identical structure.
|
|
233
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_unit_dispatches_active ON unit_dispatches(milestone_id, status)");
|
|
234
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_unit_dispatches_trace ON unit_dispatches(trace_id, turn_id)");
|
|
235
|
-
// Partial unique index — prevents two workers from claiming the same
|
|
236
|
-
// unit concurrently. Codex review MEDIUM B2: enforces double-claim guard
|
|
237
|
-
// at the DB level.
|
|
238
|
-
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_unit_dispatches_active_per_unit "
|
|
239
|
-
+ "ON unit_dispatches(unit_id) WHERE status IN ('claimed','running')");
|
|
240
|
-
// command_queue index — SQLite indexes NULLs in B-trees, so this single
|
|
241
|
-
// index serves both targeted (target_worker = ?) and broadcast
|
|
242
|
-
// (target_worker IS NULL) queries. Codex review LOW B4 documented.
|
|
243
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_command_queue_pending ON command_queue(target_worker, claimed_at)");
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Create the v25 runtime_kv table. Idempotent — uses IF NOT EXISTS.
|
|
247
|
-
*
|
|
248
|
-
* STRICT INVARIANT: runtime_kv is NON-CORRECTNESS-CRITICAL. UI cursors,
|
|
249
|
-
* dashboard caches, last-seen-version markers, resume cursors, and other
|
|
250
|
-
* "soft" state are OK. Anything that drives auto-mode control flow gets
|
|
251
|
-
* typed columns in unit_dispatches / workers / milestone_leases — never
|
|
252
|
-
* a bag of JSON in runtime_kv.
|
|
253
|
-
*
|
|
254
|
-
* Scope partitioning: ('global', '', key) for project-wide values;
|
|
255
|
-
* ('worker', worker_id, key) for per-worker state (resume cursors);
|
|
256
|
-
* ('milestone', milestone_id, key) for per-milestone soft state.
|
|
257
|
-
*/
|
|
258
|
-
function createRuntimeKvTableV25(db) {
|
|
259
|
-
db.exec(`
|
|
260
|
-
CREATE TABLE IF NOT EXISTS runtime_kv (
|
|
261
|
-
scope TEXT NOT NULL,
|
|
262
|
-
scope_id TEXT NOT NULL DEFAULT '',
|
|
263
|
-
key TEXT NOT NULL,
|
|
264
|
-
value_json TEXT NOT NULL,
|
|
265
|
-
updated_at TEXT NOT NULL,
|
|
266
|
-
PRIMARY KEY (scope, scope_id, key)
|
|
267
|
-
)
|
|
268
|
-
`);
|
|
269
|
-
}
|
|
270
|
-
function dedupeVerificationEvidenceRows(db) {
|
|
271
|
-
db.exec(`
|
|
272
|
-
DELETE FROM verification_evidence
|
|
273
|
-
WHERE rowid NOT IN (
|
|
274
|
-
SELECT MIN(rowid)
|
|
275
|
-
FROM verification_evidence
|
|
276
|
-
GROUP BY task_id, slice_id, milestone_id, command, verdict
|
|
277
|
-
)
|
|
278
|
-
`);
|
|
279
|
-
}
|
|
280
|
-
function ensureVerificationEvidenceDedupIndex(db) {
|
|
281
|
-
if (indexExists(db, "idx_verification_evidence_dedup"))
|
|
282
|
-
return;
|
|
283
|
-
dedupeVerificationEvidenceRows(db);
|
|
284
|
-
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_verification_evidence_dedup ON verification_evidence(task_id, slice_id, milestone_id, command, verdict)");
|
|
285
|
-
}
|
|
50
|
+
const providerLoader = createSqliteProviderLoader({
|
|
51
|
+
requireModule: (id) => _require(id),
|
|
52
|
+
suppressSqliteWarning,
|
|
53
|
+
nodeVersion: process.versions.node,
|
|
54
|
+
writeStderr: (message) => process.stderr.write(message),
|
|
55
|
+
});
|
|
56
|
+
export const SCHEMA_VERSION = 28;
|
|
286
57
|
function initSchema(db, fileBacked) {
|
|
287
58
|
if (fileBacked)
|
|
288
59
|
db.exec("PRAGMA journal_mode=WAL");
|
|
@@ -300,344 +71,10 @@ function initSchema(db, fileBacked) {
|
|
|
300
71
|
db.exec("PRAGMA foreign_keys = ON");
|
|
301
72
|
db.exec("BEGIN");
|
|
302
73
|
try {
|
|
303
|
-
db
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
)
|
|
308
|
-
`);
|
|
309
|
-
db.exec(`
|
|
310
|
-
CREATE TABLE IF NOT EXISTS decisions (
|
|
311
|
-
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
312
|
-
id TEXT NOT NULL UNIQUE,
|
|
313
|
-
when_context TEXT NOT NULL DEFAULT '',
|
|
314
|
-
scope TEXT NOT NULL DEFAULT '',
|
|
315
|
-
decision TEXT NOT NULL DEFAULT '',
|
|
316
|
-
choice TEXT NOT NULL DEFAULT '',
|
|
317
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
318
|
-
revisable TEXT NOT NULL DEFAULT '',
|
|
319
|
-
made_by TEXT NOT NULL DEFAULT 'agent',
|
|
320
|
-
source TEXT NOT NULL DEFAULT 'discussion', -- ADR-011 P2: 'discussion' | 'planning' | 'escalation'
|
|
321
|
-
superseded_by TEXT DEFAULT NULL
|
|
322
|
-
)
|
|
323
|
-
`);
|
|
324
|
-
db.exec(`
|
|
325
|
-
CREATE TABLE IF NOT EXISTS requirements (
|
|
326
|
-
id TEXT PRIMARY KEY,
|
|
327
|
-
class TEXT NOT NULL DEFAULT '',
|
|
328
|
-
status TEXT NOT NULL DEFAULT '',
|
|
329
|
-
description TEXT NOT NULL DEFAULT '',
|
|
330
|
-
why TEXT NOT NULL DEFAULT '',
|
|
331
|
-
source TEXT NOT NULL DEFAULT '',
|
|
332
|
-
primary_owner TEXT NOT NULL DEFAULT '',
|
|
333
|
-
supporting_slices TEXT NOT NULL DEFAULT '',
|
|
334
|
-
validation TEXT NOT NULL DEFAULT '',
|
|
335
|
-
notes TEXT NOT NULL DEFAULT '',
|
|
336
|
-
full_content TEXT NOT NULL DEFAULT '',
|
|
337
|
-
superseded_by TEXT DEFAULT NULL
|
|
338
|
-
)
|
|
339
|
-
`);
|
|
340
|
-
db.exec(`
|
|
341
|
-
CREATE TABLE IF NOT EXISTS artifacts (
|
|
342
|
-
path TEXT PRIMARY KEY,
|
|
343
|
-
artifact_type TEXT NOT NULL DEFAULT '',
|
|
344
|
-
milestone_id TEXT DEFAULT NULL,
|
|
345
|
-
slice_id TEXT DEFAULT NULL,
|
|
346
|
-
task_id TEXT DEFAULT NULL,
|
|
347
|
-
full_content TEXT NOT NULL DEFAULT '',
|
|
348
|
-
imported_at TEXT NOT NULL DEFAULT ''
|
|
349
|
-
)
|
|
350
|
-
`);
|
|
351
|
-
db.exec(`
|
|
352
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
353
|
-
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
354
|
-
id TEXT NOT NULL UNIQUE,
|
|
355
|
-
category TEXT NOT NULL,
|
|
356
|
-
content TEXT NOT NULL,
|
|
357
|
-
confidence REAL NOT NULL DEFAULT 0.8,
|
|
358
|
-
source_unit_type TEXT,
|
|
359
|
-
source_unit_id TEXT,
|
|
360
|
-
created_at TEXT NOT NULL,
|
|
361
|
-
updated_at TEXT NOT NULL,
|
|
362
|
-
superseded_by TEXT DEFAULT NULL,
|
|
363
|
-
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
364
|
-
scope TEXT NOT NULL DEFAULT 'project',
|
|
365
|
-
tags TEXT NOT NULL DEFAULT '[]',
|
|
366
|
-
structured_fields TEXT DEFAULT NULL
|
|
367
|
-
)
|
|
368
|
-
`);
|
|
369
|
-
db.exec(`
|
|
370
|
-
CREATE TABLE IF NOT EXISTS memory_processed_units (
|
|
371
|
-
unit_key TEXT PRIMARY KEY,
|
|
372
|
-
activity_file TEXT,
|
|
373
|
-
processed_at TEXT NOT NULL
|
|
374
|
-
)
|
|
375
|
-
`);
|
|
376
|
-
db.exec(`
|
|
377
|
-
CREATE TABLE IF NOT EXISTS memory_sources (
|
|
378
|
-
id TEXT PRIMARY KEY,
|
|
379
|
-
kind TEXT NOT NULL,
|
|
380
|
-
uri TEXT,
|
|
381
|
-
title TEXT,
|
|
382
|
-
content TEXT NOT NULL,
|
|
383
|
-
content_hash TEXT NOT NULL UNIQUE,
|
|
384
|
-
imported_at TEXT NOT NULL,
|
|
385
|
-
scope TEXT NOT NULL DEFAULT 'project',
|
|
386
|
-
tags TEXT NOT NULL DEFAULT '[]'
|
|
387
|
-
)
|
|
388
|
-
`);
|
|
389
|
-
db.exec(`
|
|
390
|
-
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
391
|
-
memory_id TEXT PRIMARY KEY,
|
|
392
|
-
model TEXT NOT NULL,
|
|
393
|
-
dim INTEGER NOT NULL,
|
|
394
|
-
vector BLOB NOT NULL,
|
|
395
|
-
updated_at TEXT NOT NULL
|
|
396
|
-
)
|
|
397
|
-
`);
|
|
398
|
-
db.exec(`
|
|
399
|
-
CREATE TABLE IF NOT EXISTS memory_relations (
|
|
400
|
-
from_id TEXT NOT NULL,
|
|
401
|
-
to_id TEXT NOT NULL,
|
|
402
|
-
rel TEXT NOT NULL,
|
|
403
|
-
confidence REAL NOT NULL DEFAULT 0.8,
|
|
404
|
-
created_at TEXT NOT NULL,
|
|
405
|
-
PRIMARY KEY (from_id, to_id, rel)
|
|
406
|
-
)
|
|
407
|
-
`);
|
|
408
|
-
// FTS5 virtual table mirroring memories.content for fast keyword search.
|
|
409
|
-
// Optional — if the SQLite build lacks FTS5, we fall back to LIKE scans.
|
|
410
|
-
tryCreateMemoriesFts(db);
|
|
411
|
-
db.exec(`
|
|
412
|
-
CREATE TABLE IF NOT EXISTS milestones (
|
|
413
|
-
id TEXT PRIMARY KEY,
|
|
414
|
-
title TEXT NOT NULL DEFAULT '',
|
|
415
|
-
status TEXT NOT NULL DEFAULT 'active',
|
|
416
|
-
depends_on TEXT NOT NULL DEFAULT '[]',
|
|
417
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
418
|
-
completed_at TEXT DEFAULT NULL,
|
|
419
|
-
vision TEXT NOT NULL DEFAULT '',
|
|
420
|
-
success_criteria TEXT NOT NULL DEFAULT '[]',
|
|
421
|
-
key_risks TEXT NOT NULL DEFAULT '[]',
|
|
422
|
-
proof_strategy TEXT NOT NULL DEFAULT '[]',
|
|
423
|
-
verification_contract TEXT NOT NULL DEFAULT '',
|
|
424
|
-
verification_integration TEXT NOT NULL DEFAULT '',
|
|
425
|
-
verification_operational TEXT NOT NULL DEFAULT '',
|
|
426
|
-
verification_uat TEXT NOT NULL DEFAULT '',
|
|
427
|
-
definition_of_done TEXT NOT NULL DEFAULT '[]',
|
|
428
|
-
requirement_coverage TEXT NOT NULL DEFAULT '',
|
|
429
|
-
boundary_map_markdown TEXT NOT NULL DEFAULT '',
|
|
430
|
-
sequence INTEGER DEFAULT 0
|
|
431
|
-
)
|
|
432
|
-
`);
|
|
433
|
-
db.exec(`
|
|
434
|
-
CREATE TABLE IF NOT EXISTS slices (
|
|
435
|
-
milestone_id TEXT NOT NULL,
|
|
436
|
-
id TEXT NOT NULL,
|
|
437
|
-
title TEXT NOT NULL DEFAULT '',
|
|
438
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
439
|
-
risk TEXT NOT NULL DEFAULT 'medium',
|
|
440
|
-
depends TEXT NOT NULL DEFAULT '[]',
|
|
441
|
-
demo TEXT NOT NULL DEFAULT '',
|
|
442
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
443
|
-
completed_at TEXT DEFAULT NULL,
|
|
444
|
-
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
445
|
-
full_uat_md TEXT NOT NULL DEFAULT '',
|
|
446
|
-
goal TEXT NOT NULL DEFAULT '',
|
|
447
|
-
success_criteria TEXT NOT NULL DEFAULT '',
|
|
448
|
-
proof_level TEXT NOT NULL DEFAULT '',
|
|
449
|
-
integration_closure TEXT NOT NULL DEFAULT '',
|
|
450
|
-
observability_impact TEXT NOT NULL DEFAULT '',
|
|
451
|
-
sequence INTEGER DEFAULT 0, -- Ordering hint: tools may set this to control execution order
|
|
452
|
-
replan_triggered_at TEXT DEFAULT NULL,
|
|
453
|
-
is_sketch INTEGER NOT NULL DEFAULT 0, -- ADR-011: 1 = slice is a sketch awaiting refinement
|
|
454
|
-
sketch_scope TEXT NOT NULL DEFAULT '', -- ADR-011: 2-3 sentence rough scope from plan-milestone
|
|
455
|
-
PRIMARY KEY (milestone_id, id),
|
|
456
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
457
|
-
)
|
|
458
|
-
`);
|
|
459
|
-
db.exec(`
|
|
460
|
-
CREATE TABLE IF NOT EXISTS tasks (
|
|
461
|
-
milestone_id TEXT NOT NULL,
|
|
462
|
-
slice_id TEXT NOT NULL,
|
|
463
|
-
id TEXT NOT NULL,
|
|
464
|
-
title TEXT NOT NULL DEFAULT '',
|
|
465
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
466
|
-
one_liner TEXT NOT NULL DEFAULT '',
|
|
467
|
-
narrative TEXT NOT NULL DEFAULT '',
|
|
468
|
-
verification_result TEXT NOT NULL DEFAULT '',
|
|
469
|
-
duration TEXT NOT NULL DEFAULT '',
|
|
470
|
-
completed_at TEXT DEFAULT NULL,
|
|
471
|
-
blocker_discovered INTEGER DEFAULT 0,
|
|
472
|
-
blocker_source TEXT NOT NULL DEFAULT '', -- ADR-011 P2: provenance for blocker_discovered (e.g. 'reject-escalation')
|
|
473
|
-
escalation_pending INTEGER NOT NULL DEFAULT 0, -- ADR-011 P2: pause-on-escalation flag
|
|
474
|
-
escalation_awaiting_review INTEGER NOT NULL DEFAULT 0, -- ADR-011 P2: artifact exists but continueWithDefault=true (no pause)
|
|
475
|
-
escalation_artifact_path TEXT DEFAULT NULL, -- ADR-011 P2: path to T##-ESCALATION.json
|
|
476
|
-
escalation_override_applied_at TEXT DEFAULT NULL, -- ADR-011 P2: DB claim lock for idempotent override injection
|
|
477
|
-
deviations TEXT NOT NULL DEFAULT '',
|
|
478
|
-
known_issues TEXT NOT NULL DEFAULT '',
|
|
479
|
-
key_files TEXT NOT NULL DEFAULT '[]',
|
|
480
|
-
key_decisions TEXT NOT NULL DEFAULT '[]',
|
|
481
|
-
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
482
|
-
description TEXT NOT NULL DEFAULT '',
|
|
483
|
-
estimate TEXT NOT NULL DEFAULT '',
|
|
484
|
-
files TEXT NOT NULL DEFAULT '[]',
|
|
485
|
-
verify TEXT NOT NULL DEFAULT '',
|
|
486
|
-
inputs TEXT NOT NULL DEFAULT '[]',
|
|
487
|
-
expected_output TEXT NOT NULL DEFAULT '[]',
|
|
488
|
-
observability_impact TEXT NOT NULL DEFAULT '',
|
|
489
|
-
full_plan_md TEXT NOT NULL DEFAULT '',
|
|
490
|
-
sequence INTEGER DEFAULT 0, -- Ordering hint: tools may set this to control execution order
|
|
491
|
-
PRIMARY KEY (milestone_id, slice_id, id),
|
|
492
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
493
|
-
)
|
|
494
|
-
`);
|
|
495
|
-
db.exec(`
|
|
496
|
-
CREATE TABLE IF NOT EXISTS verification_evidence (
|
|
497
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
498
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
499
|
-
slice_id TEXT NOT NULL DEFAULT '',
|
|
500
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
501
|
-
command TEXT NOT NULL DEFAULT '',
|
|
502
|
-
exit_code INTEGER DEFAULT 0,
|
|
503
|
-
verdict TEXT NOT NULL DEFAULT '',
|
|
504
|
-
duration_ms INTEGER DEFAULT 0,
|
|
505
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
506
|
-
FOREIGN KEY (milestone_id, slice_id, task_id) REFERENCES tasks(milestone_id, slice_id, id)
|
|
507
|
-
)
|
|
508
|
-
`);
|
|
509
|
-
db.exec(`
|
|
510
|
-
CREATE TABLE IF NOT EXISTS replan_history (
|
|
511
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
512
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
513
|
-
slice_id TEXT DEFAULT NULL,
|
|
514
|
-
task_id TEXT DEFAULT NULL,
|
|
515
|
-
summary TEXT NOT NULL DEFAULT '',
|
|
516
|
-
previous_artifact_path TEXT DEFAULT NULL,
|
|
517
|
-
replacement_artifact_path TEXT DEFAULT NULL,
|
|
518
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
519
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
520
|
-
)
|
|
521
|
-
`);
|
|
522
|
-
db.exec(`
|
|
523
|
-
CREATE TABLE IF NOT EXISTS assessments (
|
|
524
|
-
path TEXT PRIMARY KEY,
|
|
525
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
526
|
-
slice_id TEXT DEFAULT NULL,
|
|
527
|
-
task_id TEXT DEFAULT NULL,
|
|
528
|
-
status TEXT NOT NULL DEFAULT '',
|
|
529
|
-
scope TEXT NOT NULL DEFAULT '',
|
|
530
|
-
full_content TEXT NOT NULL DEFAULT '',
|
|
531
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
532
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
533
|
-
)
|
|
534
|
-
`);
|
|
535
|
-
db.exec(`
|
|
536
|
-
CREATE TABLE IF NOT EXISTS quality_gates (
|
|
537
|
-
milestone_id TEXT NOT NULL,
|
|
538
|
-
slice_id TEXT NOT NULL,
|
|
539
|
-
gate_id TEXT NOT NULL,
|
|
540
|
-
scope TEXT NOT NULL DEFAULT 'slice',
|
|
541
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
542
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
543
|
-
verdict TEXT NOT NULL DEFAULT '',
|
|
544
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
545
|
-
findings TEXT NOT NULL DEFAULT '',
|
|
546
|
-
evaluated_at TEXT DEFAULT NULL,
|
|
547
|
-
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
548
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
549
|
-
)
|
|
550
|
-
`);
|
|
551
|
-
// Slice dependency junction table (v14)
|
|
552
|
-
db.exec(`
|
|
553
|
-
CREATE TABLE IF NOT EXISTS slice_dependencies (
|
|
554
|
-
milestone_id TEXT NOT NULL,
|
|
555
|
-
slice_id TEXT NOT NULL,
|
|
556
|
-
depends_on_slice_id TEXT NOT NULL,
|
|
557
|
-
PRIMARY KEY (milestone_id, slice_id, depends_on_slice_id),
|
|
558
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id),
|
|
559
|
-
FOREIGN KEY (milestone_id, depends_on_slice_id) REFERENCES slices(milestone_id, id)
|
|
560
|
-
)
|
|
561
|
-
`);
|
|
562
|
-
db.exec(`
|
|
563
|
-
CREATE TABLE IF NOT EXISTS gate_runs (
|
|
564
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
565
|
-
trace_id TEXT NOT NULL,
|
|
566
|
-
turn_id TEXT NOT NULL,
|
|
567
|
-
gate_id TEXT NOT NULL,
|
|
568
|
-
gate_type TEXT NOT NULL DEFAULT '',
|
|
569
|
-
unit_type TEXT DEFAULT NULL,
|
|
570
|
-
unit_id TEXT DEFAULT NULL,
|
|
571
|
-
milestone_id TEXT DEFAULT NULL,
|
|
572
|
-
slice_id TEXT DEFAULT NULL,
|
|
573
|
-
task_id TEXT DEFAULT NULL,
|
|
574
|
-
outcome TEXT NOT NULL DEFAULT 'pass',
|
|
575
|
-
failure_class TEXT NOT NULL DEFAULT 'none',
|
|
576
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
577
|
-
findings TEXT NOT NULL DEFAULT '',
|
|
578
|
-
attempt INTEGER NOT NULL DEFAULT 1,
|
|
579
|
-
max_attempts INTEGER NOT NULL DEFAULT 1,
|
|
580
|
-
retryable INTEGER NOT NULL DEFAULT 0,
|
|
581
|
-
evaluated_at TEXT NOT NULL DEFAULT ''
|
|
582
|
-
)
|
|
583
|
-
`);
|
|
584
|
-
db.exec(`
|
|
585
|
-
CREATE TABLE IF NOT EXISTS turn_git_transactions (
|
|
586
|
-
trace_id TEXT NOT NULL,
|
|
587
|
-
turn_id TEXT NOT NULL,
|
|
588
|
-
unit_type TEXT DEFAULT NULL,
|
|
589
|
-
unit_id TEXT DEFAULT NULL,
|
|
590
|
-
stage TEXT NOT NULL DEFAULT 'turn-start',
|
|
591
|
-
action TEXT NOT NULL DEFAULT 'status-only',
|
|
592
|
-
push INTEGER NOT NULL DEFAULT 0,
|
|
593
|
-
status TEXT NOT NULL DEFAULT 'ok',
|
|
594
|
-
error TEXT DEFAULT NULL,
|
|
595
|
-
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
596
|
-
updated_at TEXT NOT NULL DEFAULT '',
|
|
597
|
-
PRIMARY KEY (trace_id, turn_id, stage)
|
|
598
|
-
)
|
|
599
|
-
`);
|
|
600
|
-
db.exec(`
|
|
601
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
602
|
-
event_id TEXT PRIMARY KEY,
|
|
603
|
-
trace_id TEXT NOT NULL,
|
|
604
|
-
turn_id TEXT DEFAULT NULL,
|
|
605
|
-
caused_by TEXT DEFAULT NULL,
|
|
606
|
-
category TEXT NOT NULL,
|
|
607
|
-
type TEXT NOT NULL,
|
|
608
|
-
ts TEXT NOT NULL,
|
|
609
|
-
payload_json TEXT NOT NULL DEFAULT '{}'
|
|
610
|
-
)
|
|
611
|
-
`);
|
|
612
|
-
db.exec(`
|
|
613
|
-
CREATE TABLE IF NOT EXISTS audit_turn_index (
|
|
614
|
-
trace_id TEXT NOT NULL,
|
|
615
|
-
turn_id TEXT NOT NULL,
|
|
616
|
-
first_ts TEXT NOT NULL,
|
|
617
|
-
last_ts TEXT NOT NULL,
|
|
618
|
-
event_count INTEGER NOT NULL DEFAULT 0,
|
|
619
|
-
PRIMARY KEY (trace_id, turn_id)
|
|
620
|
-
)
|
|
621
|
-
`);
|
|
622
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
623
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
624
|
-
// v13 indexes — hot-path dispatch queries
|
|
625
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_active ON tasks(milestone_id, slice_id, status)");
|
|
626
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_slices_active ON slices(milestone_id, status)");
|
|
627
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
628
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
629
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
630
|
-
ensureVerificationEvidenceDedupIndex(db);
|
|
631
|
-
// v14 index — slice dependency lookups
|
|
632
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_slice_deps_target ON slice_dependencies(milestone_id, depends_on_slice_id)");
|
|
633
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_gate_runs_turn ON gate_runs(trace_id, turn_id)");
|
|
634
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_gate_runs_lookup ON gate_runs(milestone_id, slice_id, task_id, gate_id)");
|
|
635
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_turn_git_tx_turn ON turn_git_transactions(trace_id, turn_id)");
|
|
636
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_trace ON audit_events(trace_id, ts)");
|
|
637
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_turn ON audit_events(trace_id, turn_id, ts)");
|
|
638
|
-
db.exec(`CREATE VIEW IF NOT EXISTS active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL`);
|
|
639
|
-
db.exec(`CREATE VIEW IF NOT EXISTS active_requirements AS SELECT * FROM requirements WHERE superseded_by IS NULL`);
|
|
640
|
-
db.exec(`CREATE VIEW IF NOT EXISTS active_memories AS SELECT * FROM memories WHERE superseded_by IS NULL`);
|
|
74
|
+
createBaseSchemaObjects(db, {
|
|
75
|
+
tryCreateMemoriesFts,
|
|
76
|
+
ensureVerificationEvidenceDedupIndex,
|
|
77
|
+
});
|
|
641
78
|
const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
|
|
642
79
|
if (existing && existing["cnt"] === 0) {
|
|
643
80
|
createCoordinationTablesV24(db);
|
|
@@ -652,10 +89,7 @@ function initSchema(db, fileBacked) {
|
|
|
652
89
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
653
90
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
|
|
654
91
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
|
|
655
|
-
db
|
|
656
|
-
":version": SCHEMA_VERSION,
|
|
657
|
-
":applied_at": new Date().toISOString(),
|
|
658
|
-
});
|
|
92
|
+
recordSchemaVersion(db, SCHEMA_VERSION);
|
|
659
93
|
}
|
|
660
94
|
db.exec("COMMIT");
|
|
661
95
|
}
|
|
@@ -665,14 +99,6 @@ function initSchema(db, fileBacked) {
|
|
|
665
99
|
}
|
|
666
100
|
migrateSchema(db);
|
|
667
101
|
}
|
|
668
|
-
function columnExists(db, table, column) {
|
|
669
|
-
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
670
|
-
return rows.some((row) => row["name"] === column);
|
|
671
|
-
}
|
|
672
|
-
function formatFtsUnavailableError(err) {
|
|
673
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
674
|
-
return message.replace(/\bmoduel\s*:\s*/gi, "module: ");
|
|
675
|
-
}
|
|
676
102
|
/**
|
|
677
103
|
* Create the FTS5 virtual table for memories plus the triggers that keep it
|
|
678
104
|
* in sync with the base table. FTS5 may be unavailable on stripped-down
|
|
@@ -680,304 +106,74 @@ function formatFtsUnavailableError(err) {
|
|
|
680
106
|
* to LIKE-based scans in `memory-store.queryMemoriesRanked`.
|
|
681
107
|
*/
|
|
682
108
|
export function tryCreateMemoriesFts(db) {
|
|
683
|
-
|
|
684
|
-
db
|
|
685
|
-
|
|
686
|
-
USING fts5(content, content='memories', content_rowid='seq', tokenize='porter unicode61')
|
|
687
|
-
`);
|
|
688
|
-
// Triggers mirror inserts / updates / deletes on the base memories table.
|
|
689
|
-
db.exec(`
|
|
690
|
-
CREATE TRIGGER IF NOT EXISTS memories_ai
|
|
691
|
-
AFTER INSERT ON memories BEGIN
|
|
692
|
-
INSERT INTO memories_fts(rowid, content) VALUES (new.seq, new.content);
|
|
693
|
-
END
|
|
694
|
-
`);
|
|
695
|
-
db.exec(`
|
|
696
|
-
CREATE TRIGGER IF NOT EXISTS memories_ad
|
|
697
|
-
AFTER DELETE ON memories BEGIN
|
|
698
|
-
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.seq, old.content);
|
|
699
|
-
END
|
|
700
|
-
`);
|
|
701
|
-
db.exec(`
|
|
702
|
-
CREATE TRIGGER IF NOT EXISTS memories_au
|
|
703
|
-
AFTER UPDATE OF content ON memories BEGIN
|
|
704
|
-
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.seq, old.content);
|
|
705
|
-
INSERT INTO memories_fts(rowid, content) VALUES (new.seq, new.content);
|
|
706
|
-
END
|
|
707
|
-
`);
|
|
708
|
-
return true;
|
|
709
|
-
}
|
|
710
|
-
catch (err) {
|
|
711
|
-
logWarning("db", `FTS5 unavailable — memory queries will use LIKE fallback: ${formatFtsUnavailableError(err)}`);
|
|
712
|
-
return false;
|
|
713
|
-
}
|
|
109
|
+
return tryCreateMemoriesFtsSchema(db, {
|
|
110
|
+
onUnavailable: (message) => logWarning("db", message),
|
|
111
|
+
});
|
|
714
112
|
}
|
|
715
113
|
export function isMemoriesFtsAvailable(db) {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
return !!row;
|
|
721
|
-
}
|
|
722
|
-
catch {
|
|
723
|
-
return false;
|
|
724
|
-
}
|
|
114
|
+
return isMemoriesFtsAvailableSchema(db);
|
|
115
|
+
}
|
|
116
|
+
function backfillMemoriesFts(db) {
|
|
117
|
+
db.exec(`INSERT INTO memories_fts(rowid, content) SELECT seq, content FROM memories`);
|
|
725
118
|
}
|
|
726
|
-
function
|
|
727
|
-
|
|
728
|
-
|
|
119
|
+
function copyQualityGateRowsToRepairedTable(db) {
|
|
120
|
+
db.exec(`
|
|
121
|
+
INSERT OR IGNORE INTO quality_gates_new
|
|
122
|
+
(milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
|
|
123
|
+
SELECT milestone_id, slice_id, gate_id, scope, COALESCE(task_id, ''), status, verdict, rationale, findings, evaluated_at
|
|
124
|
+
FROM quality_gates
|
|
125
|
+
`);
|
|
729
126
|
}
|
|
730
127
|
function migrateSchema(db) {
|
|
731
|
-
const
|
|
732
|
-
const currentVersion = row ? row["v"] : 0;
|
|
128
|
+
const currentVersion = getCurrentSchemaVersion(db);
|
|
733
129
|
if (currentVersion >= SCHEMA_VERSION)
|
|
734
130
|
return;
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
const backupPath = `${currentPath}.backup-v${currentVersion}`;
|
|
741
|
-
if (!existsSync(backupPath)) {
|
|
742
|
-
// Flush WAL to main DB file before copying — without this, the backup
|
|
743
|
-
// may be missing committed data that only exists in the -wal file.
|
|
744
|
-
try {
|
|
745
|
-
db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
746
|
-
}
|
|
747
|
-
catch { /* checkpoint is best-effort */ }
|
|
748
|
-
copyFileSync(currentPath, backupPath);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
catch (backupErr) {
|
|
752
|
-
// Log but proceed — blocking migration leaves the DB stuck at an old
|
|
753
|
-
// schema version permanently on read-only or full filesystems.
|
|
754
|
-
logWarning("db", `Pre-migration backup failed: ${backupErr instanceof Error ? backupErr.message : String(backupErr)}`);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
131
|
+
backupDatabaseBeforeMigration(db, currentPath, currentVersion, {
|
|
132
|
+
existsSync,
|
|
133
|
+
copyFileSync,
|
|
134
|
+
logWarning,
|
|
135
|
+
});
|
|
757
136
|
db.exec("BEGIN");
|
|
758
137
|
try {
|
|
759
138
|
if (currentVersion < 2) {
|
|
760
|
-
db
|
|
761
|
-
|
|
762
|
-
path TEXT PRIMARY KEY,
|
|
763
|
-
artifact_type TEXT NOT NULL DEFAULT '',
|
|
764
|
-
milestone_id TEXT DEFAULT NULL,
|
|
765
|
-
slice_id TEXT DEFAULT NULL,
|
|
766
|
-
task_id TEXT DEFAULT NULL,
|
|
767
|
-
full_content TEXT NOT NULL DEFAULT '',
|
|
768
|
-
imported_at TEXT NOT NULL DEFAULT ''
|
|
769
|
-
)
|
|
770
|
-
`);
|
|
771
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
772
|
-
":version": 2,
|
|
773
|
-
":applied_at": new Date().toISOString(),
|
|
774
|
-
});
|
|
139
|
+
applyMigrationV2Artifacts(db);
|
|
140
|
+
recordSchemaVersion(db, 2);
|
|
775
141
|
}
|
|
776
142
|
if (currentVersion < 3) {
|
|
777
|
-
db
|
|
778
|
-
|
|
779
|
-
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
780
|
-
id TEXT NOT NULL UNIQUE,
|
|
781
|
-
category TEXT NOT NULL,
|
|
782
|
-
content TEXT NOT NULL,
|
|
783
|
-
confidence REAL NOT NULL DEFAULT 0.8,
|
|
784
|
-
source_unit_type TEXT,
|
|
785
|
-
source_unit_id TEXT,
|
|
786
|
-
created_at TEXT NOT NULL,
|
|
787
|
-
updated_at TEXT NOT NULL,
|
|
788
|
-
superseded_by TEXT DEFAULT NULL,
|
|
789
|
-
hit_count INTEGER NOT NULL DEFAULT 0
|
|
790
|
-
)
|
|
791
|
-
`);
|
|
792
|
-
db.exec(`
|
|
793
|
-
CREATE TABLE IF NOT EXISTS memory_processed_units (
|
|
794
|
-
unit_key TEXT PRIMARY KEY,
|
|
795
|
-
activity_file TEXT,
|
|
796
|
-
processed_at TEXT NOT NULL
|
|
797
|
-
)
|
|
798
|
-
`);
|
|
799
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
800
|
-
db.exec("DROP VIEW IF EXISTS active_memories");
|
|
801
|
-
db.exec("CREATE VIEW active_memories AS SELECT * FROM memories WHERE superseded_by IS NULL");
|
|
802
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
803
|
-
":version": 3,
|
|
804
|
-
":applied_at": new Date().toISOString(),
|
|
805
|
-
});
|
|
143
|
+
applyMigrationV3Memories(db);
|
|
144
|
+
recordSchemaVersion(db, 3);
|
|
806
145
|
}
|
|
807
146
|
if (currentVersion < 4) {
|
|
808
|
-
|
|
809
|
-
db
|
|
810
|
-
db.exec("CREATE VIEW active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL");
|
|
811
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
812
|
-
":version": 4,
|
|
813
|
-
":applied_at": new Date().toISOString(),
|
|
814
|
-
});
|
|
147
|
+
applyMigrationV4DecisionMadeBy(db);
|
|
148
|
+
recordSchemaVersion(db, 4);
|
|
815
149
|
}
|
|
816
150
|
if (currentVersion < 5) {
|
|
817
|
-
db
|
|
818
|
-
|
|
819
|
-
id TEXT PRIMARY KEY,
|
|
820
|
-
title TEXT NOT NULL DEFAULT '',
|
|
821
|
-
status TEXT NOT NULL DEFAULT 'active',
|
|
822
|
-
created_at TEXT NOT NULL,
|
|
823
|
-
completed_at TEXT DEFAULT NULL
|
|
824
|
-
)
|
|
825
|
-
`);
|
|
826
|
-
db.exec(`
|
|
827
|
-
CREATE TABLE IF NOT EXISTS slices (
|
|
828
|
-
milestone_id TEXT NOT NULL,
|
|
829
|
-
id TEXT NOT NULL,
|
|
830
|
-
title TEXT NOT NULL DEFAULT '',
|
|
831
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
832
|
-
risk TEXT NOT NULL DEFAULT 'medium',
|
|
833
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
834
|
-
completed_at TEXT DEFAULT NULL,
|
|
835
|
-
PRIMARY KEY (milestone_id, id),
|
|
836
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
837
|
-
)
|
|
838
|
-
`);
|
|
839
|
-
db.exec(`
|
|
840
|
-
CREATE TABLE IF NOT EXISTS tasks (
|
|
841
|
-
milestone_id TEXT NOT NULL,
|
|
842
|
-
slice_id TEXT NOT NULL,
|
|
843
|
-
id TEXT NOT NULL,
|
|
844
|
-
title TEXT NOT NULL DEFAULT '',
|
|
845
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
846
|
-
one_liner TEXT NOT NULL DEFAULT '',
|
|
847
|
-
narrative TEXT NOT NULL DEFAULT '',
|
|
848
|
-
verification_result TEXT NOT NULL DEFAULT '',
|
|
849
|
-
duration TEXT NOT NULL DEFAULT '',
|
|
850
|
-
completed_at TEXT DEFAULT NULL,
|
|
851
|
-
blocker_discovered INTEGER DEFAULT 0,
|
|
852
|
-
deviations TEXT NOT NULL DEFAULT '',
|
|
853
|
-
known_issues TEXT NOT NULL DEFAULT '',
|
|
854
|
-
key_files TEXT NOT NULL DEFAULT '[]',
|
|
855
|
-
key_decisions TEXT NOT NULL DEFAULT '[]',
|
|
856
|
-
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
857
|
-
PRIMARY KEY (milestone_id, slice_id, id),
|
|
858
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
859
|
-
)
|
|
860
|
-
`);
|
|
861
|
-
db.exec(`
|
|
862
|
-
CREATE TABLE IF NOT EXISTS verification_evidence (
|
|
863
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
864
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
865
|
-
slice_id TEXT NOT NULL DEFAULT '',
|
|
866
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
867
|
-
command TEXT NOT NULL DEFAULT '',
|
|
868
|
-
exit_code INTEGER DEFAULT 0,
|
|
869
|
-
verdict TEXT NOT NULL DEFAULT '',
|
|
870
|
-
duration_ms INTEGER DEFAULT 0,
|
|
871
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
872
|
-
FOREIGN KEY (milestone_id, slice_id, task_id) REFERENCES tasks(milestone_id, slice_id, id)
|
|
873
|
-
)
|
|
874
|
-
`);
|
|
875
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
876
|
-
":version": 5,
|
|
877
|
-
":applied_at": new Date().toISOString(),
|
|
878
|
-
});
|
|
151
|
+
applyMigrationV5HierarchyTables(db);
|
|
152
|
+
recordSchemaVersion(db, 5);
|
|
879
153
|
}
|
|
880
154
|
if (currentVersion < 6) {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
884
|
-
":version": 6,
|
|
885
|
-
":applied_at": new Date().toISOString(),
|
|
886
|
-
});
|
|
155
|
+
applyMigrationV6SliceSummaries(db);
|
|
156
|
+
recordSchemaVersion(db, 6);
|
|
887
157
|
}
|
|
888
158
|
if (currentVersion < 7) {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
ensureColumn(db, "milestones", "depends_on", `ALTER TABLE milestones ADD COLUMN depends_on TEXT NOT NULL DEFAULT '[]'`);
|
|
892
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
893
|
-
":version": 7,
|
|
894
|
-
":applied_at": new Date().toISOString(),
|
|
895
|
-
});
|
|
159
|
+
applyMigrationV7Dependencies(db);
|
|
160
|
+
recordSchemaVersion(db, 7);
|
|
896
161
|
}
|
|
897
162
|
if (currentVersion < 8) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
ensureColumn(db, "milestones", "key_risks", `ALTER TABLE milestones ADD COLUMN key_risks TEXT NOT NULL DEFAULT '[]'`);
|
|
901
|
-
ensureColumn(db, "milestones", "proof_strategy", `ALTER TABLE milestones ADD COLUMN proof_strategy TEXT NOT NULL DEFAULT '[]'`);
|
|
902
|
-
ensureColumn(db, "milestones", "verification_contract", `ALTER TABLE milestones ADD COLUMN verification_contract TEXT NOT NULL DEFAULT ''`);
|
|
903
|
-
ensureColumn(db, "milestones", "verification_integration", `ALTER TABLE milestones ADD COLUMN verification_integration TEXT NOT NULL DEFAULT ''`);
|
|
904
|
-
ensureColumn(db, "milestones", "verification_operational", `ALTER TABLE milestones ADD COLUMN verification_operational TEXT NOT NULL DEFAULT ''`);
|
|
905
|
-
ensureColumn(db, "milestones", "verification_uat", `ALTER TABLE milestones ADD COLUMN verification_uat TEXT NOT NULL DEFAULT ''`);
|
|
906
|
-
ensureColumn(db, "milestones", "definition_of_done", `ALTER TABLE milestones ADD COLUMN definition_of_done TEXT NOT NULL DEFAULT '[]'`);
|
|
907
|
-
ensureColumn(db, "milestones", "requirement_coverage", `ALTER TABLE milestones ADD COLUMN requirement_coverage TEXT NOT NULL DEFAULT ''`);
|
|
908
|
-
ensureColumn(db, "milestones", "boundary_map_markdown", `ALTER TABLE milestones ADD COLUMN boundary_map_markdown TEXT NOT NULL DEFAULT ''`);
|
|
909
|
-
ensureColumn(db, "slices", "goal", `ALTER TABLE slices ADD COLUMN goal TEXT NOT NULL DEFAULT ''`);
|
|
910
|
-
ensureColumn(db, "slices", "success_criteria", `ALTER TABLE slices ADD COLUMN success_criteria TEXT NOT NULL DEFAULT ''`);
|
|
911
|
-
ensureColumn(db, "slices", "proof_level", `ALTER TABLE slices ADD COLUMN proof_level TEXT NOT NULL DEFAULT ''`);
|
|
912
|
-
ensureColumn(db, "slices", "integration_closure", `ALTER TABLE slices ADD COLUMN integration_closure TEXT NOT NULL DEFAULT ''`);
|
|
913
|
-
ensureColumn(db, "slices", "observability_impact", `ALTER TABLE slices ADD COLUMN observability_impact TEXT NOT NULL DEFAULT ''`);
|
|
914
|
-
ensureColumn(db, "tasks", "description", `ALTER TABLE tasks ADD COLUMN description TEXT NOT NULL DEFAULT ''`);
|
|
915
|
-
ensureColumn(db, "tasks", "estimate", `ALTER TABLE tasks ADD COLUMN estimate TEXT NOT NULL DEFAULT ''`);
|
|
916
|
-
ensureColumn(db, "tasks", "files", `ALTER TABLE tasks ADD COLUMN files TEXT NOT NULL DEFAULT '[]'`);
|
|
917
|
-
ensureColumn(db, "tasks", "verify", `ALTER TABLE tasks ADD COLUMN verify TEXT NOT NULL DEFAULT ''`);
|
|
918
|
-
ensureColumn(db, "tasks", "inputs", `ALTER TABLE tasks ADD COLUMN inputs TEXT NOT NULL DEFAULT '[]'`);
|
|
919
|
-
ensureColumn(db, "tasks", "expected_output", `ALTER TABLE tasks ADD COLUMN expected_output TEXT NOT NULL DEFAULT '[]'`);
|
|
920
|
-
ensureColumn(db, "tasks", "observability_impact", `ALTER TABLE tasks ADD COLUMN observability_impact TEXT NOT NULL DEFAULT ''`);
|
|
921
|
-
db.exec(`
|
|
922
|
-
CREATE TABLE IF NOT EXISTS replan_history (
|
|
923
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
924
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
925
|
-
slice_id TEXT DEFAULT NULL,
|
|
926
|
-
task_id TEXT DEFAULT NULL,
|
|
927
|
-
summary TEXT NOT NULL DEFAULT '',
|
|
928
|
-
previous_artifact_path TEXT DEFAULT NULL,
|
|
929
|
-
replacement_artifact_path TEXT DEFAULT NULL,
|
|
930
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
931
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
932
|
-
)
|
|
933
|
-
`);
|
|
934
|
-
db.exec(`
|
|
935
|
-
CREATE TABLE IF NOT EXISTS assessments (
|
|
936
|
-
path TEXT PRIMARY KEY,
|
|
937
|
-
milestone_id TEXT NOT NULL DEFAULT '',
|
|
938
|
-
slice_id TEXT DEFAULT NULL,
|
|
939
|
-
task_id TEXT DEFAULT NULL,
|
|
940
|
-
status TEXT NOT NULL DEFAULT '',
|
|
941
|
-
scope TEXT NOT NULL DEFAULT '',
|
|
942
|
-
full_content TEXT NOT NULL DEFAULT '',
|
|
943
|
-
created_at TEXT NOT NULL DEFAULT '',
|
|
944
|
-
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
945
|
-
)
|
|
946
|
-
`);
|
|
947
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
948
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
949
|
-
":version": 8,
|
|
950
|
-
":applied_at": new Date().toISOString(),
|
|
951
|
-
});
|
|
163
|
+
applyMigrationV8PlanningFields(db);
|
|
164
|
+
recordSchemaVersion(db, 8);
|
|
952
165
|
}
|
|
953
166
|
if (currentVersion < 9) {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
957
|
-
":version": 9,
|
|
958
|
-
":applied_at": new Date().toISOString(),
|
|
959
|
-
});
|
|
167
|
+
applyMigrationV9Ordering(db);
|
|
168
|
+
recordSchemaVersion(db, 9);
|
|
960
169
|
}
|
|
961
170
|
if (currentVersion < 10) {
|
|
962
|
-
|
|
963
|
-
db
|
|
964
|
-
":version": 10,
|
|
965
|
-
":applied_at": new Date().toISOString(),
|
|
966
|
-
});
|
|
171
|
+
applyMigrationV10ReplanTrigger(db);
|
|
172
|
+
recordSchemaVersion(db, 10);
|
|
967
173
|
}
|
|
968
174
|
if (currentVersion < 11) {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
// one replan record per blocker task per slice per milestone.
|
|
972
|
-
db.exec(`
|
|
973
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_replan_history_unique
|
|
974
|
-
ON replan_history(milestone_id, slice_id, task_id)
|
|
975
|
-
WHERE slice_id IS NOT NULL AND task_id IS NOT NULL
|
|
976
|
-
`);
|
|
977
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
978
|
-
":version": 11,
|
|
979
|
-
":applied_at": new Date().toISOString(),
|
|
980
|
-
});
|
|
175
|
+
applyMigrationV11TaskPlanning(db);
|
|
176
|
+
recordSchemaVersion(db, 11);
|
|
981
177
|
}
|
|
982
178
|
if (currentVersion < 12) {
|
|
983
179
|
// NOTE: The original DDL used COALESCE(task_id, '') in the PRIMARY KEY
|
|
@@ -985,295 +181,57 @@ function migrateSchema(db) {
|
|
|
985
181
|
// DBs that migrate through v12. The corrected DDL uses
|
|
986
182
|
// task_id TEXT NOT NULL DEFAULT '' with a plain column list PK. DBs that
|
|
987
183
|
// were created with the broken DDL are repaired by the v22 migration below.
|
|
988
|
-
db
|
|
989
|
-
|
|
990
|
-
milestone_id TEXT NOT NULL,
|
|
991
|
-
slice_id TEXT NOT NULL,
|
|
992
|
-
gate_id TEXT NOT NULL,
|
|
993
|
-
scope TEXT NOT NULL DEFAULT 'slice',
|
|
994
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
995
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
996
|
-
verdict TEXT NOT NULL DEFAULT '',
|
|
997
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
998
|
-
findings TEXT NOT NULL DEFAULT '',
|
|
999
|
-
evaluated_at TEXT DEFAULT NULL,
|
|
1000
|
-
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
1001
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
1002
|
-
)
|
|
1003
|
-
`);
|
|
1004
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1005
|
-
":version": 12,
|
|
1006
|
-
":applied_at": new Date().toISOString(),
|
|
1007
|
-
});
|
|
184
|
+
applyMigrationV12QualityGates(db);
|
|
185
|
+
recordSchemaVersion(db, 12);
|
|
1008
186
|
}
|
|
1009
187
|
if (currentVersion < 13) {
|
|
1010
|
-
|
|
1011
|
-
db
|
|
1012
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_slices_active ON slices(milestone_id, status)");
|
|
1013
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
1014
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
1015
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
1016
|
-
ensureVerificationEvidenceDedupIndex(db);
|
|
1017
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1018
|
-
":version": 13,
|
|
1019
|
-
":applied_at": new Date().toISOString(),
|
|
1020
|
-
});
|
|
188
|
+
applyMigrationV13HotPathIndexes(db, ensureVerificationEvidenceDedupIndex);
|
|
189
|
+
recordSchemaVersion(db, 13);
|
|
1021
190
|
}
|
|
1022
191
|
if (currentVersion < 14) {
|
|
1023
|
-
db
|
|
1024
|
-
|
|
1025
|
-
milestone_id TEXT NOT NULL,
|
|
1026
|
-
slice_id TEXT NOT NULL,
|
|
1027
|
-
depends_on_slice_id TEXT NOT NULL,
|
|
1028
|
-
PRIMARY KEY (milestone_id, slice_id, depends_on_slice_id),
|
|
1029
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id),
|
|
1030
|
-
FOREIGN KEY (milestone_id, depends_on_slice_id) REFERENCES slices(milestone_id, id)
|
|
1031
|
-
)
|
|
1032
|
-
`);
|
|
1033
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_slice_deps_target ON slice_dependencies(milestone_id, depends_on_slice_id)");
|
|
1034
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1035
|
-
":version": 14,
|
|
1036
|
-
":applied_at": new Date().toISOString(),
|
|
1037
|
-
});
|
|
192
|
+
applyMigrationV14SliceDependencies(db);
|
|
193
|
+
recordSchemaVersion(db, 14);
|
|
1038
194
|
}
|
|
1039
195
|
if (currentVersion < 15) {
|
|
1040
|
-
db
|
|
1041
|
-
|
|
1042
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1043
|
-
trace_id TEXT NOT NULL,
|
|
1044
|
-
turn_id TEXT NOT NULL,
|
|
1045
|
-
gate_id TEXT NOT NULL,
|
|
1046
|
-
gate_type TEXT NOT NULL DEFAULT '',
|
|
1047
|
-
unit_type TEXT DEFAULT NULL,
|
|
1048
|
-
unit_id TEXT DEFAULT NULL,
|
|
1049
|
-
milestone_id TEXT DEFAULT NULL,
|
|
1050
|
-
slice_id TEXT DEFAULT NULL,
|
|
1051
|
-
task_id TEXT DEFAULT NULL,
|
|
1052
|
-
outcome TEXT NOT NULL DEFAULT 'pass',
|
|
1053
|
-
failure_class TEXT NOT NULL DEFAULT 'none',
|
|
1054
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
1055
|
-
findings TEXT NOT NULL DEFAULT '',
|
|
1056
|
-
attempt INTEGER NOT NULL DEFAULT 1,
|
|
1057
|
-
max_attempts INTEGER NOT NULL DEFAULT 1,
|
|
1058
|
-
retryable INTEGER NOT NULL DEFAULT 0,
|
|
1059
|
-
evaluated_at TEXT NOT NULL DEFAULT ''
|
|
1060
|
-
)
|
|
1061
|
-
`);
|
|
1062
|
-
db.exec(`
|
|
1063
|
-
CREATE TABLE IF NOT EXISTS turn_git_transactions (
|
|
1064
|
-
trace_id TEXT NOT NULL,
|
|
1065
|
-
turn_id TEXT NOT NULL,
|
|
1066
|
-
unit_type TEXT DEFAULT NULL,
|
|
1067
|
-
unit_id TEXT DEFAULT NULL,
|
|
1068
|
-
stage TEXT NOT NULL DEFAULT 'turn-start',
|
|
1069
|
-
action TEXT NOT NULL DEFAULT 'status-only',
|
|
1070
|
-
push INTEGER NOT NULL DEFAULT 0,
|
|
1071
|
-
status TEXT NOT NULL DEFAULT 'ok',
|
|
1072
|
-
error TEXT DEFAULT NULL,
|
|
1073
|
-
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
1074
|
-
updated_at TEXT NOT NULL DEFAULT '',
|
|
1075
|
-
PRIMARY KEY (trace_id, turn_id, stage)
|
|
1076
|
-
)
|
|
1077
|
-
`);
|
|
1078
|
-
db.exec(`
|
|
1079
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
1080
|
-
event_id TEXT PRIMARY KEY,
|
|
1081
|
-
trace_id TEXT NOT NULL,
|
|
1082
|
-
turn_id TEXT DEFAULT NULL,
|
|
1083
|
-
caused_by TEXT DEFAULT NULL,
|
|
1084
|
-
category TEXT NOT NULL,
|
|
1085
|
-
type TEXT NOT NULL,
|
|
1086
|
-
ts TEXT NOT NULL,
|
|
1087
|
-
payload_json TEXT NOT NULL DEFAULT '{}'
|
|
1088
|
-
)
|
|
1089
|
-
`);
|
|
1090
|
-
db.exec(`
|
|
1091
|
-
CREATE TABLE IF NOT EXISTS audit_turn_index (
|
|
1092
|
-
trace_id TEXT NOT NULL,
|
|
1093
|
-
turn_id TEXT NOT NULL,
|
|
1094
|
-
first_ts TEXT NOT NULL,
|
|
1095
|
-
last_ts TEXT NOT NULL,
|
|
1096
|
-
event_count INTEGER NOT NULL DEFAULT 0,
|
|
1097
|
-
PRIMARY KEY (trace_id, turn_id)
|
|
1098
|
-
)
|
|
1099
|
-
`);
|
|
1100
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_gate_runs_turn ON gate_runs(trace_id, turn_id)");
|
|
1101
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_gate_runs_lookup ON gate_runs(milestone_id, slice_id, task_id, gate_id)");
|
|
1102
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_turn_git_tx_turn ON turn_git_transactions(trace_id, turn_id)");
|
|
1103
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_trace ON audit_events(trace_id, ts)");
|
|
1104
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_turn ON audit_events(trace_id, turn_id, ts)");
|
|
1105
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1106
|
-
":version": 15,
|
|
1107
|
-
":applied_at": new Date().toISOString(),
|
|
1108
|
-
});
|
|
196
|
+
applyMigrationV15AuditTables(db);
|
|
197
|
+
recordSchemaVersion(db, 15);
|
|
1109
198
|
}
|
|
1110
199
|
if (currentVersion < 16) {
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
ensureColumn(db, "slices", "sketch_scope", `ALTER TABLE slices ADD COLUMN sketch_scope TEXT NOT NULL DEFAULT ''`);
|
|
1114
|
-
// ADR-011 Phase 2: decisions can now be sourced from escalation resolutions.
|
|
1115
|
-
ensureColumn(db, "decisions", "source", `ALTER TABLE decisions ADD COLUMN source TEXT NOT NULL DEFAULT 'discussion'`);
|
|
1116
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1117
|
-
":version": 16,
|
|
1118
|
-
":applied_at": new Date().toISOString(),
|
|
1119
|
-
});
|
|
200
|
+
applyMigrationV16EscalationSource(db);
|
|
201
|
+
recordSchemaVersion(db, 16);
|
|
1120
202
|
}
|
|
1121
203
|
if (currentVersion < 17) {
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
ensureColumn(db, "tasks", "escalation_pending", `ALTER TABLE tasks ADD COLUMN escalation_pending INTEGER NOT NULL DEFAULT 0`);
|
|
1125
|
-
ensureColumn(db, "tasks", "escalation_awaiting_review", `ALTER TABLE tasks ADD COLUMN escalation_awaiting_review INTEGER NOT NULL DEFAULT 0`);
|
|
1126
|
-
ensureColumn(db, "tasks", "escalation_artifact_path", `ALTER TABLE tasks ADD COLUMN escalation_artifact_path TEXT DEFAULT NULL`);
|
|
1127
|
-
ensureColumn(db, "tasks", "escalation_override_applied_at", `ALTER TABLE tasks ADD COLUMN escalation_override_applied_at TEXT DEFAULT NULL`);
|
|
1128
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
|
|
1129
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1130
|
-
":version": 17,
|
|
1131
|
-
":applied_at": new Date().toISOString(),
|
|
1132
|
-
});
|
|
204
|
+
applyMigrationV17TaskEscalation(db);
|
|
205
|
+
recordSchemaVersion(db, 17);
|
|
1133
206
|
}
|
|
1134
207
|
if (currentVersion < 18) {
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
ensureColumn(db, "memories", "scope", `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'project'`);
|
|
1138
|
-
ensureColumn(db, "memories", "tags", `ALTER TABLE memories ADD COLUMN tags TEXT NOT NULL DEFAULT '[]'`);
|
|
1139
|
-
db.exec(`
|
|
1140
|
-
CREATE TABLE IF NOT EXISTS memory_sources (
|
|
1141
|
-
id TEXT PRIMARY KEY,
|
|
1142
|
-
kind TEXT NOT NULL,
|
|
1143
|
-
uri TEXT,
|
|
1144
|
-
title TEXT,
|
|
1145
|
-
content TEXT NOT NULL,
|
|
1146
|
-
content_hash TEXT NOT NULL UNIQUE,
|
|
1147
|
-
imported_at TEXT NOT NULL,
|
|
1148
|
-
scope TEXT NOT NULL DEFAULT 'project',
|
|
1149
|
-
tags TEXT NOT NULL DEFAULT '[]'
|
|
1150
|
-
)
|
|
1151
|
-
`);
|
|
1152
|
-
// If memory_sources already existed before v18 (created by an earlier
|
|
1153
|
-
// version of initSchema that lacked scope/tags), add the missing columns.
|
|
1154
|
-
ensureColumn(db, "memory_sources", "scope", `ALTER TABLE memory_sources ADD COLUMN scope TEXT NOT NULL DEFAULT 'project'`);
|
|
1155
|
-
ensureColumn(db, "memory_sources", "tags", `ALTER TABLE memory_sources ADD COLUMN tags TEXT NOT NULL DEFAULT '[]'`);
|
|
1156
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
|
|
1157
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
|
|
1158
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
1159
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1160
|
-
":version": 18,
|
|
1161
|
-
":applied_at": new Date().toISOString(),
|
|
1162
|
-
});
|
|
208
|
+
applyMigrationV18MemorySources(db);
|
|
209
|
+
recordSchemaVersion(db, 18);
|
|
1163
210
|
}
|
|
1164
211
|
if (currentVersion < 19) {
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
dim INTEGER NOT NULL,
|
|
1171
|
-
vector BLOB NOT NULL,
|
|
1172
|
-
updated_at TEXT NOT NULL
|
|
1173
|
-
)
|
|
1174
|
-
`);
|
|
1175
|
-
tryCreateMemoriesFts(db);
|
|
1176
|
-
// Backfill FTS5 with any existing memories (triggers only cover future writes).
|
|
1177
|
-
if (isMemoriesFtsAvailable(db)) {
|
|
1178
|
-
try {
|
|
1179
|
-
db.exec(`INSERT INTO memories_fts(rowid, content) SELECT seq, content FROM memories`);
|
|
1180
|
-
}
|
|
1181
|
-
catch (err) {
|
|
1182
|
-
logWarning("db", `FTS5 backfill failed: ${err.message}`);
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1186
|
-
":version": 19,
|
|
1187
|
-
":applied_at": new Date().toISOString(),
|
|
212
|
+
applyMigrationV19MemoryFts(db, {
|
|
213
|
+
tryCreateMemoriesFts,
|
|
214
|
+
isMemoriesFtsAvailable,
|
|
215
|
+
backfillMemoriesFts,
|
|
216
|
+
logWarning,
|
|
1188
217
|
});
|
|
218
|
+
recordSchemaVersion(db, 19);
|
|
1189
219
|
}
|
|
1190
220
|
if (currentVersion < 20) {
|
|
1191
|
-
|
|
1192
|
-
db
|
|
1193
|
-
CREATE TABLE IF NOT EXISTS memory_relations (
|
|
1194
|
-
from_id TEXT NOT NULL,
|
|
1195
|
-
to_id TEXT NOT NULL,
|
|
1196
|
-
rel TEXT NOT NULL,
|
|
1197
|
-
confidence REAL NOT NULL DEFAULT 0.8,
|
|
1198
|
-
created_at TEXT NOT NULL,
|
|
1199
|
-
PRIMARY KEY (from_id, to_id, rel)
|
|
1200
|
-
)
|
|
1201
|
-
`);
|
|
1202
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
|
|
1203
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
|
|
1204
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1205
|
-
":version": 20,
|
|
1206
|
-
":applied_at": new Date().toISOString(),
|
|
1207
|
-
});
|
|
221
|
+
applyMigrationV20MemoryRelations(db);
|
|
222
|
+
recordSchemaVersion(db, 20);
|
|
1208
223
|
}
|
|
1209
224
|
if (currentVersion < 21) {
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
// the eventual decisions->memories cutover does not lose schema fidelity.
|
|
1213
|
-
// Nullable JSON column — existing rows stay NULL until backfilled in Step 5.
|
|
1214
|
-
// Use ensureColumn for race-safety (matches v15-v18 pattern; bare ALTER
|
|
1215
|
-
// throws "duplicate column" on the loser of a concurrent open race even
|
|
1216
|
-
// though the transaction wrapper protects the schema_version row).
|
|
1217
|
-
ensureColumn(db, "memories", "structured_fields", "ALTER TABLE memories ADD COLUMN structured_fields TEXT DEFAULT NULL");
|
|
1218
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1219
|
-
":version": 21,
|
|
1220
|
-
":applied_at": new Date().toISOString(),
|
|
1221
|
-
});
|
|
225
|
+
applyMigrationV21StructuredMemories(db);
|
|
226
|
+
recordSchemaVersion(db, 21);
|
|
1222
227
|
}
|
|
1223
228
|
if (currentVersion < 22) {
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
// SQLite DDL). Those DBs have task_id nullable (dflt_value NULL, notnull 0).
|
|
1227
|
-
// Rebuild the table with the correct schema, migrating existing rows via
|
|
1228
|
-
// COALESCE so no data is lost.
|
|
1229
|
-
const qgInfo = db.prepare("PRAGMA table_info(quality_gates)").all();
|
|
1230
|
-
const taskIdCol = qgInfo.find((r) => r["name"] === "task_id");
|
|
1231
|
-
const needsRepair = taskIdCol && (taskIdCol["notnull"] === 0 || taskIdCol["notnull"] === "0");
|
|
1232
|
-
if (needsRepair) {
|
|
1233
|
-
db.exec(`
|
|
1234
|
-
CREATE TABLE quality_gates_new (
|
|
1235
|
-
milestone_id TEXT NOT NULL,
|
|
1236
|
-
slice_id TEXT NOT NULL,
|
|
1237
|
-
gate_id TEXT NOT NULL,
|
|
1238
|
-
scope TEXT NOT NULL DEFAULT 'slice',
|
|
1239
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
1240
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
1241
|
-
verdict TEXT NOT NULL DEFAULT '',
|
|
1242
|
-
rationale TEXT NOT NULL DEFAULT '',
|
|
1243
|
-
findings TEXT NOT NULL DEFAULT '',
|
|
1244
|
-
evaluated_at TEXT DEFAULT NULL,
|
|
1245
|
-
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
1246
|
-
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
1247
|
-
)
|
|
1248
|
-
`);
|
|
1249
|
-
db.exec(`
|
|
1250
|
-
INSERT OR IGNORE INTO quality_gates_new
|
|
1251
|
-
(milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
|
|
1252
|
-
SELECT milestone_id, slice_id, gate_id, scope, COALESCE(task_id, ''), status, verdict, rationale, findings, evaluated_at
|
|
1253
|
-
FROM quality_gates
|
|
1254
|
-
`);
|
|
1255
|
-
db.exec("DROP TABLE quality_gates");
|
|
1256
|
-
db.exec("ALTER TABLE quality_gates_new RENAME TO quality_gates");
|
|
1257
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
1258
|
-
}
|
|
1259
|
-
// Ensure scope column exists on quality_gates and assessments (guard
|
|
1260
|
-
// against DBs that somehow lack it after a partial migration).
|
|
1261
|
-
ensureColumn(db, "quality_gates", "scope", "ALTER TABLE quality_gates ADD COLUMN scope TEXT NOT NULL DEFAULT 'slice'");
|
|
1262
|
-
ensureColumn(db, "assessments", "scope", "ALTER TABLE assessments ADD COLUMN scope TEXT NOT NULL DEFAULT ''");
|
|
1263
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1264
|
-
":version": 22,
|
|
1265
|
-
":applied_at": new Date().toISOString(),
|
|
1266
|
-
});
|
|
229
|
+
applyMigrationV22QualityGateRepair(db, { copyQualityGateRowsToRepairedTable });
|
|
230
|
+
recordSchemaVersion(db, 22);
|
|
1267
231
|
}
|
|
1268
232
|
if (currentVersion < 23) {
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
// derivation must not read it as authoritative state.
|
|
1272
|
-
ensureColumn(db, "milestones", "sequence", "ALTER TABLE milestones ADD COLUMN sequence INTEGER DEFAULT 0");
|
|
1273
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1274
|
-
":version": 23,
|
|
1275
|
-
":applied_at": new Date().toISOString(),
|
|
1276
|
-
});
|
|
233
|
+
applyMigrationV23MilestoneQueue(db);
|
|
234
|
+
recordSchemaVersion(db, 23);
|
|
1277
235
|
}
|
|
1278
236
|
if (currentVersion < 24) {
|
|
1279
237
|
// v24: auto-mode coordination tables. See createCoordinationTablesV24
|
|
@@ -1281,19 +239,25 @@ function migrateSchema(db) {
|
|
|
1281
239
|
// helper runs in the fresh-install path); for upgraded DBs this is
|
|
1282
240
|
// the only place these tables get created.
|
|
1283
241
|
createCoordinationTablesV24(db);
|
|
1284
|
-
db
|
|
1285
|
-
":version": 24,
|
|
1286
|
-
":applied_at": new Date().toISOString(),
|
|
1287
|
-
});
|
|
242
|
+
recordSchemaVersion(db, 24);
|
|
1288
243
|
}
|
|
1289
244
|
if (currentVersion < 25) {
|
|
1290
245
|
// v25: runtime_kv non-correctness-critical key-value storage. See
|
|
1291
246
|
// createRuntimeKvTableV25 for the full schema + invariants.
|
|
1292
247
|
createRuntimeKvTableV25(db);
|
|
1293
|
-
db
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
248
|
+
recordSchemaVersion(db, 25);
|
|
249
|
+
}
|
|
250
|
+
if (currentVersion < 26) {
|
|
251
|
+
applyMigrationV26MilestoneCommitAttributions(db);
|
|
252
|
+
recordSchemaVersion(db, 26);
|
|
253
|
+
}
|
|
254
|
+
if (currentVersion < 27) {
|
|
255
|
+
applyMigrationV27ArtifactHash(db);
|
|
256
|
+
recordSchemaVersion(db, 27);
|
|
257
|
+
}
|
|
258
|
+
if (currentVersion < 28) {
|
|
259
|
+
applyMigrationV28MemoryLastHitAt(db);
|
|
260
|
+
recordSchemaVersion(db, 28);
|
|
1297
261
|
}
|
|
1298
262
|
db.exec("COMMIT");
|
|
1299
263
|
}
|
|
@@ -1306,9 +270,7 @@ let currentDb = null;
|
|
|
1306
270
|
let currentPath = null;
|
|
1307
271
|
let currentPid = 0;
|
|
1308
272
|
let _exitHandlerRegistered = false;
|
|
1309
|
-
|
|
1310
|
-
let _lastDbError = null;
|
|
1311
|
-
let _lastDbPhase = null;
|
|
273
|
+
const _dbOpenState = createDbOpenState();
|
|
1312
274
|
/**
|
|
1313
275
|
* Identity key of the workspace whose connection is currently active
|
|
1314
276
|
* (currentDb). Set by openDatabaseByWorkspace(); null when the active
|
|
@@ -1328,10 +290,33 @@ let _currentIdentityKey = null;
|
|
|
1328
290
|
* The cache allows fast re-activation of a previously opened connection when
|
|
1329
291
|
* callers switch between known workspaces via openDatabaseByWorkspace().
|
|
1330
292
|
*/
|
|
1331
|
-
const _dbCache =
|
|
293
|
+
const _dbCache = createDbConnectionCache();
|
|
1332
294
|
/** Test helper: expose the internal cache for inspection. Not for production use. */
|
|
1333
295
|
export function _getDbCache() {
|
|
1334
|
-
return _dbCache;
|
|
296
|
+
return _dbCache.asReadonlyMap();
|
|
297
|
+
}
|
|
298
|
+
function closeCachedConnection(entry, source) {
|
|
299
|
+
try {
|
|
300
|
+
entry.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
if (source === "workspace")
|
|
304
|
+
logWarning("db", `WAL checkpoint (byWorkspace) failed: ${e.message}`);
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
entry.db.exec("PRAGMA incremental_vacuum(64)");
|
|
308
|
+
}
|
|
309
|
+
catch (e) {
|
|
310
|
+
if (source === "workspace")
|
|
311
|
+
logWarning("db", `incremental vacuum (byWorkspace) failed: ${e.message}`);
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
entry.db.close();
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
if (source === "workspace")
|
|
318
|
+
logWarning("db", `database close (byWorkspace) failed: ${e.message}`);
|
|
319
|
+
}
|
|
1335
320
|
}
|
|
1336
321
|
/**
|
|
1337
322
|
* Close and evict every entry in the workspace connection cache, then call
|
|
@@ -1343,23 +328,7 @@ export function _getDbCache() {
|
|
|
1343
328
|
*/
|
|
1344
329
|
export function closeAllDatabases() {
|
|
1345
330
|
// Close all non-active cached connections first.
|
|
1346
|
-
|
|
1347
|
-
if (entry.db === currentDb)
|
|
1348
|
-
continue; // handled by closeDatabase() below
|
|
1349
|
-
_dbCache.delete(key);
|
|
1350
|
-
try {
|
|
1351
|
-
entry.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
1352
|
-
}
|
|
1353
|
-
catch { /* best-effort */ }
|
|
1354
|
-
try {
|
|
1355
|
-
entry.db.exec("PRAGMA incremental_vacuum(64)");
|
|
1356
|
-
}
|
|
1357
|
-
catch { /* best-effort */ }
|
|
1358
|
-
try {
|
|
1359
|
-
entry.db.close();
|
|
1360
|
-
}
|
|
1361
|
-
catch { /* best-effort */ }
|
|
1362
|
-
}
|
|
331
|
+
_dbCache.closeNonActive(currentDb, (entry) => closeCachedConnection(entry, "all"));
|
|
1363
332
|
closeDatabase();
|
|
1364
333
|
}
|
|
1365
334
|
/**
|
|
@@ -1387,7 +356,7 @@ export function openDatabaseByWorkspace(workspace) {
|
|
|
1387
356
|
currentDb = cached.db;
|
|
1388
357
|
currentPath = cached.dbPath;
|
|
1389
358
|
currentPid = process.pid;
|
|
1390
|
-
|
|
359
|
+
_dbOpenState.markAttempted();
|
|
1391
360
|
_currentIdentityKey = key;
|
|
1392
361
|
return true;
|
|
1393
362
|
}
|
|
@@ -1476,29 +445,12 @@ export function closeDatabaseByWorkspace(workspace) {
|
|
|
1476
445
|
}
|
|
1477
446
|
else {
|
|
1478
447
|
// Connection was displaced by a later open; close the adapter directly.
|
|
1479
|
-
|
|
1480
|
-
cached.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
1481
|
-
}
|
|
1482
|
-
catch (e) {
|
|
1483
|
-
logWarning("db", `WAL checkpoint (byWorkspace) failed: ${e.message}`);
|
|
1484
|
-
}
|
|
1485
|
-
try {
|
|
1486
|
-
cached.db.exec("PRAGMA incremental_vacuum(64)");
|
|
1487
|
-
}
|
|
1488
|
-
catch (e) {
|
|
1489
|
-
logWarning("db", `incremental vacuum (byWorkspace) failed: ${e.message}`);
|
|
1490
|
-
}
|
|
1491
|
-
try {
|
|
1492
|
-
cached.db.close();
|
|
1493
|
-
}
|
|
1494
|
-
catch (e) {
|
|
1495
|
-
logWarning("db", `database close (byWorkspace) failed: ${e.message}`);
|
|
1496
|
-
}
|
|
448
|
+
closeCachedConnection(cached, "workspace");
|
|
1497
449
|
}
|
|
1498
450
|
}
|
|
1499
451
|
export function getDbProvider() {
|
|
1500
|
-
|
|
1501
|
-
return
|
|
452
|
+
providerLoader.load();
|
|
453
|
+
return providerLoader.getProviderName();
|
|
1502
454
|
}
|
|
1503
455
|
export function isDbAvailable() {
|
|
1504
456
|
return currentDb !== null;
|
|
@@ -1510,59 +462,46 @@ export function isDbAvailable() {
|
|
|
1510
462
|
* trigger a false degraded-mode warning.
|
|
1511
463
|
*/
|
|
1512
464
|
export function wasDbOpenAttempted() {
|
|
1513
|
-
return
|
|
465
|
+
return _dbOpenState.snapshot().attempted;
|
|
1514
466
|
}
|
|
1515
467
|
export function getDbStatus() {
|
|
1516
|
-
|
|
468
|
+
providerLoader.load();
|
|
469
|
+
const openState = _dbOpenState.snapshot();
|
|
1517
470
|
return {
|
|
1518
471
|
available: currentDb !== null,
|
|
1519
|
-
provider:
|
|
1520
|
-
attempted:
|
|
1521
|
-
lastError:
|
|
1522
|
-
lastPhase:
|
|
472
|
+
provider: providerLoader.getProviderName(),
|
|
473
|
+
attempted: openState.attempted,
|
|
474
|
+
lastError: openState.lastError,
|
|
475
|
+
lastPhase: openState.lastPhase,
|
|
1523
476
|
};
|
|
1524
477
|
}
|
|
1525
478
|
export function openDatabase(path) {
|
|
1526
|
-
|
|
479
|
+
_dbOpenState.markAttempted();
|
|
1527
480
|
if (currentDb && currentPath !== path)
|
|
1528
481
|
closeDatabase();
|
|
1529
482
|
if (currentDb && currentPath === path)
|
|
1530
483
|
return true;
|
|
1531
484
|
// Reset error state only when a new open attempt is actually going to run.
|
|
1532
|
-
|
|
1533
|
-
_lastDbPhase = null;
|
|
485
|
+
_dbOpenState.clearError();
|
|
1534
486
|
let rawDb;
|
|
1535
|
-
let
|
|
1536
|
-
let fallbackModule = null;
|
|
487
|
+
let fallbackOpen = null;
|
|
1537
488
|
try {
|
|
1538
|
-
rawDb =
|
|
489
|
+
rawDb = providerLoader.openRaw(path);
|
|
1539
490
|
}
|
|
1540
491
|
catch (primaryErr) {
|
|
1541
|
-
|
|
1542
|
-
_lastDbError = primaryErr instanceof Error ? primaryErr : new Error(String(primaryErr));
|
|
492
|
+
_dbOpenState.recordError("open", primaryErr);
|
|
1543
493
|
// node:sqlite loaded but failed to open this file — try better-sqlite3 as fallback.
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
if (typeof Db === "function") {
|
|
1549
|
-
rawDb = new Db(path);
|
|
1550
|
-
fallbackProvider = "better-sqlite3";
|
|
1551
|
-
fallbackModule = Db;
|
|
1552
|
-
_lastDbError = null;
|
|
1553
|
-
_lastDbPhase = null;
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
catch {
|
|
1557
|
-
// fallback unavailable; surface original error
|
|
1558
|
-
}
|
|
494
|
+
fallbackOpen = providerLoader.tryOpenBetterSqliteFallback(path);
|
|
495
|
+
if (fallbackOpen) {
|
|
496
|
+
rawDb = fallbackOpen.rawDb;
|
|
497
|
+
_dbOpenState.clearError();
|
|
1559
498
|
}
|
|
1560
499
|
if (!rawDb)
|
|
1561
500
|
throw primaryErr;
|
|
1562
501
|
}
|
|
1563
502
|
if (!rawDb)
|
|
1564
503
|
return false;
|
|
1565
|
-
const adapter =
|
|
504
|
+
const adapter = createDbAdapter(rawDb);
|
|
1566
505
|
const fileBacked = path !== ":memory:";
|
|
1567
506
|
try {
|
|
1568
507
|
initSchema(adapter, fileBacked);
|
|
@@ -1577,8 +516,7 @@ export function openDatabase(path) {
|
|
|
1577
516
|
process.stderr.write("gsd-db: recovered corrupt database via VACUUM\n");
|
|
1578
517
|
}
|
|
1579
518
|
catch (retryErr) {
|
|
1580
|
-
|
|
1581
|
-
_lastDbError = retryErr instanceof Error ? retryErr : new Error(String(retryErr));
|
|
519
|
+
_dbOpenState.recordError("vacuum-recovery", retryErr);
|
|
1582
520
|
try {
|
|
1583
521
|
adapter.close();
|
|
1584
522
|
}
|
|
@@ -1589,8 +527,7 @@ export function openDatabase(path) {
|
|
|
1589
527
|
}
|
|
1590
528
|
}
|
|
1591
529
|
else {
|
|
1592
|
-
|
|
1593
|
-
_lastDbError = err instanceof Error ? err : new Error(String(err));
|
|
530
|
+
_dbOpenState.recordError("initSchema", err);
|
|
1594
531
|
try {
|
|
1595
532
|
adapter.close();
|
|
1596
533
|
}
|
|
@@ -1601,10 +538,8 @@ export function openDatabase(path) {
|
|
|
1601
538
|
}
|
|
1602
539
|
}
|
|
1603
540
|
// Commit fallback provider switch only after open + schema both succeeded.
|
|
1604
|
-
if (
|
|
1605
|
-
|
|
1606
|
-
providerModule = fallbackModule;
|
|
1607
|
-
}
|
|
541
|
+
if (fallbackOpen)
|
|
542
|
+
providerLoader.commitFallback(fallbackOpen);
|
|
1608
543
|
currentDb = adapter;
|
|
1609
544
|
currentPath = path;
|
|
1610
545
|
currentPid = process.pid;
|
|
@@ -1653,9 +588,7 @@ export function closeDatabase() {
|
|
|
1653
588
|
}
|
|
1654
589
|
// Reset session-scoped state unconditionally so stale error info from a
|
|
1655
590
|
// failed open doesn't persist into the next open attempt or status check.
|
|
1656
|
-
|
|
1657
|
-
_lastDbError = null;
|
|
1658
|
-
_lastDbPhase = null;
|
|
591
|
+
_dbOpenState.reset();
|
|
1659
592
|
}
|
|
1660
593
|
/**
|
|
1661
594
|
* Re-open the active database connection from disk.
|
|
@@ -1708,7 +641,15 @@ export function checkpointDatabase() {
|
|
|
1708
641
|
logWarning("db", `WAL checkpoint failed: ${e.message}`);
|
|
1709
642
|
}
|
|
1710
643
|
}
|
|
1711
|
-
|
|
644
|
+
const _transactionRunner = createDbTransactionRunner();
|
|
645
|
+
function createTransactionControls(db) {
|
|
646
|
+
return {
|
|
647
|
+
begin: () => db.exec("BEGIN"),
|
|
648
|
+
beginRead: () => db.exec("BEGIN DEFERRED"),
|
|
649
|
+
commit: () => db.exec("COMMIT"),
|
|
650
|
+
rollback: () => db.exec("ROLLBACK"),
|
|
651
|
+
};
|
|
652
|
+
}
|
|
1712
653
|
/**
|
|
1713
654
|
* Whether the current call is running inside an active SQLite transaction.
|
|
1714
655
|
* Statement-time recovery paths (e.g. VACUUM retry on a malformed memory
|
|
@@ -1716,36 +657,12 @@ let _txDepth = 0;
|
|
|
1716
657
|
* and would mask the original error with a secondary "cannot VACUUM" throw.
|
|
1717
658
|
*/
|
|
1718
659
|
export function isInTransaction() {
|
|
1719
|
-
return
|
|
660
|
+
return _transactionRunner.isInTransaction();
|
|
1720
661
|
}
|
|
1721
662
|
export function transaction(fn) {
|
|
1722
663
|
if (!currentDb)
|
|
1723
664
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1724
|
-
|
|
1725
|
-
// starting a new one. SQLite does not support nested BEGIN/COMMIT.
|
|
1726
|
-
if (_txDepth > 0) {
|
|
1727
|
-
_txDepth++;
|
|
1728
|
-
try {
|
|
1729
|
-
return fn();
|
|
1730
|
-
}
|
|
1731
|
-
finally {
|
|
1732
|
-
_txDepth--;
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
currentDb.exec("BEGIN");
|
|
1736
|
-
_txDepth++;
|
|
1737
|
-
try {
|
|
1738
|
-
const result = fn();
|
|
1739
|
-
currentDb.exec("COMMIT");
|
|
1740
|
-
return result;
|
|
1741
|
-
}
|
|
1742
|
-
catch (err) {
|
|
1743
|
-
currentDb.exec("ROLLBACK");
|
|
1744
|
-
throw err;
|
|
1745
|
-
}
|
|
1746
|
-
finally {
|
|
1747
|
-
_txDepth--;
|
|
1748
|
-
}
|
|
665
|
+
return _transactionRunner.transaction(createTransactionControls(currentDb), fn);
|
|
1749
666
|
}
|
|
1750
667
|
/**
|
|
1751
668
|
* Wrap a block of reads in a DEFERRED transaction so that all SELECTs observe
|
|
@@ -1757,39 +674,14 @@ export function transaction(fn) {
|
|
|
1757
674
|
export function readTransaction(fn) {
|
|
1758
675
|
if (!currentDb)
|
|
1759
676
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
}
|
|
1769
|
-
currentDb.exec("BEGIN DEFERRED");
|
|
1770
|
-
_txDepth++;
|
|
1771
|
-
try {
|
|
1772
|
-
const result = fn();
|
|
1773
|
-
currentDb.exec("COMMIT");
|
|
1774
|
-
return result;
|
|
1775
|
-
}
|
|
1776
|
-
catch (err) {
|
|
1777
|
-
try {
|
|
1778
|
-
currentDb.exec("ROLLBACK");
|
|
1779
|
-
}
|
|
1780
|
-
catch (rollbackErr) {
|
|
1781
|
-
// A failed ROLLBACK after a failed read is a split-brain signal —
|
|
1782
|
-
// the transaction is in an indeterminate state. Surface it via the
|
|
1783
|
-
// logger instead of swallowing it.
|
|
1784
|
-
logError("db", "snapshotState ROLLBACK failed", {
|
|
1785
|
-
error: rollbackErr.message,
|
|
1786
|
-
});
|
|
1787
|
-
}
|
|
1788
|
-
throw err;
|
|
1789
|
-
}
|
|
1790
|
-
finally {
|
|
1791
|
-
_txDepth--;
|
|
1792
|
-
}
|
|
677
|
+
return _transactionRunner.readTransaction(createTransactionControls(currentDb), fn, (rollbackErr) => {
|
|
678
|
+
// A failed ROLLBACK after a failed read is a split-brain signal —
|
|
679
|
+
// the transaction is in an indeterminate state. Surface it via the
|
|
680
|
+
// logger instead of swallowing it.
|
|
681
|
+
logError("db", "snapshotState ROLLBACK failed", {
|
|
682
|
+
error: rollbackErr.message,
|
|
683
|
+
});
|
|
684
|
+
});
|
|
1793
685
|
}
|
|
1794
686
|
export function insertDecision(d) {
|
|
1795
687
|
if (!currentDb)
|
|
@@ -1814,37 +706,13 @@ export function getDecisionById(id) {
|
|
|
1814
706
|
const row = currentDb.prepare("SELECT * FROM decisions WHERE id = ?").get(id);
|
|
1815
707
|
if (!row)
|
|
1816
708
|
return null;
|
|
1817
|
-
return
|
|
1818
|
-
seq: row["seq"],
|
|
1819
|
-
id: row["id"],
|
|
1820
|
-
when_context: row["when_context"],
|
|
1821
|
-
scope: row["scope"],
|
|
1822
|
-
decision: row["decision"],
|
|
1823
|
-
choice: row["choice"],
|
|
1824
|
-
rationale: row["rationale"],
|
|
1825
|
-
revisable: row["revisable"],
|
|
1826
|
-
made_by: row["made_by"] ?? "agent",
|
|
1827
|
-
source: row["source"] ?? "discussion",
|
|
1828
|
-
superseded_by: row["superseded_by"] ?? null,
|
|
1829
|
-
};
|
|
709
|
+
return rowToDecision(row);
|
|
1830
710
|
}
|
|
1831
711
|
export function getActiveDecisions() {
|
|
1832
712
|
if (!currentDb)
|
|
1833
713
|
return [];
|
|
1834
714
|
const rows = currentDb.prepare("SELECT * FROM active_decisions").all();
|
|
1835
|
-
return rows.map(
|
|
1836
|
-
seq: row["seq"],
|
|
1837
|
-
id: row["id"],
|
|
1838
|
-
when_context: row["when_context"],
|
|
1839
|
-
scope: row["scope"],
|
|
1840
|
-
decision: row["decision"],
|
|
1841
|
-
choice: row["choice"],
|
|
1842
|
-
rationale: row["rationale"],
|
|
1843
|
-
revisable: row["revisable"],
|
|
1844
|
-
made_by: row["made_by"] ?? "agent",
|
|
1845
|
-
source: row["source"] ?? "discussion",
|
|
1846
|
-
superseded_by: null,
|
|
1847
|
-
}));
|
|
715
|
+
return rows.map(rowToActiveDecision);
|
|
1848
716
|
}
|
|
1849
717
|
export function insertRequirement(r) {
|
|
1850
718
|
if (!currentDb)
|
|
@@ -1871,39 +739,13 @@ export function getRequirementById(id) {
|
|
|
1871
739
|
const row = currentDb.prepare("SELECT * FROM requirements WHERE id = ?").get(id);
|
|
1872
740
|
if (!row)
|
|
1873
741
|
return null;
|
|
1874
|
-
return
|
|
1875
|
-
id: row["id"],
|
|
1876
|
-
class: row["class"],
|
|
1877
|
-
status: row["status"],
|
|
1878
|
-
description: row["description"],
|
|
1879
|
-
why: row["why"],
|
|
1880
|
-
source: row["source"],
|
|
1881
|
-
primary_owner: row["primary_owner"],
|
|
1882
|
-
supporting_slices: row["supporting_slices"],
|
|
1883
|
-
validation: row["validation"],
|
|
1884
|
-
notes: row["notes"],
|
|
1885
|
-
full_content: row["full_content"],
|
|
1886
|
-
superseded_by: row["superseded_by"] ?? null,
|
|
1887
|
-
};
|
|
742
|
+
return rowToRequirement(row);
|
|
1888
743
|
}
|
|
1889
744
|
export function getActiveRequirements() {
|
|
1890
745
|
if (!currentDb)
|
|
1891
746
|
return [];
|
|
1892
747
|
const rows = currentDb.prepare("SELECT * FROM active_requirements").all();
|
|
1893
|
-
return rows.map(
|
|
1894
|
-
id: row["id"],
|
|
1895
|
-
class: row["class"],
|
|
1896
|
-
status: row["status"],
|
|
1897
|
-
description: row["description"],
|
|
1898
|
-
why: row["why"],
|
|
1899
|
-
source: row["source"],
|
|
1900
|
-
primary_owner: row["primary_owner"],
|
|
1901
|
-
supporting_slices: row["supporting_slices"],
|
|
1902
|
-
validation: row["validation"],
|
|
1903
|
-
notes: row["notes"],
|
|
1904
|
-
full_content: row["full_content"],
|
|
1905
|
-
superseded_by: null,
|
|
1906
|
-
}));
|
|
748
|
+
return rows.map(rowToActiveRequirement);
|
|
1907
749
|
}
|
|
1908
750
|
export function getRequirementCounts() {
|
|
1909
751
|
if (!currentDb) {
|
|
@@ -1912,23 +754,7 @@ export function getRequirementCounts() {
|
|
|
1912
754
|
const rows = currentDb
|
|
1913
755
|
.prepare("SELECT lower(status) as status, COUNT(*) as count FROM requirements GROUP BY lower(status)")
|
|
1914
756
|
.all();
|
|
1915
|
-
|
|
1916
|
-
for (const row of rows) {
|
|
1917
|
-
const status = String(row["status"] ?? "");
|
|
1918
|
-
const count = Number(row["count"] ?? 0);
|
|
1919
|
-
counts.total += count;
|
|
1920
|
-
if (status === "active")
|
|
1921
|
-
counts.active += count;
|
|
1922
|
-
else if (status === "validated")
|
|
1923
|
-
counts.validated += count;
|
|
1924
|
-
else if (status === "deferred")
|
|
1925
|
-
counts.deferred += count;
|
|
1926
|
-
else if (status === "out-of-scope" || status === "out_of_scope")
|
|
1927
|
-
counts.outOfScope += count;
|
|
1928
|
-
else if (status === "blocked")
|
|
1929
|
-
counts.blocked += count;
|
|
1930
|
-
}
|
|
1931
|
-
return counts;
|
|
757
|
+
return rowsToRequirementCounts(rows);
|
|
1932
758
|
}
|
|
1933
759
|
export function getDbOwnerPid() {
|
|
1934
760
|
return currentPid;
|
|
@@ -1940,9 +766,7 @@ export function _getAdapter() {
|
|
|
1940
766
|
return currentDb;
|
|
1941
767
|
}
|
|
1942
768
|
export function _resetProvider() {
|
|
1943
|
-
|
|
1944
|
-
providerModule = null;
|
|
1945
|
-
providerName = null;
|
|
769
|
+
providerLoader.reset();
|
|
1946
770
|
}
|
|
1947
771
|
export function upsertDecision(d) {
|
|
1948
772
|
if (!currentDb)
|
|
@@ -2006,8 +830,9 @@ export function clearArtifacts() {
|
|
|
2006
830
|
export function insertArtifact(a) {
|
|
2007
831
|
if (!currentDb)
|
|
2008
832
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
2009
|
-
|
|
2010
|
-
|
|
833
|
+
const contentHash = createHash("sha256").update(a.full_content).digest("hex");
|
|
834
|
+
currentDb.prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash)
|
|
835
|
+
VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at, :content_hash)`).run({
|
|
2011
836
|
":path": a.path,
|
|
2012
837
|
":artifact_type": a.artifact_type,
|
|
2013
838
|
":milestone_id": a.milestone_id,
|
|
@@ -2015,6 +840,7 @@ export function insertArtifact(a) {
|
|
|
2015
840
|
":task_id": a.task_id,
|
|
2016
841
|
":full_content": a.full_content,
|
|
2017
842
|
":imported_at": new Date().toISOString(),
|
|
843
|
+
":content_hash": contentHash,
|
|
2018
844
|
});
|
|
2019
845
|
}
|
|
2020
846
|
export function insertMilestone(m) {
|
|
@@ -2304,30 +1130,6 @@ export function upsertTaskPlanning(milestoneId, sliceId, taskId, planning) {
|
|
|
2304
1130
|
":full_plan_md": planning.fullPlanMd ?? null,
|
|
2305
1131
|
});
|
|
2306
1132
|
}
|
|
2307
|
-
function rowToSlice(row) {
|
|
2308
|
-
return {
|
|
2309
|
-
milestone_id: row["milestone_id"],
|
|
2310
|
-
id: row["id"],
|
|
2311
|
-
title: row["title"],
|
|
2312
|
-
status: row["status"],
|
|
2313
|
-
risk: row["risk"],
|
|
2314
|
-
depends: JSON.parse(row["depends"] || "[]"),
|
|
2315
|
-
demo: row["demo"] ?? "",
|
|
2316
|
-
created_at: row["created_at"],
|
|
2317
|
-
completed_at: row["completed_at"] ?? null,
|
|
2318
|
-
full_summary_md: row["full_summary_md"] ?? "",
|
|
2319
|
-
full_uat_md: row["full_uat_md"] ?? "",
|
|
2320
|
-
goal: row["goal"] ?? "",
|
|
2321
|
-
success_criteria: row["success_criteria"] ?? "",
|
|
2322
|
-
proof_level: row["proof_level"] ?? "",
|
|
2323
|
-
integration_closure: row["integration_closure"] ?? "",
|
|
2324
|
-
observability_impact: row["observability_impact"] ?? "",
|
|
2325
|
-
sequence: row["sequence"] ?? 0,
|
|
2326
|
-
replan_triggered_at: row["replan_triggered_at"] ?? null,
|
|
2327
|
-
is_sketch: row["is_sketch"] ?? 0,
|
|
2328
|
-
sketch_scope: row["sketch_scope"] ?? "",
|
|
2329
|
-
};
|
|
2330
|
-
}
|
|
2331
1133
|
export function getSlice(milestoneId, sliceId) {
|
|
2332
1134
|
if (!currentDb)
|
|
2333
1135
|
return null;
|
|
@@ -2357,82 +1159,6 @@ export function setSliceSummaryMd(milestoneId, sliceId, summaryMd, uatMd) {
|
|
|
2357
1159
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
2358
1160
|
currentDb.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
|
|
2359
1161
|
}
|
|
2360
|
-
function parseTaskArrayColumn(raw) {
|
|
2361
|
-
if (typeof raw !== "string" || raw.trim() === "")
|
|
2362
|
-
return [];
|
|
2363
|
-
try {
|
|
2364
|
-
const parsed = JSON.parse(raw);
|
|
2365
|
-
if (Array.isArray(parsed))
|
|
2366
|
-
return parsed.map((value) => String(value));
|
|
2367
|
-
if (parsed === null || parsed === undefined || parsed === "")
|
|
2368
|
-
return [];
|
|
2369
|
-
return [String(parsed)];
|
|
2370
|
-
}
|
|
2371
|
-
catch {
|
|
2372
|
-
// Older/corrupt rows may contain comma-separated strings instead of JSON.
|
|
2373
|
-
return raw
|
|
2374
|
-
.split(",")
|
|
2375
|
-
.map((value) => value.trim())
|
|
2376
|
-
.filter(Boolean);
|
|
2377
|
-
}
|
|
2378
|
-
}
|
|
2379
|
-
function rowToTask(row) {
|
|
2380
|
-
const parseTaskArray = (value) => {
|
|
2381
|
-
if (Array.isArray(value)) {
|
|
2382
|
-
return value.filter((entry) => typeof entry === "string");
|
|
2383
|
-
}
|
|
2384
|
-
if (typeof value !== "string")
|
|
2385
|
-
return [];
|
|
2386
|
-
const trimmed = value.trim();
|
|
2387
|
-
if (!trimmed)
|
|
2388
|
-
return [];
|
|
2389
|
-
try {
|
|
2390
|
-
const parsed = JSON.parse(trimmed);
|
|
2391
|
-
if (Array.isArray(parsed)) {
|
|
2392
|
-
return parsed.filter((entry) => typeof entry === "string");
|
|
2393
|
-
}
|
|
2394
|
-
if (typeof parsed === "string" && parsed.trim()) {
|
|
2395
|
-
return [parsed.trim()];
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
catch {
|
|
2399
|
-
// Older/corrupt DB rows may contain raw comma-separated paths instead of JSON arrays.
|
|
2400
|
-
}
|
|
2401
|
-
return trimmed.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
2402
|
-
};
|
|
2403
|
-
return {
|
|
2404
|
-
milestone_id: row["milestone_id"],
|
|
2405
|
-
slice_id: row["slice_id"],
|
|
2406
|
-
id: row["id"],
|
|
2407
|
-
title: row["title"],
|
|
2408
|
-
status: row["status"],
|
|
2409
|
-
one_liner: row["one_liner"],
|
|
2410
|
-
narrative: row["narrative"],
|
|
2411
|
-
verification_result: row["verification_result"],
|
|
2412
|
-
duration: row["duration"],
|
|
2413
|
-
completed_at: row["completed_at"] ?? null,
|
|
2414
|
-
blocker_discovered: row["blocker_discovered"] === 1,
|
|
2415
|
-
deviations: row["deviations"],
|
|
2416
|
-
known_issues: row["known_issues"],
|
|
2417
|
-
key_files: parseTaskArrayColumn(row["key_files"]),
|
|
2418
|
-
key_decisions: parseTaskArrayColumn(row["key_decisions"]),
|
|
2419
|
-
full_summary_md: row["full_summary_md"],
|
|
2420
|
-
description: row["description"] ?? "",
|
|
2421
|
-
estimate: row["estimate"] ?? "",
|
|
2422
|
-
files: parseTaskArray(row["files"]),
|
|
2423
|
-
verify: row["verify"] ?? "",
|
|
2424
|
-
inputs: parseTaskArray(row["inputs"]),
|
|
2425
|
-
expected_output: parseTaskArray(row["expected_output"]),
|
|
2426
|
-
observability_impact: row["observability_impact"] ?? "",
|
|
2427
|
-
full_plan_md: row["full_plan_md"] ?? "",
|
|
2428
|
-
sequence: row["sequence"] ?? 0,
|
|
2429
|
-
blocker_source: row["blocker_source"] ?? "",
|
|
2430
|
-
escalation_pending: row["escalation_pending"] ?? 0,
|
|
2431
|
-
escalation_awaiting_review: row["escalation_awaiting_review"] ?? 0,
|
|
2432
|
-
escalation_artifact_path: row["escalation_artifact_path"] ?? null,
|
|
2433
|
-
escalation_override_applied_at: row["escalation_override_applied_at"] ?? null,
|
|
2434
|
-
};
|
|
2435
|
-
}
|
|
2436
1162
|
export function getTask(milestoneId, sliceId, taskId) {
|
|
2437
1163
|
if (!currentDb)
|
|
2438
1164
|
return null;
|
|
@@ -2447,6 +1173,47 @@ export function getSliceTasks(milestoneId, sliceId) {
|
|
|
2447
1173
|
const rows = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid ORDER BY sequence, id").all({ ":mid": milestoneId, ":sid": sliceId });
|
|
2448
1174
|
return rows.map(rowToTask);
|
|
2449
1175
|
}
|
|
1176
|
+
export function getCompletedMilestoneTaskFileHints(milestoneId) {
|
|
1177
|
+
if (!currentDb)
|
|
1178
|
+
return [];
|
|
1179
|
+
const rows = currentDb.prepare(`SELECT files, key_files
|
|
1180
|
+
FROM tasks
|
|
1181
|
+
WHERE milestone_id = :mid AND status IN ('complete', 'done')`).all({ ":mid": milestoneId });
|
|
1182
|
+
const hints = new Set();
|
|
1183
|
+
for (const row of rows) {
|
|
1184
|
+
for (const raw of [row["files"], row["key_files"]]) {
|
|
1185
|
+
for (const file of parseStringArrayColumn(raw)) {
|
|
1186
|
+
const normalized = normalizeRepoPath(file);
|
|
1187
|
+
if (normalized)
|
|
1188
|
+
hints.add(normalized);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
return [...hints];
|
|
1193
|
+
}
|
|
1194
|
+
function parseStringArrayColumn(raw) {
|
|
1195
|
+
if (Array.isArray(raw))
|
|
1196
|
+
return raw.filter((entry) => typeof entry === "string");
|
|
1197
|
+
if (typeof raw !== "string")
|
|
1198
|
+
return [];
|
|
1199
|
+
const trimmed = raw.trim();
|
|
1200
|
+
if (!trimmed)
|
|
1201
|
+
return [];
|
|
1202
|
+
try {
|
|
1203
|
+
const parsed = JSON.parse(trimmed);
|
|
1204
|
+
if (Array.isArray(parsed))
|
|
1205
|
+
return parsed.filter((entry) => typeof entry === "string");
|
|
1206
|
+
if (typeof parsed === "string")
|
|
1207
|
+
return [parsed];
|
|
1208
|
+
}
|
|
1209
|
+
catch {
|
|
1210
|
+
return trimmed.split(",");
|
|
1211
|
+
}
|
|
1212
|
+
return [];
|
|
1213
|
+
}
|
|
1214
|
+
function normalizeRepoPath(file) {
|
|
1215
|
+
return file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
1216
|
+
}
|
|
2450
1217
|
// ─── ADR-011 Phase 2 escalation helpers ──────────────────────────────────
|
|
2451
1218
|
/** Set pause-on-escalation state on a completed task. Mutually exclusive with awaiting_review. */
|
|
2452
1219
|
export function setTaskEscalationPending(milestoneId, sliceId, taskId, artifactPath) {
|
|
@@ -2557,39 +1324,6 @@ export function getVerificationEvidence(milestoneId, sliceId, taskId) {
|
|
|
2557
1324
|
const rows = currentDb.prepare("SELECT * FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid ORDER BY id").all({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
|
|
2558
1325
|
return rows;
|
|
2559
1326
|
}
|
|
2560
|
-
function rowToMilestone(row) {
|
|
2561
|
-
return {
|
|
2562
|
-
id: row["id"],
|
|
2563
|
-
title: row["title"],
|
|
2564
|
-
status: row["status"],
|
|
2565
|
-
depends_on: JSON.parse(row["depends_on"] || "[]"),
|
|
2566
|
-
created_at: row["created_at"],
|
|
2567
|
-
completed_at: row["completed_at"] ?? null,
|
|
2568
|
-
vision: row["vision"] ?? "",
|
|
2569
|
-
success_criteria: JSON.parse(row["success_criteria"] || "[]"),
|
|
2570
|
-
key_risks: JSON.parse(row["key_risks"] || "[]"),
|
|
2571
|
-
proof_strategy: JSON.parse(row["proof_strategy"] || "[]"),
|
|
2572
|
-
verification_contract: row["verification_contract"] ?? "",
|
|
2573
|
-
verification_integration: row["verification_integration"] ?? "",
|
|
2574
|
-
verification_operational: row["verification_operational"] ?? "",
|
|
2575
|
-
verification_uat: row["verification_uat"] ?? "",
|
|
2576
|
-
definition_of_done: JSON.parse(row["definition_of_done"] || "[]"),
|
|
2577
|
-
requirement_coverage: row["requirement_coverage"] ?? "",
|
|
2578
|
-
boundary_map_markdown: row["boundary_map_markdown"] ?? "",
|
|
2579
|
-
sequence: Number(row["sequence"] ?? 0),
|
|
2580
|
-
};
|
|
2581
|
-
}
|
|
2582
|
-
function rowToArtifact(row) {
|
|
2583
|
-
return {
|
|
2584
|
-
path: row["path"],
|
|
2585
|
-
artifact_type: row["artifact_type"],
|
|
2586
|
-
milestone_id: row["milestone_id"] ?? null,
|
|
2587
|
-
slice_id: row["slice_id"] ?? null,
|
|
2588
|
-
task_id: row["task_id"] ?? null,
|
|
2589
|
-
full_content: row["full_content"],
|
|
2590
|
-
imported_at: row["imported_at"],
|
|
2591
|
-
};
|
|
2592
|
-
}
|
|
2593
1327
|
export function getAllMilestones() {
|
|
2594
1328
|
if (!currentDb)
|
|
2595
1329
|
return [];
|
|
@@ -2689,13 +1423,13 @@ export function getActiveMilestoneIdFromDb() {
|
|
|
2689
1423
|
const row = currentDb.prepare("SELECT id, status FROM milestones WHERE status NOT IN ('complete', 'parked') ORDER BY id LIMIT 1").get();
|
|
2690
1424
|
if (!row)
|
|
2691
1425
|
return null;
|
|
2692
|
-
return
|
|
1426
|
+
return rowToIdStatusSummary(row);
|
|
2693
1427
|
}
|
|
2694
1428
|
/** Fast slice status check — avoids deserializing JSON depends/planning fields. */
|
|
2695
1429
|
export function getSliceStatusSummary(milestoneId) {
|
|
2696
1430
|
if (!currentDb)
|
|
2697
1431
|
return [];
|
|
2698
|
-
return currentDb.prepare("SELECT id, status FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId }).map(
|
|
1432
|
+
return currentDb.prepare("SELECT id, status FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId }).map(rowToIdStatusSummary);
|
|
2699
1433
|
}
|
|
2700
1434
|
/** Fast task status check — avoids deserializing JSON arrays and large text fields. */
|
|
2701
1435
|
export function getActiveTaskIdFromDb(milestoneId, sliceId) {
|
|
@@ -2704,20 +1438,18 @@ export function getActiveTaskIdFromDb(milestoneId, sliceId) {
|
|
|
2704
1438
|
const row = currentDb.prepare("SELECT id, status, title FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND status NOT IN ('complete', 'done') ORDER BY sequence, id LIMIT 1").get({ ":mid": milestoneId, ":sid": sliceId });
|
|
2705
1439
|
if (!row)
|
|
2706
1440
|
return null;
|
|
2707
|
-
return
|
|
1441
|
+
return rowToActiveTaskSummary(row);
|
|
2708
1442
|
}
|
|
2709
1443
|
/** Count tasks by status for a slice — useful for progress reporting without full row load. */
|
|
2710
1444
|
export function getSliceTaskCounts(milestoneId, sliceId) {
|
|
2711
1445
|
if (!currentDb)
|
|
2712
|
-
return
|
|
1446
|
+
return emptyTaskStatusCounts();
|
|
2713
1447
|
const row = currentDb.prepare(`SELECT
|
|
2714
1448
|
COUNT(*) as total,
|
|
2715
1449
|
SUM(CASE WHEN status IN ('complete', 'done') THEN 1 ELSE 0 END) as done,
|
|
2716
1450
|
SUM(CASE WHEN status NOT IN ('complete', 'done') THEN 1 ELSE 0 END) as pending
|
|
2717
1451
|
FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`).get({ ":mid": milestoneId, ":sid": sliceId });
|
|
2718
|
-
|
|
2719
|
-
return { total: 0, done: 0, pending: 0 };
|
|
2720
|
-
return { total: row["total"] ?? 0, done: row["done"] ?? 0, pending: row["pending"] ?? 0 };
|
|
1452
|
+
return rowToTaskStatusCounts(row);
|
|
2721
1453
|
}
|
|
2722
1454
|
// ─── Slice Dependencies (junction table) ─────────────────────────────────
|
|
2723
1455
|
/** Sync the slice_dependencies junction table from a slice's JSON depends array. */
|
|
@@ -2733,7 +1465,8 @@ export function syncSliceDependencies(milestoneId, sliceId, depends) {
|
|
|
2733
1465
|
export function getDependentSlices(milestoneId, sliceId) {
|
|
2734
1466
|
if (!currentDb)
|
|
2735
1467
|
return [];
|
|
2736
|
-
|
|
1468
|
+
const rows = currentDb.prepare("SELECT slice_id FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid").all({ ":mid": milestoneId, ":sid": sliceId });
|
|
1469
|
+
return rowsToStringColumn(rows, "slice_id");
|
|
2737
1470
|
}
|
|
2738
1471
|
// ─── Worktree DB Helpers ──────────────────────────────────────────────────
|
|
2739
1472
|
export function copyWorktreeDb(srcDbPath, destDbPath) {
|
|
@@ -2799,6 +1532,13 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
2799
1532
|
const hasEscalationAwaiting = wtTaskInfo.some((col) => col["name"] === "escalation_awaiting_review");
|
|
2800
1533
|
const hasEscalationArtifact = wtTaskInfo.some((col) => col["name"] === "escalation_artifact_path");
|
|
2801
1534
|
const hasEscalationOverride = wtTaskInfo.some((col) => col["name"] === "escalation_override_applied_at");
|
|
1535
|
+
const wtArtifactInfo = adapter.prepare("PRAGMA wt.table_info('artifacts')").all();
|
|
1536
|
+
const hasArtifactContentHash = wtArtifactInfo.some((col) => col["name"] === "content_hash");
|
|
1537
|
+
const wtMemoryInfo = adapter.prepare("PRAGMA wt.table_info('memories')").all();
|
|
1538
|
+
const hasMemoryScope = wtMemoryInfo.some((col) => col["name"] === "scope");
|
|
1539
|
+
const hasMemoryTags = wtMemoryInfo.some((col) => col["name"] === "tags");
|
|
1540
|
+
const hasMemoryStructuredFields = wtMemoryInfo.some((col) => col["name"] === "structured_fields");
|
|
1541
|
+
const hasMemoryLastHitAt = wtMemoryInfo.some((col) => col["name"] === "last_hit_at");
|
|
2802
1542
|
const decConf = adapter.prepare(`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR ${hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"} OR m.superseded_by IS NOT w.superseded_by`).all();
|
|
2803
1543
|
for (const row of decConf)
|
|
2804
1544
|
conflicts.push(`decision ${row["id"]}: modified in both`);
|
|
@@ -2831,12 +1571,17 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
2831
1571
|
supporting_slices, validation, notes, full_content, superseded_by
|
|
2832
1572
|
FROM wt.requirements
|
|
2833
1573
|
`).run());
|
|
1574
|
+
// V27: preserve content_hash. If the worktree predates V27 (no column),
|
|
1575
|
+
// fall back to the main DB's existing hash so reconcile doesn't null
|
|
1576
|
+
// out integrity fingerprints on artifacts that were unchanged in wt.
|
|
2834
1577
|
merged.artifacts = countChanges(adapter.prepare(`
|
|
2835
1578
|
INSERT OR REPLACE INTO artifacts (
|
|
2836
|
-
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
1579
|
+
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
|
|
2837
1580
|
)
|
|
2838
|
-
SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
2839
|
-
|
|
1581
|
+
SELECT w.path, w.artifact_type, w.milestone_id, w.slice_id, w.task_id, w.full_content, w.imported_at,
|
|
1582
|
+
${hasArtifactContentHash ? "w.content_hash" : "m.content_hash"}
|
|
1583
|
+
FROM wt.artifacts w
|
|
1584
|
+
LEFT JOIN artifacts m ON m.path = w.path
|
|
2840
1585
|
`).run());
|
|
2841
1586
|
// Merge milestones — worktree may have updated status/planning fields.
|
|
2842
1587
|
// Never downgrade status: complete > active > pre-planning (#4372).
|
|
@@ -2934,15 +1679,25 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
2934
1679
|
FROM wt.tasks w
|
|
2935
1680
|
LEFT JOIN tasks m ON m.milestone_id = w.milestone_id AND m.slice_id = w.slice_id AND m.id = w.id
|
|
2936
1681
|
`).run());
|
|
2937
|
-
// Merge memories — keep worktree-learned insights
|
|
1682
|
+
// Merge memories — keep worktree-learned insights.
|
|
1683
|
+
// V18 (scope, tags), V21 (structured_fields), V28 (last_hit_at): for each
|
|
1684
|
+
// column the wt may not yet have (older worktree DB), fall back to the
|
|
1685
|
+
// main DB's existing value via LEFT JOIN so reconcile never silently
|
|
1686
|
+
// resets these fields to defaults on rows that already had them.
|
|
2938
1687
|
merged.memories = countChanges(adapter.prepare(`
|
|
2939
1688
|
INSERT OR REPLACE INTO memories (
|
|
2940
1689
|
seq, id, category, content, confidence, source_unit_type, source_unit_id,
|
|
2941
|
-
created_at, updated_at, superseded_by, hit_count
|
|
1690
|
+
created_at, updated_at, superseded_by, hit_count,
|
|
1691
|
+
scope, tags, structured_fields, last_hit_at
|
|
2942
1692
|
)
|
|
2943
|
-
SELECT seq, id, category, content, confidence, source_unit_type, source_unit_id,
|
|
2944
|
-
created_at, updated_at, superseded_by, hit_count
|
|
2945
|
-
|
|
1693
|
+
SELECT w.seq, w.id, w.category, w.content, w.confidence, w.source_unit_type, w.source_unit_id,
|
|
1694
|
+
w.created_at, w.updated_at, w.superseded_by, w.hit_count,
|
|
1695
|
+
${hasMemoryScope ? "w.scope" : "COALESCE(m.scope, 'project')"},
|
|
1696
|
+
${hasMemoryTags ? "w.tags" : "COALESCE(m.tags, '[]')"},
|
|
1697
|
+
${hasMemoryStructuredFields ? "w.structured_fields" : "m.structured_fields"},
|
|
1698
|
+
${hasMemoryLastHitAt ? "w.last_hit_at" : "m.last_hit_at"}
|
|
1699
|
+
FROM wt.memories w
|
|
1700
|
+
LEFT JOIN memories m ON m.id = w.id
|
|
2946
1701
|
`).run());
|
|
2947
1702
|
// Merge verification evidence — append-only, use INSERT OR IGNORE to avoid duplicates
|
|
2948
1703
|
merged.verification_evidence = countChanges(adapter.prepare(`
|
|
@@ -3058,6 +1813,7 @@ export function deleteMilestone(milestoneId) {
|
|
|
3058
1813
|
currentDb.prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
3059
1814
|
currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
3060
1815
|
currentDb.prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1816
|
+
currentDb.prepare(`DELETE FROM milestone_commit_attributions WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
3061
1817
|
currentDb.prepare(`DELETE FROM milestone_leases WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
3062
1818
|
currentDb.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
|
|
3063
1819
|
});
|
|
@@ -3103,20 +1859,6 @@ export function getLatestAssessmentByScope(milestoneId, scope) {
|
|
|
3103
1859
|
return row ?? null;
|
|
3104
1860
|
}
|
|
3105
1861
|
// ─── Quality Gates ───────────────────────────────────────────────────────
|
|
3106
|
-
function rowToGate(row) {
|
|
3107
|
-
return {
|
|
3108
|
-
milestone_id: row["milestone_id"],
|
|
3109
|
-
slice_id: row["slice_id"],
|
|
3110
|
-
gate_id: row["gate_id"],
|
|
3111
|
-
scope: row["scope"],
|
|
3112
|
-
task_id: row["task_id"] ?? "",
|
|
3113
|
-
status: row["status"],
|
|
3114
|
-
verdict: row["status"] === "pending" ? null : row["verdict"],
|
|
3115
|
-
rationale: row["rationale"] || "",
|
|
3116
|
-
findings: row["findings"] || "",
|
|
3117
|
-
evaluated_at: row["evaluated_at"] ?? null,
|
|
3118
|
-
};
|
|
3119
|
-
}
|
|
3120
1862
|
export function insertGateRow(g) {
|
|
3121
1863
|
if (!currentDb)
|
|
3122
1864
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
@@ -3299,6 +2041,59 @@ export function upsertTurnGitTransaction(entry) {
|
|
|
3299
2041
|
":updated_at": entry.updatedAt,
|
|
3300
2042
|
});
|
|
3301
2043
|
}
|
|
2044
|
+
export function getMilestoneCommitAttributionShas(milestoneId) {
|
|
2045
|
+
if (!currentDb)
|
|
2046
|
+
return [];
|
|
2047
|
+
const rows = currentDb.prepare(`SELECT commit_sha
|
|
2048
|
+
FROM milestone_commit_attributions
|
|
2049
|
+
WHERE milestone_id = :mid
|
|
2050
|
+
ORDER BY created_at, commit_sha`).all({ ":mid": milestoneId });
|
|
2051
|
+
return rows
|
|
2052
|
+
.map((row) => typeof row["commit_sha"] === "string" ? row["commit_sha"] : "")
|
|
2053
|
+
.filter(Boolean);
|
|
2054
|
+
}
|
|
2055
|
+
export function recordMilestoneCommitAttribution(entry) {
|
|
2056
|
+
if (!currentDb)
|
|
2057
|
+
return;
|
|
2058
|
+
transaction(() => {
|
|
2059
|
+
currentDb.prepare(`INSERT OR REPLACE INTO milestone_commit_attributions (
|
|
2060
|
+
commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
|
|
2061
|
+
) VALUES (
|
|
2062
|
+
:commit_sha, :milestone_id, :slice_id, :task_id, :source, :confidence, :files_json, :created_at
|
|
2063
|
+
)`).run({
|
|
2064
|
+
":commit_sha": entry.commitSha,
|
|
2065
|
+
":milestone_id": entry.milestoneId,
|
|
2066
|
+
":slice_id": entry.sliceId ?? null,
|
|
2067
|
+
":task_id": entry.taskId ?? null,
|
|
2068
|
+
":source": entry.source,
|
|
2069
|
+
":confidence": entry.confidence,
|
|
2070
|
+
":files_json": JSON.stringify(entry.files),
|
|
2071
|
+
":created_at": entry.createdAt,
|
|
2072
|
+
});
|
|
2073
|
+
currentDb.prepare(`INSERT OR IGNORE INTO audit_events (
|
|
2074
|
+
event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
|
|
2075
|
+
) VALUES (
|
|
2076
|
+
:event_id, :trace_id, :turn_id, :caused_by, :category, :type, :ts, :payload_json
|
|
2077
|
+
)`).run({
|
|
2078
|
+
":event_id": `milestone-commit-attribution:${entry.milestoneId}:${entry.commitSha}`,
|
|
2079
|
+
":trace_id": "milestone-commit-attribution",
|
|
2080
|
+
":turn_id": null,
|
|
2081
|
+
":caused_by": null,
|
|
2082
|
+
":category": "git",
|
|
2083
|
+
":type": "milestone-commit-attribution-recorded",
|
|
2084
|
+
":ts": entry.createdAt,
|
|
2085
|
+
":payload_json": JSON.stringify({
|
|
2086
|
+
commitSha: entry.commitSha,
|
|
2087
|
+
milestoneId: entry.milestoneId,
|
|
2088
|
+
sliceId: entry.sliceId ?? null,
|
|
2089
|
+
taskId: entry.taskId ?? null,
|
|
2090
|
+
source: entry.source,
|
|
2091
|
+
confidence: entry.confidence,
|
|
2092
|
+
files: entry.files,
|
|
2093
|
+
}),
|
|
2094
|
+
});
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
3302
2097
|
export function insertAuditEvent(entry) {
|
|
3303
2098
|
if (!currentDb)
|
|
3304
2099
|
return;
|
|
@@ -3385,6 +2180,7 @@ export function clearEngineHierarchy() {
|
|
|
3385
2180
|
currentDb.exec("DELETE FROM slice_dependencies");
|
|
3386
2181
|
currentDb.exec("DELETE FROM assessments");
|
|
3387
2182
|
currentDb.exec("DELETE FROM replan_history");
|
|
2183
|
+
currentDb.exec("DELETE FROM milestone_commit_attributions");
|
|
3388
2184
|
currentDb.exec("DELETE FROM tasks");
|
|
3389
2185
|
currentDb.exec("DELETE FROM slices");
|
|
3390
2186
|
currentDb.exec("DELETE FROM milestone_leases");
|
|
@@ -3660,7 +2456,7 @@ export function updateMemoryContentRow(id, content, confidence, updatedAt) {
|
|
|
3660
2456
|
export function incrementMemoryHitCount(id, updatedAt) {
|
|
3661
2457
|
if (!currentDb)
|
|
3662
2458
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
3663
|
-
currentDb.prepare("UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at WHERE id = :id").run({ ":updated_at": updatedAt, ":id": id });
|
|
2459
|
+
currentDb.prepare("UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at, last_hit_at = :last_hit_at WHERE id = :id").run({ ":updated_at": updatedAt, ":last_hit_at": updatedAt, ":id": id });
|
|
3664
2460
|
}
|
|
3665
2461
|
export function supersedeMemoryRow(oldId, newId, updatedAt) {
|
|
3666
2462
|
if (!currentDb)
|