@opengsd/gsd-pi 1.2.0-dev.b1abb545 → 1.2.0-dev.fb12b103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +7 -29
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +5 -2
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
- package/dist/resources/extensions/gsd/auto/orchestrator.js +40 -9
- package/dist/resources/extensions/gsd/auto/phases.js +6 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +12 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +15 -10
- package/dist/resources/extensions/gsd/auto-start.js +21 -21
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
- package/dist/resources/extensions/gsd/auto.js +8 -20
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +151 -20
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +5 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +372 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
- package/dist/resources/extensions/gsd/guidance.js +98 -0
- package/dist/resources/extensions/gsd/guided-flow.js +51 -5
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
- package/dist/resources/extensions/gsd/paths.js +37 -24
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/preferences.js +14 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +1 -20
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/uat-policy.js +2 -1
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +28 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +18 -26
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +14 -47
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +29 -54
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +37 -47
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +9 -26
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +55 -57
- package/dist/web/standalone/node_modules/postcss/lib/node.js +31 -99
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +9 -10
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +11 -30
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +28 -69
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +2 -6
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/dist/web/standalone/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -11
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +6 -3
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +46 -21
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +478 -484
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +500 -533
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +5 -2
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +46 -10
- package/src/resources/extensions/gsd/auto/phases.ts +10 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +12 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -26
- package/src/resources/extensions/gsd/auto-start.ts +21 -22
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
- package/src/resources/extensions/gsd/auto.ts +20 -24
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +180 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +5 -16
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +453 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
- package/src/resources/extensions/gsd/guidance.ts +139 -0
- package/src/resources/extensions/gsd/guided-flow.ts +50 -5
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
- package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
- package/src/resources/extensions/gsd/paths.ts +42 -22
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/preferences.ts +18 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +4 -21
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +16 -19
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +24 -29
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/uat-policy.ts +2 -1
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +29 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Worktree DB reconciliation writers for the single-writer layer.
|
|
3
|
+
// Owns copyWorktreeDb + reconcileWorktreeDb: the ATTACH-and-merge of an
|
|
4
|
+
// auto-worktree's gsd.db back into the project-root DB, with conflict
|
|
5
|
+
// detection. Reads the shared engine handle via getDbOrNull(); opens the
|
|
6
|
+
// project-root DB via the engine's openDatabase().
|
|
7
|
+
import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { logError, logWarning } from "../../workflow-logger.js";
|
|
11
|
+
import { getDbOrNull, openDatabase } from "../engine.js";
|
|
12
|
+
import { TERMINAL_STATUS_SQL } from "../sql-constants.js";
|
|
13
|
+
|
|
14
|
+
export function copyWorktreeDb(srcDbPath: string, destDbPath: string): boolean {
|
|
15
|
+
try {
|
|
16
|
+
if (!existsSync(srcDbPath)) return false;
|
|
17
|
+
const destDir = dirname(destDbPath);
|
|
18
|
+
mkdirSync(destDir, { recursive: true });
|
|
19
|
+
copyFileSync(srcDbPath, destDbPath);
|
|
20
|
+
return true;
|
|
21
|
+
} catch (err) {
|
|
22
|
+
logError("db", "failed to copy DB to worktree", { error: (err as Error).message });
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ReconcileResult {
|
|
28
|
+
decisions: number;
|
|
29
|
+
requirements: number;
|
|
30
|
+
artifacts: number;
|
|
31
|
+
milestones: number;
|
|
32
|
+
slices: number;
|
|
33
|
+
tasks: number;
|
|
34
|
+
memories: number;
|
|
35
|
+
replan_history: number;
|
|
36
|
+
assessments: number;
|
|
37
|
+
quality_gates: number;
|
|
38
|
+
slice_dependencies: number;
|
|
39
|
+
verification_evidence: number;
|
|
40
|
+
gate_runs: number;
|
|
41
|
+
milestone_commit_attributions: number;
|
|
42
|
+
conflicts: string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function reconcileWorktreeDb(
|
|
46
|
+
mainDbPath: string,
|
|
47
|
+
worktreeDbPath: string,
|
|
48
|
+
): ReconcileResult {
|
|
49
|
+
const zero: ReconcileResult = {
|
|
50
|
+
decisions: 0,
|
|
51
|
+
requirements: 0,
|
|
52
|
+
artifacts: 0,
|
|
53
|
+
milestones: 0,
|
|
54
|
+
slices: 0,
|
|
55
|
+
tasks: 0,
|
|
56
|
+
memories: 0,
|
|
57
|
+
replan_history: 0,
|
|
58
|
+
assessments: 0,
|
|
59
|
+
quality_gates: 0,
|
|
60
|
+
slice_dependencies: 0,
|
|
61
|
+
verification_evidence: 0,
|
|
62
|
+
gate_runs: 0,
|
|
63
|
+
milestone_commit_attributions: 0,
|
|
64
|
+
conflicts: [],
|
|
65
|
+
};
|
|
66
|
+
if (!existsSync(worktreeDbPath)) return zero;
|
|
67
|
+
// Guard: bail when both paths resolve to the same physical file.
|
|
68
|
+
// ATTACHing a WAL-mode DB to itself corrupts the WAL (#2823).
|
|
69
|
+
try {
|
|
70
|
+
if (realpathSync(mainDbPath) === realpathSync(worktreeDbPath)) return zero;
|
|
71
|
+
} catch (e) { logWarning("db", `realpathSync failed: ${(e as Error).message}`); }
|
|
72
|
+
// Sanitize path: reject any characters that could break ATTACH syntax.
|
|
73
|
+
// ATTACH DATABASE doesn't support parameterized paths in all providers,
|
|
74
|
+
// so we use strict allowlist validation instead.
|
|
75
|
+
if (/['";\x00]/.test(worktreeDbPath)) {
|
|
76
|
+
logError("db", "worktree DB reconciliation failed: path contains unsafe characters");
|
|
77
|
+
return zero;
|
|
78
|
+
}
|
|
79
|
+
if (!getDbOrNull()!) {
|
|
80
|
+
const opened = openDatabase(mainDbPath);
|
|
81
|
+
if (!opened) {
|
|
82
|
+
logError("db", "worktree DB reconciliation failed: cannot open main DB");
|
|
83
|
+
return zero;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const adapter = getDbOrNull()!!;
|
|
87
|
+
const conflicts: string[] = [];
|
|
88
|
+
try {
|
|
89
|
+
adapter.exec(`ATTACH DATABASE '${worktreeDbPath}' AS wt`);
|
|
90
|
+
try {
|
|
91
|
+
function countChanges(result: unknown): number {
|
|
92
|
+
return typeof result === "object" && result !== null ? ((result as { changes?: number }).changes ?? 0) : 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function wtTableInfo(tableName: string): Array<Record<string, unknown>> {
|
|
96
|
+
return adapter.prepare(`PRAGMA wt.table_info('${tableName}')`).all() as Array<Record<string, unknown>>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const wtInfo = wtTableInfo("decisions");
|
|
100
|
+
const hasWtDecisions = wtInfo.length > 0;
|
|
101
|
+
const hasMadeBy = wtInfo.some((col) => col["name"] === "made_by");
|
|
102
|
+
// ADR-011: worktree may predate schema v16/v17. For missing columns we
|
|
103
|
+
// fall through to the main DB's existing value (not a literal default)
|
|
104
|
+
// so reconcile never silently clears state the main tree has recorded.
|
|
105
|
+
const hasDecisionSource = wtInfo.some((col) => col["name"] === "source");
|
|
106
|
+
const wtRequirementInfo = wtTableInfo("requirements");
|
|
107
|
+
const hasWtRequirements = wtRequirementInfo.length > 0;
|
|
108
|
+
const wtMilestoneInfo = wtTableInfo("milestones");
|
|
109
|
+
const hasWtMilestones = wtMilestoneInfo.length > 0;
|
|
110
|
+
const hasMilestoneSequence = wtMilestoneInfo.some((col) => col["name"] === "sequence");
|
|
111
|
+
const wtSliceInfo = wtTableInfo("slices");
|
|
112
|
+
const hasWtSlices = wtSliceInfo.length > 0;
|
|
113
|
+
const hasIsSketch = wtSliceInfo.some((col) => col["name"] === "is_sketch");
|
|
114
|
+
const hasSketchScope = wtSliceInfo.some((col) => col["name"] === "sketch_scope");
|
|
115
|
+
const hasSliceTargetRepositories = wtSliceInfo.some((col) => col["name"] === "target_repositories");
|
|
116
|
+
const wtTaskInfo = wtTableInfo("tasks");
|
|
117
|
+
const hasWtTasks = wtTaskInfo.length > 0;
|
|
118
|
+
const hasTaskTargetRepositories = wtTaskInfo.some((col) => col["name"] === "target_repositories");
|
|
119
|
+
const hasBlockerSource = wtTaskInfo.some((col) => col["name"] === "blocker_source");
|
|
120
|
+
const hasEscalationPending = wtTaskInfo.some((col) => col["name"] === "escalation_pending");
|
|
121
|
+
const hasEscalationAwaiting = wtTaskInfo.some((col) => col["name"] === "escalation_awaiting_review");
|
|
122
|
+
const hasEscalationArtifact = wtTaskInfo.some((col) => col["name"] === "escalation_artifact_path");
|
|
123
|
+
const hasEscalationOverride = wtTaskInfo.some((col) => col["name"] === "escalation_override_applied_at");
|
|
124
|
+
const wtArtifactInfo = wtTableInfo("artifacts");
|
|
125
|
+
const hasWtArtifacts = wtArtifactInfo.length > 0;
|
|
126
|
+
const wtMemoryInfo = wtTableInfo("memories");
|
|
127
|
+
const hasWtMemories = wtMemoryInfo.length > 0;
|
|
128
|
+
const hasMemoryScope = wtMemoryInfo.some((col) => col["name"] === "scope");
|
|
129
|
+
const hasMemoryTags = wtMemoryInfo.some((col) => col["name"] === "tags");
|
|
130
|
+
const hasMemoryStructuredFields = wtMemoryInfo.some((col) => col["name"] === "structured_fields");
|
|
131
|
+
const hasMemoryLastHitAt = wtMemoryInfo.some((col) => col["name"] === "last_hit_at");
|
|
132
|
+
const hasWtReplanHistory = wtTableInfo("replan_history").length > 0;
|
|
133
|
+
const hasWtAssessments = wtTableInfo("assessments").length > 0;
|
|
134
|
+
const hasWtQualityGates = wtTableInfo("quality_gates").length > 0;
|
|
135
|
+
const hasWtSliceDependencies = wtTableInfo("slice_dependencies").length > 0;
|
|
136
|
+
const hasWtVerificationEvidence = wtTableInfo("verification_evidence").length > 0;
|
|
137
|
+
const hasWtGateRuns = wtTableInfo("gate_runs").length > 0;
|
|
138
|
+
const hasWtMilestoneCommitAttributions = wtTableInfo("milestone_commit_attributions").length > 0;
|
|
139
|
+
|
|
140
|
+
if (hasWtDecisions) {
|
|
141
|
+
const decConf = adapter.prepare(
|
|
142
|
+
`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 ${
|
|
143
|
+
hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"
|
|
144
|
+
} OR m.superseded_by IS NOT w.superseded_by`,
|
|
145
|
+
).all();
|
|
146
|
+
for (const row of decConf) conflicts.push(`decision ${(row as Record<string, unknown>)["id"]}: modified in both`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (hasWtRequirements) {
|
|
150
|
+
const reqConf = adapter.prepare(
|
|
151
|
+
`SELECT m.id FROM requirements m INNER JOIN wt.requirements w ON m.id = w.id WHERE m.description != w.description OR m.status != w.status OR m.notes != w.notes OR m.superseded_by IS NOT w.superseded_by`,
|
|
152
|
+
).all();
|
|
153
|
+
for (const row of reqConf) conflicts.push(`requirement ${(row as Record<string, unknown>)["id"]}: modified in both`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const merged: Omit<ReconcileResult, "conflicts"> = {
|
|
157
|
+
decisions: 0,
|
|
158
|
+
requirements: 0,
|
|
159
|
+
artifacts: 0,
|
|
160
|
+
milestones: 0,
|
|
161
|
+
slices: 0,
|
|
162
|
+
tasks: 0,
|
|
163
|
+
memories: 0,
|
|
164
|
+
replan_history: 0,
|
|
165
|
+
assessments: 0,
|
|
166
|
+
quality_gates: 0,
|
|
167
|
+
slice_dependencies: 0,
|
|
168
|
+
verification_evidence: 0,
|
|
169
|
+
gate_runs: 0,
|
|
170
|
+
milestone_commit_attributions: 0,
|
|
171
|
+
};
|
|
172
|
+
const sliceTargetRepositoriesSql = hasSliceTargetRepositories
|
|
173
|
+
? `CASE
|
|
174
|
+
WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
|
|
175
|
+
THEN m.target_repositories
|
|
176
|
+
ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
|
|
177
|
+
END`
|
|
178
|
+
: "COALESCE(m.target_repositories, '[]')";
|
|
179
|
+
const taskTargetRepositoriesSql = hasTaskTargetRepositories
|
|
180
|
+
? `CASE
|
|
181
|
+
WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
|
|
182
|
+
THEN m.target_repositories
|
|
183
|
+
ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
|
|
184
|
+
END`
|
|
185
|
+
: "COALESCE(m.target_repositories, '[]')";
|
|
186
|
+
|
|
187
|
+
adapter.exec("BEGIN");
|
|
188
|
+
try {
|
|
189
|
+
// Join the target decisions so we can prefer an existing main.source
|
|
190
|
+
// when the worktree predates v16 — otherwise a write-through reconcile
|
|
191
|
+
// would clobber 'escalation'-sourced decisions with the literal default.
|
|
192
|
+
if (hasWtDecisions) {
|
|
193
|
+
merged.decisions = countChanges(adapter.prepare(`
|
|
194
|
+
INSERT INTO decisions (
|
|
195
|
+
id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by
|
|
196
|
+
)
|
|
197
|
+
SELECT w.id, w.when_context, w.scope, w.decision, w.choice, w.rationale, w.revisable, ${
|
|
198
|
+
hasMadeBy ? "w.made_by" : "COALESCE(m.made_by, 'agent')"
|
|
199
|
+
}, ${
|
|
200
|
+
hasDecisionSource ? "w.source" : "COALESCE(m.source, 'discussion')"
|
|
201
|
+
}, w.superseded_by
|
|
202
|
+
FROM wt.decisions w
|
|
203
|
+
LEFT JOIN decisions m ON m.id = w.id
|
|
204
|
+
WHERE true
|
|
205
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
206
|
+
when_context = excluded.when_context,
|
|
207
|
+
scope = excluded.scope,
|
|
208
|
+
decision = excluded.decision,
|
|
209
|
+
choice = excluded.choice,
|
|
210
|
+
rationale = excluded.rationale,
|
|
211
|
+
revisable = excluded.revisable,
|
|
212
|
+
made_by = excluded.made_by,
|
|
213
|
+
source = excluded.source,
|
|
214
|
+
superseded_by = excluded.superseded_by
|
|
215
|
+
`).run());
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (hasWtRequirements) {
|
|
219
|
+
merged.requirements = countChanges(adapter.prepare(`
|
|
220
|
+
INSERT OR REPLACE INTO requirements (
|
|
221
|
+
id, class, status, description, why, source, primary_owner,
|
|
222
|
+
supporting_slices, validation, notes, full_content, superseded_by
|
|
223
|
+
)
|
|
224
|
+
SELECT id, class, status, description, why, source, primary_owner,
|
|
225
|
+
supporting_slices, validation, notes, full_content, superseded_by
|
|
226
|
+
FROM wt.requirements
|
|
227
|
+
`).run());
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Always recompute artifact hashes from the content being merged. Older
|
|
231
|
+
// worktree DBs may not have content_hash at all, and migrated old DBs can
|
|
232
|
+
// carry stale default/null hashes after their content changed.
|
|
233
|
+
if (hasWtArtifacts) {
|
|
234
|
+
const artifactRows = adapter.prepare(`
|
|
235
|
+
SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
236
|
+
FROM wt.artifacts
|
|
237
|
+
`).all() as Array<Record<string, unknown>>;
|
|
238
|
+
const artifactStmt = adapter.prepare(`
|
|
239
|
+
INSERT OR REPLACE INTO artifacts (
|
|
240
|
+
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
|
|
241
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
242
|
+
`);
|
|
243
|
+
for (const row of artifactRows) {
|
|
244
|
+
const fullContent = String(row["full_content"] ?? "");
|
|
245
|
+
merged.artifacts += countChanges(artifactStmt.run(
|
|
246
|
+
row["path"],
|
|
247
|
+
row["artifact_type"],
|
|
248
|
+
row["milestone_id"] ?? null,
|
|
249
|
+
row["slice_id"] ?? null,
|
|
250
|
+
row["task_id"] ?? null,
|
|
251
|
+
fullContent,
|
|
252
|
+
row["imported_at"],
|
|
253
|
+
createHash("sha256").update(fullContent).digest("hex"),
|
|
254
|
+
));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Merge milestones — worktree may have updated status/planning fields.
|
|
259
|
+
// Never downgrade status: complete > active > pre-planning (#4372).
|
|
260
|
+
// A stale worktree may carry an older 'active' status for a milestone
|
|
261
|
+
// that the main DB has already marked 'complete'; preserve the higher status.
|
|
262
|
+
if (hasWtMilestones) {
|
|
263
|
+
merged.milestones = countChanges(adapter.prepare(`
|
|
264
|
+
INSERT OR REPLACE INTO milestones (
|
|
265
|
+
id, title, status, depends_on, created_at, completed_at,
|
|
266
|
+
vision, success_criteria, key_risks, proof_strategy,
|
|
267
|
+
verification_contract, verification_integration, verification_operational, verification_uat,
|
|
268
|
+
definition_of_done, requirement_coverage, boundary_map_markdown, sequence
|
|
269
|
+
)
|
|
270
|
+
SELECT w.id, w.title,
|
|
271
|
+
CASE
|
|
272
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
273
|
+
THEN m.status ELSE w.status
|
|
274
|
+
END,
|
|
275
|
+
w.depends_on,
|
|
276
|
+
CASE
|
|
277
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
278
|
+
THEN m.created_at ELSE w.created_at
|
|
279
|
+
END,
|
|
280
|
+
CASE
|
|
281
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
282
|
+
THEN m.completed_at ELSE w.completed_at
|
|
283
|
+
END,
|
|
284
|
+
w.vision, w.success_criteria, w.key_risks, w.proof_strategy,
|
|
285
|
+
w.verification_contract, w.verification_integration, w.verification_operational, w.verification_uat,
|
|
286
|
+
w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown,
|
|
287
|
+
${hasMilestoneSequence ? "COALESCE(w.sequence, 0)" : "COALESCE(m.sequence, 0)"}
|
|
288
|
+
FROM wt.milestones w
|
|
289
|
+
LEFT JOIN milestones m ON m.id = w.id
|
|
290
|
+
`).run());
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Merge slices — preserve worktree progress but never downgrade completed status (#2558).
|
|
294
|
+
// ADR-011 Phase 1: carry is_sketch + sketch_scope so reconcile doesn't
|
|
295
|
+
// silently clear sketch metadata. When the worktree predates v16,
|
|
296
|
+
// fall back to the main DB's existing value rather than a literal 0/''.
|
|
297
|
+
if (hasWtSlices) {
|
|
298
|
+
merged.slices = countChanges(adapter.prepare(`
|
|
299
|
+
INSERT OR REPLACE INTO slices (
|
|
300
|
+
milestone_id, id, title, status, risk, depends, demo, created_at, completed_at,
|
|
301
|
+
full_summary_md, full_uat_md, goal, success_criteria, proof_level,
|
|
302
|
+
integration_closure, observability_impact, target_repositories, sequence, replan_triggered_at,
|
|
303
|
+
is_sketch, sketch_scope
|
|
304
|
+
)
|
|
305
|
+
SELECT w.milestone_id, w.id, w.title,
|
|
306
|
+
CASE
|
|
307
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
308
|
+
THEN m.status ELSE w.status
|
|
309
|
+
END,
|
|
310
|
+
w.risk, w.depends, w.demo, w.created_at,
|
|
311
|
+
CASE
|
|
312
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
313
|
+
THEN m.completed_at ELSE w.completed_at
|
|
314
|
+
END,
|
|
315
|
+
w.full_summary_md, w.full_uat_md, w.goal, w.success_criteria, w.proof_level,
|
|
316
|
+
w.integration_closure, w.observability_impact,
|
|
317
|
+
${sliceTargetRepositoriesSql},
|
|
318
|
+
w.sequence, w.replan_triggered_at,
|
|
319
|
+
${hasIsSketch ? "w.is_sketch" : "COALESCE(m.is_sketch, 0)"},
|
|
320
|
+
${hasSketchScope ? "w.sketch_scope" : "COALESCE(m.sketch_scope, '')"}
|
|
321
|
+
FROM wt.slices w
|
|
322
|
+
LEFT JOIN slices m ON m.milestone_id = w.milestone_id AND m.id = w.id
|
|
323
|
+
`).run());
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Merge tasks — preserve execution results, never downgrade completed status (#2558).
|
|
327
|
+
// ADR-011 P2: carry blocker_source + escalation_* columns so worktree reconcile
|
|
328
|
+
// doesn't silently clear escalation state back to defaults.
|
|
329
|
+
if (hasWtTasks) {
|
|
330
|
+
merged.tasks = countChanges(adapter.prepare(`
|
|
331
|
+
INSERT OR REPLACE INTO tasks (
|
|
332
|
+
milestone_id, slice_id, id, title, status, one_liner, narrative,
|
|
333
|
+
verification_result, duration, completed_at, blocker_discovered,
|
|
334
|
+
deviations, known_issues, key_files, key_decisions, full_summary_md,
|
|
335
|
+
description, estimate, files, verify, inputs, expected_output,
|
|
336
|
+
observability_impact, full_plan_md, target_repositories, sequence,
|
|
337
|
+
blocker_source, escalation_pending, escalation_awaiting_review,
|
|
338
|
+
escalation_artifact_path, escalation_override_applied_at
|
|
339
|
+
)
|
|
340
|
+
SELECT w.milestone_id, w.slice_id, w.id, w.title,
|
|
341
|
+
CASE
|
|
342
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
343
|
+
THEN m.status ELSE w.status
|
|
344
|
+
END,
|
|
345
|
+
w.one_liner, w.narrative,
|
|
346
|
+
w.verification_result, w.duration,
|
|
347
|
+
CASE
|
|
348
|
+
WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
|
|
349
|
+
THEN m.completed_at ELSE w.completed_at
|
|
350
|
+
END,
|
|
351
|
+
w.blocker_discovered,
|
|
352
|
+
w.deviations, w.known_issues, w.key_files, w.key_decisions, w.full_summary_md,
|
|
353
|
+
w.description, w.estimate, w.files, w.verify, w.inputs, w.expected_output,
|
|
354
|
+
w.observability_impact, w.full_plan_md,
|
|
355
|
+
${taskTargetRepositoriesSql},
|
|
356
|
+
w.sequence,
|
|
357
|
+
${hasBlockerSource ? "w.blocker_source" : "COALESCE(m.blocker_source, '')"},
|
|
358
|
+
${hasEscalationPending ? "w.escalation_pending" : "COALESCE(m.escalation_pending, 0)"},
|
|
359
|
+
${hasEscalationAwaiting ? "w.escalation_awaiting_review" : "COALESCE(m.escalation_awaiting_review, 0)"},
|
|
360
|
+
${hasEscalationArtifact ? "w.escalation_artifact_path" : "m.escalation_artifact_path"},
|
|
361
|
+
${hasEscalationOverride ? "w.escalation_override_applied_at" : "m.escalation_override_applied_at"}
|
|
362
|
+
FROM wt.tasks w
|
|
363
|
+
LEFT JOIN tasks m ON m.milestone_id = w.milestone_id AND m.slice_id = w.slice_id AND m.id = w.id
|
|
364
|
+
`).run());
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Merge memories — keep worktree-learned insights.
|
|
368
|
+
// V18 (scope, tags), V21 (structured_fields), V28 (last_hit_at): for each
|
|
369
|
+
// column the wt may not yet have (older worktree DB), fall back to the
|
|
370
|
+
// main DB's existing value via LEFT JOIN so reconcile never silently
|
|
371
|
+
// resets these fields to defaults on rows that already had them.
|
|
372
|
+
if (hasWtMemories) {
|
|
373
|
+
merged.memories = countChanges(adapter.prepare(`
|
|
374
|
+
INSERT OR REPLACE INTO memories (
|
|
375
|
+
seq, id, category, content, confidence, source_unit_type, source_unit_id,
|
|
376
|
+
created_at, updated_at, superseded_by, hit_count,
|
|
377
|
+
scope, tags, structured_fields, last_hit_at
|
|
378
|
+
)
|
|
379
|
+
SELECT w.seq, w.id, w.category, w.content, w.confidence, w.source_unit_type, w.source_unit_id,
|
|
380
|
+
w.created_at, w.updated_at, w.superseded_by, w.hit_count,
|
|
381
|
+
${hasMemoryScope ? "w.scope" : "COALESCE(m.scope, 'project')"},
|
|
382
|
+
${hasMemoryTags ? "w.tags" : "COALESCE(m.tags, '[]')"},
|
|
383
|
+
${hasMemoryStructuredFields ? "w.structured_fields" : "m.structured_fields"},
|
|
384
|
+
${hasMemoryLastHitAt ? "w.last_hit_at" : "m.last_hit_at"}
|
|
385
|
+
FROM wt.memories w
|
|
386
|
+
LEFT JOIN memories m ON m.id = w.id
|
|
387
|
+
`).run());
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (hasWtReplanHistory) {
|
|
391
|
+
merged.replan_history = countChanges(adapter.prepare(`
|
|
392
|
+
INSERT INTO replan_history (
|
|
393
|
+
milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at
|
|
394
|
+
)
|
|
395
|
+
SELECT w.milestone_id, w.slice_id, w.task_id, w.summary, w.previous_artifact_path, w.replacement_artifact_path, w.created_at
|
|
396
|
+
FROM wt.replan_history w
|
|
397
|
+
WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
|
|
398
|
+
AND NOT EXISTS (
|
|
399
|
+
SELECT 1 FROM replan_history m
|
|
400
|
+
WHERE m.milestone_id = w.milestone_id
|
|
401
|
+
AND m.slice_id IS w.slice_id
|
|
402
|
+
AND m.task_id IS w.task_id
|
|
403
|
+
AND m.summary = w.summary
|
|
404
|
+
AND m.previous_artifact_path IS w.previous_artifact_path
|
|
405
|
+
AND m.replacement_artifact_path IS w.replacement_artifact_path
|
|
406
|
+
)
|
|
407
|
+
`).run());
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (hasWtAssessments) {
|
|
411
|
+
merged.assessments = countChanges(adapter.prepare(`
|
|
412
|
+
INSERT OR REPLACE INTO assessments (
|
|
413
|
+
path, milestone_id, slice_id, task_id, status, scope, full_content, created_at
|
|
414
|
+
)
|
|
415
|
+
SELECT w.path, w.milestone_id, w.slice_id, w.task_id, w.status, w.scope, w.full_content, w.created_at
|
|
416
|
+
FROM wt.assessments w
|
|
417
|
+
WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
|
|
418
|
+
`).run());
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (hasWtQualityGates) {
|
|
422
|
+
merged.quality_gates = countChanges(adapter.prepare(`
|
|
423
|
+
INSERT OR REPLACE INTO quality_gates (
|
|
424
|
+
milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at
|
|
425
|
+
)
|
|
426
|
+
SELECT w.milestone_id, w.slice_id, w.gate_id, w.scope, COALESCE(w.task_id, ''), w.status, w.verdict, w.rationale, w.findings, w.evaluated_at
|
|
427
|
+
FROM wt.quality_gates w
|
|
428
|
+
WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
|
|
429
|
+
`).run());
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (hasWtSliceDependencies) {
|
|
433
|
+
merged.slice_dependencies = countChanges(adapter.prepare(`
|
|
434
|
+
INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id)
|
|
435
|
+
SELECT w.milestone_id, w.slice_id, w.depends_on_slice_id
|
|
436
|
+
FROM wt.slice_dependencies w
|
|
437
|
+
WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
|
|
438
|
+
AND EXISTS (SELECT 1 FROM slices d WHERE d.milestone_id = w.milestone_id AND d.id = w.depends_on_slice_id)
|
|
439
|
+
`).run());
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Merge verification evidence — append-only, use INSERT OR IGNORE to avoid duplicates
|
|
443
|
+
if (hasWtVerificationEvidence) {
|
|
444
|
+
merged.verification_evidence = countChanges(adapter.prepare(`
|
|
445
|
+
INSERT OR IGNORE INTO verification_evidence (
|
|
446
|
+
task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
|
|
447
|
+
)
|
|
448
|
+
SELECT task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
|
|
449
|
+
FROM wt.verification_evidence
|
|
450
|
+
`).run());
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (hasWtGateRuns) {
|
|
454
|
+
merged.gate_runs = countChanges(adapter.prepare(`
|
|
455
|
+
INSERT INTO gate_runs (
|
|
456
|
+
trace_id, turn_id, gate_id, gate_type, unit_type, unit_id, milestone_id, slice_id, task_id,
|
|
457
|
+
outcome, failure_class, rationale, findings, attempt, max_attempts, retryable, evaluated_at
|
|
458
|
+
)
|
|
459
|
+
SELECT w.trace_id, w.turn_id, w.gate_id, w.gate_type, w.unit_type, w.unit_id, w.milestone_id, w.slice_id, w.task_id,
|
|
460
|
+
w.outcome, w.failure_class, w.rationale, w.findings, w.attempt, w.max_attempts, w.retryable, w.evaluated_at
|
|
461
|
+
FROM wt.gate_runs w
|
|
462
|
+
WHERE NOT EXISTS (
|
|
463
|
+
SELECT 1 FROM gate_runs m
|
|
464
|
+
WHERE m.trace_id = w.trace_id
|
|
465
|
+
AND m.turn_id = w.turn_id
|
|
466
|
+
AND m.gate_id = w.gate_id
|
|
467
|
+
AND m.attempt = w.attempt
|
|
468
|
+
AND m.evaluated_at = w.evaluated_at
|
|
469
|
+
)
|
|
470
|
+
`).run());
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (hasWtMilestoneCommitAttributions) {
|
|
474
|
+
merged.milestone_commit_attributions = countChanges(adapter.prepare(`
|
|
475
|
+
INSERT OR REPLACE INTO milestone_commit_attributions (
|
|
476
|
+
commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
|
|
477
|
+
)
|
|
478
|
+
SELECT w.commit_sha, w.milestone_id, w.slice_id, w.task_id, w.source, w.confidence, w.files_json, w.created_at
|
|
479
|
+
FROM wt.milestone_commit_attributions w
|
|
480
|
+
WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
|
|
481
|
+
`).run());
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
adapter.exec("COMMIT");
|
|
485
|
+
} catch (txErr) {
|
|
486
|
+
try { adapter.exec("ROLLBACK"); } catch (e) { logWarning("db", `rollback failed: ${(e as Error).message}`); }
|
|
487
|
+
throw txErr;
|
|
488
|
+
}
|
|
489
|
+
return { ...merged, conflicts };
|
|
490
|
+
} finally {
|
|
491
|
+
try { adapter.exec("DETACH DATABASE wt"); } catch (e) { logWarning("db", `detach worktree DB failed: ${(e as Error).message}`); }
|
|
492
|
+
}
|
|
493
|
+
} catch (err) {
|
|
494
|
+
logError("db", "worktree DB reconciliation failed", { error: (err as Error).message });
|
|
495
|
+
return { ...zero, conflicts };
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ─── Replan & Assessment Helpers ──────────────────────────────────────────
|
|
500
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Status Transition Core (ADR-030) — the single row-level
|
|
3
|
+
// chokepoint every generic status write funnels through. Owns the milestone
|
|
4
|
+
// closed→open guard and is the one place future row-level status policy lands.
|
|
5
|
+
// The update*Status faces in gsd-db.ts delegate here.
|
|
6
|
+
//
|
|
7
|
+
// Behavior this pass is intentionally identical to the prior per-face writes.
|
|
8
|
+
// Two ADR-030 responsibilities are deferred for safety and documented inline:
|
|
9
|
+
// - Write-normalization via toStatus(): workflow-reconcile replays journal
|
|
10
|
+
// events that write raw "done"/"in-progress" and tests assert those exact
|
|
11
|
+
// stored values, so converging on write is a separate, behavior-sensitive
|
|
12
|
+
// change (migrate replay/import to canonical first).
|
|
13
|
+
// - Generalizing the closed→open guard to task/slice: four legitimate reopen
|
|
14
|
+
// callers (undo, tools/reopen-task, auto-post-unit, tools/plan-slice) move
|
|
15
|
+
// entities to open statuses through the generic faces. Generalizing safely
|
|
16
|
+
// needs sanctioned reopenTaskStatus/reopenSliceStatus faces first, mirroring
|
|
17
|
+
// the existing milestone updateMilestoneStatus/reopenMilestoneStatus split.
|
|
18
|
+
import { getDbOrNull } from "../engine.js";
|
|
19
|
+
import { GSDError, GSD_STALE_STATE } from "../../errors.js";
|
|
20
|
+
import { isClosedStatus } from "../../status-guards.js";
|
|
21
|
+
|
|
22
|
+
/** A single row-level status write, discriminated by entity (the faces' arity). */
|
|
23
|
+
export type StatusTransition =
|
|
24
|
+
| { entity: "task"; milestoneId: string; sliceId: string; taskId: string; status: string; completedAt?: string | null }
|
|
25
|
+
| { entity: "slice"; milestoneId: string; sliceId: string; status: string; completedAt?: string | null }
|
|
26
|
+
| { entity: "milestone"; milestoneId: string; status: string; completedAt?: string | null };
|
|
27
|
+
|
|
28
|
+
function requireDb() {
|
|
29
|
+
const db = getDbOrNull();
|
|
30
|
+
if (!db) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
31
|
+
return db;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Apply a row-level status transition. The single chokepoint for generic status
|
|
36
|
+
* writes — the update*Status faces delegate here so the guard and (future)
|
|
37
|
+
* normalization/journal/cache policy live in one place rather than per face.
|
|
38
|
+
*
|
|
39
|
+
* Milestone closed→open guard: generic updates may close, park/unpark, or
|
|
40
|
+
* advance a milestone, but may not reopen a closed one; callers must use
|
|
41
|
+
* reopenMilestoneStatus() (gsd_milestone_reopen). Tasks and slices are not yet
|
|
42
|
+
* guarded — see the file header.
|
|
43
|
+
*/
|
|
44
|
+
export function applyStatusTransition(t: StatusTransition): void {
|
|
45
|
+
const db = requireDb();
|
|
46
|
+
const completedAt = t.completedAt ?? null;
|
|
47
|
+
|
|
48
|
+
switch (t.entity) {
|
|
49
|
+
case "task":
|
|
50
|
+
db.prepare(
|
|
51
|
+
`UPDATE tasks SET status = :status, completed_at = :completed_at
|
|
52
|
+
WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`,
|
|
53
|
+
).run({
|
|
54
|
+
":status": t.status,
|
|
55
|
+
":completed_at": completedAt,
|
|
56
|
+
":milestone_id": t.milestoneId,
|
|
57
|
+
":slice_id": t.sliceId,
|
|
58
|
+
":id": t.taskId,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
|
|
62
|
+
case "slice":
|
|
63
|
+
db.prepare(
|
|
64
|
+
`UPDATE slices SET status = :status, completed_at = :completed_at
|
|
65
|
+
WHERE milestone_id = :milestone_id AND id = :id`,
|
|
66
|
+
).run({
|
|
67
|
+
":status": t.status,
|
|
68
|
+
":completed_at": completedAt,
|
|
69
|
+
":milestone_id": t.milestoneId,
|
|
70
|
+
":id": t.sliceId,
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
|
|
74
|
+
case "milestone": {
|
|
75
|
+
const row = db.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": t.milestoneId });
|
|
76
|
+
const currentStatus = typeof row?.["status"] === "string" ? (row["status"] as string) : null;
|
|
77
|
+
if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(t.status)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Cannot update closed milestone ${t.milestoneId} from ${currentStatus} to ${t.status}; use gsd_milestone_reopen for an explicit reopen.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
db.prepare(
|
|
83
|
+
`UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
|
|
84
|
+
).run({ ":status": t.status, ":completed_at": completedAt, ":id": t.milestoneId });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -15,6 +15,7 @@ import { join } from "node:path";
|
|
|
15
15
|
|
|
16
16
|
import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
|
|
17
17
|
import { detectPythonExecutable } from "./python-resolver.js";
|
|
18
|
+
import { projectRootFromWorktreePath } from "./worktree-root.js";
|
|
18
19
|
|
|
19
20
|
// ── Types ──────────────────────────────────────────────────────────────────
|
|
20
21
|
|
|
@@ -38,27 +39,18 @@ const CMD_TIMEOUT = 5_000;
|
|
|
38
39
|
|
|
39
40
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
40
41
|
|
|
41
|
-
/** Worktree sentinel — path segment that marks an auto-worktree directory. */
|
|
42
|
-
const WORKTREE_PATH_SEGMENT = `${join(".gsd", "worktrees")}/`;
|
|
43
|
-
|
|
44
42
|
/**
|
|
45
|
-
* Resolve the project root when running inside a
|
|
46
|
-
*
|
|
43
|
+
* Resolve the project root when running inside a GSD auto-worktree.
|
|
44
|
+
* Returns `null` if not in a worktree.
|
|
47
45
|
*
|
|
48
46
|
* Detection order:
|
|
49
47
|
* 1. `GSD_WORKTREE` env var (set by the worktree launcher)
|
|
50
|
-
* 2.
|
|
48
|
+
* 2. worktree segment in basePath (via worktree-root's layout matching)
|
|
51
49
|
*/
|
|
52
50
|
function resolveWorktreeProjectRoot(basePath: string): string | null {
|
|
53
51
|
const envRoot = process.env.GSD_WORKTREE;
|
|
54
52
|
if (envRoot) return envRoot;
|
|
55
|
-
|
|
56
|
-
const normalised = basePath.replace(/\\/g, "/");
|
|
57
|
-
const idx = normalised.indexOf(WORKTREE_PATH_SEGMENT.replace(/\\/g, "/"));
|
|
58
|
-
if (idx === -1) return null;
|
|
59
|
-
|
|
60
|
-
// Everything before `.gsd/worktrees/` is the project root
|
|
61
|
-
return basePath.slice(0, idx);
|
|
53
|
+
return projectRootFromWorktreePath(basePath);
|
|
62
54
|
}
|
|
63
55
|
|
|
64
56
|
function tryExec(cmd: string, cwd: string): string | null {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type { DoctorIssue, DoctorIssueCode, DoctorReport, DoctorSummary } from "./doctor-types.js";
|
|
1
|
+
import type { DoctorIssue, DoctorIssueCode, DoctorReport, DoctorSummary, DoctorSeverity } from "./doctor-types.js";
|
|
2
|
+
import { doctorFixHint } from "./guidance.js";
|
|
3
|
+
|
|
4
|
+
function severityTag(severity: DoctorSeverity): string {
|
|
5
|
+
return severity === "error" ? "ERROR" : severity === "warning" ? "WARN" : "INFO";
|
|
6
|
+
}
|
|
2
7
|
|
|
3
8
|
function matchesScope(unitId: string, scope?: string): boolean {
|
|
4
9
|
if (!scope) return true;
|
|
@@ -53,8 +58,9 @@ export function formatDoctorReport(
|
|
|
53
58
|
if (scopedIssues.length > 0) {
|
|
54
59
|
lines.push("Priority issues:");
|
|
55
60
|
for (const issue of scopedIssues.slice(0, maxIssues)) {
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
lines.push(`- [${severityTag(issue.severity)}] ${issue.unitId}: ${issue.message}${issue.file ? ` (${issue.file})` : ""}`);
|
|
62
|
+
const hint = doctorFixHint(issue.code);
|
|
63
|
+
if (hint && issue.severity !== "info") lines.push(` Fix: ${hint}`);
|
|
58
64
|
}
|
|
59
65
|
if (scopedIssues.length > maxIssues) {
|
|
60
66
|
lines.push(`- ...and ${scopedIssues.length - maxIssues} more in scope`);
|
|
@@ -72,10 +78,9 @@ export function formatDoctorReport(
|
|
|
72
78
|
|
|
73
79
|
export function formatDoctorIssuesForPrompt(issues: DoctorIssue[]): string {
|
|
74
80
|
if (issues.length === 0) return "- No remaining issues in scope.";
|
|
75
|
-
return issues.map(issue =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}).join("\n");
|
|
81
|
+
return issues.map(issue =>
|
|
82
|
+
`- [${severityTag(issue.severity)}] ${issue.unitId} | ${issue.code} | ${issue.message}${issue.file ? ` | file: ${issue.file}` : ""} | fixable: ${issue.fixable ? "yes" : "no"}`
|
|
83
|
+
).join("\n");
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
/**
|