@cleocode/core 2026.9.21 → 2026.9.23
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/agents/scaffold.d.ts.map +1 -1
- package/dist/agents/scaffold.js +0 -1
- package/dist/agents/scaffold.js.map +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +4 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/build-provenance.json +6 -0
- package/dist/decide/audit.d.ts +7 -1
- package/dist/decide/audit.d.ts.map +1 -1
- package/dist/decide/audit.js.map +1 -1
- package/dist/decide/client.d.ts +46 -4
- package/dist/decide/client.d.ts.map +1 -1
- package/dist/decide/client.js +328 -33
- package/dist/decide/client.js.map +1 -1
- package/dist/decide/credentials.d.ts +28 -4
- package/dist/decide/credentials.d.ts.map +1 -1
- package/dist/decide/credentials.js +50 -12
- package/dist/decide/credentials.js.map +1 -1
- package/dist/decide/index.d.ts +10 -4
- package/dist/decide/index.d.ts.map +1 -1
- package/dist/decide/index.js +10 -4
- package/dist/decide/index.js.map +1 -1
- package/dist/decide/jev-wire.d.ts +100 -8
- package/dist/decide/jev-wire.d.ts.map +1 -1
- package/dist/decide/jev-wire.js +402 -55
- package/dist/decide/jev-wire.js.map +1 -1
- package/dist/decide/operations.d.ts +97 -20
- package/dist/decide/operations.d.ts.map +1 -1
- package/dist/decide/operations.js +180 -28
- package/dist/decide/operations.js.map +1 -1
- package/dist/decide/provider-state.d.ts +89 -0
- package/dist/decide/provider-state.d.ts.map +1 -0
- package/dist/decide/provider-state.js +134 -0
- package/dist/decide/provider-state.js.map +1 -0
- package/dist/decide/provider.d.ts +26 -5
- package/dist/decide/provider.d.ts.map +1 -1
- package/dist/decide/provider.js.map +1 -1
- package/dist/decide/providers.d.ts +58 -0
- package/dist/decide/providers.d.ts.map +1 -0
- package/dist/decide/providers.js +69 -0
- package/dist/decide/providers.js.map +1 -0
- package/dist/decide/site.d.ts +2 -2
- package/dist/decide/site.d.ts.map +1 -1
- package/dist/decide/site.js +2 -0
- package/dist/decide/site.js.map +1 -1
- package/dist/decide/sites/list.d.ts +46 -0
- package/dist/decide/sites/list.d.ts.map +1 -0
- package/dist/decide/sites/list.js +206 -0
- package/dist/decide/sites/list.js.map +1 -0
- package/dist/decide/sites/registry.d.ts +130 -0
- package/dist/decide/sites/registry.d.ts.map +1 -0
- package/dist/decide/sites/registry.js +375 -0
- package/dist/decide/sites/registry.js.map +1 -0
- package/dist/decide/spend.d.ts +196 -0
- package/dist/decide/spend.d.ts.map +1 -0
- package/dist/decide/spend.js +387 -0
- package/dist/decide/spend.js.map +1 -0
- package/dist/decide/wizard.d.ts +53 -0
- package/dist/decide/wizard.d.ts.map +1 -0
- package/dist/decide/wizard.js +144 -0
- package/dist/decide/wizard.js.map +1 -0
- package/dist/dispatch/mutate-projection.d.ts.map +1 -1
- package/dist/dispatch/mutate-projection.js +5 -0
- package/dist/dispatch/mutate-projection.js.map +1 -1
- package/dist/docs/docs-audit.d.ts.map +1 -1
- package/dist/docs/docs-audit.js +1 -2
- package/dist/docs/docs-audit.js.map +1 -1
- package/dist/docs/docs-update.d.ts.map +1 -1
- package/dist/docs/docs-update.js +25 -9
- package/dist/docs/docs-update.js.map +1 -1
- package/dist/docs/export-document.js +1073 -628
- package/dist/docs/export-document.js.map +3 -3
- package/dist/doctor/knowledge.d.ts +16 -1
- package/dist/doctor/knowledge.d.ts.map +1 -1
- package/dist/doctor/knowledge.js +53 -17
- package/dist/doctor/knowledge.js.map +1 -1
- package/dist/engine/engine-ops.d.ts +36 -6
- package/dist/engine/engine-ops.d.ts.map +1 -1
- package/dist/engine/engine-ops.js +115 -14
- package/dist/engine/engine-ops.js.map +1 -1
- package/dist/gateway-client/generated/types.gen.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/scaffold-workflows.d.ts.map +1 -1
- package/dist/init/scaffold-workflows.js +6 -3
- package/dist/init/scaffold-workflows.js.map +1 -1
- package/dist/init/upgrade-workflows.d.ts.map +1 -1
- package/dist/init/upgrade-workflows.js +6 -3
- package/dist/init/upgrade-workflows.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +51 -11
- package/dist/init.js.map +1 -1
- package/dist/inject/index.d.ts.map +1 -1
- package/dist/inject/index.js +8 -3
- package/dist/inject/index.js.map +1 -1
- package/dist/internal.d.ts +3 -3
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -2
- package/dist/internal.js.map +1 -1
- package/dist/llm/plugin-facade.js +1184 -739
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/attention.d.ts.map +1 -1
- package/dist/memory/attention.js +2 -2
- package/dist/memory/attention.js.map +1 -1
- package/dist/memory/decision-contradiction.d.ts +3 -3
- package/dist/memory/decision-contradiction.d.ts.map +1 -1
- package/dist/memory/decision-contradiction.js +4 -3
- package/dist/memory/decision-contradiction.js.map +1 -1
- package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
- package/dist/memory/graph-memory-bridge.js +2 -0
- package/dist/memory/graph-memory-bridge.js.map +1 -1
- package/dist/memory/observation-type-decision.d.ts +2 -2
- package/dist/memory/observation-type-decision.d.ts.map +1 -1
- package/dist/memory/observation-type-decision.js +3 -2
- package/dist/memory/observation-type-decision.js.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.d.ts +111 -0
- package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.js +230 -2
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
- package/dist/nexus/analyze-orchestrator.d.ts +38 -0
- package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
- package/dist/nexus/analyze-orchestrator.js +96 -21
- package/dist/nexus/analyze-orchestrator.js.map +1 -1
- package/dist/nexus/knowledge.d.ts.map +1 -1
- package/dist/nexus/knowledge.js +15 -4
- package/dist/nexus/knowledge.js.map +1 -1
- package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
- package/dist/nexus/migrations/M-split-graph.js +4 -0
- package/dist/nexus/migrations/M-split-graph.js.map +1 -1
- package/dist/nexus/store.d.ts.map +1 -1
- package/dist/nexus/store.js +2 -0
- package/dist/nexus/store.js.map +1 -1
- package/dist/nexus/stored-roots.d.ts +65 -0
- package/dist/nexus/stored-roots.d.ts.map +1 -1
- package/dist/nexus/stored-roots.js +73 -0
- package/dist/nexus/stored-roots.js.map +1 -1
- package/dist/orchestrate/lifecycle-ops.d.ts.map +1 -1
- package/dist/orchestrate/lifecycle-ops.js +4 -1
- package/dist/orchestrate/lifecycle-ops.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +13 -8
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/orchestrate/plan.d.ts.map +1 -1
- package/dist/orchestrate/plan.js +8 -2
- package/dist/orchestrate/plan.js.map +1 -1
- package/dist/orchestrate/query-ops.d.ts +7 -2
- package/dist/orchestrate/query-ops.d.ts.map +1 -1
- package/dist/orchestrate/query-ops.js +17 -6
- package/dist/orchestrate/query-ops.js.map +1 -1
- package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
- package/dist/orchestrate/spawn-ops.js +5 -14
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestration/bootstrap.d.ts.map +1 -1
- package/dist/orchestration/bootstrap.js +4 -2
- package/dist/orchestration/bootstrap.js.map +1 -1
- package/dist/orchestration/index.d.ts +1 -0
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +4 -3
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lead-rollup.d.ts +8 -5
- package/dist/orchestration/lead-rollup.d.ts.map +1 -1
- package/dist/orchestration/lead-rollup.js +46 -17
- package/dist/orchestration/lead-rollup.js.map +1 -1
- package/dist/orchestration/owner-decision-readiness.d.ts +2 -2
- package/dist/orchestration/owner-decision-readiness.d.ts.map +1 -1
- package/dist/orchestration/owner-decision-readiness.js +3 -2
- package/dist/orchestration/owner-decision-readiness.js.map +1 -1
- package/dist/orchestration/parallel.d.ts.map +1 -1
- package/dist/orchestration/parallel.js +10 -17
- package/dist/orchestration/parallel.js.map +1 -1
- package/dist/orchestration/spawn-prompt.d.ts +4 -1
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +3 -2
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/status.d.ts +8 -3
- package/dist/orchestration/status.d.ts.map +1 -1
- package/dist/orchestration/status.js +9 -6
- package/dist/orchestration/status.js.map +1 -1
- package/dist/orchestration/validate-spawn.d.ts.map +1 -1
- package/dist/orchestration/validate-spawn.js +2 -0
- package/dist/orchestration/validate-spawn.js.map +1 -1
- package/dist/orchestration/wave-topic.d.ts +54 -0
- package/dist/orchestration/wave-topic.d.ts.map +1 -0
- package/dist/orchestration/wave-topic.js +68 -0
- package/dist/orchestration/wave-topic.js.map +1 -0
- package/dist/orchestration/waves.d.ts +47 -8
- package/dist/orchestration/waves.d.ts.map +1 -1
- package/dist/orchestration/waves.js +152 -43
- package/dist/orchestration/waves.js.map +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +6 -2
- package/dist/phases/index.js.map +1 -1
- package/dist/project-scope.d.ts +34 -0
- package/dist/project-scope.d.ts.map +1 -1
- package/dist/project-scope.js +73 -0
- package/dist/project-scope.js.map +1 -1
- package/dist/release/ci-evidence.d.ts +10 -0
- package/dist/release/ci-evidence.d.ts.map +1 -1
- package/dist/release/ci-evidence.js +23 -7
- package/dist/release/ci-evidence.js.map +1 -1
- package/dist/release/github-pr.d.ts +30 -0
- package/dist/release/github-pr.d.ts.map +1 -1
- package/dist/release/github-pr.js +42 -1
- package/dist/release/github-pr.js.map +1 -1
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +6 -3
- package/dist/release/plan.js.map +1 -1
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +12 -4
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/routing/capability-matrix.d.ts.map +1 -1
- package/dist/routing/capability-matrix.js +7 -0
- package/dist/routing/capability-matrix.js.map +1 -1
- package/dist/security/input-sanitization.d.ts.map +1 -1
- package/dist/security/input-sanitization.js +9 -2
- package/dist/security/input-sanitization.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +1193 -748
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/session/engine-ops.d.ts +6 -0
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +36 -4
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/briefing.d.ts +17 -0
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +68 -68
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/drift-watchdog.d.ts.map +1 -1
- package/dist/sessions/drift-watchdog.js +4 -3
- package/dist/sessions/drift-watchdog.js.map +1 -1
- package/dist/sessions/focus-state-store.d.ts +94 -1
- package/dist/sessions/focus-state-store.d.ts.map +1 -1
- package/dist/sessions/focus-state-store.js +100 -1
- package/dist/sessions/focus-state-store.js.map +1 -1
- package/dist/sessions/index.d.ts +2 -2
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +1 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/session-drift.d.ts.map +1 -1
- package/dist/sessions/session-drift.js +4 -3
- package/dist/sessions/session-drift.js.map +1 -1
- package/dist/setup/config-json-merge.d.ts +28 -0
- package/dist/setup/config-json-merge.d.ts.map +1 -1
- package/dist/setup/config-json-merge.js +51 -0
- package/dist/setup/config-json-merge.js.map +1 -1
- package/dist/setup/index.d.ts +13 -10
- package/dist/setup/index.d.ts.map +1 -1
- package/dist/setup/index.js +15 -10
- package/dist/setup/index.js.map +1 -1
- package/dist/setup/sections/llm.js +1 -1
- package/dist/setup/sections/llm.js.map +1 -1
- package/dist/setup/sections/system-one.d.ts +28 -0
- package/dist/setup/sections/system-one.d.ts.map +1 -0
- package/dist/setup/sections/system-one.js +53 -0
- package/dist/setup/sections/system-one.js.map +1 -0
- package/dist/setup/wizard.d.ts +15 -1
- package/dist/setup/wizard.d.ts.map +1 -1
- package/dist/setup/wizard.js +15 -0
- package/dist/setup/wizard.js.map +1 -1
- package/dist/skills/discovery.d.ts +12 -1
- package/dist/skills/discovery.d.ts.map +1 -1
- package/dist/skills/discovery.js +27 -2
- package/dist/skills/discovery.js.map +1 -1
- package/dist/skills/orchestrator/startup.d.ts.map +1 -1
- package/dist/skills/orchestrator/startup.js +10 -5
- package/dist/skills/orchestrator/startup.js.map +1 -1
- package/dist/skills/prune-bundled.d.ts +306 -0
- package/dist/skills/prune-bundled.d.ts.map +1 -0
- package/dist/skills/prune-bundled.js +652 -0
- package/dist/skills/prune-bundled.js.map +1 -0
- package/dist/skills/types.d.ts +9 -1
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/skills/types.js +17 -34
- package/dist/skills/types.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +26 -2
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/stats/index.d.ts.map +1 -1
- package/dist/stats/index.js +4 -2
- package/dist/stats/index.js.map +1 -1
- package/dist/store/agent-registry-accessor.d.ts.map +1 -1
- package/dist/store/agent-registry-accessor.js +2 -0
- package/dist/store/agent-registry-accessor.js.map +1 -1
- package/dist/store/backup-pack.js +1 -1
- package/dist/store/backup-pack.js.map +1 -1
- package/dist/store/backup.d.ts +15 -1
- package/dist/store/backup.d.ts.map +1 -1
- package/dist/store/backup.js +18 -2
- package/dist/store/backup.js.map +1 -1
- package/dist/store/conduit-sqlite.d.ts.map +1 -1
- package/dist/store/conduit-sqlite.js +3 -0
- package/dist/store/conduit-sqlite.js.map +1 -1
- package/dist/store/credential-transfer.d.ts.map +1 -1
- package/dist/store/credential-transfer.js +2 -0
- package/dist/store/credential-transfer.js.map +1 -1
- package/dist/store/cross-db-cleanup.d.ts.map +1 -1
- package/dist/store/cross-db-cleanup.js +2 -0
- package/dist/store/cross-db-cleanup.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +13 -2
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -1
- package/dist/store/migrate-signaldock-to-conduit.js +3 -0
- package/dist/store/migrate-signaldock-to-conduit.js.map +1 -1
- package/dist/store/migration-manager.d.ts.map +1 -1
- package/dist/store/migration-manager.js +37 -3
- package/dist/store/migration-manager.js.map +1 -1
- package/dist/store/migration-sqlite.d.ts.map +1 -1
- package/dist/store/migration-sqlite.js +2 -0
- package/dist/store/migration-sqlite.js.map +1 -1
- package/dist/store/nexus-sqlite.d.ts.map +1 -1
- package/dist/store/nexus-sqlite.js +3 -0
- package/dist/store/nexus-sqlite.js.map +1 -1
- package/dist/store/open-cleo-db.d.ts.map +1 -1
- package/dist/store/open-cleo-db.js +3 -0
- package/dist/store/open-cleo-db.js.map +1 -1
- package/dist/store/portable-bundle-import.d.ts.map +1 -1
- package/dist/store/portable-bundle-import.js +2 -0
- package/dist/store/portable-bundle-import.js.map +1 -1
- package/dist/store/portable-bundle-relocate.d.ts.map +1 -1
- package/dist/store/portable-bundle-relocate.js +2 -0
- package/dist/store/portable-bundle-relocate.js.map +1 -1
- package/dist/store/portable-bundle-scan.js +1 -1
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/ports/domain-binding.d.ts.map +1 -1
- package/dist/store/ports/domain-binding.js +5 -0
- package/dist/store/ports/domain-binding.js.map +1 -1
- package/dist/store/skills-db.d.ts +17 -0
- package/dist/store/skills-db.d.ts.map +1 -1
- package/dist/store/skills-db.js +30 -0
- package/dist/store/skills-db.js.map +1 -1
- package/dist/store/snapshot-gate.d.ts.map +1 -1
- package/dist/store/snapshot-gate.js +3 -0
- package/dist/store/snapshot-gate.js.map +1 -1
- package/dist/store/split-brain-import.d.ts.map +1 -1
- package/dist/store/split-brain-import.js +2 -0
- package/dist/store/split-brain-import.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +19 -2
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sqlite-native.d.ts.map +1 -1
- package/dist/store/sqlite-native.js +1 -0
- package/dist/store/sqlite-native.js.map +1 -1
- package/dist/store/sqlite.d.ts +14 -0
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +31 -4
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +46 -1
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +131 -5
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/worktree-build-guard.d.ts +191 -0
- package/dist/store/worktree-build-guard.d.ts.map +1 -0
- package/dist/store/worktree-build-guard.js +486 -0
- package/dist/store/worktree-build-guard.js.map +1 -0
- package/dist/store/worktree-isolation-guard.d.ts +27 -0
- package/dist/store/worktree-isolation-guard.d.ts.map +1 -1
- package/dist/store/worktree-isolation-guard.js +71 -3
- package/dist/store/worktree-isolation-guard.js.map +1 -1
- package/dist/store/writer-lease.d.ts.map +1 -1
- package/dist/store/writer-lease.js +2 -0
- package/dist/store/writer-lease.js.map +1 -1
- package/dist/system/backup.d.ts +6 -2
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/backup.js +6 -3
- package/dist/system/backup.js.map +1 -1
- package/dist/system/inject-generate.d.ts.map +1 -1
- package/dist/system/inject-generate.js +4 -4
- package/dist/system/inject-generate.js.map +1 -1
- package/dist/task-tools/index.d.ts +4 -2
- package/dist/task-tools/index.d.ts.map +1 -1
- package/dist/task-tools/index.js +3 -2
- package/dist/task-tools/index.js.map +1 -1
- package/dist/task-tools/score-task-priority.d.ts +93 -18
- package/dist/task-tools/score-task-priority.d.ts.map +1 -1
- package/dist/task-tools/score-task-priority.js +193 -81
- package/dist/task-tools/score-task-priority.js.map +1 -1
- package/dist/task-work/index.d.ts +6 -0
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +6 -3
- package/dist/task-work/index.js.map +1 -1
- package/dist/tasks/affected-packages.d.ts +62 -13
- package/dist/tasks/affected-packages.d.ts.map +1 -1
- package/dist/tasks/affected-packages.js +158 -33
- package/dist/tasks/affected-packages.js.map +1 -1
- package/dist/tasks/affected-scope.d.ts +59 -0
- package/dist/tasks/affected-scope.d.ts.map +1 -0
- package/dist/tasks/affected-scope.js +81 -0
- package/dist/tasks/affected-scope.js.map +1 -0
- package/dist/tasks/analyze.d.ts +29 -1
- package/dist/tasks/analyze.d.ts.map +1 -1
- package/dist/tasks/analyze.js +52 -36
- package/dist/tasks/analyze.js.map +1 -1
- package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
- package/dist/tasks/backfill-child-projections.js +4 -1
- package/dist/tasks/backfill-child-projections.js.map +1 -1
- package/dist/tasks/change-set.d.ts +24 -0
- package/dist/tasks/change-set.d.ts.map +1 -1
- package/dist/tasks/change-set.js +143 -11
- package/dist/tasks/change-set.js.map +1 -1
- package/dist/tasks/command-line.d.ts +54 -0
- package/dist/tasks/command-line.d.ts.map +1 -0
- package/dist/tasks/command-line.js +151 -0
- package/dist/tasks/command-line.js.map +1 -0
- package/dist/tasks/complete.d.ts +10 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +49 -0
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/component-pr.d.ts +106 -0
- package/dist/tasks/component-pr.d.ts.map +1 -0
- package/dist/tasks/component-pr.js +275 -0
- package/dist/tasks/component-pr.js.map +1 -0
- package/dist/tasks/delete.d.ts.map +1 -1
- package/dist/tasks/delete.js +20 -0
- package/dist/tasks/delete.js.map +1 -1
- package/dist/tasks/done-plan.d.ts +21 -1
- package/dist/tasks/done-plan.d.ts.map +1 -1
- package/dist/tasks/done-plan.js +170 -15
- package/dist/tasks/done-plan.js.map +1 -1
- package/dist/tasks/done-record.d.ts.map +1 -1
- package/dist/tasks/done-record.js +9 -80
- package/dist/tasks/done-record.js.map +1 -1
- package/dist/tasks/duplicate-detector.d.ts +3 -3
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +4 -3
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/tasks/engine-wrap-ops.d.ts +29 -0
- package/dist/tasks/engine-wrap-ops.d.ts.map +1 -1
- package/dist/tasks/engine-wrap-ops.js +40 -0
- package/dist/tasks/engine-wrap-ops.js.map +1 -1
- package/dist/tasks/engine-wrap.d.ts +1 -1
- package/dist/tasks/engine-wrap.d.ts.map +1 -1
- package/dist/tasks/engine-wrap.js +1 -1
- package/dist/tasks/engine-wrap.js.map +1 -1
- package/dist/tasks/evidence.d.ts +49 -2
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +85 -9
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +48 -12
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/ops.d.ts +1 -0
- package/dist/tasks/ops.d.ts.map +1 -1
- package/dist/tasks/ranking-audit.d.ts +122 -0
- package/dist/tasks/ranking-audit.d.ts.map +1 -0
- package/dist/tasks/ranking-audit.js +193 -0
- package/dist/tasks/ranking-audit.js.map +1 -0
- package/dist/tasks/task-analyze.d.ts.map +1 -1
- package/dist/tasks/task-analyze.js +19 -32
- package/dist/tasks/task-analyze.js.map +1 -1
- package/dist/tasks/task-next.d.ts +48 -2
- package/dist/tasks/task-next.d.ts.map +1 -1
- package/dist/tasks/task-next.js +84 -102
- package/dist/tasks/task-next.js.map +1 -1
- package/dist/tasks/task-ops.d.ts +1 -1
- package/dist/tasks/task-ops.d.ts.map +1 -1
- package/dist/tasks/task-ops.js +1 -1
- package/dist/tasks/task-ops.js.map +1 -1
- package/dist/tasks/tool-resolver.d.ts +7 -1
- package/dist/tasks/tool-resolver.d.ts.map +1 -1
- package/dist/tasks/tool-resolver.js +24 -10
- package/dist/tasks/tool-resolver.js.map +1 -1
- package/dist/tasks/update.d.ts +8 -2
- package/dist/tasks/update.d.ts.map +1 -1
- package/dist/tasks/update.js +28 -1
- package/dist/tasks/update.js.map +1 -1
- package/dist/telemetry/sqlite.d.ts.map +1 -1
- package/dist/telemetry/sqlite.js +2 -0
- package/dist/telemetry/sqlite.js.map +1 -1
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/doctor/checks.js +2 -2
- package/dist/validation/doctor/checks.js.map +1 -1
- package/dist/validation/engine-ops.d.ts +9 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +24 -1
- package/dist/validation/engine-ops.js.map +1 -1
- package/dist/validation/validate-ops.d.ts.map +1 -1
- package/dist/validation/validate-ops.js +9 -3
- package/dist/validation/validate-ops.js.map +1 -1
- package/dist/worktree/worktree-adopt.d.ts.map +1 -1
- package/dist/worktree/worktree-adopt.js +5 -2
- package/dist/worktree/worktree-adopt.js.map +1 -1
- package/package.json +14 -14
- package/schemas/config.schema.json +13 -0
- package/templates/CLEO-INJECTION.md +1 -1
- package/templates/CLEO-REFERENCE.md +5 -1
|
@@ -344,7 +344,7 @@ var init_acceptance_gate_schema = __esm({
|
|
|
344
344
|
message: "Result cannot precede input capture"
|
|
345
345
|
});
|
|
346
346
|
const executable = ["test", "command", "lint"].includes(result.kind);
|
|
347
|
-
if (executable && !binding.invocation)
|
|
347
|
+
if (executable && !binding.invocation && result.result !== "error")
|
|
348
348
|
context.addIssue({
|
|
349
349
|
code: "custom",
|
|
350
350
|
path: ["binding", "invocation"],
|
|
@@ -3086,12 +3086,21 @@ var init_operations_registry = __esm({
|
|
|
3086
3086
|
gateway: "query",
|
|
3087
3087
|
domain: "tasks",
|
|
3088
3088
|
operation: "history",
|
|
3089
|
-
description: "Show task work history
|
|
3089
|
+
description: "Show task work history; with taskId, the task audit trail; with ranking, who changed its priority/severity/kind/depends and why (T12693)",
|
|
3090
3090
|
tier: 1,
|
|
3091
3091
|
idempotent: true,
|
|
3092
3092
|
sessionRequired: false,
|
|
3093
3093
|
requiredParams: [],
|
|
3094
|
-
params: [
|
|
3094
|
+
params: [
|
|
3095
|
+
{ name: "taskId", type: "string", required: false, description: "Task to show history for" },
|
|
3096
|
+
{ name: "limit", type: "number", required: false, description: "Maximum entries" },
|
|
3097
|
+
{
|
|
3098
|
+
name: "ranking",
|
|
3099
|
+
type: "boolean",
|
|
3100
|
+
required: false,
|
|
3101
|
+
description: "Only ranking-input changes (actor, session, reason, before/after)"
|
|
3102
|
+
}
|
|
3103
|
+
]
|
|
3095
3104
|
},
|
|
3096
3105
|
{
|
|
3097
3106
|
gateway: "query",
|
|
@@ -5586,6 +5595,32 @@ var init_operations_registry = __esm({
|
|
|
5586
5595
|
],
|
|
5587
5596
|
outputSchema: OUTPUT_CONTRACTS["tasks.assignee"]
|
|
5588
5597
|
},
|
|
5598
|
+
{
|
|
5599
|
+
gateway: "mutate",
|
|
5600
|
+
domain: "tasks",
|
|
5601
|
+
operation: "ranking.revert",
|
|
5602
|
+
description: "tasks.ranking.revert (mutate) \u2014 undo one recorded ranking change (priority/severity/kind/depends) as a new audited change (T12693, D11161)",
|
|
5603
|
+
tier: 1,
|
|
5604
|
+
idempotent: false,
|
|
5605
|
+
sessionRequired: false,
|
|
5606
|
+
requiredParams: ["entryId"],
|
|
5607
|
+
params: [
|
|
5608
|
+
{
|
|
5609
|
+
name: "entryId",
|
|
5610
|
+
type: "string",
|
|
5611
|
+
required: true,
|
|
5612
|
+
description: "ranking_changed audit row id (cleo history ranking <taskId>)",
|
|
5613
|
+
cli: { positional: true }
|
|
5614
|
+
},
|
|
5615
|
+
{ name: "reason", type: "string", required: false, description: "Why it is reverted" },
|
|
5616
|
+
{
|
|
5617
|
+
name: "force",
|
|
5618
|
+
type: "boolean",
|
|
5619
|
+
required: false,
|
|
5620
|
+
description: "Revert even though a field changed again since"
|
|
5621
|
+
}
|
|
5622
|
+
]
|
|
5623
|
+
},
|
|
5589
5624
|
{
|
|
5590
5625
|
gateway: "mutate",
|
|
5591
5626
|
domain: "tasks",
|
|
@@ -10509,7 +10544,7 @@ var init_operations_registry = __esm({
|
|
|
10509
10544
|
type: "string",
|
|
10510
10545
|
required: false,
|
|
10511
10546
|
enum: DOCS_LIFECYCLE_STATUSES,
|
|
10512
|
-
description: `Override the new lifecycle status. Defaults to "draft" on every update. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
|
|
10547
|
+
description: `Override the new lifecycle status. Defaults to "draft" on every update. Alone (no file or content) it changes only the lifecycle status. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
|
|
10513
10548
|
},
|
|
10514
10549
|
{
|
|
10515
10550
|
name: "dryRun",
|
|
@@ -12996,11 +13031,13 @@ var init_evidence_atom_schema = __esm({
|
|
|
12996
13031
|
});
|
|
12997
13032
|
prAtomSchema = z10.object({
|
|
12998
13033
|
kind: z10.literal("pr"),
|
|
12999
|
-
prNumber: z10.number().int().positive("pr atom requires a positive integer PR number")
|
|
13034
|
+
prNumber: z10.number().int().positive("pr atom requires a positive integer PR number"),
|
|
13035
|
+
componentPrNumber: z10.number().int().positive().optional()
|
|
13000
13036
|
});
|
|
13001
13037
|
ciAtomSchema = z10.object({
|
|
13002
13038
|
kind: z10.literal("ci"),
|
|
13003
|
-
prNumber: z10.number().int().positive("ci atom requires a positive integer PR number")
|
|
13039
|
+
prNumber: z10.number().int().positive("ci atom requires a positive integer PR number"),
|
|
13040
|
+
componentPrNumber: z10.number().int().positive().optional()
|
|
13004
13041
|
});
|
|
13005
13042
|
locDropAtomSchema = z10.object({
|
|
13006
13043
|
kind: z10.literal("loc-drop"),
|
|
@@ -13051,7 +13088,10 @@ var init_evidence_atom_schema = __esm({
|
|
|
13051
13088
|
["commit", "note"],
|
|
13052
13089
|
["decision", "files"],
|
|
13053
13090
|
["decision", "note"],
|
|
13054
|
-
["pr", "files"]
|
|
13091
|
+
["pr", "files"],
|
|
13092
|
+
// T12689: a deletion-only PR (no bytes to hash). Contextual validation
|
|
13093
|
+
// accepts this only when every change the PR made is a deletion.
|
|
13094
|
+
["pr", "note"]
|
|
13055
13095
|
]
|
|
13056
13096
|
},
|
|
13057
13097
|
testsPassed: { oneOf: [["test-run"], ["tool"], ["ci"]] },
|
|
@@ -16953,7 +16993,7 @@ var init_collection_keys = __esm({
|
|
|
16953
16993
|
|
|
16954
16994
|
// packages/contracts/src/decide.ts
|
|
16955
16995
|
import { z as z24 } from "zod";
|
|
16956
|
-
var DECISION_QUESTION_TYPES, DECISION_OUTCOME_SOURCES, DECISION_REQUEST_LIMITS, decisionQuestionTypeSchema, decisionOutcomeSourceSchema, decisionInstructionsSchema, unitIntervalSchema, decisionStateSchema, noulDecisionQuestionSchema, choiceDecisionQuestionSchema, scoreDecisionQuestionSchema, decisionQuestionSchema, decisionRequestSchema, noulDecisionAnswerSchema, choiceDecisionAnswerSchema, scoreDecisionAnswerSchema, decisionAnswerSchema, decisionOutcomeSchema, decisionProviderConfigSchema;
|
|
16996
|
+
var DECISION_QUESTION_TYPES, DECISION_OUTCOME_SOURCES, DECISION_REQUEST_LIMITS, DECISION_PROVIDER_KINDS, decisionQuestionTypeSchema, decisionOutcomeSourceSchema, decisionInstructionsSchema, unitIntervalSchema, decisionStateSchema, noulDecisionQuestionSchema, choiceDecisionQuestionSchema, scoreDecisionQuestionSchema, decisionQuestionSchema, decisionRequestSchema, noulDecisionAnswerSchema, choiceDecisionAnswerSchema, scoreDecisionAnswerSchema, decisionAnswerSchema, decisionOutcomeSchema, decisionProviderKindSchema, decisionProviderConfigSchema;
|
|
16957
16997
|
var init_decide = __esm({
|
|
16958
16998
|
"packages/contracts/src/decide.ts"() {
|
|
16959
16999
|
"use strict";
|
|
@@ -16977,6 +17017,7 @@ var init_decide = __esm({
|
|
|
16977
17017
|
/** Maximum number of levels on a `score` question's scale. */
|
|
16978
17018
|
maxScoreLevels: 10
|
|
16979
17019
|
};
|
|
17020
|
+
DECISION_PROVIDER_KINDS = ["layahost", "jev"];
|
|
16980
17021
|
decisionQuestionTypeSchema = z24.enum(DECISION_QUESTION_TYPES);
|
|
16981
17022
|
decisionOutcomeSourceSchema = z24.enum(DECISION_OUTCOME_SOURCES);
|
|
16982
17023
|
decisionInstructionsSchema = z24.union([z24.string(), z24.record(z24.string(), z24.json())]);
|
|
@@ -17014,6 +17055,8 @@ var init_decide = __esm({
|
|
|
17014
17055
|
]);
|
|
17015
17056
|
decisionRequestSchema = z24.object({
|
|
17016
17057
|
model: z24.string().min(1).optional(),
|
|
17058
|
+
lang: z24.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$/).optional(),
|
|
17059
|
+
cache: z24.boolean().optional(),
|
|
17017
17060
|
state: decisionStateSchema,
|
|
17018
17061
|
questions: z24.record(z24.string().min(1), decisionQuestionSchema).refine(
|
|
17019
17062
|
(questions) => {
|
|
@@ -17054,14 +17097,26 @@ var init_decide = __esm({
|
|
|
17054
17097
|
requestId: z24.string().min(1).optional(),
|
|
17055
17098
|
latencyMs: z24.number().nonnegative(),
|
|
17056
17099
|
costUsd: z24.number().nonnegative().optional(),
|
|
17100
|
+
costMicros: z24.number().int().nonnegative().optional(),
|
|
17101
|
+
balanceMicros: z24.number().int().optional(),
|
|
17102
|
+
checkpoint: z24.string().min(1).optional(),
|
|
17057
17103
|
inputTokens: z24.number().int().nonnegative().optional()
|
|
17058
17104
|
});
|
|
17105
|
+
decisionProviderKindSchema = z24.enum(DECISION_PROVIDER_KINDS);
|
|
17059
17106
|
decisionProviderConfigSchema = z24.object({
|
|
17060
|
-
baseUrl: z24.url()
|
|
17107
|
+
baseUrl: z24.url(),
|
|
17108
|
+
provider: decisionProviderKindSchema.optional()
|
|
17061
17109
|
});
|
|
17062
17110
|
}
|
|
17063
17111
|
});
|
|
17064
17112
|
|
|
17113
|
+
// packages/contracts/src/decide-sites.ts
|
|
17114
|
+
var init_decide_sites = __esm({
|
|
17115
|
+
"packages/contracts/src/decide-sites.ts"() {
|
|
17116
|
+
"use strict";
|
|
17117
|
+
}
|
|
17118
|
+
});
|
|
17119
|
+
|
|
17065
17120
|
// packages/contracts/src/task-id.ts
|
|
17066
17121
|
var init_task_id = __esm({
|
|
17067
17122
|
"packages/contracts/src/task-id.ts"() {
|
|
@@ -17143,6 +17198,7 @@ var init_src = __esm({
|
|
|
17143
17198
|
init_caamp_markers();
|
|
17144
17199
|
init_collection_keys();
|
|
17145
17200
|
init_decide();
|
|
17201
|
+
init_decide_sites();
|
|
17146
17202
|
init_task_id();
|
|
17147
17203
|
}
|
|
17148
17204
|
});
|
|
@@ -18640,6 +18696,37 @@ function linkedWorktreeMainRoot(dir) {
|
|
|
18640
18696
|
if (basename2(commonDir) === ".git") return dirname2(commonDir);
|
|
18641
18697
|
return readCoreWorktree(commonDir);
|
|
18642
18698
|
}
|
|
18699
|
+
function describeWorktreeOwner(dir) {
|
|
18700
|
+
const mainRoot = linkedWorktreeMainRoot(dir);
|
|
18701
|
+
if (mainRoot === null) {
|
|
18702
|
+
const bare = bareRepositoryOfWorktree(dir);
|
|
18703
|
+
return bare === null ? "owning repository unknown (unreadable gitlink)" : `owning repository ${bare} is a bare git repository with no main checkout to hold a CLEO store; clone it to a regular checkout, run \`cleo init\` there, and create worktrees from that checkout`;
|
|
18704
|
+
}
|
|
18705
|
+
let projectId = null;
|
|
18706
|
+
try {
|
|
18707
|
+
const parsed = JSON.parse(
|
|
18708
|
+
readFileSync2(join3(mainRoot, ".cleo", "project-info.json"), "utf-8")
|
|
18709
|
+
);
|
|
18710
|
+
if (typeof parsed === "object" && parsed !== null && "projectId" in parsed) {
|
|
18711
|
+
const value = parsed.projectId;
|
|
18712
|
+
if (typeof value === "string" && value !== "") projectId = value;
|
|
18713
|
+
}
|
|
18714
|
+
} catch {
|
|
18715
|
+
}
|
|
18716
|
+
return projectId === null ? `owning repository ${mainRoot} (not an initialised CLEO project)` : `owning project ${mainRoot} (projectId ${projectId})`;
|
|
18717
|
+
}
|
|
18718
|
+
function bareRepositoryOfWorktree(dir) {
|
|
18719
|
+
const gitdir = readGitlinkTarget(dir);
|
|
18720
|
+
if (!gitdir || basename2(dirname2(gitdir)) !== "worktrees") return null;
|
|
18721
|
+
const commonDir = dirname2(dirname2(gitdir));
|
|
18722
|
+
try {
|
|
18723
|
+
const config = readFileSync2(join3(commonDir, "config"), "utf-8");
|
|
18724
|
+
const core = /^\[core\][^[]*/m.exec(config)?.[0] ?? "";
|
|
18725
|
+
return /^\s*bare\s*=\s*true\s*$/im.test(core) ? commonDir : null;
|
|
18726
|
+
} catch {
|
|
18727
|
+
return null;
|
|
18728
|
+
}
|
|
18729
|
+
}
|
|
18643
18730
|
function readCoreWorktree(gitDir) {
|
|
18644
18731
|
try {
|
|
18645
18732
|
const config = readFileSync2(join3(gitDir, "config"), "utf-8");
|
|
@@ -19089,13 +19176,13 @@ function captureWriteFence(input) {
|
|
|
19089
19176
|
return writeFence;
|
|
19090
19177
|
}
|
|
19091
19178
|
function observeOperation(context, work) {
|
|
19092
|
-
return new Promise((
|
|
19179
|
+
return new Promise((resolve16) => {
|
|
19093
19180
|
let observed = false;
|
|
19094
19181
|
const finish = (result) => {
|
|
19095
19182
|
if (observed) return;
|
|
19096
19183
|
observed = true;
|
|
19097
19184
|
context.signal.removeEventListener("abort", abort);
|
|
19098
|
-
|
|
19185
|
+
resolve16(result);
|
|
19099
19186
|
};
|
|
19100
19187
|
const abort = () => {
|
|
19101
19188
|
const reason = context.signal.reason;
|
|
@@ -19729,7 +19816,7 @@ var init_sql = __esm({
|
|
|
19729
19816
|
return new SQL([new StringChunk(str)]);
|
|
19730
19817
|
}
|
|
19731
19818
|
_sql.raw = raw;
|
|
19732
|
-
function
|
|
19819
|
+
function join36(chunks, separator) {
|
|
19733
19820
|
const result = [];
|
|
19734
19821
|
for (const [i, chunk] of chunks.entries()) {
|
|
19735
19822
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -19737,7 +19824,7 @@ var init_sql = __esm({
|
|
|
19737
19824
|
}
|
|
19738
19825
|
return new SQL(result);
|
|
19739
19826
|
}
|
|
19740
|
-
_sql.join =
|
|
19827
|
+
_sql.join = join36;
|
|
19741
19828
|
function identifier2(value) {
|
|
19742
19829
|
return new Name(value);
|
|
19743
19830
|
}
|
|
@@ -21752,7 +21839,7 @@ var init_select = __esm({
|
|
|
21752
21839
|
const baseTableName = this.tableName;
|
|
21753
21840
|
const tableName = getTableLikeName(table);
|
|
21754
21841
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
21755
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
21842
|
+
if (typeof tableName === "string" && this.config.joins?.some((join36) => join36.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
21756
21843
|
if (!this.isPartialSelect) {
|
|
21757
21844
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
21758
21845
|
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
@@ -23349,7 +23436,7 @@ var init_dialect = __esm({
|
|
|
23349
23436
|
if (!joins2) return;
|
|
23350
23437
|
const withEntries = Object.entries(joins2).filter(([_, v]) => v);
|
|
23351
23438
|
if (!withEntries.length) return;
|
|
23352
|
-
return sql.join(withEntries.map(([k,
|
|
23439
|
+
return sql.join(withEntries.map(([k, join36]) => {
|
|
23353
23440
|
const relation = tableConfig.relations[k];
|
|
23354
23441
|
const isSingle2 = is(relation, One);
|
|
23355
23442
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -23360,7 +23447,7 @@ var init_dialect = __esm({
|
|
|
23360
23447
|
table: targetTable,
|
|
23361
23448
|
mode: isSingle2 ? "first" : "many",
|
|
23362
23449
|
schema,
|
|
23363
|
-
queryConfig:
|
|
23450
|
+
queryConfig: join36,
|
|
23364
23451
|
tableConfig: schema[relation.targetTableName],
|
|
23365
23452
|
relationWhere: filter,
|
|
23366
23453
|
isNested: true,
|
|
@@ -23374,7 +23461,7 @@ var init_dialect = __esm({
|
|
|
23374
23461
|
key: k,
|
|
23375
23462
|
selection: innerQuery.selection,
|
|
23376
23463
|
isArray: !isSingle2,
|
|
23377
|
-
isOptional: (relation.optional ?? false) ||
|
|
23464
|
+
isOptional: (relation.optional ?? false) || join36 !== true && !!join36.where
|
|
23378
23465
|
});
|
|
23379
23466
|
const jsonColumns = sql.join(innerQuery.selection.map((s) => {
|
|
23380
23467
|
return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
|
|
@@ -23796,7 +23883,7 @@ var init_update = __esm({
|
|
|
23796
23883
|
createJoin(joinType) {
|
|
23797
23884
|
return ((table, on) => {
|
|
23798
23885
|
const tableName = getTableLikeName(table);
|
|
23799
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
23886
|
+
if (typeof tableName === "string" && this.config.joins.some((join36) => join36.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
23800
23887
|
if (typeof on === "function") {
|
|
23801
23888
|
const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
|
|
23802
23889
|
on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -24952,7 +25039,7 @@ async function withWriteRetry(fn, opts = {}) {
|
|
|
24952
25039
|
throw contentionErr;
|
|
24953
25040
|
}
|
|
24954
25041
|
function sleep(ms) {
|
|
24955
|
-
return new Promise((
|
|
25042
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
24956
25043
|
}
|
|
24957
25044
|
var DEFAULT_MAX_ATTEMPTS, DEFAULT_BASE_DELAY_MS, DEFAULT_JITTER_MS;
|
|
24958
25045
|
var init_with_retry = __esm({
|
|
@@ -24964,9 +25051,250 @@ var init_with_retry = __esm({
|
|
|
24964
25051
|
}
|
|
24965
25052
|
});
|
|
24966
25053
|
|
|
25054
|
+
// packages/core/src/store/worktree-build-guard.ts
|
|
25055
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
25056
|
+
import { createRequire } from "node:module";
|
|
25057
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
25058
|
+
import { fileURLToPath } from "node:url";
|
|
25059
|
+
function realOrResolved(path2) {
|
|
25060
|
+
try {
|
|
25061
|
+
return realpathSync3(path2);
|
|
25062
|
+
} catch {
|
|
25063
|
+
return resolve2(path2);
|
|
25064
|
+
}
|
|
25065
|
+
}
|
|
25066
|
+
function isWithin(root, path2) {
|
|
25067
|
+
const local = relative2(root, path2);
|
|
25068
|
+
return local === "" || !isAbsolute3(local) && local !== ".." && !local.startsWith(`..${sep2}`);
|
|
25069
|
+
}
|
|
25070
|
+
function insideGitCheckout(dir) {
|
|
25071
|
+
let current = dir;
|
|
25072
|
+
for (; ; ) {
|
|
25073
|
+
if (existsSync4(join5(current, ".git"))) return true;
|
|
25074
|
+
const parent = dirname3(current);
|
|
25075
|
+
if (parent === current) return false;
|
|
25076
|
+
current = parent;
|
|
25077
|
+
}
|
|
25078
|
+
}
|
|
25079
|
+
function insideTestSandbox(path2) {
|
|
25080
|
+
let dir = dirname3(path2);
|
|
25081
|
+
for (; ; ) {
|
|
25082
|
+
if (existsSync4(join5(dir, TEST_SANDBOX_MARKER))) return !insideGitCheckout(dir);
|
|
25083
|
+
const parent = dirname3(dir);
|
|
25084
|
+
if (parent === dir) return false;
|
|
25085
|
+
dir = parent;
|
|
25086
|
+
}
|
|
25087
|
+
}
|
|
25088
|
+
function linkedWorktreeRootOf(path2) {
|
|
25089
|
+
let dir = realOrResolved(path2);
|
|
25090
|
+
for (; ; ) {
|
|
25091
|
+
if (isGitLinkedCheckout(dir)) return dir;
|
|
25092
|
+
if (existsSync4(join5(dir, ".git"))) return null;
|
|
25093
|
+
const parent = dirname3(dir);
|
|
25094
|
+
if (parent === dir) return null;
|
|
25095
|
+
dir = parent;
|
|
25096
|
+
}
|
|
25097
|
+
}
|
|
25098
|
+
function readBuildProvenance(codePath) {
|
|
25099
|
+
let dir = dirname3(codePath);
|
|
25100
|
+
for (; ; ) {
|
|
25101
|
+
const stamp = join5(dir, "build-provenance.json");
|
|
25102
|
+
if (existsSync4(stamp)) {
|
|
25103
|
+
try {
|
|
25104
|
+
const parsed = JSON.parse(readFileSync3(stamp, "utf8"));
|
|
25105
|
+
if (typeof parsed === "object" && parsed !== null && "linkedWorktree" in parsed) {
|
|
25106
|
+
const value = parsed.linkedWorktree;
|
|
25107
|
+
if (value === null || typeof value === "string") return { linkedWorktree: value };
|
|
25108
|
+
}
|
|
25109
|
+
} catch {
|
|
25110
|
+
}
|
|
25111
|
+
return null;
|
|
25112
|
+
}
|
|
25113
|
+
if (existsSync4(join5(dir, "package.json"))) return null;
|
|
25114
|
+
const parent = dirname3(dir);
|
|
25115
|
+
if (parent === dir) return null;
|
|
25116
|
+
dir = parent;
|
|
25117
|
+
}
|
|
25118
|
+
}
|
|
25119
|
+
function devBuildWorktree(options = {}) {
|
|
25120
|
+
const codePath = options.codePath ?? overrides?.codePath ?? fileURLToPath(import.meta.url);
|
|
25121
|
+
const provenance = options.provenance !== void 0 ? options.provenance : overrides?.provenance !== void 0 ? overrides.provenance : readBuildProvenance(codePath);
|
|
25122
|
+
if (provenance) return provenance.linkedWorktree;
|
|
25123
|
+
if (codePath.split(/[\\/]/).includes("node_modules")) return null;
|
|
25124
|
+
return linkedWorktreeRootOf(codePath);
|
|
25125
|
+
}
|
|
25126
|
+
function schemaWriteRefusal(dbPath, options = {}) {
|
|
25127
|
+
const env = options.env ?? overrides?.env ?? process.env;
|
|
25128
|
+
const buildWorktree = devBuildWorktree(options);
|
|
25129
|
+
if (buildWorktree === null) return null;
|
|
25130
|
+
const store = realOrResolved(dbPath);
|
|
25131
|
+
if (isWithin(realOrResolved(buildWorktree), store)) return null;
|
|
25132
|
+
if (env["VITEST"]) return null;
|
|
25133
|
+
const honourTestSandbox = options.honourTestSandbox ?? overrides?.honourTestSandbox ?? true;
|
|
25134
|
+
if (honourTestSandbox && insideTestSandbox(store)) return null;
|
|
25135
|
+
if (env[ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV] === "1") return null;
|
|
25136
|
+
return `Refusing to change the schema of ${store}: this CLI was built inside the git worktree ${buildWorktree}, and its schema may be unreleased. Run the released \`cleo\` against this store, or opt in with ${ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV}=1 (T12687).`;
|
|
25137
|
+
}
|
|
25138
|
+
function decisionFor(dbPath) {
|
|
25139
|
+
const key = realOrResolved(dbPath);
|
|
25140
|
+
if (!decisions.has(key)) decisions.set(key, schemaWriteRefusal(key));
|
|
25141
|
+
return decisions.get(key) ?? null;
|
|
25142
|
+
}
|
|
25143
|
+
function isWorktreeBuildSchemaError(error) {
|
|
25144
|
+
return error instanceof Error && error.message.includes(E_WORKTREE_BUILD_SCHEMA);
|
|
25145
|
+
}
|
|
25146
|
+
function codes() {
|
|
25147
|
+
if (authorizerCodes) return authorizerCodes;
|
|
25148
|
+
const sqlite = createRequire(import.meta.url)("node:sqlite").constants;
|
|
25149
|
+
authorizerCodes = {
|
|
25150
|
+
sqlite,
|
|
25151
|
+
creates: /* @__PURE__ */ new Map([
|
|
25152
|
+
[sqlite.SQLITE_CREATE_TABLE, "table"],
|
|
25153
|
+
[sqlite.SQLITE_CREATE_VTABLE, "table"],
|
|
25154
|
+
[sqlite.SQLITE_CREATE_INDEX, "index"],
|
|
25155
|
+
[sqlite.SQLITE_CREATE_TRIGGER, "trigger"],
|
|
25156
|
+
[sqlite.SQLITE_CREATE_VIEW, "view"]
|
|
25157
|
+
]),
|
|
25158
|
+
changes: /* @__PURE__ */ new Set([
|
|
25159
|
+
sqlite.SQLITE_ALTER_TABLE,
|
|
25160
|
+
sqlite.SQLITE_DROP_TABLE,
|
|
25161
|
+
sqlite.SQLITE_DROP_INDEX,
|
|
25162
|
+
sqlite.SQLITE_DROP_TRIGGER,
|
|
25163
|
+
sqlite.SQLITE_DROP_VIEW,
|
|
25164
|
+
sqlite.SQLITE_DROP_VTABLE
|
|
25165
|
+
])
|
|
25166
|
+
};
|
|
25167
|
+
return authorizerCodes;
|
|
25168
|
+
}
|
|
25169
|
+
function attachRefusal(name2) {
|
|
25170
|
+
if (name2 === "" || name2 === ":memory:") return null;
|
|
25171
|
+
if (typeof name2 !== "string" || /^file:/i.test(name2) || name2.includes("?")) {
|
|
25172
|
+
return UNKNOWN_ATTACH_REFUSAL;
|
|
25173
|
+
}
|
|
25174
|
+
return decisionFor(name2);
|
|
25175
|
+
}
|
|
25176
|
+
function readSchemas(nativeDb) {
|
|
25177
|
+
const schemas = /* @__PURE__ */ new Map();
|
|
25178
|
+
const list = nativeDb.prepare("PRAGMA database_list").all();
|
|
25179
|
+
for (const { name: name2, file } of list) {
|
|
25180
|
+
if (name2 === "temp") continue;
|
|
25181
|
+
const rows = nativeDb.prepare(`SELECT type, name FROM "${name2.replaceAll('"', '""')}".sqlite_master`).all();
|
|
25182
|
+
schemas.set(name2.toLowerCase(), {
|
|
25183
|
+
refusal: file ? decisionFor(file) : null,
|
|
25184
|
+
// '' = in-memory
|
|
25185
|
+
objects: new Set(rows.map((r) => `${r.type}:${r.name}`))
|
|
25186
|
+
});
|
|
25187
|
+
}
|
|
25188
|
+
return schemas;
|
|
25189
|
+
}
|
|
25190
|
+
function guardActive() {
|
|
25191
|
+
const env = overrides?.env ?? process.env;
|
|
25192
|
+
if (env["VITEST"]) return false;
|
|
25193
|
+
if (overrides) return devBuildWorktree() !== null;
|
|
25194
|
+
if (processBuildWorktree === void 0) processBuildWorktree = devBuildWorktree();
|
|
25195
|
+
return processBuildWorktree !== null;
|
|
25196
|
+
}
|
|
25197
|
+
function installSchemaWriteGuard(nativeDb) {
|
|
25198
|
+
if (!guardActive()) return false;
|
|
25199
|
+
const location = nativeDb.location();
|
|
25200
|
+
const mainRefusal = location ? decisionFor(location) : null;
|
|
25201
|
+
if (typeof nativeDb.setAuthorizer !== "function") {
|
|
25202
|
+
if (mainRefusal) throw new WorktreeBuildSchemaError(mainRefusal);
|
|
25203
|
+
return false;
|
|
25204
|
+
}
|
|
25205
|
+
const state = {
|
|
25206
|
+
schemas: readSchemas(nativeDb),
|
|
25207
|
+
unmappedAttachRefusal: null,
|
|
25208
|
+
stale: false,
|
|
25209
|
+
lastDenied: null
|
|
25210
|
+
};
|
|
25211
|
+
guards.set(nativeDb, state);
|
|
25212
|
+
const { sqlite, creates, changes } = codes();
|
|
25213
|
+
nativeDb.setAuthorizer((action, arg1, arg2, dbName) => {
|
|
25214
|
+
if (action === sqlite.SQLITE_ATTACH) {
|
|
25215
|
+
const refusal2 = attachRefusal(arg1);
|
|
25216
|
+
if (refusal2 && !state.unmappedAttachRefusal) state.unmappedAttachRefusal = refusal2;
|
|
25217
|
+
return sqlite.SQLITE_OK;
|
|
25218
|
+
}
|
|
25219
|
+
if (action === sqlite.SQLITE_DETACH) {
|
|
25220
|
+
state.stale = true;
|
|
25221
|
+
return sqlite.SQLITE_OK;
|
|
25222
|
+
}
|
|
25223
|
+
const createType = creates.get(action);
|
|
25224
|
+
if (createType === void 0 && !changes.has(action)) return sqlite.SQLITE_OK;
|
|
25225
|
+
const schema = ((action === sqlite.SQLITE_ALTER_TABLE ? arg1 : dbName) ?? "main").toLowerCase();
|
|
25226
|
+
if (schema === "temp") return sqlite.SQLITE_OK;
|
|
25227
|
+
const mapped = state.schemas.get(schema);
|
|
25228
|
+
const policy = state.stale ? void 0 : mapped;
|
|
25229
|
+
const refusal = policy ? policy.refusal : (mapped?.refusal ?? null) || state.unmappedAttachRefusal;
|
|
25230
|
+
if (refusal === null) return sqlite.SQLITE_OK;
|
|
25231
|
+
if (createType !== void 0 && policy?.objects.has(`${createType}:${arg1}`)) {
|
|
25232
|
+
return sqlite.SQLITE_OK;
|
|
25233
|
+
}
|
|
25234
|
+
state.lastDenied = {
|
|
25235
|
+
what: createType !== void 0 ? `CREATE ${createType} ${schema}.${arg1}` : `schema change on ${schema}.${(action === sqlite.SQLITE_ALTER_TABLE ? arg2 : arg1) ?? ""}`,
|
|
25236
|
+
refusal
|
|
25237
|
+
};
|
|
25238
|
+
return sqlite.SQLITE_DENY;
|
|
25239
|
+
});
|
|
25240
|
+
return mainRefusal !== null;
|
|
25241
|
+
}
|
|
25242
|
+
function refreshSchemaWriteGuard(nativeDb) {
|
|
25243
|
+
const state = guards.get(nativeDb);
|
|
25244
|
+
if (!state) return;
|
|
25245
|
+
state.schemas = readSchemas(nativeDb);
|
|
25246
|
+
state.unmappedAttachRefusal = null;
|
|
25247
|
+
state.stale = false;
|
|
25248
|
+
}
|
|
25249
|
+
function explainSchemaWriteDenial(nativeDb, error) {
|
|
25250
|
+
if (!(error instanceof Error) || !/not authorized/i.test(error.message)) return error;
|
|
25251
|
+
const denied = guards.get(nativeDb)?.lastDenied;
|
|
25252
|
+
if (!denied) return error;
|
|
25253
|
+
return new WorktreeBuildSchemaError(`${denied.refusal} Denied: ${denied.what}.`);
|
|
25254
|
+
}
|
|
25255
|
+
function pendingMigrations(nativeDb, migrations) {
|
|
25256
|
+
const hasJournal = nativeDb.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '__drizzle_migrations'").get();
|
|
25257
|
+
const applied = hasJournal ? new Set(
|
|
25258
|
+
nativeDb.prepare('SELECT hash FROM main."__drizzle_migrations"').all().map((row) => row.hash)
|
|
25259
|
+
) : /* @__PURE__ */ new Set();
|
|
25260
|
+
return migrations.filter((m) => !applied.has(m.hash)).map((m) => m.name ?? m.hash);
|
|
25261
|
+
}
|
|
25262
|
+
function assertNoPendingMigrationsForWorktreeBuild(nativeDb, migrations) {
|
|
25263
|
+
const dbPath = nativeDb.location();
|
|
25264
|
+
if (!dbPath) return;
|
|
25265
|
+
const refusal = decisionFor(dbPath);
|
|
25266
|
+
if (refusal === null) return;
|
|
25267
|
+
const pending = pendingMigrations(nativeDb, migrations);
|
|
25268
|
+
if (pending.length === 0) return;
|
|
25269
|
+
throw new WorktreeBuildSchemaError(`${refusal} Pending migrations: ${pending.join(", ")}.`);
|
|
25270
|
+
}
|
|
25271
|
+
var ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV, TEST_SANDBOX_MARKER, E_WORKTREE_BUILD_SCHEMA, overrides, decisions, WorktreeBuildSchemaError, authorizerCodes, guards, UNKNOWN_ATTACH_REFUSAL, processBuildWorktree;
|
|
25272
|
+
var init_worktree_build_guard = __esm({
|
|
25273
|
+
"packages/core/src/store/worktree-build-guard.ts"() {
|
|
25274
|
+
"use strict";
|
|
25275
|
+
init_src();
|
|
25276
|
+
init_errors2();
|
|
25277
|
+
init_project_scope();
|
|
25278
|
+
ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV = "CLEO_ALLOW_WORKTREE_BUILD_MIGRATIONS";
|
|
25279
|
+
TEST_SANDBOX_MARKER = ".cleo-test-sandbox";
|
|
25280
|
+
E_WORKTREE_BUILD_SCHEMA = "E_WORKTREE_BUILD_SCHEMA";
|
|
25281
|
+
overrides = null;
|
|
25282
|
+
decisions = /* @__PURE__ */ new Map();
|
|
25283
|
+
WorktreeBuildSchemaError = class extends CleoError {
|
|
25284
|
+
constructor(message) {
|
|
25285
|
+
super(8 /* CONFIG_ERROR */, `${E_WORKTREE_BUILD_SCHEMA}: ${message}`, {
|
|
25286
|
+
fix: `Use the released \`cleo\` for this store, run the build against a store inside its own worktree, or set ${ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV}=1 to accept the schema change.`
|
|
25287
|
+
});
|
|
25288
|
+
}
|
|
25289
|
+
};
|
|
25290
|
+
guards = /* @__PURE__ */ new WeakMap();
|
|
25291
|
+
UNKNOWN_ATTACH_REFUSAL = "a store was ATTACHed by a bound, computed or URI filename, so this build cannot tell whose store it is; schema changes on unmapped schemas are refused until the guard is refreshed";
|
|
25292
|
+
}
|
|
25293
|
+
});
|
|
25294
|
+
|
|
24967
25295
|
// packages/core/src/store/migration-manager.ts
|
|
24968
|
-
import { copyFileSync, existsSync as
|
|
24969
|
-
import { dirname as
|
|
25296
|
+
import { copyFileSync, existsSync as existsSync5 } from "node:fs";
|
|
25297
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
24970
25298
|
function stripSqlComments(sql32) {
|
|
24971
25299
|
return sql32.replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
24972
25300
|
}
|
|
@@ -25005,10 +25333,10 @@ function computeEliminatedTables(migrations) {
|
|
|
25005
25333
|
return eliminated;
|
|
25006
25334
|
}
|
|
25007
25335
|
function resolveConsolidationCutoverPrefix(migrationsFolder) {
|
|
25008
|
-
const parent =
|
|
25336
|
+
const parent = dirname4(migrationsFolder);
|
|
25009
25337
|
for (const setName of ["drizzle-cleo-project", "drizzle-cleo-global"]) {
|
|
25010
|
-
const folder =
|
|
25011
|
-
if (!
|
|
25338
|
+
const folder = join6(parent, setName);
|
|
25339
|
+
if (!existsSync5(folder)) continue;
|
|
25012
25340
|
try {
|
|
25013
25341
|
const consolidation = readMigrationFiles({ migrationsFolder: folder }).find(
|
|
25014
25342
|
(m) => /-consolidation-cleo-/.test(m.name ?? "")
|
|
@@ -25032,7 +25360,7 @@ function tableExists(nativeDb, tableName) {
|
|
|
25032
25360
|
}
|
|
25033
25361
|
function createSafetyBackup(dbPath) {
|
|
25034
25362
|
const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
|
|
25035
|
-
if (!
|
|
25363
|
+
if (!existsSync5(backupPath)) {
|
|
25036
25364
|
try {
|
|
25037
25365
|
copyFileSync(dbPath, backupPath);
|
|
25038
25366
|
} catch {
|
|
@@ -25150,6 +25478,16 @@ function readSiblingMigrationHashes(siblingFolder) {
|
|
|
25150
25478
|
return /* @__PURE__ */ new Set();
|
|
25151
25479
|
}
|
|
25152
25480
|
}
|
|
25481
|
+
function readSiblingNewestMillis(siblingFolder) {
|
|
25482
|
+
try {
|
|
25483
|
+
return Math.max(
|
|
25484
|
+
0,
|
|
25485
|
+
...readMigrationFiles({ migrationsFolder: siblingFolder }).map((m) => m.folderMillis)
|
|
25486
|
+
);
|
|
25487
|
+
} catch {
|
|
25488
|
+
return 0;
|
|
25489
|
+
}
|
|
25490
|
+
}
|
|
25153
25491
|
function ensureJournalHashUnique(nativeDb) {
|
|
25154
25492
|
if (!tableExists(nativeDb, "__drizzle_migrations")) return;
|
|
25155
25493
|
try {
|
|
@@ -25198,6 +25536,7 @@ function upgradeSharedJournalFormat(nativeDb, lineageFolders) {
|
|
|
25198
25536
|
return { named, unnamed: rows.length - named };
|
|
25199
25537
|
}
|
|
25200
25538
|
function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsystem, siblingMigrationsFolders = []) {
|
|
25539
|
+
assertNoPendingMigrationsForWorktreeBuild(nativeDb, readMigrationFiles({ migrationsFolder }));
|
|
25201
25540
|
const eliminatedTables = computeEliminatedTables(readMigrationFiles({ migrationsFolder }));
|
|
25202
25541
|
const cutoverPrefix = resolveConsolidationCutoverPrefix(migrationsFolder);
|
|
25203
25542
|
if (siblingMigrationsFolders.length > 0)
|
|
@@ -25229,8 +25568,15 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
|
|
|
25229
25568
|
knownHashes.add(m);
|
|
25230
25569
|
}
|
|
25231
25570
|
}
|
|
25232
|
-
const
|
|
25233
|
-
|
|
25571
|
+
const newestKnownMillis = Math.max(
|
|
25572
|
+
0,
|
|
25573
|
+
...localMigrations.map((m) => m.folderMillis),
|
|
25574
|
+
...siblingMigrationsFolders.filter((folder) => folder !== migrationsFolder).map(readSiblingNewestMillis)
|
|
25575
|
+
);
|
|
25576
|
+
const dbEntries = nativeDb.prepare('SELECT id, hash, created_at FROM "__drizzle_migrations"').all();
|
|
25577
|
+
const orphanedEntries = dbEntries.filter(
|
|
25578
|
+
(e) => !knownHashes.has(e.hash) && !(Number(e.created_at) > newestKnownMillis)
|
|
25579
|
+
);
|
|
25234
25580
|
const hasOrphanedEntries = orphanedEntries.length > 0;
|
|
25235
25581
|
if (hasOrphanedEntries) {
|
|
25236
25582
|
const dbHashes = new Set(dbEntries.map((e) => e.hash));
|
|
@@ -25472,6 +25818,8 @@ function sanitizeMigrationStatements(migrations) {
|
|
|
25472
25818
|
}
|
|
25473
25819
|
function migrateSanitized(db, config) {
|
|
25474
25820
|
const raw = readMigrationFiles(config);
|
|
25821
|
+
const client = db.$client;
|
|
25822
|
+
if (client) assertNoPendingMigrationsForWorktreeBuild(client, raw);
|
|
25475
25823
|
const sanitized = sanitizeMigrationStatements(raw);
|
|
25476
25824
|
migrateSync(sanitized, db._.session, config);
|
|
25477
25825
|
}
|
|
@@ -25535,6 +25883,7 @@ var init_migration_manager = __esm({
|
|
|
25535
25883
|
init_sqlite_core();
|
|
25536
25884
|
init_logger2();
|
|
25537
25885
|
init_with_retry();
|
|
25886
|
+
init_worktree_build_guard();
|
|
25538
25887
|
MAX_MIGRATION_RETRIES = 5;
|
|
25539
25888
|
MIGRATION_RETRY_BASE_DELAY_MS = 100;
|
|
25540
25889
|
MIGRATION_RETRY_MAX_DELAY_MS = 2e3;
|
|
@@ -25544,13 +25893,13 @@ var init_migration_manager = __esm({
|
|
|
25544
25893
|
});
|
|
25545
25894
|
|
|
25546
25895
|
// packages/core/src/store/relocated-store-guard.ts
|
|
25547
|
-
import { existsSync as
|
|
25548
|
-
import { createRequire } from "node:module";
|
|
25549
|
-
import { basename as basename3, dirname as
|
|
25896
|
+
import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
25897
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
25898
|
+
import { basename as basename3, dirname as dirname5 } from "node:path";
|
|
25550
25899
|
import { readDeclaredProjectIdentity as readDeclaredProjectIdentity2, readPortableProjectId } from "@cleocode/paths";
|
|
25551
25900
|
function real2(p) {
|
|
25552
25901
|
try {
|
|
25553
|
-
return
|
|
25902
|
+
return realpathSync4(p);
|
|
25554
25903
|
} catch {
|
|
25555
25904
|
return p;
|
|
25556
25905
|
}
|
|
@@ -25567,7 +25916,7 @@ function liveElsewhere(globalDbPath, projectId, root) {
|
|
|
25567
25916
|
"SELECT project_path AS projectPath FROM nexus_project_registry WHERE project_id = ?"
|
|
25568
25917
|
).get(projectId);
|
|
25569
25918
|
const live = row?.projectPath;
|
|
25570
|
-
if (!live || paths.has(live) || !
|
|
25919
|
+
if (!live || paths.has(live) || !existsSync6(live)) return null;
|
|
25571
25920
|
if (!isStrictlyInsideDir(root, live)) return null;
|
|
25572
25921
|
return readDeclaredProjectIdentity2(live)?.projectId === projectId ? live : null;
|
|
25573
25922
|
} catch {
|
|
@@ -25581,14 +25930,14 @@ function detectRelocatedRoot(root, globalDbPath) {
|
|
|
25581
25930
|
if (tombstone)
|
|
25582
25931
|
return { projectId: tombstone.projectId, movedTo: tombstone.movedTo, via: "tombstone" };
|
|
25583
25932
|
const declared = readPortableProjectId(root);
|
|
25584
|
-
if (declared.status !== "valid" || !
|
|
25933
|
+
if (declared.status !== "valid" || !existsSync6(globalDbPath)) return null;
|
|
25585
25934
|
const movedTo = liveElsewhere(globalDbPath, declared.projectId, root);
|
|
25586
25935
|
return movedTo ? { projectId: declared.projectId, movedTo, via: "registry" } : null;
|
|
25587
25936
|
}
|
|
25588
25937
|
function assertStoreNotRelocated(dbPath, globalDbPath) {
|
|
25589
|
-
if (basename3(dbPath) !== "cleo.db" || basename3(
|
|
25590
|
-
if (
|
|
25591
|
-
const root =
|
|
25938
|
+
if (basename3(dbPath) !== "cleo.db" || basename3(dirname5(dbPath)) !== ".cleo") return;
|
|
25939
|
+
if (existsSync6(dbPath) || globalDbPath === dbPath) return;
|
|
25940
|
+
const root = dirname5(dirname5(dbPath));
|
|
25592
25941
|
if (_adopted.has(root)) return;
|
|
25593
25942
|
const moved = detectRelocatedRoot(root, globalDbPath);
|
|
25594
25943
|
if (moved) throw projectMovedError(root, moved, void 0, moved.via);
|
|
@@ -25598,17 +25947,17 @@ var init_relocated_store_guard = __esm({
|
|
|
25598
25947
|
"packages/core/src/store/relocated-store-guard.ts"() {
|
|
25599
25948
|
"use strict";
|
|
25600
25949
|
init_project_tombstone();
|
|
25601
|
-
_require =
|
|
25950
|
+
_require = createRequire2(import.meta.url);
|
|
25602
25951
|
_adopted = /* @__PURE__ */ new Set();
|
|
25603
25952
|
}
|
|
25604
25953
|
});
|
|
25605
25954
|
|
|
25606
25955
|
// packages/core/src/store/resolve-migrations-folder.ts
|
|
25607
|
-
import { createRequire as
|
|
25608
|
-
import { dirname as
|
|
25609
|
-
import { fileURLToPath } from "node:url";
|
|
25956
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
25957
|
+
import { dirname as dirname6, join as join7 } from "node:path";
|
|
25958
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
25610
25959
|
function coreRootFromEntry(entryPath) {
|
|
25611
|
-
return
|
|
25960
|
+
return dirname6(dirname6(entryPath));
|
|
25612
25961
|
}
|
|
25613
25962
|
function resolveConsolidatedJournalSiblings(ownSetName) {
|
|
25614
25963
|
return CONSOLIDATED_JOURNAL_LINEAGES.filter((name2) => name2 !== ownSetName).map(
|
|
@@ -25618,14 +25967,14 @@ function resolveConsolidatedJournalSiblings(ownSetName) {
|
|
|
25618
25967
|
function resolveCorePackageMigrationsFolder(setName) {
|
|
25619
25968
|
try {
|
|
25620
25969
|
const resolved = import.meta.resolve("@cleocode/core", import.meta.url);
|
|
25621
|
-
const entryPath =
|
|
25622
|
-
return
|
|
25970
|
+
const entryPath = fileURLToPath2(resolved);
|
|
25971
|
+
return join7(coreRootFromEntry(entryPath), "migrations", setName);
|
|
25623
25972
|
} catch {
|
|
25624
25973
|
}
|
|
25625
|
-
const _require7 =
|
|
25974
|
+
const _require7 = createRequire3(import.meta.url);
|
|
25626
25975
|
try {
|
|
25627
25976
|
const entryPath = _require7.resolve("@cleocode/core");
|
|
25628
|
-
return
|
|
25977
|
+
return join7(coreRootFromEntry(entryPath), "migrations", setName);
|
|
25629
25978
|
} catch (err) {
|
|
25630
25979
|
throw new Error(
|
|
25631
25980
|
`resolveCorePackageMigrationsFolder("${setName}"): cannot locate @cleocode/core from "${import.meta.url}". Ensure @cleocode/core is installed (workspace or npm). Original error: ${err.message}`
|
|
@@ -25735,11 +26084,11 @@ var init_sqlite_pragmas = __esm({
|
|
|
25735
26084
|
});
|
|
25736
26085
|
|
|
25737
26086
|
// packages/core/src/store/worktree-isolation-guard.ts
|
|
25738
|
-
import { basename as basename4, dirname as
|
|
26087
|
+
import { basename as basename4, dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
|
|
25739
26088
|
function assertStorePathIsNotWorktreeResident(role, dbPath) {
|
|
25740
|
-
const cleoDir =
|
|
26089
|
+
const cleoDir = dirname7(dbPath);
|
|
25741
26090
|
if (basename4(cleoDir) !== ".cleo") return;
|
|
25742
|
-
const projectRoot =
|
|
26091
|
+
const projectRoot = dirname7(cleoDir);
|
|
25743
26092
|
if (!isGitLinkedCheckout(projectRoot)) return;
|
|
25744
26093
|
if (process.env["CLEO_ALLOW_WORKTREE_DB_CREATE"] === "1") {
|
|
25745
26094
|
process.stderr.write(
|
|
@@ -25748,9 +26097,10 @@ function assertStorePathIsNotWorktreeResident(role, dbPath) {
|
|
|
25748
26097
|
);
|
|
25749
26098
|
return;
|
|
25750
26099
|
}
|
|
26100
|
+
const owner = describeWorktreeOwner(projectRoot);
|
|
25751
26101
|
throw new CleoError(
|
|
25752
26102
|
8 /* CONFIG_ERROR */,
|
|
25753
|
-
`E_WT_DB_ISOLATION_VIOLATION: refusing to open '${role}' DB at ${dbPath} \u2014 parent ${projectRoot} is a git worktree (gitlink). DBs must open against the canonical project root.`,
|
|
26103
|
+
`E_WT_DB_ISOLATION_VIOLATION: refusing to open '${role}' DB at ${dbPath} \u2014 parent ${projectRoot} is a git worktree (gitlink); ${owner}. DBs must open against the canonical project root.`,
|
|
25754
26104
|
{
|
|
25755
26105
|
fix: `Run from the canonical project root, or make sure the worktree's main repository is an initialised CLEO project so it resolves there. Inspect stranded worktree stores with \`cleo doctor worktree-stores\`. Emergency override (audited): CLEO_ALLOW_WORKTREE_DB_CREATE=1.`
|
|
25756
26106
|
}
|
|
@@ -25763,7 +26113,7 @@ function assertDbPathIsNotWorktreeResident(role, cwd) {
|
|
|
25763
26113
|
} catch {
|
|
25764
26114
|
return;
|
|
25765
26115
|
}
|
|
25766
|
-
assertStorePathIsNotWorktreeResident(role,
|
|
26116
|
+
assertStorePathIsNotWorktreeResident(role, join8(cleoDir, PROJECT_STORE_FILENAME2));
|
|
25767
26117
|
}
|
|
25768
26118
|
var PROJECT_STORE_FILENAME2;
|
|
25769
26119
|
var init_worktree_isolation_guard = __esm({
|
|
@@ -25783,10 +26133,10 @@ __export(sqlite_native_exports, {
|
|
|
25783
26133
|
getDbSyncConstructor: () => getDbSyncConstructor,
|
|
25784
26134
|
openNativeDatabase: () => openNativeDatabase
|
|
25785
26135
|
});
|
|
25786
|
-
import { realpathSync as
|
|
25787
|
-
import { createRequire as
|
|
26136
|
+
import { realpathSync as realpathSync5 } from "node:fs";
|
|
26137
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
25788
26138
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
25789
|
-
import { delimiter, dirname as
|
|
26139
|
+
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute4, join as join9, resolve as resolve4, sep as sep3 } from "node:path";
|
|
25790
26140
|
function getDbSyncConstructor() {
|
|
25791
26141
|
if (_ctor === null) {
|
|
25792
26142
|
const mod = _require2("node:sqlite");
|
|
@@ -25795,19 +26145,19 @@ function getDbSyncConstructor() {
|
|
|
25795
26145
|
return _ctor;
|
|
25796
26146
|
}
|
|
25797
26147
|
function resolveAbsoluteSafe(p) {
|
|
25798
|
-
const abs =
|
|
26148
|
+
const abs = isAbsolute4(p) ? p : resolve4(p);
|
|
25799
26149
|
try {
|
|
25800
|
-
return
|
|
26150
|
+
return realpathSync5(abs);
|
|
25801
26151
|
} catch {
|
|
25802
26152
|
const missingParts = [];
|
|
25803
26153
|
let cursor = abs;
|
|
25804
26154
|
while (true) {
|
|
25805
|
-
const parent =
|
|
26155
|
+
const parent = dirname8(cursor);
|
|
25806
26156
|
if (parent === cursor) return abs;
|
|
25807
|
-
missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(
|
|
26157
|
+
missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep3) ? 0 : 1)));
|
|
25808
26158
|
cursor = parent;
|
|
25809
26159
|
try {
|
|
25810
|
-
return
|
|
26160
|
+
return join9(realpathSync5(cursor), ...missingParts);
|
|
25811
26161
|
} catch {
|
|
25812
26162
|
}
|
|
25813
26163
|
}
|
|
@@ -25815,7 +26165,7 @@ function resolveAbsoluteSafe(p) {
|
|
|
25815
26165
|
}
|
|
25816
26166
|
function isPathUnder(child, parent) {
|
|
25817
26167
|
if (child === parent) return true;
|
|
25818
|
-
const withSep = parent.endsWith(
|
|
26168
|
+
const withSep = parent.endsWith(sep3) ? parent : parent + sep3;
|
|
25819
26169
|
return child.startsWith(withSep);
|
|
25820
26170
|
}
|
|
25821
26171
|
function assertVitestSafePath(path2) {
|
|
@@ -25838,6 +26188,7 @@ function openNativeDatabase(path2, options) {
|
|
|
25838
26188
|
assertVitestSafePath(path2);
|
|
25839
26189
|
const DatabaseSyncCtor = getDbSyncConstructor();
|
|
25840
26190
|
const db = new DatabaseSyncCtor(path2, {
|
|
26191
|
+
// schema-guard-exempt: the native chokepoint; every writable caller installs the guard
|
|
25841
26192
|
enableForeignKeyConstraints: true,
|
|
25842
26193
|
readOnly: options?.readonly ?? false,
|
|
25843
26194
|
// Default handle-open lock timeout mirrors the SSoT busy_timeout
|
|
@@ -25889,7 +26240,7 @@ var init_sqlite_native = __esm({
|
|
|
25889
26240
|
"packages/core/src/store/sqlite-native.ts"() {
|
|
25890
26241
|
"use strict";
|
|
25891
26242
|
init_sqlite_pragmas();
|
|
25892
|
-
_require2 =
|
|
26243
|
+
_require2 = createRequire4(import.meta.url);
|
|
25893
26244
|
_ctor = null;
|
|
25894
26245
|
}
|
|
25895
26246
|
});
|
|
@@ -25963,7 +26314,7 @@ var init_writer_lease_schema = __esm({
|
|
|
25963
26314
|
// packages/core/src/store/writer-lease.ts
|
|
25964
26315
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
25965
26316
|
import { randomUUID } from "node:crypto";
|
|
25966
|
-
import { realpathSync as
|
|
26317
|
+
import { realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
25967
26318
|
import { resolve as resolvePath } from "node:path";
|
|
25968
26319
|
function log() {
|
|
25969
26320
|
if (_log === null) _log = getLogger("writer-lease");
|
|
@@ -26053,7 +26404,7 @@ function resolveDbIdentity(db) {
|
|
|
26053
26404
|
return identity;
|
|
26054
26405
|
}
|
|
26055
26406
|
function sleepAsync(ms) {
|
|
26056
|
-
return new Promise((
|
|
26407
|
+
return new Promise((resolve16) => setTimeout(resolve16, Math.max(0, Math.round(ms))));
|
|
26057
26408
|
}
|
|
26058
26409
|
function isPidAlive(pid) {
|
|
26059
26410
|
try {
|
|
@@ -26392,7 +26743,7 @@ function assertColdOpenFile(frame) {
|
|
|
26392
26743
|
async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
|
|
26393
26744
|
opts.execution?.assertActive();
|
|
26394
26745
|
const captured = opts.requiredIdentity;
|
|
26395
|
-
const path2 =
|
|
26746
|
+
const path2 = realpathSync6(captured.dbPath);
|
|
26396
26747
|
const identity = statSync2(path2, { bigint: true });
|
|
26397
26748
|
if (captured.scope !== scope || captured.fileDevice !== String(identity.dev) || captured.fileInode !== String(identity.ino)) {
|
|
26398
26749
|
throw new LeaseUnavailableError(
|
|
@@ -26425,6 +26776,7 @@ async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
|
|
|
26425
26776
|
}
|
|
26426
26777
|
const remaining = opts.execution ? Math.max(1, opts.execution.deadlineAt - Date.now()) : ACQUIRE_DEADLINE_MS;
|
|
26427
26778
|
const owned = openNativeDatabase(path2, { timeout: Math.min(ACQUIRE_DEADLINE_MS, remaining) });
|
|
26779
|
+
installSchemaWriteGuard(owned);
|
|
26428
26780
|
try {
|
|
26429
26781
|
opts.execution?.assertActive();
|
|
26430
26782
|
const afterOpen = statSync2(path2, { bigint: true });
|
|
@@ -26618,6 +26970,7 @@ var init_writer_lease = __esm({
|
|
|
26618
26970
|
init_background_ops();
|
|
26619
26971
|
init_dual_scope_db();
|
|
26620
26972
|
init_sqlite_native();
|
|
26973
|
+
init_worktree_build_guard();
|
|
26621
26974
|
init_writer_lease_schema();
|
|
26622
26975
|
DEFAULT_TTL_MS = 3e4;
|
|
26623
26976
|
DEFAULT_PRIORITY = 100;
|
|
@@ -27160,10 +27513,10 @@ var init_monitor = __esm({
|
|
|
27160
27513
|
|
|
27161
27514
|
// packages/core/src/resources/supervisor-admit.ts
|
|
27162
27515
|
import { connect } from "node:net";
|
|
27163
|
-
import { join as
|
|
27516
|
+
import { join as join10 } from "node:path";
|
|
27164
27517
|
import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
|
|
27165
27518
|
function resolveSupervisorSocketPath() {
|
|
27166
|
-
return process.env.CLEO_SUPERVISOR_SOCKET ??
|
|
27519
|
+
return process.env.CLEO_SUPERVISOR_SOCKET ?? join10(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
|
|
27167
27520
|
}
|
|
27168
27521
|
async function sendResourceAdmit(socketPath, cls, holderId, budget) {
|
|
27169
27522
|
const result = await sendLeaseRequest(
|
|
@@ -27186,7 +27539,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
|
|
|
27186
27539
|
return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
|
|
27187
27540
|
}
|
|
27188
27541
|
function sendLeaseRequest(socketPath, request, expectedKind) {
|
|
27189
|
-
return new Promise((
|
|
27542
|
+
return new Promise((resolve16) => {
|
|
27190
27543
|
const id = `ra-${process.pid}-${request.kind}`;
|
|
27191
27544
|
const envelope = LeaseIpcRequestEnvelopeSchema.parse({
|
|
27192
27545
|
protocol_version: LEASE_IPC_PROTOCOL_VERSION,
|
|
@@ -27204,7 +27557,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
|
|
|
27204
27557
|
settled = true;
|
|
27205
27558
|
socket.removeAllListeners();
|
|
27206
27559
|
socket.destroy();
|
|
27207
|
-
|
|
27560
|
+
resolve16(value);
|
|
27208
27561
|
};
|
|
27209
27562
|
const degrade = (reason) => done({ unavailable: true, reason });
|
|
27210
27563
|
socket.setTimeout(REQUEST_TIMEOUT_MS);
|
|
@@ -27275,9 +27628,9 @@ __export(governor_exports, {
|
|
|
27275
27628
|
resolveGovernorMode: () => resolveGovernorMode,
|
|
27276
27629
|
slotFileCount: () => slotFileCount
|
|
27277
27630
|
});
|
|
27278
|
-
import { existsSync as
|
|
27631
|
+
import { existsSync as existsSync7, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
27279
27632
|
import { availableParallelism, totalmem } from "node:os";
|
|
27280
|
-
import { join as
|
|
27633
|
+
import { join as join11 } from "node:path";
|
|
27281
27634
|
import lockfile from "proper-lockfile";
|
|
27282
27635
|
function log2() {
|
|
27283
27636
|
if (_log2 === null) _log2 = getLogger("resource-governor");
|
|
@@ -27346,14 +27699,14 @@ function clamp(lo, v, hi) {
|
|
|
27346
27699
|
return Math.max(lo, Math.min(v, hi));
|
|
27347
27700
|
}
|
|
27348
27701
|
function governorSlotDir(cls) {
|
|
27349
|
-
return
|
|
27702
|
+
return join11(getCleoHome(), "locks", `resource-${cls}`);
|
|
27350
27703
|
}
|
|
27351
27704
|
function ensureSlotFiles(dir, count) {
|
|
27352
|
-
if (!
|
|
27705
|
+
if (!existsSync7(dir)) mkdirSync(dir, { recursive: true });
|
|
27353
27706
|
const paths = [];
|
|
27354
27707
|
for (let i = 0; i < count; i++) {
|
|
27355
|
-
const p =
|
|
27356
|
-
if (!
|
|
27708
|
+
const p = join11(dir, `slot-${i}.lock`);
|
|
27709
|
+
if (!existsSync7(p)) writeFileSync3(p, "", { flag: "a" });
|
|
27357
27710
|
paths.push(p);
|
|
27358
27711
|
}
|
|
27359
27712
|
return paths;
|
|
@@ -27393,7 +27746,7 @@ function shuffledIndices(n) {
|
|
|
27393
27746
|
}
|
|
27394
27747
|
async function countHeldSlots(cls, budget) {
|
|
27395
27748
|
const dir = governorSlotDir(cls);
|
|
27396
|
-
if (!
|
|
27749
|
+
if (!existsSync7(dir)) return 0;
|
|
27397
27750
|
const slots = ensureSlotFiles(dir, budget);
|
|
27398
27751
|
let held = 0;
|
|
27399
27752
|
for (const path2 of slots) {
|
|
@@ -27408,7 +27761,7 @@ async function countHeldSlots(cls, budget) {
|
|
|
27408
27761
|
}
|
|
27409
27762
|
function slotFileCount(cls) {
|
|
27410
27763
|
const dir = governorSlotDir(cls);
|
|
27411
|
-
if (!
|
|
27764
|
+
if (!existsSync7(dir)) return 0;
|
|
27412
27765
|
return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
|
|
27413
27766
|
}
|
|
27414
27767
|
var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
|
|
@@ -27608,11 +27961,11 @@ var init_lock = __esm({
|
|
|
27608
27961
|
|
|
27609
27962
|
// packages/core/src/store/atomic.ts
|
|
27610
27963
|
import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
|
|
27611
|
-
import { dirname as
|
|
27964
|
+
import { dirname as dirname9 } from "node:path";
|
|
27612
27965
|
import writeFileAtomic from "write-file-atomic";
|
|
27613
27966
|
async function atomicWrite(filePath, data, options) {
|
|
27614
27967
|
try {
|
|
27615
|
-
await mkdir(
|
|
27968
|
+
await mkdir(dirname9(filePath), { recursive: true });
|
|
27616
27969
|
await writeFileAtomic(filePath, data, {
|
|
27617
27970
|
encoding: options?.encoding ?? "utf8",
|
|
27618
27971
|
mode: options?.mode
|
|
@@ -27645,7 +27998,7 @@ var init_atomic = __esm({
|
|
|
27645
27998
|
|
|
27646
27999
|
// packages/core/src/store/backup.ts
|
|
27647
28000
|
import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
27648
|
-
import { basename as basename5, join as
|
|
28001
|
+
import { basename as basename5, dirname as dirname10, join as join12 } from "node:path";
|
|
27649
28002
|
async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
|
|
27650
28003
|
try {
|
|
27651
28004
|
await mkdir2(backupDir, { recursive: true });
|
|
@@ -27656,14 +28009,14 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
|
|
|
27656
28009
|
throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
|
|
27657
28010
|
}
|
|
27658
28011
|
for (let i = maxBackups; i >= 1; i--) {
|
|
27659
|
-
const current =
|
|
28012
|
+
const current = join12(backupDir, `${fileName}.${i}`);
|
|
27660
28013
|
if (i === maxBackups) {
|
|
27661
28014
|
try {
|
|
27662
28015
|
await unlink2(current);
|
|
27663
28016
|
} catch {
|
|
27664
28017
|
}
|
|
27665
28018
|
} else {
|
|
27666
|
-
const next =
|
|
28019
|
+
const next = join12(backupDir, `${fileName}.${i + 1}`);
|
|
27667
28020
|
try {
|
|
27668
28021
|
await stat2(current);
|
|
27669
28022
|
await fsRename(current, next);
|
|
@@ -27671,7 +28024,7 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
|
|
|
27671
28024
|
}
|
|
27672
28025
|
}
|
|
27673
28026
|
}
|
|
27674
|
-
const backupPath =
|
|
28027
|
+
const backupPath = join12(backupDir, `${fileName}.1`);
|
|
27675
28028
|
await copyFile(filePath, backupPath);
|
|
27676
28029
|
return backupPath;
|
|
27677
28030
|
} catch (err) {
|
|
@@ -27685,6 +28038,7 @@ var init_backup = __esm({
|
|
|
27685
28038
|
"use strict";
|
|
27686
28039
|
init_src();
|
|
27687
28040
|
init_errors2();
|
|
28041
|
+
init_worktree_isolation_guard();
|
|
27688
28042
|
DEFAULT_MAX_BACKUPS = 5;
|
|
27689
28043
|
}
|
|
27690
28044
|
});
|
|
@@ -27969,7 +28323,7 @@ __export(identity_exports, {
|
|
|
27969
28323
|
import { execFile } from "node:child_process";
|
|
27970
28324
|
import { createHash as createHash2 } from "node:crypto";
|
|
27971
28325
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
27972
|
-
import { join as
|
|
28326
|
+
import { join as join13, resolve as resolve5 } from "node:path";
|
|
27973
28327
|
import { promisify } from "node:util";
|
|
27974
28328
|
import { legacyProjectId } from "@cleocode/paths";
|
|
27975
28329
|
import { legacyProjectId as legacyProjectId2 } from "@cleocode/paths";
|
|
@@ -27977,14 +28331,14 @@ async function findGitRoot(fromPath, execution) {
|
|
|
27977
28331
|
execution?.assertActive();
|
|
27978
28332
|
try {
|
|
27979
28333
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
27980
|
-
cwd:
|
|
28334
|
+
cwd: resolve5(fromPath),
|
|
27981
28335
|
signal: execution?.signal,
|
|
27982
28336
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
27983
28337
|
killSignal: "SIGKILL",
|
|
27984
28338
|
maxBuffer: 64 * 1024
|
|
27985
28339
|
});
|
|
27986
28340
|
execution?.assertActive();
|
|
27987
|
-
return
|
|
28341
|
+
return resolve5(stdout.trim());
|
|
27988
28342
|
} catch {
|
|
27989
28343
|
execution?.assertActive();
|
|
27990
28344
|
return null;
|
|
@@ -27994,7 +28348,7 @@ async function findGitRemoteUrl(fromPath, execution) {
|
|
|
27994
28348
|
execution?.assertActive();
|
|
27995
28349
|
try {
|
|
27996
28350
|
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
|
|
27997
|
-
cwd:
|
|
28351
|
+
cwd: resolve5(fromPath),
|
|
27998
28352
|
signal: execution?.signal,
|
|
27999
28353
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
28000
28354
|
killSignal: "SIGKILL",
|
|
@@ -28024,7 +28378,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
|
|
|
28024
28378
|
try {
|
|
28025
28379
|
const args = ["--no-replace-objects", "rev-list", "--max-parents=0", "HEAD"];
|
|
28026
28380
|
const { stdout } = await execFileAsync("git", args, {
|
|
28027
|
-
cwd:
|
|
28381
|
+
cwd: resolve5(fromPath),
|
|
28028
28382
|
signal: execution?.signal,
|
|
28029
28383
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
28030
28384
|
killSignal: "SIGKILL",
|
|
@@ -28047,7 +28401,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
|
|
|
28047
28401
|
async function readProjectInfoName(repoRoot, execution) {
|
|
28048
28402
|
execution?.assertActive();
|
|
28049
28403
|
try {
|
|
28050
|
-
const raw = await readFile3(
|
|
28404
|
+
const raw = await readFile3(join13(repoRoot, ".cleo", "project-info.json"), {
|
|
28051
28405
|
encoding: "utf8",
|
|
28052
28406
|
signal: execution?.signal
|
|
28053
28407
|
});
|
|
@@ -28062,7 +28416,7 @@ async function readProjectInfoName(repoRoot, execution) {
|
|
|
28062
28416
|
}
|
|
28063
28417
|
async function projectPathFingerprint(repoPath, execution) {
|
|
28064
28418
|
execution?.assertActive();
|
|
28065
|
-
const realRepoPath =
|
|
28419
|
+
const realRepoPath = resolve5(repoPath);
|
|
28066
28420
|
const results = await Promise.allSettled([
|
|
28067
28421
|
findGitRoot(realRepoPath, execution),
|
|
28068
28422
|
findGitRemoteUrl(realRepoPath, execution)
|
|
@@ -28086,9 +28440,9 @@ async function projectPathFingerprint(repoPath, execution) {
|
|
|
28086
28440
|
}
|
|
28087
28441
|
function computeLegacyAliases(repoPath, additionalPaths) {
|
|
28088
28442
|
const aliases = /* @__PURE__ */ new Set();
|
|
28089
|
-
aliases.add(legacyProjectId(
|
|
28443
|
+
aliases.add(legacyProjectId(resolve5(repoPath)));
|
|
28090
28444
|
for (const p of additionalPaths ?? []) {
|
|
28091
|
-
aliases.add(legacyProjectId(
|
|
28445
|
+
aliases.add(legacyProjectId(resolve5(p)));
|
|
28092
28446
|
}
|
|
28093
28447
|
return [...aliases];
|
|
28094
28448
|
}
|
|
@@ -28122,17 +28476,17 @@ var init_project_identity = __esm({
|
|
|
28122
28476
|
});
|
|
28123
28477
|
|
|
28124
28478
|
// packages/core/src/scaffold/ensure-config.ts
|
|
28125
|
-
import { existsSync as
|
|
28126
|
-
import { basename as basename6, dirname as
|
|
28127
|
-
import { fileURLToPath as
|
|
28479
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
28480
|
+
import { basename as basename6, dirname as dirname11, join as join14, resolve as resolve6 } from "node:path";
|
|
28481
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
28128
28482
|
function getPackageRoot() {
|
|
28129
|
-
const thisFile =
|
|
28130
|
-
return
|
|
28483
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
28484
|
+
return resolve6(dirname11(thisFile), "..", "..");
|
|
28131
28485
|
}
|
|
28132
28486
|
function getCleoVersion() {
|
|
28133
28487
|
try {
|
|
28134
|
-
const pkgPath =
|
|
28135
|
-
const pkg = JSON.parse(
|
|
28488
|
+
const pkgPath = join14(getPackageRoot(), "package.json");
|
|
28489
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
28136
28490
|
return pkg.version ?? "0.0.0";
|
|
28137
28491
|
} catch {
|
|
28138
28492
|
return "0.0.0";
|
|
@@ -28491,25 +28845,25 @@ var init_recovery = __esm({
|
|
|
28491
28845
|
// packages/core/src/store/exodus/archive.ts
|
|
28492
28846
|
import {
|
|
28493
28847
|
copyFileSync as copyFileSync2,
|
|
28494
|
-
existsSync as
|
|
28848
|
+
existsSync as existsSync9,
|
|
28495
28849
|
mkdirSync as mkdirSync2,
|
|
28496
|
-
readFileSync as
|
|
28850
|
+
readFileSync as readFileSync5,
|
|
28497
28851
|
renameSync as renameSync3,
|
|
28498
28852
|
unlinkSync,
|
|
28499
28853
|
writeFileSync as writeFileSync4
|
|
28500
28854
|
} from "node:fs";
|
|
28501
|
-
import { basename as basename7, dirname as
|
|
28855
|
+
import { basename as basename7, dirname as dirname12, join as join15, resolve as resolve7 } from "node:path";
|
|
28502
28856
|
import { z as z26 } from "zod";
|
|
28503
28857
|
function scopeBaseDir(scope, cwd, targetDbPath) {
|
|
28504
|
-
if (targetDbPath !== void 0) return
|
|
28858
|
+
if (targetDbPath !== void 0) return dirname12(targetDbPath);
|
|
28505
28859
|
return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
|
|
28506
28860
|
}
|
|
28507
28861
|
function exodusArchiveDir(scope, cwd, targetDbPath) {
|
|
28508
|
-
return
|
|
28862
|
+
return join15(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
|
|
28509
28863
|
}
|
|
28510
28864
|
function exodusMarkerPath(scope, cwd, targetDbPath) {
|
|
28511
28865
|
const marker = targetDbPath !== void 0 && basename7(targetDbPath) !== "cleo.db" ? `${basename7(targetDbPath)}.${MARKER_FILENAME_BY_SCOPE[scope]}` : MARKER_FILENAME_BY_SCOPE[scope];
|
|
28512
|
-
return
|
|
28866
|
+
return join15(scopeBaseDir(scope, cwd, targetDbPath), marker);
|
|
28513
28867
|
}
|
|
28514
28868
|
function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
|
|
28515
28869
|
let markerPath;
|
|
@@ -28519,13 +28873,13 @@ function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
|
|
|
28519
28873
|
if (targetDbPath) throw error;
|
|
28520
28874
|
return false;
|
|
28521
28875
|
}
|
|
28522
|
-
if (!
|
|
28523
|
-
const marker = markerIdentity.parse(JSON.parse(
|
|
28876
|
+
if (!existsSync9(markerPath)) return false;
|
|
28877
|
+
const marker = markerIdentity.parse(JSON.parse(readFileSync5(markerPath, "utf8")));
|
|
28524
28878
|
if (nativeDb && (!marker.databaseIdentity || !hasExodusDatabaseIdentity(nativeDb, marker.databaseIdentity)))
|
|
28525
28879
|
throw new Error(
|
|
28526
28880
|
"Exodus completion marker does not certify this database generation; assessment required"
|
|
28527
28881
|
);
|
|
28528
|
-
return marker.scope === scope && (!targetDbPath || !marker.targetDbPath ||
|
|
28882
|
+
return marker.scope === scope && (!targetDbPath || !marker.targetDbPath || resolve7(marker.targetDbPath) === resolve7(targetDbPath));
|
|
28529
28883
|
}
|
|
28530
28884
|
function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, databaseIdentity) {
|
|
28531
28885
|
const markerPath = exodusMarkerPath(scope, cwd, targetDbPath);
|
|
@@ -28537,7 +28891,7 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
|
|
|
28537
28891
|
cleoVersion: getCleoVersion(),
|
|
28538
28892
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28539
28893
|
archivedSources: [...archivedSources],
|
|
28540
|
-
targetDbPath:
|
|
28894
|
+
targetDbPath: resolve7(targetDbPath ?? join15(baseDir, "cleo.db")),
|
|
28541
28895
|
...databaseIdentity ? { databaseIdentity } : {}
|
|
28542
28896
|
};
|
|
28543
28897
|
const tmpPath = `${markerPath}.tmp`;
|
|
@@ -28548,10 +28902,10 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
|
|
|
28548
28902
|
}
|
|
28549
28903
|
function moveFileInto(srcPath, destDir) {
|
|
28550
28904
|
mkdirSync2(destDir, { recursive: true });
|
|
28551
|
-
let dest =
|
|
28552
|
-
if (
|
|
28905
|
+
let dest = join15(destDir, basename7(srcPath));
|
|
28906
|
+
if (existsSync9(dest)) {
|
|
28553
28907
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
|
|
28554
|
-
dest =
|
|
28908
|
+
dest = join15(destDir, `${basename7(srcPath)}.${stamp}`);
|
|
28555
28909
|
}
|
|
28556
28910
|
try {
|
|
28557
28911
|
renameSync3(srcPath, dest);
|
|
@@ -28562,14 +28916,14 @@ function moveFileInto(srcPath, destDir) {
|
|
|
28562
28916
|
return dest;
|
|
28563
28917
|
}
|
|
28564
28918
|
function archiveSourceDb(source, cwd, targetDbPath) {
|
|
28565
|
-
if (!
|
|
28919
|
+
if (!existsSync9(source.path)) {
|
|
28566
28920
|
return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
|
|
28567
28921
|
}
|
|
28568
28922
|
const destDir = exodusArchiveDir(source.targetScope, cwd, targetDbPath);
|
|
28569
28923
|
const archivedTo = moveFileInto(source.path, destDir);
|
|
28570
28924
|
for (const suffix of SIDECAR_SUFFIXES) {
|
|
28571
28925
|
const sidecar = `${source.path}${suffix}`;
|
|
28572
|
-
if (
|
|
28926
|
+
if (existsSync9(sidecar)) {
|
|
28573
28927
|
try {
|
|
28574
28928
|
moveFileInto(sidecar, destDir);
|
|
28575
28929
|
} catch (err) {
|
|
@@ -28617,7 +28971,7 @@ function detectStrandedResidue(sources, cwd) {
|
|
|
28617
28971
|
const stranded = [];
|
|
28618
28972
|
for (const source of sources) {
|
|
28619
28973
|
if (!markedScopes.has(source.targetScope)) continue;
|
|
28620
|
-
if (
|
|
28974
|
+
if (existsSync9(source.path)) {
|
|
28621
28975
|
stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
|
|
28622
28976
|
}
|
|
28623
28977
|
}
|
|
@@ -28682,7 +29036,7 @@ __export(open_cleo_db_exports, {
|
|
|
28682
29036
|
openCleoDbSnapshot: () => openCleoDbSnapshot,
|
|
28683
29037
|
validateProjectIdConsistency: () => validateProjectIdConsistency
|
|
28684
29038
|
});
|
|
28685
|
-
import { createRequire as
|
|
29039
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
28686
29040
|
function unwrapNativeSqliteDb(db) {
|
|
28687
29041
|
if (db && typeof db === "object" && "$client" in db) {
|
|
28688
29042
|
return db.$client ?? db;
|
|
@@ -28746,9 +29100,10 @@ async function openCleoDb(role, cwd) {
|
|
|
28746
29100
|
}
|
|
28747
29101
|
function openCleoDbSnapshot(path2, options = {}) {
|
|
28748
29102
|
const { readOnly = true, applyPragmas = true } = options;
|
|
28749
|
-
const _require7 =
|
|
29103
|
+
const _require7 = createRequire5(import.meta.url);
|
|
28750
29104
|
const { DatabaseSync: DatabaseSyncCtor } = _require7("node:sqlite");
|
|
28751
29105
|
const db = new DatabaseSyncCtor(path2, { readOnly });
|
|
29106
|
+
if (!readOnly) installSchemaWriteGuard(db);
|
|
28752
29107
|
if (applyPragmas) {
|
|
28753
29108
|
applyPerfPragmas(db, { enableWal: !readOnly });
|
|
28754
29109
|
}
|
|
@@ -28776,6 +29131,7 @@ var init_open_cleo_db = __esm({
|
|
|
28776
29131
|
init_project_info();
|
|
28777
29132
|
init_dual_scope_db();
|
|
28778
29133
|
init_sqlite_pragmas();
|
|
29134
|
+
init_worktree_build_guard();
|
|
28779
29135
|
init_worktree_isolation_guard();
|
|
28780
29136
|
PROJECT_ID_TRACKING_ROLES = /* @__PURE__ */ new Set(["global"]);
|
|
28781
29137
|
}
|
|
@@ -29115,7 +29471,7 @@ var init_table_name_map = __esm({
|
|
|
29115
29471
|
});
|
|
29116
29472
|
|
|
29117
29473
|
// packages/core/src/store/exodus/count-parity.ts
|
|
29118
|
-
import { existsSync as
|
|
29474
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
29119
29475
|
function listTables(db) {
|
|
29120
29476
|
return db.prepare(
|
|
29121
29477
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
|
|
@@ -29136,14 +29492,14 @@ function rowCount(db, tableName) {
|
|
|
29136
29492
|
function computeCountParity(sources, projectDbPath, globalDbPath) {
|
|
29137
29493
|
const entries = [];
|
|
29138
29494
|
let skipped = 0;
|
|
29139
|
-
if (!
|
|
29495
|
+
if (!existsSync10(projectDbPath) || !existsSync10(globalDbPath)) {
|
|
29140
29496
|
return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
29141
29497
|
}
|
|
29142
29498
|
const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
|
|
29143
29499
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
29144
29500
|
try {
|
|
29145
29501
|
for (const src of sources) {
|
|
29146
|
-
if (!
|
|
29502
|
+
if (!existsSync10(src.path)) continue;
|
|
29147
29503
|
const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
29148
29504
|
try {
|
|
29149
29505
|
for (const legacyTable of listTables(srcSnap.db)) {
|
|
@@ -29201,8 +29557,8 @@ var init_count_parity = __esm({
|
|
|
29201
29557
|
});
|
|
29202
29558
|
|
|
29203
29559
|
// packages/core/src/store/exodus/plan.ts
|
|
29204
|
-
import { existsSync as
|
|
29205
|
-
import { join as
|
|
29560
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
|
|
29561
|
+
import { join as join16 } from "node:path";
|
|
29206
29562
|
function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
|
|
29207
29563
|
return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
|
|
29208
29564
|
}
|
|
@@ -29213,33 +29569,33 @@ function buildSourceDescriptors(cwd) {
|
|
|
29213
29569
|
// Project-tier — go into consolidated project-scope cleo.db
|
|
29214
29570
|
{
|
|
29215
29571
|
name: "tasks",
|
|
29216
|
-
path:
|
|
29572
|
+
path: join16(cleoDir, "tasks.db"),
|
|
29217
29573
|
targetScope: "project"
|
|
29218
29574
|
},
|
|
29219
29575
|
{
|
|
29220
29576
|
name: "brain (project)",
|
|
29221
|
-
path:
|
|
29577
|
+
path: join16(cleoDir, "brain.db"),
|
|
29222
29578
|
targetScope: "project"
|
|
29223
29579
|
},
|
|
29224
29580
|
{
|
|
29225
29581
|
name: "conduit",
|
|
29226
|
-
path:
|
|
29582
|
+
path: join16(cleoDir, "conduit.db"),
|
|
29227
29583
|
targetScope: "project"
|
|
29228
29584
|
},
|
|
29229
29585
|
// Global-tier — go into consolidated global-scope cleo.db
|
|
29230
29586
|
{
|
|
29231
29587
|
name: "nexus",
|
|
29232
|
-
path:
|
|
29588
|
+
path: join16(cleoHome, "nexus.db"),
|
|
29233
29589
|
targetScope: "global"
|
|
29234
29590
|
},
|
|
29235
29591
|
{
|
|
29236
29592
|
name: "signaldock",
|
|
29237
|
-
path:
|
|
29593
|
+
path: join16(cleoHome, "signaldock.db"),
|
|
29238
29594
|
targetScope: "global"
|
|
29239
29595
|
},
|
|
29240
29596
|
{
|
|
29241
29597
|
name: "skills",
|
|
29242
|
-
path:
|
|
29598
|
+
path: join16(cleoHome, "skills.db"),
|
|
29243
29599
|
targetScope: "global"
|
|
29244
29600
|
}
|
|
29245
29601
|
];
|
|
@@ -29268,7 +29624,7 @@ function findExistingStaging(cleoDir) {
|
|
|
29268
29624
|
const entries = readdirSync3(cleoDir, { withFileTypes: true });
|
|
29269
29625
|
const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
|
|
29270
29626
|
if (stagingDirs.length > 0) {
|
|
29271
|
-
return
|
|
29627
|
+
return join16(cleoDir, stagingDirs[0]);
|
|
29272
29628
|
}
|
|
29273
29629
|
} catch {
|
|
29274
29630
|
}
|
|
@@ -29284,7 +29640,7 @@ function buildExodusPlan(cwd) {
|
|
|
29284
29640
|
const availableBytes = getAvailableBytes(cleoDir);
|
|
29285
29641
|
const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
|
|
29286
29642
|
const existingStaging = findExistingStaging(cleoDir);
|
|
29287
|
-
const stagingDir = existingStaging ??
|
|
29643
|
+
const stagingDir = existingStaging ?? join16(cleoDir, deriveStagingDirName());
|
|
29288
29644
|
const resumeFromStaging = existingStaging !== null;
|
|
29289
29645
|
const projectDbPath = resolveDualScopeDbPath("project", cwd);
|
|
29290
29646
|
const globalDbPath = resolveDualScopeDbPath("global");
|
|
@@ -29303,7 +29659,7 @@ function buildExodusPlan(cwd) {
|
|
|
29303
29659
|
};
|
|
29304
29660
|
}
|
|
29305
29661
|
function sourcesPresent(sources) {
|
|
29306
|
-
return sources.some((s) =>
|
|
29662
|
+
return sources.some((s) => existsSync11(s.path));
|
|
29307
29663
|
}
|
|
29308
29664
|
var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
|
|
29309
29665
|
var init_plan2 = __esm({
|
|
@@ -29317,18 +29673,18 @@ var init_plan2 = __esm({
|
|
|
29317
29673
|
});
|
|
29318
29674
|
|
|
29319
29675
|
// packages/core/src/store/exodus/health.ts
|
|
29320
|
-
import { existsSync as
|
|
29676
|
+
import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
|
|
29321
29677
|
function buildExodusHealth(cwd) {
|
|
29322
29678
|
const plan = buildExodusPlan(cwd);
|
|
29323
|
-
const anyLegacyPresent = plan.sources.some((s) =>
|
|
29679
|
+
const anyLegacyPresent = plan.sources.some((s) => existsSync12(s.path));
|
|
29324
29680
|
const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
29325
29681
|
const consolidatedExistsByScope = {
|
|
29326
|
-
project:
|
|
29327
|
-
global:
|
|
29682
|
+
project: existsSync12(plan.projectDbPath),
|
|
29683
|
+
global: existsSync12(plan.globalDbPath)
|
|
29328
29684
|
};
|
|
29329
29685
|
const buildScope = (scope) => {
|
|
29330
29686
|
const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
|
|
29331
|
-
const present =
|
|
29687
|
+
const present = existsSync12(s.path);
|
|
29332
29688
|
let bytes = 0;
|
|
29333
29689
|
if (present) {
|
|
29334
29690
|
try {
|
|
@@ -29680,8 +30036,8 @@ var init_types = __esm({
|
|
|
29680
30036
|
});
|
|
29681
30037
|
|
|
29682
30038
|
// packages/core/src/store/backup-sidecar.ts
|
|
29683
|
-
import { existsSync as
|
|
29684
|
-
import { join as
|
|
30039
|
+
import { existsSync as existsSync13, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
30040
|
+
import { join as join17 } from "node:path";
|
|
29685
30041
|
function formatBackupTimestamp(d) {
|
|
29686
30042
|
const pad = (n, len = 2) => String(n).padStart(len, "0");
|
|
29687
30043
|
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
@@ -29692,8 +30048,8 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29692
30048
|
const ownedPattern = new RegExp(`\\.${escapedType}-`);
|
|
29693
30049
|
const files = readdirSync4(backupDir).filter((f) => !f.endsWith(".meta.json") && !f.endsWith(".tmp") && ownedPattern.test(f)).map((f) => ({
|
|
29694
30050
|
name: f,
|
|
29695
|
-
path:
|
|
29696
|
-
mtimeMs: statSync5(
|
|
30051
|
+
path: join17(backupDir, f),
|
|
30052
|
+
mtimeMs: statSync5(join17(backupDir, f)).mtimeMs
|
|
29697
30053
|
})).sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
29698
30054
|
while (files.length > maxSnapshots) {
|
|
29699
30055
|
const oldest = files.shift();
|
|
@@ -29701,7 +30057,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29701
30057
|
try {
|
|
29702
30058
|
unlinkSync2(oldest.path);
|
|
29703
30059
|
const metaPath = `${oldest.path}.meta.json`;
|
|
29704
|
-
if (
|
|
30060
|
+
if (existsSync13(metaPath)) unlinkSync2(metaPath);
|
|
29705
30061
|
} catch {
|
|
29706
30062
|
}
|
|
29707
30063
|
}
|
|
@@ -29709,7 +30065,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29709
30065
|
}
|
|
29710
30066
|
}
|
|
29711
30067
|
function writeBackupSidecar(backupDir, sidecar) {
|
|
29712
|
-
const dest =
|
|
30068
|
+
const dest = join17(backupDir, `${sidecar.backupId}.meta.json`);
|
|
29713
30069
|
const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
|
|
29714
30070
|
writeFileSync5(tmp, JSON.stringify(sidecar, null, 2));
|
|
29715
30071
|
renameSync4(tmp, dest);
|
|
@@ -29721,23 +30077,23 @@ var init_backup_sidecar = __esm({
|
|
|
29721
30077
|
});
|
|
29722
30078
|
|
|
29723
30079
|
// packages/core/src/store/pre-repair-snapshot.ts
|
|
29724
|
-
import { existsSync as
|
|
29725
|
-
import { dirname as
|
|
30080
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
|
|
30081
|
+
import { dirname as dirname13, join as join18 } from "node:path";
|
|
29726
30082
|
function writePreRepairSnapshot(nativeDb, dbPath, label) {
|
|
29727
30083
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
29728
|
-
const backupDir =
|
|
30084
|
+
const backupDir = join18(dirname13(dbPath), "backups");
|
|
29729
30085
|
mkdirSync3(backupDir, { recursive: true });
|
|
29730
|
-
const snapshotPath =
|
|
30086
|
+
const snapshotPath = join18(backupDir, `cleo-pre-${label}-${stamp}.db`);
|
|
29731
30087
|
nativeDb.exec(`VACUUM INTO '${snapshotPath.replace(/'/g, "''")}'`);
|
|
29732
30088
|
return snapshotPath;
|
|
29733
30089
|
}
|
|
29734
30090
|
function existingAncestor(path2) {
|
|
29735
30091
|
let p = path2;
|
|
29736
|
-
while (!
|
|
30092
|
+
while (!existsSync14(p) && dirname13(p) !== p) p = dirname13(p);
|
|
29737
30093
|
return p;
|
|
29738
30094
|
}
|
|
29739
30095
|
function planMigrationSnapshot(nativeDb, dbPath) {
|
|
29740
|
-
const backupDir =
|
|
30096
|
+
const backupDir = join18(dirname13(dbPath), "backups", "sqlite");
|
|
29741
30097
|
const pragma = (name2) => Number(nativeDb.prepare(`PRAGMA main.${name2}`).get()[name2] ?? 0);
|
|
29742
30098
|
const liveBytes = (pragma("page_count") - pragma("freelist_count")) * pragma("page_size");
|
|
29743
30099
|
let availableBytes = null;
|
|
@@ -29749,13 +30105,13 @@ function planMigrationSnapshot(nativeDb, dbPath) {
|
|
|
29749
30105
|
}
|
|
29750
30106
|
const base = `migration-${formatBackupTimestamp(/* @__PURE__ */ new Date())}`;
|
|
29751
30107
|
let backupId = base;
|
|
29752
|
-
for (let n = 2;
|
|
30108
|
+
for (let n = 2; existsSync14(join18(backupDir, `${backupId}.meta.json`)); n++) {
|
|
29753
30109
|
backupId = `${base}-${n}`;
|
|
29754
30110
|
}
|
|
29755
30111
|
return {
|
|
29756
30112
|
backupDir,
|
|
29757
30113
|
backupId,
|
|
29758
|
-
snapshotPath:
|
|
30114
|
+
snapshotPath: join18(backupDir, `cleo.db.${backupId}`),
|
|
29759
30115
|
requiredBytes: liveBytes + SNAPSHOT_HEADROOM_BYTES,
|
|
29760
30116
|
availableBytes
|
|
29761
30117
|
};
|
|
@@ -29995,7 +30351,7 @@ var init_legacy_tasks_lineage = __esm({
|
|
|
29995
30351
|
|
|
29996
30352
|
// packages/core/src/store/ports/domain-binding.ts
|
|
29997
30353
|
import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
|
|
29998
|
-
import { resolve as
|
|
30354
|
+
import { resolve as resolve8 } from "node:path";
|
|
29999
30355
|
function getCleoRuntime() {
|
|
30000
30356
|
if (!_runtime) {
|
|
30001
30357
|
_runtime = createCleoRuntime();
|
|
@@ -30063,6 +30419,8 @@ async function bindAgainst(key, store, establish) {
|
|
|
30063
30419
|
() => establish(native, store)
|
|
30064
30420
|
);
|
|
30065
30421
|
return { store, native, db };
|
|
30422
|
+
} catch (error) {
|
|
30423
|
+
throw explainSchemaWriteDenial(native, error);
|
|
30066
30424
|
} finally {
|
|
30067
30425
|
membership.active = false;
|
|
30068
30426
|
}
|
|
@@ -30112,7 +30470,7 @@ async function bindLive(scope, key, dbPath, openStore, establish) {
|
|
|
30112
30470
|
);
|
|
30113
30471
|
}
|
|
30114
30472
|
async function bindProjectDomain(domain, cwd, establish) {
|
|
30115
|
-
const dbPath =
|
|
30473
|
+
const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
|
|
30116
30474
|
const row = await bindLive(
|
|
30117
30475
|
"project",
|
|
30118
30476
|
bindingKey("project", dbPath, domain),
|
|
@@ -30123,7 +30481,7 @@ async function bindProjectDomain(domain, cwd, establish) {
|
|
|
30123
30481
|
return row;
|
|
30124
30482
|
}
|
|
30125
30483
|
async function bindGlobalDomain(domain, establish, cwd) {
|
|
30126
|
-
const dbPath =
|
|
30484
|
+
const dbPath = resolve8(resolveDualScopeDbPath("global"));
|
|
30127
30485
|
const row = await bindLive(
|
|
30128
30486
|
"global",
|
|
30129
30487
|
bindingKey("global", dbPath, domain),
|
|
@@ -30134,7 +30492,7 @@ async function bindGlobalDomain(domain, establish, cwd) {
|
|
|
30134
30492
|
return row;
|
|
30135
30493
|
}
|
|
30136
30494
|
async function bindGlobalDomainAtPath(domain, dbPath, establish) {
|
|
30137
|
-
const normalized =
|
|
30495
|
+
const normalized = resolve8(dbPath);
|
|
30138
30496
|
const row = await bindLive(
|
|
30139
30497
|
"global",
|
|
30140
30498
|
bindingKey("global", normalized, domain),
|
|
@@ -30145,7 +30503,7 @@ async function bindGlobalDomainAtPath(domain, dbPath, establish) {
|
|
|
30145
30503
|
return row;
|
|
30146
30504
|
}
|
|
30147
30505
|
function peekDomainAtPath(scope, dbPath, domain) {
|
|
30148
|
-
const row = _bindings.get(bindingKey(scope,
|
|
30506
|
+
const row = _bindings.get(bindingKey(scope, resolve8(dbPath), domain));
|
|
30149
30507
|
if (!row?.native.isOpen) return null;
|
|
30150
30508
|
return row;
|
|
30151
30509
|
}
|
|
@@ -30154,12 +30512,12 @@ function releaseDomainBindings(filter) {
|
|
|
30154
30512
|
_bindings.clear();
|
|
30155
30513
|
return;
|
|
30156
30514
|
}
|
|
30157
|
-
const wantPath = filter.dbPath === void 0 ? void 0 :
|
|
30515
|
+
const wantPath = filter.dbPath === void 0 ? void 0 : resolve8(filter.dbPath);
|
|
30158
30516
|
for (const key of [..._bindings.keys()]) {
|
|
30159
|
-
const
|
|
30517
|
+
const sep6 = key.indexOf("::");
|
|
30160
30518
|
const lastSep = key.lastIndexOf("::");
|
|
30161
|
-
const scope = key.slice(0,
|
|
30162
|
-
const dbPath = key.slice(
|
|
30519
|
+
const scope = key.slice(0, sep6);
|
|
30520
|
+
const dbPath = key.slice(sep6 + 2, lastSep);
|
|
30163
30521
|
const domain = key.slice(lastSep + 2);
|
|
30164
30522
|
if (filter.scope !== void 0 && scope !== filter.scope) continue;
|
|
30165
30523
|
if (wantPath !== void 0 && dbPath !== wantPath) continue;
|
|
@@ -30174,7 +30532,7 @@ function boundProjectNative(domain, cwd) {
|
|
|
30174
30532
|
return peekProjectDomain(domain, cwd)?.native ?? null;
|
|
30175
30533
|
}
|
|
30176
30534
|
function peekProjectDomain(domain, cwd) {
|
|
30177
|
-
const dbPath =
|
|
30535
|
+
const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
|
|
30178
30536
|
const row = _bindings.get(bindingKey("project", dbPath, domain));
|
|
30179
30537
|
if (row?.native.isOpen) return row;
|
|
30180
30538
|
if (cwd !== void 0) return null;
|
|
@@ -30189,7 +30547,7 @@ function peekProjectDomain(domain, cwd) {
|
|
|
30189
30547
|
return sole ?? null;
|
|
30190
30548
|
}
|
|
30191
30549
|
function peekGlobalDomain(domain) {
|
|
30192
|
-
const dbPath =
|
|
30550
|
+
const dbPath = resolve8(resolveDualScopeDbPath("global"));
|
|
30193
30551
|
const row = _bindings.get(bindingKey("global", dbPath, domain));
|
|
30194
30552
|
if (!row || !row.native.isOpen) return null;
|
|
30195
30553
|
return row;
|
|
@@ -30200,6 +30558,7 @@ var init_domain_binding = __esm({
|
|
|
30200
30558
|
"use strict";
|
|
30201
30559
|
init_project_scope();
|
|
30202
30560
|
init_dual_scope_db();
|
|
30561
|
+
init_worktree_build_guard();
|
|
30203
30562
|
_runtime = null;
|
|
30204
30563
|
_bindings = /* @__PURE__ */ new Map();
|
|
30205
30564
|
_inflight = /* @__PURE__ */ new Map();
|
|
@@ -30210,9 +30569,9 @@ var init_domain_binding = __esm({
|
|
|
30210
30569
|
|
|
30211
30570
|
// packages/core/src/telemetry/sqlite.ts
|
|
30212
30571
|
import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
30213
|
-
import { dirname as
|
|
30572
|
+
import { dirname as dirname14, join as join19 } from "node:path";
|
|
30214
30573
|
function getTelemetryDbPath() {
|
|
30215
|
-
return
|
|
30574
|
+
return join19(getCleoHome(), DB_FILENAME);
|
|
30216
30575
|
}
|
|
30217
30576
|
function resolveTelemetryMigrationsFolder() {
|
|
30218
30577
|
return resolveCorePackageMigrationsFolder("drizzle-telemetry");
|
|
@@ -30260,8 +30619,9 @@ async function getTelemetryDb() {
|
|
|
30260
30619
|
_initPromise = (async () => {
|
|
30261
30620
|
const dbPath = requestedPath;
|
|
30262
30621
|
_dbPath = dbPath;
|
|
30263
|
-
mkdirSync4(
|
|
30622
|
+
mkdirSync4(dirname14(dbPath), { recursive: true });
|
|
30264
30623
|
const nativeDb = openNativeDatabase(dbPath);
|
|
30624
|
+
installSchemaWriteGuard(nativeDb);
|
|
30265
30625
|
_nativeDb = nativeDb;
|
|
30266
30626
|
const db = drizzle({ client: nativeDb });
|
|
30267
30627
|
runTelemetryMigrations(nativeDb, db);
|
|
@@ -30282,6 +30642,7 @@ var init_sqlite2 = __esm({
|
|
|
30282
30642
|
init_migration_manager();
|
|
30283
30643
|
init_resolve_migrations_folder();
|
|
30284
30644
|
init_sqlite3();
|
|
30645
|
+
init_worktree_build_guard();
|
|
30285
30646
|
DB_FILENAME = "telemetry.db";
|
|
30286
30647
|
TELEMETRY_SCHEMA_VERSION = "1.0.0";
|
|
30287
30648
|
_db = null;
|
|
@@ -30292,11 +30653,11 @@ var init_sqlite2 = __esm({
|
|
|
30292
30653
|
});
|
|
30293
30654
|
|
|
30294
30655
|
// packages/core/src/store/agent-registry-store.ts
|
|
30295
|
-
import { existsSync as
|
|
30296
|
-
import { join as
|
|
30656
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
30657
|
+
import { join as join20 } from "node:path";
|
|
30297
30658
|
function getGlobalAgentRegistryDbPath() {
|
|
30298
30659
|
const cleoHome = getCleoHome();
|
|
30299
|
-
const dbPath =
|
|
30660
|
+
const dbPath = join20(cleoHome, "cleo.db");
|
|
30300
30661
|
if (!dbPath.startsWith(cleoHome)) {
|
|
30301
30662
|
throw new Error(
|
|
30302
30663
|
`BUG: getGlobalAgentRegistryDbPath() resolved to "${dbPath}" which is NOT under getCleoHome() ("${cleoHome}"). The Agent Registry is global-only per ADR-037. This indicates a code path that bypasses path resolution \u2014 fix the caller, do not suppress this error.`
|
|
@@ -30363,7 +30724,7 @@ function establishAgentRegistrySchema(native) {
|
|
|
30363
30724
|
}
|
|
30364
30725
|
async function ensureGlobalAgentRegistryDb() {
|
|
30365
30726
|
const dbPath = getGlobalAgentRegistryDbPath();
|
|
30366
|
-
const alreadyExists =
|
|
30727
|
+
const alreadyExists = existsSync15(dbPath);
|
|
30367
30728
|
let created = false;
|
|
30368
30729
|
const { native: nativeDb } = await bindGlobalDomainAtPath(
|
|
30369
30730
|
AGENT_REGISTRY_DOMAIN,
|
|
@@ -30408,8 +30769,8 @@ var init_agent_registry_store = __esm({
|
|
|
30408
30769
|
});
|
|
30409
30770
|
|
|
30410
30771
|
// packages/core/src/store/conduit-sqlite.ts
|
|
30411
|
-
import { existsSync as
|
|
30412
|
-
import { createRequire as
|
|
30772
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
30773
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
30413
30774
|
function _getDrizzle() {
|
|
30414
30775
|
if (_drizzle === null) {
|
|
30415
30776
|
const mod = _require3("drizzle-orm/node-sqlite");
|
|
@@ -30437,7 +30798,7 @@ function runConduitMigrations(nativeDb) {
|
|
|
30437
30798
|
}
|
|
30438
30799
|
async function ensureConduitDb(projectRoot) {
|
|
30439
30800
|
const dbPath = getConduitDbPath(projectRoot);
|
|
30440
|
-
const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null ||
|
|
30801
|
+
const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync16(dbPath);
|
|
30441
30802
|
await bindConduitDomain(projectRoot);
|
|
30442
30803
|
return { action: alreadyExists ? "exists" : "created", path: dbPath };
|
|
30443
30804
|
}
|
|
@@ -30463,7 +30824,8 @@ var init_conduit_sqlite = __esm({
|
|
|
30463
30824
|
init_domain_binding();
|
|
30464
30825
|
init_resolve_migrations_folder();
|
|
30465
30826
|
init_sqlite_pragmas();
|
|
30466
|
-
|
|
30827
|
+
init_worktree_build_guard();
|
|
30828
|
+
_require3 = createRequire6(import.meta.url);
|
|
30467
30829
|
({ DatabaseSync: DatabaseSync2 } = _require3("node:sqlite"));
|
|
30468
30830
|
_drizzle = null;
|
|
30469
30831
|
CONDUIT_SCHEMA_VERSION = "2026.4.23";
|
|
@@ -32337,216 +32699,6 @@ var init_memory_schema = __esm({
|
|
|
32337
32699
|
}
|
|
32338
32700
|
});
|
|
32339
32701
|
|
|
32340
|
-
// packages/core/src/store/snapshot-gate.ts
|
|
32341
|
-
import { join as join20 } from "node:path";
|
|
32342
|
-
function readGateState(db) {
|
|
32343
|
-
const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
|
|
32344
|
-
const state = { generation: 0, prefixes: {} };
|
|
32345
|
-
if (!row) return state;
|
|
32346
|
-
try {
|
|
32347
|
-
const parsed = JSON.parse(row.value);
|
|
32348
|
-
if (parsed === null || typeof parsed !== "object") return state;
|
|
32349
|
-
if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
|
|
32350
|
-
state.generation = parsed.generation;
|
|
32351
|
-
}
|
|
32352
|
-
for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
|
|
32353
|
-
if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
|
|
32354
|
-
state.prefixes[prefix] = {
|
|
32355
|
-
generation: e.generation,
|
|
32356
|
-
startedAt: e.startedAt,
|
|
32357
|
-
completedAt: e.completedAt
|
|
32358
|
-
};
|
|
32359
|
-
}
|
|
32360
|
-
}
|
|
32361
|
-
} catch {
|
|
32362
|
-
}
|
|
32363
|
-
return state;
|
|
32364
|
-
}
|
|
32365
|
-
function writeGateState(db, state) {
|
|
32366
|
-
db.prepare(
|
|
32367
|
-
"INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
32368
|
-
).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
|
|
32369
|
-
}
|
|
32370
|
-
function tryReadGateState(db) {
|
|
32371
|
-
if (!db) return null;
|
|
32372
|
-
try {
|
|
32373
|
-
return readGateState(db);
|
|
32374
|
-
} catch {
|
|
32375
|
-
return null;
|
|
32376
|
-
}
|
|
32377
|
-
}
|
|
32378
|
-
function needsSnapshot(entry, mode, nowMs, seenGeneration) {
|
|
32379
|
-
if (!entry) return true;
|
|
32380
|
-
if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
|
|
32381
|
-
const elapsed = nowMs - entry.startedAt;
|
|
32382
|
-
return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
|
|
32383
|
-
}
|
|
32384
|
-
async function runGatedSnapshot(opts, snapshot) {
|
|
32385
|
-
const now = opts.now ?? Date.now;
|
|
32386
|
-
const mode = opts.mode ?? "routine";
|
|
32387
|
-
const db = opts.stateDb;
|
|
32388
|
-
const none = (skipped, error) => ({
|
|
32389
|
-
snapshotted: [],
|
|
32390
|
-
linked: [],
|
|
32391
|
-
absent: [],
|
|
32392
|
-
failed: [],
|
|
32393
|
-
skipped,
|
|
32394
|
-
...error !== void 0 && { error }
|
|
32395
|
-
});
|
|
32396
|
-
const entryState = tryReadGateState(db);
|
|
32397
|
-
const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
|
|
32398
|
-
if (mode === "routine") {
|
|
32399
|
-
if (!entryState) return none("state-unavailable");
|
|
32400
|
-
const nowMs = now();
|
|
32401
|
-
if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
|
|
32402
|
-
return none("debounced");
|
|
32403
|
-
}
|
|
32404
|
-
}
|
|
32405
|
-
const lockPath2 = join20(opts.backupDir, GATE_LOCK_BASENAME);
|
|
32406
|
-
let release;
|
|
32407
|
-
try {
|
|
32408
|
-
release = await acquireLock(lockPath2, {
|
|
32409
|
-
retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
|
|
32410
|
-
stale: SNAPSHOT_LOCK_STALE_MS,
|
|
32411
|
-
// A compromised lock (e.g. the backup dir was removed) must not throw
|
|
32412
|
-
// from a timer and crash the host process.
|
|
32413
|
-
onCompromised: () => {
|
|
32414
|
-
}
|
|
32415
|
-
});
|
|
32416
|
-
} catch {
|
|
32417
|
-
if (mode === "routine") return none("in-flight");
|
|
32418
|
-
return none(
|
|
32419
|
-
"lock-timeout",
|
|
32420
|
-
`Snapshot lock ${lockPath2}.lock is still held after waiting. Another snapshot is running, or a crashed process left the lock (it expires after ${SNAPSHOT_LOCK_STALE_MS / 6e4} minutes). Remove it if no snapshot is running.`
|
|
32421
|
-
);
|
|
32422
|
-
}
|
|
32423
|
-
try {
|
|
32424
|
-
try {
|
|
32425
|
-
opts.onLockAcquired?.();
|
|
32426
|
-
} catch {
|
|
32427
|
-
}
|
|
32428
|
-
const state = tryReadGateState(db);
|
|
32429
|
-
if (!state && mode === "routine") return none("state-unavailable");
|
|
32430
|
-
const startMs = now();
|
|
32431
|
-
const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
|
|
32432
|
-
(p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
|
|
32433
|
-
);
|
|
32434
|
-
if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
|
|
32435
|
-
const generation = (state?.generation ?? 0) + 1;
|
|
32436
|
-
let claimed = false;
|
|
32437
|
-
if (db && state) {
|
|
32438
|
-
try {
|
|
32439
|
-
writeGateState(db, { ...state, generation });
|
|
32440
|
-
claimed = true;
|
|
32441
|
-
} catch {
|
|
32442
|
-
}
|
|
32443
|
-
}
|
|
32444
|
-
const snapshotted = [];
|
|
32445
|
-
const linked = [];
|
|
32446
|
-
const absent = [];
|
|
32447
|
-
const failed = [];
|
|
32448
|
-
for (const prefix of admitted) {
|
|
32449
|
-
try {
|
|
32450
|
-
const outcome = await snapshot(prefix);
|
|
32451
|
-
if (outcome === "absent") absent.push(prefix);
|
|
32452
|
-
else {
|
|
32453
|
-
snapshotted.push(prefix);
|
|
32454
|
-
if (outcome === "linked") linked.push(prefix);
|
|
32455
|
-
}
|
|
32456
|
-
} catch {
|
|
32457
|
-
failed.push(prefix);
|
|
32458
|
-
}
|
|
32459
|
-
}
|
|
32460
|
-
const satisfied = [...snapshotted, ...absent];
|
|
32461
|
-
if (db && claimed && satisfied.length > 0) {
|
|
32462
|
-
try {
|
|
32463
|
-
const latest = readGateState(db);
|
|
32464
|
-
const completedAt = now();
|
|
32465
|
-
latest.generation = Math.max(latest.generation, generation);
|
|
32466
|
-
for (const p of satisfied) {
|
|
32467
|
-
latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
|
|
32468
|
-
}
|
|
32469
|
-
writeGateState(db, latest);
|
|
32470
|
-
} catch {
|
|
32471
|
-
}
|
|
32472
|
-
}
|
|
32473
|
-
return { snapshotted, linked, absent, failed, skipped: null };
|
|
32474
|
-
} finally {
|
|
32475
|
-
await release().catch(() => {
|
|
32476
|
-
});
|
|
32477
|
-
}
|
|
32478
|
-
}
|
|
32479
|
-
function isValidStamp(ymd, hms) {
|
|
32480
|
-
const y = Number(ymd.slice(0, 4));
|
|
32481
|
-
const mo = Number(ymd.slice(4, 6));
|
|
32482
|
-
const d = Number(ymd.slice(6, 8));
|
|
32483
|
-
const h = Number(hms.slice(0, 2));
|
|
32484
|
-
const mi = Number(hms.slice(2, 4));
|
|
32485
|
-
const se = Number(hms.slice(4, 6));
|
|
32486
|
-
if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
|
|
32487
|
-
const probe = new Date(Date.UTC(y, mo - 1, d));
|
|
32488
|
-
return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
|
|
32489
|
-
}
|
|
32490
|
-
function selectSnapshotsToKeep(names, ctx = {}) {
|
|
32491
|
-
const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
|
|
32492
|
-
const keep = /* @__PURE__ */ new Set();
|
|
32493
|
-
const stamped = [];
|
|
32494
|
-
for (const name2 of names) {
|
|
32495
|
-
const m = STAMP_PATTERN.exec(name2);
|
|
32496
|
-
const ymd = m?.[1];
|
|
32497
|
-
const hms = m?.[2];
|
|
32498
|
-
if (!ymd || !hms || !isValidStamp(ymd, hms)) {
|
|
32499
|
-
keep.add(name2);
|
|
32500
|
-
continue;
|
|
32501
|
-
}
|
|
32502
|
-
const stamp = `${ymd}-${hms}`;
|
|
32503
|
-
if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
|
|
32504
|
-
keep.add(name2);
|
|
32505
|
-
continue;
|
|
32506
|
-
}
|
|
32507
|
-
stamped.push({ name: name2, stamp });
|
|
32508
|
-
}
|
|
32509
|
-
if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
|
|
32510
|
-
stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
|
|
32511
|
-
for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
|
|
32512
|
-
const keepNewestPerBucket = (bucketOf, slots) => {
|
|
32513
|
-
const seen = /* @__PURE__ */ new Set();
|
|
32514
|
-
for (const s of stamped) {
|
|
32515
|
-
const bucket = bucketOf(s.stamp);
|
|
32516
|
-
if (seen.has(bucket)) continue;
|
|
32517
|
-
if (seen.size >= slots) break;
|
|
32518
|
-
seen.add(bucket);
|
|
32519
|
-
keep.add(s.name);
|
|
32520
|
-
}
|
|
32521
|
-
};
|
|
32522
|
-
keepNewestPerBucket(
|
|
32523
|
-
(stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
|
|
32524
|
-
policy.quarterHourly
|
|
32525
|
-
);
|
|
32526
|
-
keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
|
|
32527
|
-
keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
|
|
32528
|
-
return keep;
|
|
32529
|
-
}
|
|
32530
|
-
var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
|
|
32531
|
-
var init_snapshot_gate = __esm({
|
|
32532
|
-
"packages/core/src/store/snapshot-gate.ts"() {
|
|
32533
|
-
"use strict";
|
|
32534
|
-
init_lock();
|
|
32535
|
-
SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
|
|
32536
|
-
SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
|
|
32537
|
-
SNAPSHOT_LOCK_WAIT_RETRIES = 90;
|
|
32538
|
-
SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
|
|
32539
|
-
GATE_LOCK_BASENAME = ".snapshot-gate";
|
|
32540
|
-
DEFAULT_SNAPSHOT_RETENTION = {
|
|
32541
|
-
latest: 1,
|
|
32542
|
-
quarterHourly: 3,
|
|
32543
|
-
hourly: 3,
|
|
32544
|
-
daily: 3
|
|
32545
|
-
};
|
|
32546
|
-
STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
|
|
32547
|
-
}
|
|
32548
|
-
});
|
|
32549
|
-
|
|
32550
32702
|
// packages/core/src/store/twin-collapse.ts
|
|
32551
32703
|
import { createHash as createHash3 } from "node:crypto";
|
|
32552
32704
|
function hasMainTable(db, name2) {
|
|
@@ -32623,6 +32775,22 @@ function mergeSchemaMetaValue(key, bare, twin) {
|
|
|
32623
32775
|
const field = SCHEMA_META_COUNTER_FIELDS[key];
|
|
32624
32776
|
return field === void 0 ? bare : withMaxCounter(bare, twin, field);
|
|
32625
32777
|
}
|
|
32778
|
+
function mirrorCounterToBare(db, key) {
|
|
32779
|
+
if (SCHEMA_META_COUNTER_FIELDS[key] === void 0) return;
|
|
32780
|
+
if (!hasMainTable(db, "schema_meta")) return;
|
|
32781
|
+
const twin = readKv(db, "tasks_schema_meta", key);
|
|
32782
|
+
if (twin === void 0) return;
|
|
32783
|
+
const bare = readKv(db, "schema_meta", key);
|
|
32784
|
+
const next = bare === void 0 ? twin : mergeSchemaMetaValue(key, bare, twin);
|
|
32785
|
+
if (next === null || next === bare) return;
|
|
32786
|
+
writeKv(db, "schema_meta", key, next);
|
|
32787
|
+
}
|
|
32788
|
+
function bareCounterOf(db, key) {
|
|
32789
|
+
const name2 = SCHEMA_META_COUNTER_FIELDS[key];
|
|
32790
|
+
if (name2 === void 0 || !hasMainTable(db, "schema_meta")) return 0;
|
|
32791
|
+
const bare = readKv(db, "schema_meta", key);
|
|
32792
|
+
return (bare === void 0 ? void 0 : counterOf(bare, name2)) ?? 0;
|
|
32793
|
+
}
|
|
32626
32794
|
function kvRows(db, table, schema = "main") {
|
|
32627
32795
|
const rows = db.prepare(`SELECT key, value FROM ${schema}.${table}`).all();
|
|
32628
32796
|
return new Map(rows.map((r) => [r.key, r.value]));
|
|
@@ -32755,6 +32923,39 @@ function applyStickyRows(db, schema, plan) {
|
|
|
32755
32923
|
}
|
|
32756
32924
|
return { inserted, replaced: 0, deleted };
|
|
32757
32925
|
}
|
|
32926
|
+
function tagsOf(tagsJson) {
|
|
32927
|
+
if (!tagsJson) return [];
|
|
32928
|
+
try {
|
|
32929
|
+
const parsed = JSON.parse(tagsJson);
|
|
32930
|
+
if (!Array.isArray(parsed)) return [];
|
|
32931
|
+
return [...new Set(parsed.filter((t) => typeof t === "string" && t.length > 0))];
|
|
32932
|
+
} catch {
|
|
32933
|
+
return [];
|
|
32934
|
+
}
|
|
32935
|
+
}
|
|
32936
|
+
function syncStickyJunction(db, schema) {
|
|
32937
|
+
const notes = db.prepare("SELECT id, tags_json FROM main.brain_sticky_notes").all();
|
|
32938
|
+
const have = /* @__PURE__ */ new Map();
|
|
32939
|
+
for (const r of db.prepare(`SELECT sticky_id, tag FROM ${schema}.brain_sticky_tags`).all()) {
|
|
32940
|
+
const set = have.get(r.sticky_id) ?? /* @__PURE__ */ new Set();
|
|
32941
|
+
set.add(r.tag);
|
|
32942
|
+
have.set(r.sticky_id, set);
|
|
32943
|
+
}
|
|
32944
|
+
const insert = db.prepare(
|
|
32945
|
+
`INSERT OR IGNORE INTO ${schema}.brain_sticky_tags (sticky_id, tag) VALUES (?, ?)`
|
|
32946
|
+
);
|
|
32947
|
+
const del = db.prepare(`DELETE FROM ${schema}.brain_sticky_tags WHERE sticky_id = ? AND tag = ?`);
|
|
32948
|
+
let inserted = 0;
|
|
32949
|
+
let deleted = 0;
|
|
32950
|
+
for (const note of notes) {
|
|
32951
|
+
const want = new Set(tagsOf(note.tags_json));
|
|
32952
|
+
const current = have.get(note.id) ?? /* @__PURE__ */ new Set();
|
|
32953
|
+
for (const tag of want)
|
|
32954
|
+
if (!current.has(tag)) inserted += Number(insert.run(note.id, tag).changes);
|
|
32955
|
+
for (const tag of current) if (!want.has(tag)) deleted += Number(del.run(note.id, tag).changes);
|
|
32956
|
+
}
|
|
32957
|
+
return { inserted, deleted };
|
|
32958
|
+
}
|
|
32758
32959
|
function twinCollapseFailureOf(db) {
|
|
32759
32960
|
return degraded.get(db);
|
|
32760
32961
|
}
|
|
@@ -32964,7 +33165,7 @@ function collapseTwinTables(nativeDb, dbPath, options = {}) {
|
|
|
32964
33165
|
}
|
|
32965
33166
|
return inOrder();
|
|
32966
33167
|
}
|
|
32967
|
-
var log6, TWIN_COLLAPSE_MARKER_PREFIX, TWIN_COLLAPSE_FAILURE_PREFIX, SCHEMA_META_COUNTER_FIELDS, SCHEMA_META_NEVER_DELETED, MAX_CONFLICTS, sha, ABSENT, hashMap, emptyPlan, SCHEMA_META, hashSets, EMPTY_SET, STICKY_TAGS, PAIRS, degraded, SHADOW_WRITE_REFUSED, SHADOW_WRITE_OPS;
|
|
33168
|
+
var log6, TWIN_COLLAPSE_MARKER_PREFIX, TWIN_COLLAPSE_FAILURE_PREFIX, SNAPSHOT_GATE_KEY, SCHEMA_META_COUNTER_FIELDS, SCHEMA_META_NEVER_DELETED, MAX_CONFLICTS, sha, ABSENT, hashMap, emptyPlan, SCHEMA_META, hashSets, EMPTY_SET, STICKY_TAGS, PAIRS, degraded, SHADOW_WRITE_REFUSED, SHADOW_WRITE_OPS;
|
|
32968
33169
|
var init_twin_collapse = __esm({
|
|
32969
33170
|
"packages/core/src/store/twin-collapse.ts"() {
|
|
32970
33171
|
"use strict";
|
|
@@ -32972,18 +33173,18 @@ var init_twin_collapse = __esm({
|
|
|
32972
33173
|
init_errors2();
|
|
32973
33174
|
init_logger2();
|
|
32974
33175
|
init_pre_repair_snapshot();
|
|
32975
|
-
init_snapshot_gate();
|
|
32976
33176
|
log6 = getLogger("twin-collapse");
|
|
32977
33177
|
TWIN_COLLAPSE_MARKER_PREFIX = "twin_collapse:";
|
|
32978
33178
|
TWIN_COLLAPSE_FAILURE_PREFIX = "twin_collapse_failed:";
|
|
33179
|
+
SNAPSHOT_GATE_KEY = "sqlite_snapshot_gate";
|
|
32979
33180
|
SCHEMA_META_COUNTER_FIELDS = {
|
|
32980
33181
|
task_id_sequence: "counter",
|
|
32981
|
-
[
|
|
33182
|
+
[SNAPSHOT_GATE_KEY]: "generation",
|
|
32982
33183
|
file_meta: "generation"
|
|
32983
33184
|
};
|
|
32984
33185
|
SCHEMA_META_NEVER_DELETED = /* @__PURE__ */ new Set([
|
|
32985
33186
|
"task_id_sequence",
|
|
32986
|
-
|
|
33187
|
+
SNAPSHOT_GATE_KEY
|
|
32987
33188
|
]);
|
|
32988
33189
|
MAX_CONFLICTS = 50;
|
|
32989
33190
|
sha = (value) => createHash3("sha256").update(value).digest("hex");
|
|
@@ -33048,7 +33249,12 @@ var init_twin_collapse = __esm({
|
|
|
33048
33249
|
throw new Error(
|
|
33049
33250
|
`sticky_tags collapse did not verify: ${missing} missing, ${lingering} not removed`
|
|
33050
33251
|
);
|
|
33051
|
-
|
|
33252
|
+
const synced = syncStickyJunction(db, "main");
|
|
33253
|
+
return {
|
|
33254
|
+
inserted: counts.inserted + synced.inserted,
|
|
33255
|
+
replaced: 0,
|
|
33256
|
+
deleted: counts.deleted + synced.deleted
|
|
33257
|
+
};
|
|
33052
33258
|
},
|
|
33053
33259
|
shadow(db, plan) {
|
|
33054
33260
|
db.exec(
|
|
@@ -33059,6 +33265,7 @@ var init_twin_collapse = __esm({
|
|
|
33059
33265
|
"INSERT INTO temp.brain_sticky_tags (sticky_id, tag) SELECT sticky_id, tag FROM main.brain_sticky_tags"
|
|
33060
33266
|
);
|
|
33061
33267
|
applyStickyRows(db, "temp", plan);
|
|
33268
|
+
syncStickyJunction(db, "temp");
|
|
33062
33269
|
}
|
|
33063
33270
|
};
|
|
33064
33271
|
PAIRS = [SCHEMA_META, STICKY_TAGS];
|
|
@@ -33090,7 +33297,7 @@ __export(config_exports, {
|
|
|
33090
33297
|
parseConfigValue: () => parseConfigValue,
|
|
33091
33298
|
setConfigValue: () => setConfigValue
|
|
33092
33299
|
});
|
|
33093
|
-
import { existsSync as
|
|
33300
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
33094
33301
|
function getNestedValue(obj, path2) {
|
|
33095
33302
|
const parts = path2.split(".");
|
|
33096
33303
|
let current = obj;
|
|
@@ -33212,7 +33419,7 @@ function parseConfigValue(value) {
|
|
|
33212
33419
|
}
|
|
33213
33420
|
async function setConfigValue(key, value, cwd, opts) {
|
|
33214
33421
|
const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
|
|
33215
|
-
if (!
|
|
33422
|
+
if (!existsSync17(configPath)) {
|
|
33216
33423
|
await atomicWriteJson(configPath, {});
|
|
33217
33424
|
}
|
|
33218
33425
|
const config = await readJson(configPath) ?? {};
|
|
@@ -33224,7 +33431,7 @@ async function setConfigValue(key, value, cwd, opts) {
|
|
|
33224
33431
|
async function applyStrictnessPreset(preset, cwd, opts) {
|
|
33225
33432
|
const definition = STRICTNESS_PRESETS[preset];
|
|
33226
33433
|
const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
|
|
33227
|
-
if (!
|
|
33434
|
+
if (!existsSync17(configPath)) {
|
|
33228
33435
|
await atomicWriteJson(configPath, {});
|
|
33229
33436
|
}
|
|
33230
33437
|
const config = await readJson(configPath) ?? {};
|
|
@@ -33801,6 +34008,7 @@ var init_cross_db_cleanup = __esm({
|
|
|
33801
34008
|
"use strict";
|
|
33802
34009
|
init_memory_sqlite();
|
|
33803
34010
|
init_memory_schema();
|
|
34011
|
+
init_worktree_build_guard();
|
|
33804
34012
|
}
|
|
33805
34013
|
});
|
|
33806
34014
|
|
|
@@ -38493,7 +38701,7 @@ __export(sqlite_data_accessor_exports, {
|
|
|
38493
38701
|
setMetaValue: () => setMetaValue
|
|
38494
38702
|
});
|
|
38495
38703
|
import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
|
|
38496
|
-
import { resolve as
|
|
38704
|
+
import { resolve as resolve9 } from "node:path";
|
|
38497
38705
|
import {
|
|
38498
38706
|
and as and5,
|
|
38499
38707
|
eq as eq6,
|
|
@@ -38533,9 +38741,12 @@ async function writeMetaValue(cwd, key, value) {
|
|
|
38533
38741
|
target: tasksSchemaMeta.key,
|
|
38534
38742
|
set: { value: json }
|
|
38535
38743
|
}).run();
|
|
38744
|
+
const native = getNativeTasksDb(cwd);
|
|
38745
|
+
if (native) mirrorCounterToBare(native, key);
|
|
38536
38746
|
}
|
|
38537
38747
|
function advanceTaskIdSequence(nativeDb, floor) {
|
|
38538
38748
|
assertTwinCollapseWritable(nativeDb);
|
|
38749
|
+
const lowest = Math.max(floor, bareCounterOf(nativeDb, "task_id_sequence"));
|
|
38539
38750
|
nativeDb.prepare(`
|
|
38540
38751
|
UPDATE tasks_schema_meta
|
|
38541
38752
|
SET value = json_set(value,
|
|
@@ -38544,7 +38755,8 @@ function advanceTaskIdSequence(nativeDb, floor) {
|
|
|
38544
38755
|
'$.checksum', 'alloc-' || strftime('%s','now')
|
|
38545
38756
|
)
|
|
38546
38757
|
WHERE key = 'task_id_sequence'
|
|
38547
|
-
`).run(
|
|
38758
|
+
`).run(lowest, lowest);
|
|
38759
|
+
mirrorCounterToBare(nativeDb, "task_id_sequence");
|
|
38548
38760
|
const row = nativeDb.prepare(`
|
|
38549
38761
|
SELECT json_extract(value, '$.counter') AS counter
|
|
38550
38762
|
FROM tasks_schema_meta WHERE key = 'task_id_sequence'
|
|
@@ -38598,7 +38810,7 @@ function bindTaskAccessorScope(accessor, scope) {
|
|
|
38598
38810
|
}
|
|
38599
38811
|
async function createSqliteDataAccessor(cwd) {
|
|
38600
38812
|
const scope = captureProjectScope(
|
|
38601
|
-
|
|
38813
|
+
resolve9(cwd ?? getProjectRoot()),
|
|
38602
38814
|
worktreeScope.getStore()
|
|
38603
38815
|
);
|
|
38604
38816
|
return worktreeScope.run(
|
|
@@ -38713,7 +38925,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38713
38925
|
actor: entry.actor ?? "system",
|
|
38714
38926
|
detailsJson: entry.details ? JSON.stringify(entry.details) : "{}",
|
|
38715
38927
|
beforeJson: entry.before ? JSON.stringify(entry.before) : null,
|
|
38716
|
-
afterJson: entry.after ? JSON.stringify(entry.after) : null
|
|
38928
|
+
afterJson: entry.after ? JSON.stringify(entry.after) : null,
|
|
38929
|
+
// T12693: the session a ranking change ran in.
|
|
38930
|
+
sessionId: typeof entry.sessionId === "string" ? entry.sessionId : null
|
|
38717
38931
|
}).run()
|
|
38718
38932
|
);
|
|
38719
38933
|
});
|
|
@@ -38721,6 +38935,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38721
38935
|
async queryAuditLog(query) {
|
|
38722
38936
|
const db = await getDb(cwd);
|
|
38723
38937
|
const conditions = [];
|
|
38938
|
+
if (query.ids && query.ids.length > 0) {
|
|
38939
|
+
conditions.push(inArray4(tasksAuditLog.id, [...query.ids]));
|
|
38940
|
+
}
|
|
38724
38941
|
if (query.taskIds && query.taskIds.length > 0) {
|
|
38725
38942
|
conditions.push(inArray4(tasksAuditLog.taskId, [...query.taskIds]));
|
|
38726
38943
|
}
|
|
@@ -38739,7 +38956,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38739
38956
|
actor: tasksAuditLog.actor,
|
|
38740
38957
|
detailsJson: tasksAuditLog.detailsJson,
|
|
38741
38958
|
beforeJson: tasksAuditLog.beforeJson,
|
|
38742
|
-
afterJson: tasksAuditLog.afterJson
|
|
38959
|
+
afterJson: tasksAuditLog.afterJson,
|
|
38960
|
+
sessionId: tasksAuditLog.sessionId
|
|
38743
38961
|
}).from(tasksAuditLog).where(conditions.length > 0 ? and5(...conditions) : void 0).orderBy(sql26`${tasksAuditLog.timestamp} DESC`).limit(limit).all();
|
|
38744
38962
|
return rows.map((row) => ({
|
|
38745
38963
|
id: row.id,
|
|
@@ -38749,7 +38967,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38749
38967
|
actor: row.actor,
|
|
38750
38968
|
detailsJson: row.detailsJson ?? null,
|
|
38751
38969
|
beforeJson: row.beforeJson ?? null,
|
|
38752
|
-
afterJson: row.afterJson ?? null
|
|
38970
|
+
afterJson: row.afterJson ?? null,
|
|
38971
|
+
sessionId: row.sessionId ?? null
|
|
38753
38972
|
}));
|
|
38754
38973
|
},
|
|
38755
38974
|
// ---- Fine-grained task operations (T5034) ----
|
|
@@ -39587,7 +39806,7 @@ var init_sqlite_data_accessor = __esm({
|
|
|
39587
39806
|
});
|
|
39588
39807
|
|
|
39589
39808
|
// packages/core/src/sequence/index.ts
|
|
39590
|
-
import { existsSync as
|
|
39809
|
+
import { existsSync as existsSync18, readFileSync as readFileSync6, renameSync as renameSync5 } from "node:fs";
|
|
39591
39810
|
import { join as join21 } from "node:path";
|
|
39592
39811
|
function getLegacySequenceJsonPath(cwd) {
|
|
39593
39812
|
return join21(resolveOrCwd(cwd), ".cleo", ".sequence.json");
|
|
@@ -39604,19 +39823,19 @@ function isSeedSequence(value) {
|
|
|
39604
39823
|
return value.counter === 0 && value.lastId === "T000" && value.checksum === "seed";
|
|
39605
39824
|
}
|
|
39606
39825
|
function readLegacySequenceFile(path2) {
|
|
39607
|
-
if (!
|
|
39826
|
+
if (!existsSync18(path2)) return null;
|
|
39608
39827
|
try {
|
|
39609
|
-
const parsed = JSON.parse(
|
|
39828
|
+
const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
|
|
39610
39829
|
return isValidSequenceState(parsed) ? parsed : null;
|
|
39611
39830
|
} catch {
|
|
39612
39831
|
return null;
|
|
39613
39832
|
}
|
|
39614
39833
|
}
|
|
39615
39834
|
function renameLegacyFile(path2) {
|
|
39616
|
-
if (!
|
|
39835
|
+
if (!existsSync18(path2)) return;
|
|
39617
39836
|
const migratedPath = `${path2}.migrated`;
|
|
39618
39837
|
try {
|
|
39619
|
-
if (!
|
|
39838
|
+
if (!existsSync18(migratedPath)) {
|
|
39620
39839
|
renameSync5(path2, migratedPath);
|
|
39621
39840
|
return;
|
|
39622
39841
|
}
|
|
@@ -39782,12 +40001,12 @@ var init_checkpoint_git_dir = __esm({
|
|
|
39782
40001
|
|
|
39783
40002
|
// packages/core/src/store/git-checkpoint.ts
|
|
39784
40003
|
import { execFile as execFile2 } from "node:child_process";
|
|
39785
|
-
import { existsSync as
|
|
40004
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
39786
40005
|
import { readFile as readFile4, writeFile } from "node:fs/promises";
|
|
39787
|
-
import { join as join23, resolve as
|
|
40006
|
+
import { join as join23, resolve as resolve10 } from "node:path";
|
|
39788
40007
|
import { promisify as promisify2 } from "node:util";
|
|
39789
40008
|
function makeCleoGitEnv(cleoDir) {
|
|
39790
|
-
const abs =
|
|
40009
|
+
const abs = resolve10(cleoDir);
|
|
39791
40010
|
return {
|
|
39792
40011
|
...process.env,
|
|
39793
40012
|
GIT_DIR: checkpointGitDir(abs),
|
|
@@ -39797,7 +40016,7 @@ function makeCleoGitEnv(cleoDir) {
|
|
|
39797
40016
|
async function cleoGitCommand(args, cleoDir) {
|
|
39798
40017
|
try {
|
|
39799
40018
|
const result = await execFileAsync2("git", args, {
|
|
39800
|
-
cwd:
|
|
40019
|
+
cwd: resolve10(cleoDir),
|
|
39801
40020
|
// absolute cwd so relative paths in args resolve correctly
|
|
39802
40021
|
env: makeCleoGitEnv(cleoDir),
|
|
39803
40022
|
timeout: 1e4
|
|
@@ -39808,7 +40027,7 @@ async function cleoGitCommand(args, cleoDir) {
|
|
|
39808
40027
|
}
|
|
39809
40028
|
}
|
|
39810
40029
|
function isCleoGitInitialized(cleoDir) {
|
|
39811
|
-
return
|
|
40030
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "HEAD"));
|
|
39812
40031
|
}
|
|
39813
40032
|
async function loadStateFileAllowlist(cwd) {
|
|
39814
40033
|
try {
|
|
@@ -39852,14 +40071,14 @@ async function isCleoGitRepo(cleoDir) {
|
|
|
39852
40071
|
return result.success && (result.stdout === "true" || isCleoGitInitialized(cleoDir));
|
|
39853
40072
|
}
|
|
39854
40073
|
function isMergeInProgress(cleoDir) {
|
|
39855
|
-
return
|
|
40074
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
|
|
39856
40075
|
}
|
|
39857
40076
|
async function isDetachedHead(cleoDir) {
|
|
39858
40077
|
const result = await cleoGitCommand(["symbolic-ref", "HEAD"], cleoDir);
|
|
39859
40078
|
return !result.success;
|
|
39860
40079
|
}
|
|
39861
40080
|
function isRebaseInProgress(cleoDir) {
|
|
39862
|
-
return
|
|
40081
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync19(join23(checkpointGitDir(cleoDir), "rebase-apply"));
|
|
39863
40082
|
}
|
|
39864
40083
|
async function recordCheckpointTime(cleoDir) {
|
|
39865
40084
|
try {
|
|
@@ -39883,7 +40102,7 @@ async function getChangedStateFiles(cleoDir, cwd) {
|
|
|
39883
40102
|
const allStateFiles = await getAllStateFiles(cwd);
|
|
39884
40103
|
for (const stateFile of allStateFiles) {
|
|
39885
40104
|
const fullPath = join23(cleoDir, stateFile);
|
|
39886
|
-
if (!
|
|
40105
|
+
if (!existsSync19(fullPath)) continue;
|
|
39887
40106
|
const diffResult = await cleoGitCommand(["diff", "--quiet", "--", stateFile], cleoDir);
|
|
39888
40107
|
const cachedResult = await cleoGitCommand(
|
|
39889
40108
|
["diff", "--cached", "--quiet", "--", stateFile],
|
|
@@ -39910,7 +40129,7 @@ async function shouldCheckpoint(options) {
|
|
|
39910
40129
|
const config = await loadCheckpointConfig(cwd);
|
|
39911
40130
|
if (!config.enabled) return false;
|
|
39912
40131
|
const cleoDir = getCleoDir(cwd);
|
|
39913
|
-
if (!
|
|
40132
|
+
if (!existsSync19(cleoDir)) return false;
|
|
39914
40133
|
if (!isCleoGitInitialized(cleoDir)) return false;
|
|
39915
40134
|
if (!await isCleoGitRepo(cleoDir)) return false;
|
|
39916
40135
|
if (isMergeInProgress(cleoDir)) return false;
|
|
@@ -39983,6 +40202,218 @@ var init_git_checkpoint = __esm({
|
|
|
39983
40202
|
}
|
|
39984
40203
|
});
|
|
39985
40204
|
|
|
40205
|
+
// packages/core/src/store/snapshot-gate.ts
|
|
40206
|
+
import { join as join24 } from "node:path";
|
|
40207
|
+
function readGateState(db) {
|
|
40208
|
+
const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
|
|
40209
|
+
const state = { generation: 0, prefixes: {} };
|
|
40210
|
+
if (!row) return state;
|
|
40211
|
+
try {
|
|
40212
|
+
const parsed = JSON.parse(row.value);
|
|
40213
|
+
if (parsed === null || typeof parsed !== "object") return state;
|
|
40214
|
+
if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
|
|
40215
|
+
state.generation = parsed.generation;
|
|
40216
|
+
}
|
|
40217
|
+
for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
|
|
40218
|
+
if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
|
|
40219
|
+
state.prefixes[prefix] = {
|
|
40220
|
+
generation: e.generation,
|
|
40221
|
+
startedAt: e.startedAt,
|
|
40222
|
+
completedAt: e.completedAt
|
|
40223
|
+
};
|
|
40224
|
+
}
|
|
40225
|
+
}
|
|
40226
|
+
} catch {
|
|
40227
|
+
}
|
|
40228
|
+
return state;
|
|
40229
|
+
}
|
|
40230
|
+
function writeGateState(db, state) {
|
|
40231
|
+
db.prepare(
|
|
40232
|
+
"INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
40233
|
+
).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
|
|
40234
|
+
mirrorCounterToBare(db, SNAPSHOT_GATE_META_KEY);
|
|
40235
|
+
}
|
|
40236
|
+
function tryReadGateState(db) {
|
|
40237
|
+
if (!db) return null;
|
|
40238
|
+
try {
|
|
40239
|
+
return readGateState(db);
|
|
40240
|
+
} catch {
|
|
40241
|
+
return null;
|
|
40242
|
+
}
|
|
40243
|
+
}
|
|
40244
|
+
function needsSnapshot(entry, mode, nowMs, seenGeneration) {
|
|
40245
|
+
if (!entry) return true;
|
|
40246
|
+
if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
|
|
40247
|
+
const elapsed = nowMs - entry.startedAt;
|
|
40248
|
+
return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
|
|
40249
|
+
}
|
|
40250
|
+
async function runGatedSnapshot(opts, snapshot) {
|
|
40251
|
+
const now = opts.now ?? Date.now;
|
|
40252
|
+
const mode = opts.mode ?? "routine";
|
|
40253
|
+
const db = opts.stateDb;
|
|
40254
|
+
const none = (skipped, error) => ({
|
|
40255
|
+
snapshotted: [],
|
|
40256
|
+
linked: [],
|
|
40257
|
+
absent: [],
|
|
40258
|
+
failed: [],
|
|
40259
|
+
skipped,
|
|
40260
|
+
...error !== void 0 && { error }
|
|
40261
|
+
});
|
|
40262
|
+
const entryState = tryReadGateState(db);
|
|
40263
|
+
const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
|
|
40264
|
+
if (mode === "routine") {
|
|
40265
|
+
if (!entryState) return none("state-unavailable");
|
|
40266
|
+
const nowMs = now();
|
|
40267
|
+
if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
|
|
40268
|
+
return none("debounced");
|
|
40269
|
+
}
|
|
40270
|
+
}
|
|
40271
|
+
const lockPath2 = join24(opts.backupDir, GATE_LOCK_BASENAME);
|
|
40272
|
+
let release;
|
|
40273
|
+
try {
|
|
40274
|
+
release = await acquireLock(lockPath2, {
|
|
40275
|
+
retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
|
|
40276
|
+
stale: SNAPSHOT_LOCK_STALE_MS,
|
|
40277
|
+
// A compromised lock (e.g. the backup dir was removed) must not throw
|
|
40278
|
+
// from a timer and crash the host process.
|
|
40279
|
+
onCompromised: () => {
|
|
40280
|
+
}
|
|
40281
|
+
});
|
|
40282
|
+
} catch {
|
|
40283
|
+
if (mode === "routine") return none("in-flight");
|
|
40284
|
+
return none(
|
|
40285
|
+
"lock-timeout",
|
|
40286
|
+
`Snapshot lock ${lockPath2}.lock is still held after waiting. Another snapshot is running, or a crashed process left the lock (it expires after ${SNAPSHOT_LOCK_STALE_MS / 6e4} minutes). Remove it if no snapshot is running.`
|
|
40287
|
+
);
|
|
40288
|
+
}
|
|
40289
|
+
try {
|
|
40290
|
+
try {
|
|
40291
|
+
opts.onLockAcquired?.();
|
|
40292
|
+
} catch {
|
|
40293
|
+
}
|
|
40294
|
+
const state = tryReadGateState(db);
|
|
40295
|
+
if (!state && mode === "routine") return none("state-unavailable");
|
|
40296
|
+
const startMs = now();
|
|
40297
|
+
const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
|
|
40298
|
+
(p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
|
|
40299
|
+
);
|
|
40300
|
+
if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
|
|
40301
|
+
const generation = (state?.generation ?? 0) + 1;
|
|
40302
|
+
let claimed = false;
|
|
40303
|
+
if (db && state) {
|
|
40304
|
+
try {
|
|
40305
|
+
writeGateState(db, { ...state, generation });
|
|
40306
|
+
claimed = true;
|
|
40307
|
+
} catch {
|
|
40308
|
+
}
|
|
40309
|
+
}
|
|
40310
|
+
const snapshotted = [];
|
|
40311
|
+
const linked = [];
|
|
40312
|
+
const absent = [];
|
|
40313
|
+
const failed = [];
|
|
40314
|
+
for (const prefix of admitted) {
|
|
40315
|
+
try {
|
|
40316
|
+
const outcome = await snapshot(prefix);
|
|
40317
|
+
if (outcome === "absent") absent.push(prefix);
|
|
40318
|
+
else {
|
|
40319
|
+
snapshotted.push(prefix);
|
|
40320
|
+
if (outcome === "linked") linked.push(prefix);
|
|
40321
|
+
}
|
|
40322
|
+
} catch {
|
|
40323
|
+
failed.push(prefix);
|
|
40324
|
+
}
|
|
40325
|
+
}
|
|
40326
|
+
const satisfied = [...snapshotted, ...absent];
|
|
40327
|
+
if (db && claimed && satisfied.length > 0) {
|
|
40328
|
+
try {
|
|
40329
|
+
const latest = readGateState(db);
|
|
40330
|
+
const completedAt = now();
|
|
40331
|
+
latest.generation = Math.max(latest.generation, generation);
|
|
40332
|
+
for (const p of satisfied) {
|
|
40333
|
+
latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
|
|
40334
|
+
}
|
|
40335
|
+
writeGateState(db, latest);
|
|
40336
|
+
} catch {
|
|
40337
|
+
}
|
|
40338
|
+
}
|
|
40339
|
+
return { snapshotted, linked, absent, failed, skipped: null };
|
|
40340
|
+
} finally {
|
|
40341
|
+
await release().catch(() => {
|
|
40342
|
+
});
|
|
40343
|
+
}
|
|
40344
|
+
}
|
|
40345
|
+
function isValidStamp(ymd, hms) {
|
|
40346
|
+
const y = Number(ymd.slice(0, 4));
|
|
40347
|
+
const mo = Number(ymd.slice(4, 6));
|
|
40348
|
+
const d = Number(ymd.slice(6, 8));
|
|
40349
|
+
const h = Number(hms.slice(0, 2));
|
|
40350
|
+
const mi = Number(hms.slice(2, 4));
|
|
40351
|
+
const se = Number(hms.slice(4, 6));
|
|
40352
|
+
if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
|
|
40353
|
+
const probe = new Date(Date.UTC(y, mo - 1, d));
|
|
40354
|
+
return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
|
|
40355
|
+
}
|
|
40356
|
+
function selectSnapshotsToKeep(names, ctx = {}) {
|
|
40357
|
+
const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
|
|
40358
|
+
const keep = /* @__PURE__ */ new Set();
|
|
40359
|
+
const stamped = [];
|
|
40360
|
+
for (const name2 of names) {
|
|
40361
|
+
const m = STAMP_PATTERN.exec(name2);
|
|
40362
|
+
const ymd = m?.[1];
|
|
40363
|
+
const hms = m?.[2];
|
|
40364
|
+
if (!ymd || !hms || !isValidStamp(ymd, hms)) {
|
|
40365
|
+
keep.add(name2);
|
|
40366
|
+
continue;
|
|
40367
|
+
}
|
|
40368
|
+
const stamp = `${ymd}-${hms}`;
|
|
40369
|
+
if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
|
|
40370
|
+
keep.add(name2);
|
|
40371
|
+
continue;
|
|
40372
|
+
}
|
|
40373
|
+
stamped.push({ name: name2, stamp });
|
|
40374
|
+
}
|
|
40375
|
+
if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
|
|
40376
|
+
stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
|
|
40377
|
+
for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
|
|
40378
|
+
const keepNewestPerBucket = (bucketOf, slots) => {
|
|
40379
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40380
|
+
for (const s of stamped) {
|
|
40381
|
+
const bucket = bucketOf(s.stamp);
|
|
40382
|
+
if (seen.has(bucket)) continue;
|
|
40383
|
+
if (seen.size >= slots) break;
|
|
40384
|
+
seen.add(bucket);
|
|
40385
|
+
keep.add(s.name);
|
|
40386
|
+
}
|
|
40387
|
+
};
|
|
40388
|
+
keepNewestPerBucket(
|
|
40389
|
+
(stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
|
|
40390
|
+
policy.quarterHourly
|
|
40391
|
+
);
|
|
40392
|
+
keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
|
|
40393
|
+
keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
|
|
40394
|
+
return keep;
|
|
40395
|
+
}
|
|
40396
|
+
var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
|
|
40397
|
+
var init_snapshot_gate = __esm({
|
|
40398
|
+
"packages/core/src/store/snapshot-gate.ts"() {
|
|
40399
|
+
"use strict";
|
|
40400
|
+
init_lock();
|
|
40401
|
+
init_twin_collapse();
|
|
40402
|
+
SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
|
|
40403
|
+
SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
|
|
40404
|
+
SNAPSHOT_LOCK_WAIT_RETRIES = 90;
|
|
40405
|
+
SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
|
|
40406
|
+
GATE_LOCK_BASENAME = ".snapshot-gate";
|
|
40407
|
+
DEFAULT_SNAPSHOT_RETENTION = {
|
|
40408
|
+
latest: 1,
|
|
40409
|
+
quarterHourly: 3,
|
|
40410
|
+
hourly: 3,
|
|
40411
|
+
daily: 3
|
|
40412
|
+
};
|
|
40413
|
+
STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
|
|
40414
|
+
}
|
|
40415
|
+
});
|
|
40416
|
+
|
|
39986
40417
|
// packages/core/src/store/data-safety-central.ts
|
|
39987
40418
|
import { eq as eq7 } from "drizzle-orm";
|
|
39988
40419
|
function inSafetyScope(cwd, operation) {
|
|
@@ -40393,7 +40824,7 @@ __export(data_accessor_exports, {
|
|
|
40393
40824
|
getAccessorDb: () => getAccessorDb,
|
|
40394
40825
|
getTaskAccessor: () => getTaskAccessor
|
|
40395
40826
|
});
|
|
40396
|
-
import { resolve as
|
|
40827
|
+
import { resolve as resolve11 } from "node:path";
|
|
40397
40828
|
function assertTestEnv(dbPath) {
|
|
40398
40829
|
const testMode = process.env["CLEO_TEST_MODE"];
|
|
40399
40830
|
if (testMode !== "1") return;
|
|
@@ -40414,7 +40845,7 @@ function assertTestEnv(dbPath) {
|
|
|
40414
40845
|
}
|
|
40415
40846
|
}
|
|
40416
40847
|
async function createDataAccessor(cwd) {
|
|
40417
|
-
const root =
|
|
40848
|
+
const root = resolve11(cwd ?? getProjectRoot());
|
|
40418
40849
|
const inherited = worktreeScope.getStore();
|
|
40419
40850
|
const captured = inherited ? { ...inherited } : void 0;
|
|
40420
40851
|
captured?.execution?.assertActive();
|
|
@@ -40458,7 +40889,7 @@ __export(memory_sqlite_exports, {
|
|
|
40458
40889
|
resetBrainDbState: () => resetBrainDbState,
|
|
40459
40890
|
resolveBrainMigrationsFolder: () => resolveBrainMigrationsFolder
|
|
40460
40891
|
});
|
|
40461
|
-
import { createRequire as
|
|
40892
|
+
import { createRequire as createRequire7 } from "node:module";
|
|
40462
40893
|
function _getDrizzle2() {
|
|
40463
40894
|
if (_drizzle2 === null) {
|
|
40464
40895
|
const mod = _require4("drizzle-orm/node-sqlite");
|
|
@@ -40595,7 +41026,7 @@ var init_memory_sqlite = __esm({
|
|
|
40595
41026
|
init_resolve_migrations_folder();
|
|
40596
41027
|
init_memory_schema();
|
|
40597
41028
|
init_twin_collapse();
|
|
40598
|
-
_require4 =
|
|
41029
|
+
_require4 = createRequire7(import.meta.url);
|
|
40599
41030
|
_drizzle2 = null;
|
|
40600
41031
|
BRAIN_SCHEMA_VERSION = "1.0.0";
|
|
40601
41032
|
CONSOLIDATED_BRAIN_TABLES = [
|
|
@@ -40783,11 +41214,11 @@ var init_skills_schema = __esm({
|
|
|
40783
41214
|
});
|
|
40784
41215
|
|
|
40785
41216
|
// packages/core/src/store/skills-db.ts
|
|
40786
|
-
import { join as
|
|
41217
|
+
import { join as join25 } from "node:path";
|
|
40787
41218
|
import { and as and6, eq as eq8 } from "drizzle-orm";
|
|
40788
41219
|
function getDefaultSkillsDbPath() {
|
|
40789
41220
|
const cleoHome = getCleoHome();
|
|
40790
|
-
const dbPath =
|
|
41221
|
+
const dbPath = join25(cleoHome, "cleo.db");
|
|
40791
41222
|
if (!dbPath.startsWith(cleoHome)) {
|
|
40792
41223
|
throw new Error(
|
|
40793
41224
|
`BUG: getDefaultSkillsDbPath() resolved to "${dbPath}" which is NOT under getCleoHome() ("${cleoHome}"). The skills registry is global-only per SG-CLEO-SKILLS-architecture-v3.md \xA74. Fix the caller, do not suppress.`
|
|
@@ -40835,19 +41266,19 @@ import {
|
|
|
40835
41266
|
chmodSync,
|
|
40836
41267
|
closeSync,
|
|
40837
41268
|
copyFileSync as copyFileSync3,
|
|
40838
|
-
existsSync as
|
|
41269
|
+
existsSync as existsSync20,
|
|
40839
41270
|
fsyncSync,
|
|
40840
41271
|
linkSync,
|
|
40841
41272
|
mkdirSync as mkdirSync5,
|
|
40842
41273
|
openSync,
|
|
40843
41274
|
readdirSync as readdirSync5,
|
|
40844
|
-
realpathSync as
|
|
41275
|
+
realpathSync as realpathSync7,
|
|
40845
41276
|
renameSync as renameSync6,
|
|
40846
41277
|
rmSync,
|
|
40847
41278
|
statSync as statSync6,
|
|
40848
41279
|
unlinkSync as unlinkSync3
|
|
40849
41280
|
} from "node:fs";
|
|
40850
|
-
import { dirname as
|
|
41281
|
+
import { dirname as dirname15, join as join26, sep as sep4 } from "node:path";
|
|
40851
41282
|
function resolveInventoryPath(entry, cwd) {
|
|
40852
41283
|
try {
|
|
40853
41284
|
if (entry.tier === "global") {
|
|
@@ -40883,8 +41314,8 @@ async function openAgentRegistryDbForSnapshot() {
|
|
|
40883
41314
|
}
|
|
40884
41315
|
async function openTelemetryDbForSnapshot() {
|
|
40885
41316
|
try {
|
|
40886
|
-
const path2 =
|
|
40887
|
-
if (!
|
|
41317
|
+
const path2 = join26(getCleoHome(), "telemetry.db");
|
|
41318
|
+
if (!existsSync20(path2)) return null;
|
|
40888
41319
|
} catch {
|
|
40889
41320
|
return null;
|
|
40890
41321
|
}
|
|
@@ -40996,7 +41427,7 @@ function rotateSnapshots(backupDir, prefix, justWritten) {
|
|
|
40996
41427
|
for (const name2 of names) {
|
|
40997
41428
|
if (keep.has(name2)) continue;
|
|
40998
41429
|
try {
|
|
40999
|
-
unlinkSync3(
|
|
41430
|
+
unlinkSync3(join26(backupDir, name2));
|
|
41000
41431
|
} catch {
|
|
41001
41432
|
}
|
|
41002
41433
|
}
|
|
@@ -41018,7 +41449,7 @@ async function snapshotProjectTargetsGated(targets, opts) {
|
|
|
41018
41449
|
let backupDir;
|
|
41019
41450
|
try {
|
|
41020
41451
|
const cleoDir = getCleoDir(cwd);
|
|
41021
|
-
backupDir =
|
|
41452
|
+
backupDir = join26(cleoDir, "backups", "sqlite");
|
|
41022
41453
|
mkdirSync5(backupDir, { recursive: true });
|
|
41023
41454
|
} catch {
|
|
41024
41455
|
return null;
|
|
@@ -41050,7 +41481,7 @@ function sourceFileOf(db) {
|
|
|
41050
41481
|
const location = db.location();
|
|
41051
41482
|
if (!location) return null;
|
|
41052
41483
|
try {
|
|
41053
|
-
return
|
|
41484
|
+
return realpathSync7(location);
|
|
41054
41485
|
} catch {
|
|
41055
41486
|
return location;
|
|
41056
41487
|
}
|
|
@@ -41061,10 +41492,10 @@ function hasLocation(db) {
|
|
|
41061
41492
|
function assertOwnedByProject(source, prefix, cwd) {
|
|
41062
41493
|
let cleoDir = getCleoDir(cwd);
|
|
41063
41494
|
try {
|
|
41064
|
-
cleoDir =
|
|
41495
|
+
cleoDir = realpathSync7(cleoDir);
|
|
41065
41496
|
} catch {
|
|
41066
41497
|
}
|
|
41067
|
-
if (!source.startsWith(cleoDir +
|
|
41498
|
+
if (!source.startsWith(cleoDir + sep4)) {
|
|
41068
41499
|
throw new Error(
|
|
41069
41500
|
`refusing to snapshot ${prefix}: its database ${source} is not inside ${cleoDir}`
|
|
41070
41501
|
);
|
|
@@ -41093,7 +41524,7 @@ function commitSnapshotFile(tmp, dest) {
|
|
|
41093
41524
|
}
|
|
41094
41525
|
renameSync6(tmp, dest);
|
|
41095
41526
|
try {
|
|
41096
|
-
const dirFd = openSync(
|
|
41527
|
+
const dirFd = openSync(dirname15(dest), "r");
|
|
41097
41528
|
try {
|
|
41098
41529
|
fsyncSync(dirFd);
|
|
41099
41530
|
} finally {
|
|
@@ -41116,7 +41547,7 @@ function removeDeadTempSnapshots(backupDir) {
|
|
|
41116
41547
|
const m = TEMP_SNAPSHOT_RE.exec(name2);
|
|
41117
41548
|
if (!m) continue;
|
|
41118
41549
|
const pid = Number(m[1]);
|
|
41119
|
-
const path2 =
|
|
41550
|
+
const path2 = join26(backupDir, name2);
|
|
41120
41551
|
const stale = pid !== process.pid && (!isPidAlive2(pid) || Date.now() - statSync6(path2).mtimeMs > TEMP_SNAPSHOT_MAX_AGE_MS);
|
|
41121
41552
|
if (stale) rmSync(path2, { force: true });
|
|
41122
41553
|
}
|
|
@@ -41126,7 +41557,7 @@ function removeDeadTempSnapshots(backupDir) {
|
|
|
41126
41557
|
async function freeSnapshotName(backupDir, prefix) {
|
|
41127
41558
|
for (let attempt = 0; attempt < SNAPSHOT_NAME_ATTEMPTS; attempt++) {
|
|
41128
41559
|
const name2 = `${prefix}-${formatTimestamp(/* @__PURE__ */ new Date())}.db`;
|
|
41129
|
-
if (!
|
|
41560
|
+
if (!existsSync20(join26(backupDir, name2))) return name2;
|
|
41130
41561
|
await new Promise((r) => setTimeout(r, 1e3 - Date.now() % 1e3 + 5));
|
|
41131
41562
|
}
|
|
41132
41563
|
throw new Error(`no free snapshot filename for ${prefix} in ${backupDir}`);
|
|
@@ -41154,7 +41585,7 @@ async function snapshotOne(target, backupDir, writtenBySource, cwd) {
|
|
|
41154
41585
|
if (opened && target.closeDb) target.closeDb(opened);
|
|
41155
41586
|
throw err;
|
|
41156
41587
|
}
|
|
41157
|
-
const dest =
|
|
41588
|
+
const dest = join26(backupDir, destName);
|
|
41158
41589
|
removeDeadTempSnapshots(backupDir);
|
|
41159
41590
|
const existing = source !== null ? writtenBySource.get(source) : void 0;
|
|
41160
41591
|
if (existing !== void 0) {
|
|
@@ -41208,13 +41639,13 @@ async function vacuumIntoBackup(opts = {}) {
|
|
|
41208
41639
|
function listSqliteBackupsForPrefix(prefix, cwd) {
|
|
41209
41640
|
try {
|
|
41210
41641
|
const cleoDir = getCleoDir(cwd);
|
|
41211
|
-
const backupDir =
|
|
41212
|
-
if (!
|
|
41642
|
+
const backupDir = join26(cleoDir, "backups", "sqlite");
|
|
41643
|
+
if (!existsSync20(backupDir)) return [];
|
|
41213
41644
|
const pattern = snapshotPattern(prefix);
|
|
41214
41645
|
return readdirSync5(backupDir).filter((f) => pattern.test(f)).map((f) => ({
|
|
41215
41646
|
name: f,
|
|
41216
|
-
path:
|
|
41217
|
-
mtimeMs: statSync6(
|
|
41647
|
+
path: join26(backupDir, f),
|
|
41648
|
+
mtimeMs: statSync6(join26(backupDir, f)).mtimeMs
|
|
41218
41649
|
})).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
41219
41650
|
} catch {
|
|
41220
41651
|
return [];
|
|
@@ -41284,15 +41715,16 @@ __export(sqlite_exports, {
|
|
|
41284
41715
|
resetDbState: () => resetDbState,
|
|
41285
41716
|
resolveMigrationsFolder: () => resolveMigrationsFolder,
|
|
41286
41717
|
schema: () => tasks_schema_exports,
|
|
41287
|
-
seedTasksMeta: () => seedTasksMeta
|
|
41718
|
+
seedTasksMeta: () => seedTasksMeta,
|
|
41719
|
+
worktreeRecoveryRefusal: () => worktreeRecoveryRefusal
|
|
41288
41720
|
});
|
|
41289
|
-
import { copyFileSync as copyFileSync4, existsSync as
|
|
41290
|
-
import { createRequire as
|
|
41291
|
-
import { basename as basename8, dirname as
|
|
41721
|
+
import { copyFileSync as copyFileSync4, existsSync as existsSync21, realpathSync as realpathSync8, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41722
|
+
import { createRequire as createRequire8 } from "node:module";
|
|
41723
|
+
import { basename as basename8, dirname as dirname16, resolve as resolve12 } from "node:path";
|
|
41292
41724
|
import { eq as eq9 } from "drizzle-orm";
|
|
41293
41725
|
function _getDrizzle3() {
|
|
41294
41726
|
if (_drizzle3 === null) {
|
|
41295
|
-
const _require7 =
|
|
41727
|
+
const _require7 = createRequire8(import.meta.url);
|
|
41296
41728
|
const mod = _require7("drizzle-orm/node-sqlite");
|
|
41297
41729
|
_drizzle3 = mod.drizzle;
|
|
41298
41730
|
}
|
|
@@ -41328,13 +41760,19 @@ function countBackupTasks(backupDb) {
|
|
|
41328
41760
|
return 0;
|
|
41329
41761
|
}
|
|
41330
41762
|
function isSameDirectory(a, b) {
|
|
41331
|
-
if (
|
|
41763
|
+
if (resolve12(a) === resolve12(b)) return true;
|
|
41332
41764
|
try {
|
|
41333
|
-
return
|
|
41765
|
+
return realpathSync8(a) === realpathSync8(b);
|
|
41334
41766
|
} catch {
|
|
41335
41767
|
return false;
|
|
41336
41768
|
}
|
|
41337
41769
|
}
|
|
41770
|
+
function worktreeRecoveryRefusal(dbPath) {
|
|
41771
|
+
const storeCleoDir = dirname16(dbPath);
|
|
41772
|
+
const root = dirname16(storeCleoDir);
|
|
41773
|
+
if (basename8(storeCleoDir) !== ".cleo" || !isGitLinkedCheckout(root)) return null;
|
|
41774
|
+
return `Auto-recovery refused: ${dbPath} lives inside the git worktree ${root}; ${describeWorktreeOwner(root)}. A worktree uses its owning project's store and never receives a restored copy (T12460, T12677).`;
|
|
41775
|
+
}
|
|
41338
41776
|
async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
41339
41777
|
const { openNativeDatabase: openNativeDatabase2 } = await Promise.resolve().then(() => (init_sqlite_native(), sqlite_native_exports));
|
|
41340
41778
|
const log15 = getLogger("sqlite");
|
|
@@ -41343,12 +41781,10 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
41343
41781
|
const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks_tasks").get();
|
|
41344
41782
|
const taskCount = countResult?.cnt ?? 0;
|
|
41345
41783
|
if (taskCount > 0) return false;
|
|
41346
|
-
const storeCleoDir =
|
|
41347
|
-
|
|
41348
|
-
|
|
41349
|
-
|
|
41350
|
-
"Auto-recovery refused: the empty store lives inside a git worktree (T12460). Worktrees must resolve the parent project store."
|
|
41351
|
-
);
|
|
41784
|
+
const storeCleoDir = dirname16(dbPath);
|
|
41785
|
+
const worktreeRefusal = worktreeRecoveryRefusal(dbPath);
|
|
41786
|
+
if (worktreeRefusal !== null) {
|
|
41787
|
+
log15.warn({ dbPath }, worktreeRefusal);
|
|
41352
41788
|
return false;
|
|
41353
41789
|
}
|
|
41354
41790
|
const backups = listSqliteBackups(cwd);
|
|
@@ -41356,7 +41792,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
41356
41792
|
return false;
|
|
41357
41793
|
}
|
|
41358
41794
|
const newestBackup = backups[0];
|
|
41359
|
-
const backupCleoDir =
|
|
41795
|
+
const backupCleoDir = dirname16(dirname16(dirname16(newestBackup.path)));
|
|
41360
41796
|
if (!isSameDirectory(backupCleoDir, storeCleoDir)) {
|
|
41361
41797
|
log15.warn(
|
|
41362
41798
|
{ dbPath, backupPath: newestBackup.path },
|
|
@@ -41478,6 +41914,7 @@ function runMigrations(nativeDb, db, dbPath) {
|
|
|
41478
41914
|
try {
|
|
41479
41915
|
migrateWithRetry(db, migrationsFolder, nativeDb, "tasks", "sqlite");
|
|
41480
41916
|
} catch (error) {
|
|
41917
|
+
if (isWorktreeBuildSchemaError(error)) throw error;
|
|
41481
41918
|
if (isSqliteBusy(error) || !tableExists(nativeDb, "tasks_tasks")) throw error;
|
|
41482
41919
|
try {
|
|
41483
41920
|
rebuildLegacyTasksLineage(
|
|
@@ -41519,7 +41956,7 @@ async function getSchemaVersion(cwd) {
|
|
|
41519
41956
|
return result[0]?.value ?? null;
|
|
41520
41957
|
}
|
|
41521
41958
|
function dbExists(cwd) {
|
|
41522
|
-
return
|
|
41959
|
+
return existsSync21(resolveDualScopeDbPath("project", cwd));
|
|
41523
41960
|
}
|
|
41524
41961
|
function getNativeDb(cwd) {
|
|
41525
41962
|
return boundProjectNative("tasks", cwd);
|
|
@@ -41555,6 +41992,7 @@ var init_sqlite3 = __esm({
|
|
|
41555
41992
|
init_resolve_migrations_folder();
|
|
41556
41993
|
init_sqlite_backup();
|
|
41557
41994
|
init_twin_collapse();
|
|
41995
|
+
init_worktree_build_guard();
|
|
41558
41996
|
init_worktree_isolation_guard();
|
|
41559
41997
|
init_sqlite_native();
|
|
41560
41998
|
init_tasks_schema();
|
|
@@ -41583,15 +42021,15 @@ var init_sqlite3 = __esm({
|
|
|
41583
42021
|
// packages/core/src/store/exodus/migrate.ts
|
|
41584
42022
|
import {
|
|
41585
42023
|
copyFileSync as copyFileSync5,
|
|
41586
|
-
existsSync as
|
|
42024
|
+
existsSync as existsSync22,
|
|
41587
42025
|
mkdirSync as mkdirSync6,
|
|
41588
|
-
readFileSync as
|
|
42026
|
+
readFileSync as readFileSync7,
|
|
41589
42027
|
renameSync as renameSync8,
|
|
41590
42028
|
statSync as statSync7,
|
|
41591
42029
|
unlinkSync as unlinkSync5,
|
|
41592
42030
|
writeFileSync as writeFileSync6
|
|
41593
42031
|
} from "node:fs";
|
|
41594
|
-
import { join as
|
|
42032
|
+
import { join as join27 } from "node:path";
|
|
41595
42033
|
function getSqliteVersion(db) {
|
|
41596
42034
|
try {
|
|
41597
42035
|
const row = db.prepare("SELECT sqlite_version() AS v").get();
|
|
@@ -41622,24 +42060,24 @@ function restoreGrandfatheredGuards(db, suspended) {
|
|
|
41622
42060
|
}
|
|
41623
42061
|
}
|
|
41624
42062
|
function writeJournal(stagingDir, journal) {
|
|
41625
|
-
const journalPath =
|
|
42063
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
41626
42064
|
const tmpPath = `${journalPath}.tmp`;
|
|
41627
42065
|
writeFileSync6(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
|
|
41628
42066
|
renameSync8(tmpPath, journalPath);
|
|
41629
42067
|
}
|
|
41630
42068
|
function readJournal(stagingDir) {
|
|
41631
|
-
const journalPath =
|
|
41632
|
-
if (!
|
|
42069
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
42070
|
+
if (!existsSync22(journalPath)) return null;
|
|
41633
42071
|
try {
|
|
41634
|
-
return JSON.parse(
|
|
42072
|
+
return JSON.parse(readFileSync7(journalPath, "utf8"));
|
|
41635
42073
|
} catch {
|
|
41636
42074
|
return null;
|
|
41637
42075
|
}
|
|
41638
42076
|
}
|
|
41639
42077
|
function clearExodusJournal(stagingDir) {
|
|
41640
|
-
const journalPath =
|
|
42078
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
41641
42079
|
try {
|
|
41642
|
-
if (!
|
|
42080
|
+
if (!existsSync22(journalPath)) return false;
|
|
41643
42081
|
unlinkSync5(journalPath);
|
|
41644
42082
|
log10.info(
|
|
41645
42083
|
{ stagingDir },
|
|
@@ -41935,7 +42373,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
41935
42373
|
mkdirSync6(stagingDir, { recursive: true });
|
|
41936
42374
|
let sqliteVersion = "unknown";
|
|
41937
42375
|
for (const src of sources) {
|
|
41938
|
-
if (
|
|
42376
|
+
if (existsSync22(src.path)) {
|
|
41939
42377
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
41940
42378
|
sqliteVersion = getSqliteVersion(snap.db);
|
|
41941
42379
|
snap.close();
|
|
@@ -41965,15 +42403,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
41965
42403
|
let reseedProject = null;
|
|
41966
42404
|
try {
|
|
41967
42405
|
for (const src of sources) {
|
|
41968
|
-
if (!
|
|
41969
|
-
const backupDest =
|
|
42406
|
+
if (!existsSync22(src.path)) continue;
|
|
42407
|
+
const backupDest = join27(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
|
|
41970
42408
|
const srcBytes = safeStatBytes(src.path);
|
|
41971
42409
|
const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
|
|
41972
42410
|
if (skipStagingCopy) {
|
|
41973
42411
|
onProgress?.(
|
|
41974
42412
|
`Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
|
|
41975
42413
|
);
|
|
41976
|
-
} else if (!
|
|
42414
|
+
} else if (!existsSync22(backupDest)) {
|
|
41977
42415
|
onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
|
|
41978
42416
|
copyFileSync5(src.path, backupDest);
|
|
41979
42417
|
backupPaths.push(backupDest);
|
|
@@ -42006,8 +42444,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
42006
42444
|
}
|
|
42007
42445
|
prepareExodusRecovery(projectNative, stagingDir);
|
|
42008
42446
|
if (globalNative !== null) prepareExodusRecovery(globalNative, stagingDir);
|
|
42009
|
-
const projectSources = sources.filter((s) => s.targetScope === "project" &&
|
|
42010
|
-
const globalSources = sources.filter((s) => s.targetScope === "global" &&
|
|
42447
|
+
const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
|
|
42448
|
+
const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync22(s.path));
|
|
42011
42449
|
if (globalNative === null && globalSources.length > 0)
|
|
42012
42450
|
throw new Error("A projectOnly exodus run was given global-scope sources");
|
|
42013
42451
|
await migrateScope(
|
|
@@ -42315,9 +42753,9 @@ __export(reconcile_exports, {
|
|
|
42315
42753
|
reconcileSupersededStores: () => reconcileSupersededStores,
|
|
42316
42754
|
unmigratedBareSources: () => unmigratedBareSources
|
|
42317
42755
|
});
|
|
42318
|
-
import { copyFileSync as copyFileSync6, existsSync as
|
|
42756
|
+
import { copyFileSync as copyFileSync6, existsSync as existsSync23, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
42319
42757
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
42320
|
-
import { basename as basename9, join as
|
|
42758
|
+
import { basename as basename9, join as join28 } from "node:path";
|
|
42321
42759
|
function ident2(name2) {
|
|
42322
42760
|
return `"${name2.replace(/"/g, '""')}"`;
|
|
42323
42761
|
}
|
|
@@ -42386,7 +42824,7 @@ function assessSupersededProjectStores(liveStorePath, sources, resolveTarget = r
|
|
|
42386
42824
|
}
|
|
42387
42825
|
function legacySourcesHoldRows(sources) {
|
|
42388
42826
|
for (const src of sources) {
|
|
42389
|
-
if (!
|
|
42827
|
+
if (!existsSync23(src.path)) continue;
|
|
42390
42828
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
42391
42829
|
try {
|
|
42392
42830
|
for (const table of orderTablesForCopy(snap.db)) {
|
|
@@ -42417,8 +42855,8 @@ async function bareTaskCoreSource(liveStorePath, resolveTarget, outDir) {
|
|
|
42417
42855
|
live.close();
|
|
42418
42856
|
}
|
|
42419
42857
|
if (tables.length === 0) return null;
|
|
42420
|
-
const seedPath = await buildFreshProjectStore(
|
|
42421
|
-
const path2 =
|
|
42858
|
+
const seedPath = await buildFreshProjectStore(join28(outDir, "fresh-project-seed.db"));
|
|
42859
|
+
const path2 = join28(outDir, "cleo-bare-task-core.db");
|
|
42422
42860
|
const snap = openCleoDbSnapshot(path2, { readOnly: false });
|
|
42423
42861
|
let kept = 0;
|
|
42424
42862
|
try {
|
|
@@ -42466,7 +42904,7 @@ async function buildFreshProjectStore(path2) {
|
|
|
42466
42904
|
}
|
|
42467
42905
|
function snapshotFresherBareRows(barePath, legacyTasksPath, stagingDir) {
|
|
42468
42906
|
if (legacyTasksPath === void 0) return null;
|
|
42469
|
-
const path2 =
|
|
42907
|
+
const path2 = join28(stagingDir, "cleo-bare-task-core-fresher.db");
|
|
42470
42908
|
const snap = openCleoDbSnapshot(barePath, { readOnly: true });
|
|
42471
42909
|
try {
|
|
42472
42910
|
snap.db.exec(`VACUUM INTO '${path2.replace(/'/g, "''")}'`);
|
|
@@ -42617,7 +43055,7 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
|
|
|
42617
43055
|
const additive = options.additive === true;
|
|
42618
43056
|
const plan = buildExodusPlan(projectRoot);
|
|
42619
43057
|
const resolveTarget = await buildRuntimeTargetResolver();
|
|
42620
|
-
const scratch = mkdtempSync(
|
|
43058
|
+
const scratch = mkdtempSync(join28(tmpdir3(), "cleo-reconcile-"));
|
|
42621
43059
|
try {
|
|
42622
43060
|
return await reconcileWithScratch(
|
|
42623
43061
|
projectRoot,
|
|
@@ -42633,8 +43071,8 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
|
|
|
42633
43071
|
}
|
|
42634
43072
|
}
|
|
42635
43073
|
async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath, plan, resolveTarget, scratch) {
|
|
42636
|
-
const fileSources = plan.sources.filter((s) => s.targetScope === "project" &&
|
|
42637
|
-
const bare = !additive &&
|
|
43074
|
+
const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync23(s.path));
|
|
43075
|
+
const bare = !additive && existsSync23(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
|
|
42638
43076
|
const copyResolver = additive ? (sourceName, legacyTable) => {
|
|
42639
43077
|
const r = resolveTarget(sourceName, legacyTable);
|
|
42640
43078
|
return r.kind !== "skip" && isLiveAuthoritative(sourceName, legacyTable, r.targetName) ? { kind: "skip", reason: "additive: live-authoritative task graph" } : r;
|
|
@@ -42653,7 +43091,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42653
43091
|
stagingDir: null,
|
|
42654
43092
|
receiptPath: null
|
|
42655
43093
|
};
|
|
42656
|
-
if (sources.length === 0 || !
|
|
43094
|
+
if (sources.length === 0 || !existsSync23(liveStorePath)) {
|
|
42657
43095
|
return {
|
|
42658
43096
|
...base,
|
|
42659
43097
|
outcome: "nothing-to-reconcile",
|
|
@@ -42693,11 +43131,11 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42693
43131
|
};
|
|
42694
43132
|
}
|
|
42695
43133
|
const iso = (/* @__PURE__ */ new Date()).toISOString().replace(/[:]/g, "").replace(/\..+Z$/, "Z");
|
|
42696
|
-
const stagingDir =
|
|
43134
|
+
const stagingDir = join28(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
|
|
42697
43135
|
mkdirSync7(stagingDir, { recursive: true });
|
|
42698
43136
|
const copySources = sources.map((s) => {
|
|
42699
43137
|
if (s !== bare) return s;
|
|
42700
|
-
const kept =
|
|
43138
|
+
const kept = join28(stagingDir, basename9(s.path));
|
|
42701
43139
|
copyFileSync6(s.path, kept);
|
|
42702
43140
|
return { ...s, path: kept };
|
|
42703
43141
|
});
|
|
@@ -42717,7 +43155,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42717
43155
|
const result = await withLock(
|
|
42718
43156
|
`${liveStorePath}.exodus-on-open.lock`,
|
|
42719
43157
|
async () => {
|
|
42720
|
-
const liveBefore =
|
|
43158
|
+
const liveBefore = join28(scratch, "live-before.db");
|
|
42721
43159
|
snapshotLive(liveStorePath, liveBefore);
|
|
42722
43160
|
const migrated = await runExodusMigrate(reconcilePlan, false, (msg) => log11.debug(msg), {
|
|
42723
43161
|
projectOnly: true,
|
|
@@ -42767,7 +43205,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42767
43205
|
},
|
|
42768
43206
|
{ stale: 6e5, retries: 30 }
|
|
42769
43207
|
);
|
|
42770
|
-
const receiptPath =
|
|
43208
|
+
const receiptPath = join28(stagingDir, RECEIPT_FILENAME);
|
|
42771
43209
|
const receipt2 = { ...result, receiptPath };
|
|
42772
43210
|
writeFileSync7(receiptPath, `${JSON.stringify(receipt2, null, 2)}
|
|
42773
43211
|
`, "utf8");
|
|
@@ -42844,20 +43282,20 @@ var init_seal = __esm({
|
|
|
42844
43282
|
});
|
|
42845
43283
|
|
|
42846
43284
|
// packages/core/src/store/exodus/status.ts
|
|
42847
|
-
import { existsSync as
|
|
42848
|
-
import { join as
|
|
43285
|
+
import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync8, statSync as statSync8 } from "node:fs";
|
|
43286
|
+
import { join as join29 } from "node:path";
|
|
42849
43287
|
function readJournal2(stagingDir) {
|
|
42850
|
-
const p =
|
|
42851
|
-
if (!
|
|
43288
|
+
const p = join29(stagingDir, JOURNAL_FILENAME2);
|
|
43289
|
+
if (!existsSync24(p)) return null;
|
|
42852
43290
|
try {
|
|
42853
|
-
return JSON.parse(
|
|
43291
|
+
return JSON.parse(readFileSync8(p, "utf8"));
|
|
42854
43292
|
} catch {
|
|
42855
43293
|
return null;
|
|
42856
43294
|
}
|
|
42857
43295
|
}
|
|
42858
43296
|
function findStagingDirs(cleoDir) {
|
|
42859
43297
|
try {
|
|
42860
|
-
return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) =>
|
|
43298
|
+
return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join29(cleoDir, e.name)).sort().reverse();
|
|
42861
43299
|
} catch {
|
|
42862
43300
|
return [];
|
|
42863
43301
|
}
|
|
@@ -42880,15 +43318,15 @@ function runExodusStatus(cwd) {
|
|
|
42880
43318
|
const sourcesInfo = plan.sources.map((s) => ({
|
|
42881
43319
|
name: s.name,
|
|
42882
43320
|
path: s.path,
|
|
42883
|
-
exists:
|
|
43321
|
+
exists: existsSync24(s.path),
|
|
42884
43322
|
bytes: safeBytes(s.path)
|
|
42885
43323
|
}));
|
|
42886
43324
|
return {
|
|
42887
43325
|
hasStaging: latestStaging !== null,
|
|
42888
43326
|
stagingDir: latestStaging,
|
|
42889
43327
|
journal,
|
|
42890
|
-
projectDbExists:
|
|
42891
|
-
globalDbExists:
|
|
43328
|
+
projectDbExists: existsSync24(projectDbPath),
|
|
43329
|
+
globalDbExists: existsSync24(globalDbPath),
|
|
42892
43330
|
sourcesPresent: sourcesInfo.some((s) => s.exists),
|
|
42893
43331
|
sources: sourcesInfo
|
|
42894
43332
|
};
|
|
@@ -42905,8 +43343,8 @@ var init_status = __esm({
|
|
|
42905
43343
|
});
|
|
42906
43344
|
|
|
42907
43345
|
// packages/core/src/store/exodus/verify-migration.ts
|
|
42908
|
-
import { existsSync as
|
|
42909
|
-
import { createRequire as
|
|
43346
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
43347
|
+
import { createRequire as createRequire9 } from "node:module";
|
|
42910
43348
|
function orderByClause(db, tableName) {
|
|
42911
43349
|
try {
|
|
42912
43350
|
const pragma = db.prepare(`PRAGMA table_info("${tableName}")`).all();
|
|
@@ -43170,7 +43608,7 @@ function orphanAlreadyInSource(targetDb, fk, sources, resolveTarget = resolveCon
|
|
|
43170
43608
|
const anyFeeder = (targetTable, probe) => {
|
|
43171
43609
|
for (const feeder of feedersOf(targetTable)) {
|
|
43172
43610
|
const src = sources.find((s) => s.name === feeder.sourceName);
|
|
43173
|
-
if (src === void 0 || !
|
|
43611
|
+
if (src === void 0 || !existsSync25(src.path)) continue;
|
|
43174
43612
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
43175
43613
|
try {
|
|
43176
43614
|
if (!tableExists3(snap.db, feeder.legacyTable)) continue;
|
|
@@ -43225,7 +43663,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43225
43663
|
const preExistingForeignKeyViolations = [];
|
|
43226
43664
|
const failureLines = [];
|
|
43227
43665
|
const sourceOrphanSigs = /* @__PURE__ */ new Set();
|
|
43228
|
-
if (!
|
|
43666
|
+
if (!existsSync25(projectDbPath)) {
|
|
43229
43667
|
return {
|
|
43230
43668
|
ok: false,
|
|
43231
43669
|
tables: [],
|
|
@@ -43236,7 +43674,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43236
43674
|
error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
|
|
43237
43675
|
};
|
|
43238
43676
|
}
|
|
43239
|
-
if (!
|
|
43677
|
+
if (!existsSync25(globalDbPath)) {
|
|
43240
43678
|
return {
|
|
43241
43679
|
ok: false,
|
|
43242
43680
|
tables: [],
|
|
@@ -43251,7 +43689,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43251
43689
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
43252
43690
|
try {
|
|
43253
43691
|
for (const src of sources) {
|
|
43254
|
-
if (!
|
|
43692
|
+
if (!existsSync25(src.path)) {
|
|
43255
43693
|
onProgress?.(`Skipping ${src.name} (not present)`);
|
|
43256
43694
|
continue;
|
|
43257
43695
|
}
|
|
@@ -43446,7 +43884,7 @@ var init_verify_migration = __esm({
|
|
|
43446
43884
|
init_column_transforms();
|
|
43447
43885
|
init_table_name_map();
|
|
43448
43886
|
log13 = getLogger("verify-migration");
|
|
43449
|
-
_require5 =
|
|
43887
|
+
_require5 = createRequire9(import.meta.url);
|
|
43450
43888
|
CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
|
|
43451
43889
|
}
|
|
43452
43890
|
});
|
|
@@ -43542,11 +43980,11 @@ __export(on_open_exports, {
|
|
|
43542
43980
|
maybeRunExodusOnOpen: () => maybeRunExodusOnOpen,
|
|
43543
43981
|
withExodusOnOpenSuppressed: () => withExodusOnOpenSuppressed
|
|
43544
43982
|
});
|
|
43545
|
-
import { existsSync as
|
|
43983
|
+
import { existsSync as existsSync26, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
|
|
43546
43984
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
43547
|
-
import { join as
|
|
43985
|
+
import { join as join30, resolve as resolve13 } from "node:path";
|
|
43548
43986
|
async function withExodusOnOpenSuppressed(dbPath, fn) {
|
|
43549
|
-
const key =
|
|
43987
|
+
const key = resolve13(dbPath);
|
|
43550
43988
|
_reconcileInProgress.set(key, (_reconcileInProgress.get(key) ?? 0) + 1);
|
|
43551
43989
|
try {
|
|
43552
43990
|
return await fn();
|
|
@@ -43584,7 +44022,7 @@ function remedyFor(scope) {
|
|
|
43584
44022
|
}
|
|
43585
44023
|
async function strandedLegacySources(scope, cwd) {
|
|
43586
44024
|
const { buildExodusPlan: buildExodusPlan2, legacySourcesHoldRows: legacySourcesHoldRows2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
|
|
43587
|
-
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope &&
|
|
44025
|
+
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync26(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
|
|
43588
44026
|
}
|
|
43589
44027
|
async function rollbackBothScopes(plan) {
|
|
43590
44028
|
const { getDualScopeNativeDb: getDualScopeNativeDb2, openDualScopeDbAtPath: openDualScopeDbAtPath2 } = await Promise.resolve().then(() => (init_dual_scope_db(), dual_scope_db_exports));
|
|
@@ -43662,7 +44100,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43662
44100
|
if (_exodusInProgress) {
|
|
43663
44101
|
return { outcome: "skipped", reason: "re-entrant open during active migration" };
|
|
43664
44102
|
}
|
|
43665
|
-
if (_reconcileInProgress.has(
|
|
44103
|
+
if (_reconcileInProgress.has(resolve13(dbPath))) {
|
|
43666
44104
|
return {
|
|
43667
44105
|
outcome: "skipped",
|
|
43668
44106
|
reason: "an explicit superseded-store reconcile of this store is in progress"
|
|
@@ -43695,14 +44133,14 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43695
44133
|
const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
|
|
43696
44134
|
const plan = buildExodusPlan2(cwd);
|
|
43697
44135
|
const plannedTarget = scope === "project" ? plan.projectDbPath : plan.globalDbPath;
|
|
43698
|
-
if (
|
|
44136
|
+
if (resolve13(plannedTarget) !== resolve13(dbPath)) {
|
|
43699
44137
|
return {
|
|
43700
44138
|
outcome: "aborted",
|
|
43701
44139
|
reason: `migration plan target ${plannedTarget} does not match opened database ${dbPath}; no migration applied`
|
|
43702
44140
|
};
|
|
43703
44141
|
}
|
|
43704
44142
|
const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
|
|
43705
|
-
if (!scopeSources.some((s) =>
|
|
44143
|
+
if (!scopeSources.some((s) => existsSync26(s.path))) {
|
|
43706
44144
|
return {
|
|
43707
44145
|
outcome: "skipped",
|
|
43708
44146
|
reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
|
|
@@ -43719,12 +44157,12 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43719
44157
|
{
|
|
43720
44158
|
scope,
|
|
43721
44159
|
dbPath,
|
|
43722
|
-
sources: plan.sources.filter((s) =>
|
|
44160
|
+
sources: plan.sources.filter((s) => existsSync26(s.path)).map((s) => s.name)
|
|
43723
44161
|
},
|
|
43724
44162
|
"exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
|
|
43725
44163
|
);
|
|
43726
44164
|
_exodusInProgress = true;
|
|
43727
|
-
const bareScratch = mkdtempSync2(
|
|
44165
|
+
const bareScratch = mkdtempSync2(join30(tmpdir4(), "cleo-exodus-bare-"));
|
|
43728
44166
|
try {
|
|
43729
44167
|
const { buildRuntimeTargetResolver: buildRuntimeTargetResolver2 } = await Promise.resolve().then(() => (init_runtime_targets(), runtime_targets_exports));
|
|
43730
44168
|
const resolveTarget = await buildRuntimeTargetResolver2();
|
|
@@ -43732,7 +44170,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43732
44170
|
const bare = scope === "project" ? await unmigratedBareSources2(
|
|
43733
44171
|
dbPath,
|
|
43734
44172
|
resolveTarget,
|
|
43735
|
-
plan.sources.find((s) => s.name === "tasks" &&
|
|
44173
|
+
plan.sources.find((s) => s.name === "tasks" && existsSync26(s.path))?.path,
|
|
43736
44174
|
bareScratch
|
|
43737
44175
|
) : { first: [], last: [] };
|
|
43738
44176
|
const migratePlan = { ...plan, sources: [...bare.first, ...plan.sources, ...bare.last] };
|
|
@@ -43796,7 +44234,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43796
44234
|
"exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
|
|
43797
44235
|
);
|
|
43798
44236
|
try {
|
|
43799
|
-
const consumed = plan.sources.filter((s) =>
|
|
44237
|
+
const consumed = plan.sources.filter((s) => existsSync26(s.path));
|
|
43800
44238
|
const identities = await sealTargets(plan, consumed);
|
|
43801
44239
|
const archiveResult = archiveMigratedSources(consumed, cwd, plan, identities);
|
|
43802
44240
|
log14.info(
|
|
@@ -43871,9 +44309,9 @@ __export(dual_scope_db_exports, {
|
|
|
43871
44309
|
upsertIdempotent: () => upsertIdempotent,
|
|
43872
44310
|
withStoreSchemaOwnership: () => withStoreSchemaOwnership
|
|
43873
44311
|
});
|
|
43874
|
-
import { existsSync as
|
|
43875
|
-
import { createRequire as
|
|
43876
|
-
import { dirname as
|
|
44312
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
|
|
44313
|
+
import { createRequire as createRequire10 } from "node:module";
|
|
44314
|
+
import { dirname as dirname17, join as join31, resolve as resolve14 } from "node:path";
|
|
43877
44315
|
function getDualScopeNativeDb(handle) {
|
|
43878
44316
|
const db = handle.db;
|
|
43879
44317
|
if ("$client" in db && db.$client instanceof getDatabaseSyncCtor()) return db.$client;
|
|
@@ -43895,9 +44333,9 @@ function cacheKey(scope, dbPath) {
|
|
|
43895
44333
|
}
|
|
43896
44334
|
function resolveDualScopeDbPath(scope, cwd, capturedGlobalHome) {
|
|
43897
44335
|
if (scope === "project") {
|
|
43898
|
-
return
|
|
44336
|
+
return join31(resolveCleoDir(cwd), "cleo.db");
|
|
43899
44337
|
}
|
|
43900
|
-
return
|
|
44338
|
+
return join31(capturedGlobalHome ?? getCleoHome(), "cleo.db");
|
|
43901
44339
|
}
|
|
43902
44340
|
function migrationsSetName(scope) {
|
|
43903
44341
|
return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
|
|
@@ -43947,8 +44385,8 @@ async function openDualScopeDb(scope, cwd, options) {
|
|
|
43947
44385
|
async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
43948
44386
|
execution?.assertActive();
|
|
43949
44387
|
log15.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
|
|
43950
|
-
const dir =
|
|
43951
|
-
if (!
|
|
44388
|
+
const dir = dirname17(dbPath);
|
|
44389
|
+
if (!existsSync27(dir)) {
|
|
43952
44390
|
mkdirSync8(dir, { recursive: true });
|
|
43953
44391
|
}
|
|
43954
44392
|
execution?.assertActive();
|
|
@@ -43956,6 +44394,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
|
43956
44394
|
const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
|
|
43957
44395
|
try {
|
|
43958
44396
|
applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
|
|
44397
|
+
installSchemaWriteGuard(nativeDb);
|
|
43959
44398
|
const drizzle2 = getDrizzle();
|
|
43960
44399
|
const db = drizzle2({ client: nativeDb });
|
|
43961
44400
|
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
@@ -44004,11 +44443,12 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
|
44004
44443
|
execution?.assertActive();
|
|
44005
44444
|
return handle;
|
|
44006
44445
|
} catch (err) {
|
|
44446
|
+
const explained = explainSchemaWriteDenial(nativeDb, err);
|
|
44007
44447
|
try {
|
|
44008
44448
|
nativeDb.close();
|
|
44009
44449
|
} catch {
|
|
44010
44450
|
}
|
|
44011
|
-
throw
|
|
44451
|
+
throw explained;
|
|
44012
44452
|
}
|
|
44013
44453
|
}
|
|
44014
44454
|
async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
@@ -44029,7 +44469,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44029
44469
|
);
|
|
44030
44470
|
}
|
|
44031
44471
|
const dedicated = options?.dedicated === true;
|
|
44032
|
-
const normalizedPath =
|
|
44472
|
+
const normalizedPath = resolve14(dbPath);
|
|
44033
44473
|
const key = cacheKey(scope, normalizedPath);
|
|
44034
44474
|
if (!dedicated) {
|
|
44035
44475
|
const existing = _cache.get(key);
|
|
@@ -44066,8 +44506,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44066
44506
|
}
|
|
44067
44507
|
let initResolve = null;
|
|
44068
44508
|
let initReject = null;
|
|
44069
|
-
const initPromise = new Promise((
|
|
44070
|
-
initResolve =
|
|
44509
|
+
const initPromise = new Promise((resolve16, reject) => {
|
|
44510
|
+
initResolve = resolve16;
|
|
44071
44511
|
initReject = reject;
|
|
44072
44512
|
});
|
|
44073
44513
|
_cache.set(key, {
|
|
@@ -44088,8 +44528,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44088
44528
|
try {
|
|
44089
44529
|
execution?.assertActive();
|
|
44090
44530
|
log15.debug({ scope, dbPath: normalizedPath }, "opening dual-scope cleo.db");
|
|
44091
|
-
const dir =
|
|
44092
|
-
if (!
|
|
44531
|
+
const dir = dirname17(normalizedPath);
|
|
44532
|
+
if (!existsSync27(dir)) {
|
|
44093
44533
|
mkdirSync8(dir, { recursive: true });
|
|
44094
44534
|
}
|
|
44095
44535
|
execution?.assertActive();
|
|
@@ -44097,6 +44537,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44097
44537
|
const nativeDb = new DatabaseSyncCtor(normalizedPath, { allowExtension: true });
|
|
44098
44538
|
openingNative = nativeDb;
|
|
44099
44539
|
applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
|
|
44540
|
+
installSchemaWriteGuard(nativeDb);
|
|
44100
44541
|
const drizzle2 = getDrizzle();
|
|
44101
44542
|
const db = drizzle2({ client: nativeDb });
|
|
44102
44543
|
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
@@ -44227,12 +44668,13 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44227
44668
|
execution?.assertActive();
|
|
44228
44669
|
initResolve(finalHandle);
|
|
44229
44670
|
} catch (err) {
|
|
44671
|
+
const explained = openingNative ? explainSchemaWriteDenial(openingNative, err) : err;
|
|
44230
44672
|
try {
|
|
44231
44673
|
if (!published && openingNative?.isOpen) openingNative.close();
|
|
44232
44674
|
} catch (closeError) {
|
|
44233
44675
|
log15.warn({ closeError }, "failed to close unpublished database initializer");
|
|
44234
44676
|
}
|
|
44235
|
-
initReject(
|
|
44677
|
+
initReject(explained);
|
|
44236
44678
|
}
|
|
44237
44679
|
})();
|
|
44238
44680
|
return initPromise;
|
|
@@ -44305,6 +44747,7 @@ var init_dual_scope_db = __esm({
|
|
|
44305
44747
|
init_relocated_store_guard();
|
|
44306
44748
|
init_resolve_migrations_folder();
|
|
44307
44749
|
init_sqlite_pragmas();
|
|
44750
|
+
init_worktree_build_guard();
|
|
44308
44751
|
init_worktree_isolation_guard();
|
|
44309
44752
|
init_writer_lease();
|
|
44310
44753
|
ExodusAbortWriteUnsafeError = class extends Error {
|
|
@@ -44327,7 +44770,7 @@ var init_dual_scope_db = __esm({
|
|
|
44327
44770
|
}
|
|
44328
44771
|
};
|
|
44329
44772
|
_cache = /* @__PURE__ */ new Map();
|
|
44330
|
-
_require6 =
|
|
44773
|
+
_require6 = createRequire10(import.meta.url);
|
|
44331
44774
|
_drizzle4 = null;
|
|
44332
44775
|
_DatabaseSyncCtor = null;
|
|
44333
44776
|
EntryCancelledError = class extends Error {
|
|
@@ -44358,7 +44801,7 @@ var init_dual_scope_db = __esm({
|
|
|
44358
44801
|
}
|
|
44359
44802
|
/** @inheritdoc */
|
|
44360
44803
|
async openProject(dbPath, options) {
|
|
44361
|
-
const normalized =
|
|
44804
|
+
const normalized = resolve14(dbPath);
|
|
44362
44805
|
if (options?.dedicated) {
|
|
44363
44806
|
const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
|
|
44364
44807
|
dedicated: true
|
|
@@ -44370,7 +44813,7 @@ var init_dual_scope_db = __esm({
|
|
|
44370
44813
|
/** @inheritdoc */
|
|
44371
44814
|
async openGlobal(options) {
|
|
44372
44815
|
const dbPath = resolveDualScopeDbPath("global");
|
|
44373
|
-
const normalized =
|
|
44816
|
+
const normalized = resolve14(dbPath);
|
|
44374
44817
|
if (options?.dedicated) {
|
|
44375
44818
|
const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
|
|
44376
44819
|
dedicated: true
|
|
@@ -44381,7 +44824,7 @@ var init_dual_scope_db = __esm({
|
|
|
44381
44824
|
}
|
|
44382
44825
|
/** @inheritdoc */
|
|
44383
44826
|
async openGlobalAt(dbPath, options) {
|
|
44384
|
-
const normalized =
|
|
44827
|
+
const normalized = resolve14(dbPath);
|
|
44385
44828
|
if (options?.dedicated) {
|
|
44386
44829
|
const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
|
|
44387
44830
|
dedicated: true
|
|
@@ -44392,7 +44835,7 @@ var init_dual_scope_db = __esm({
|
|
|
44392
44835
|
}
|
|
44393
44836
|
/** @inheritdoc */
|
|
44394
44837
|
closeProject(dbPath) {
|
|
44395
|
-
const normalized =
|
|
44838
|
+
const normalized = resolve14(dbPath);
|
|
44396
44839
|
this.closeEntry("project", normalized);
|
|
44397
44840
|
}
|
|
44398
44841
|
/** @inheritdoc */
|
|
@@ -44429,8 +44872,8 @@ var init_dual_scope_db = __esm({
|
|
|
44429
44872
|
const entryId = ++this._nextId;
|
|
44430
44873
|
let initResolve;
|
|
44431
44874
|
let initReject;
|
|
44432
|
-
const initPromise = new Promise((
|
|
44433
|
-
initResolve =
|
|
44875
|
+
const initPromise = new Promise((resolve16, reject) => {
|
|
44876
|
+
initResolve = resolve16;
|
|
44434
44877
|
initReject = reject;
|
|
44435
44878
|
});
|
|
44436
44879
|
this._registry.set(key, { id: entryId, store: null, initPromise });
|
|
@@ -45223,8 +45666,8 @@ __export(nexus_sqlite_exports, {
|
|
|
45223
45666
|
resetNexusDbState: () => resetNexusDbState,
|
|
45224
45667
|
resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
|
|
45225
45668
|
});
|
|
45226
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
45227
|
-
import { join as
|
|
45669
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync28 } from "node:fs";
|
|
45670
|
+
import { join as join32 } from "node:path";
|
|
45228
45671
|
function getNexusDbPath(cwd) {
|
|
45229
45672
|
return resolveDualScopeDbPath("project", cwd);
|
|
45230
45673
|
}
|
|
@@ -45260,12 +45703,13 @@ function ensureGlobalRegistryAttached(nativeDb) {
|
|
|
45260
45703
|
}
|
|
45261
45704
|
}
|
|
45262
45705
|
nativeDb.exec(`ATTACH DATABASE '${escaped}' AS ${NEXUS_GLOBAL_ATTACH_ALIAS}`);
|
|
45706
|
+
refreshSchemaWriteGuard(nativeDb);
|
|
45263
45707
|
}
|
|
45264
45708
|
function resolveNexusMigrationsFolder() {
|
|
45265
45709
|
return resolveCorePackageMigrationsFolder("drizzle-nexus");
|
|
45266
45710
|
}
|
|
45267
45711
|
function getNestedNexusSentinelPath() {
|
|
45268
|
-
return
|
|
45712
|
+
return join32(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
|
|
45269
45713
|
}
|
|
45270
45714
|
function detectAndWarnOnNestedNexus() {
|
|
45271
45715
|
let nestedPath;
|
|
@@ -45274,7 +45718,7 @@ function detectAndWarnOnNestedNexus() {
|
|
|
45274
45718
|
} catch {
|
|
45275
45719
|
return false;
|
|
45276
45720
|
}
|
|
45277
|
-
if (!
|
|
45721
|
+
if (!existsSync28(nestedPath)) return false;
|
|
45278
45722
|
if (_warnedNestedPaths.has(nestedPath)) return false;
|
|
45279
45723
|
_warnedNestedPaths.add(nestedPath);
|
|
45280
45724
|
const canonicalPath = getNexusDbPath();
|
|
@@ -45433,7 +45877,7 @@ function runNexusMigrations(nativeDb, db, dbPath) {
|
|
|
45433
45877
|
const migrationsFolder = resolveNexusMigrationsFolder();
|
|
45434
45878
|
if (tableExists4(nativeDb, "nexus_nodes")) {
|
|
45435
45879
|
const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
|
|
45436
|
-
if (!
|
|
45880
|
+
if (!existsSync28(backupPath)) {
|
|
45437
45881
|
try {
|
|
45438
45882
|
copyFileSync7(dbPath, backupPath);
|
|
45439
45883
|
} catch {
|
|
@@ -45528,6 +45972,7 @@ var init_nexus_sqlite = __esm({
|
|
|
45528
45972
|
init_resolve_migrations_folder();
|
|
45529
45973
|
init_nexus_schema();
|
|
45530
45974
|
init_with_retry();
|
|
45975
|
+
init_worktree_build_guard();
|
|
45531
45976
|
NEXUS_SCHEMA_VERSION = "1.0.0";
|
|
45532
45977
|
NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
|
|
45533
45978
|
NESTED_NEXUS_SENTINEL = "nexus.db";
|
|
@@ -45562,15 +46007,15 @@ var init_legacy_alias = __esm({
|
|
|
45562
46007
|
|
|
45563
46008
|
// packages/core/src/llm/stable-device-id.ts
|
|
45564
46009
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
45565
|
-
import { existsSync as
|
|
45566
|
-
import { dirname as
|
|
46010
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
|
|
46011
|
+
import { dirname as dirname18 } from "node:path";
|
|
45567
46012
|
import { resolveStableDeviceIdPath } from "@cleocode/paths";
|
|
45568
46013
|
function getStableDeviceId() {
|
|
45569
46014
|
if (_cachedDeviceId !== null) return _cachedDeviceId;
|
|
45570
46015
|
const path2 = resolveStableDeviceIdPath();
|
|
45571
|
-
if (
|
|
46016
|
+
if (existsSync29(path2)) {
|
|
45572
46017
|
try {
|
|
45573
|
-
const raw =
|
|
46018
|
+
const raw = readFileSync9(path2, "utf-8").trim();
|
|
45574
46019
|
if (raw.length > 0) {
|
|
45575
46020
|
_cachedDeviceId = raw;
|
|
45576
46021
|
return raw;
|
|
@@ -45580,8 +46025,8 @@ function getStableDeviceId() {
|
|
|
45580
46025
|
}
|
|
45581
46026
|
const fresh = randomUUID3();
|
|
45582
46027
|
try {
|
|
45583
|
-
const dir =
|
|
45584
|
-
if (!
|
|
46028
|
+
const dir = dirname18(path2);
|
|
46029
|
+
if (!existsSync29(dir)) {
|
|
45585
46030
|
mkdirSync9(dir, { recursive: true });
|
|
45586
46031
|
}
|
|
45587
46032
|
const tmpPath = `${path2}.tmp.${process.pid}`;
|
|
@@ -45618,8 +46063,8 @@ var init_registry_roots = __esm({
|
|
|
45618
46063
|
// packages/core/src/nexus/projects-scan.ts
|
|
45619
46064
|
async function withinBudget(promise, ms) {
|
|
45620
46065
|
let timer;
|
|
45621
|
-
const expiry = new Promise((
|
|
45622
|
-
timer = setTimeout(() =>
|
|
46066
|
+
const expiry = new Promise((resolve16) => {
|
|
46067
|
+
timer = setTimeout(() => resolve16("timeout"), ms);
|
|
45623
46068
|
timer.unref();
|
|
45624
46069
|
});
|
|
45625
46070
|
try {
|
|
@@ -45657,9 +46102,9 @@ __export(path_map_exports, {
|
|
|
45657
46102
|
supersededRegistryPath: () => supersededRegistryPath,
|
|
45658
46103
|
touchProjectLocation: () => touchProjectLocation
|
|
45659
46104
|
});
|
|
45660
|
-
import { existsSync as
|
|
46105
|
+
import { existsSync as existsSync30, lstatSync, readdirSync as readdirSync7 } from "node:fs";
|
|
45661
46106
|
import { lstat, readdir as readdir2 } from "node:fs/promises";
|
|
45662
|
-
import { isAbsolute as
|
|
46107
|
+
import { isAbsolute as isAbsolute5, join as join33, relative as relative3, sep as sep5 } from "node:path";
|
|
45663
46108
|
import { canonicalizePath as canonicalizePath3, readDeclaredProjectIdentity as readDeclaredProjectIdentity3 } from "@cleocode/paths";
|
|
45664
46109
|
import { and as and7, desc as desc3, eq as eq11, inArray as inArray5, ne as ne3 } from "drizzle-orm";
|
|
45665
46110
|
function holdingKey(projectId, path2) {
|
|
@@ -45675,7 +46120,7 @@ function isSupersededRegistryPath(projectPath) {
|
|
|
45675
46120
|
return projectPath.startsWith(SUPERSEDED_PATH_PREFIX);
|
|
45676
46121
|
}
|
|
45677
46122
|
function projectHolding(path2, projectId) {
|
|
45678
|
-
const cleoDir =
|
|
46123
|
+
const cleoDir = join33(path2, ".cleo");
|
|
45679
46124
|
try {
|
|
45680
46125
|
lstatSync(cleoDir);
|
|
45681
46126
|
readdirSync7(cleoDir);
|
|
@@ -45687,7 +46132,7 @@ function projectHolding(path2, projectId) {
|
|
|
45687
46132
|
return declared === null || declared.projectId === projectId ? "yes" : "no";
|
|
45688
46133
|
}
|
|
45689
46134
|
async function probeProjectHolding(path2, projectId, timeoutMs) {
|
|
45690
|
-
const cleoDir =
|
|
46135
|
+
const cleoDir = join33(path2, ".cleo");
|
|
45691
46136
|
const probe = async () => {
|
|
45692
46137
|
try {
|
|
45693
46138
|
await lstat(cleoDir);
|
|
@@ -45705,8 +46150,8 @@ async function probeProjectHolding(path2, projectId, timeoutMs) {
|
|
|
45705
46150
|
return declared === null || declared.projectId === projectId ? "yes" : "no";
|
|
45706
46151
|
}
|
|
45707
46152
|
function isStrictlyInside(outer, inner) {
|
|
45708
|
-
const rel =
|
|
45709
|
-
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${
|
|
46153
|
+
const rel = relative3(canonicalizePath3(outer), canonicalizePath3(inner));
|
|
46154
|
+
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep5}`) && !isAbsolute5(rel);
|
|
45710
46155
|
}
|
|
45711
46156
|
function locationKey(projectId, deviceId, path2) {
|
|
45712
46157
|
return and7(
|
|
@@ -45868,7 +46313,7 @@ function hasOtherLiveLocation(db, record, deviceId) {
|
|
|
45868
46313
|
ne3(projectLocations.path, record.projectPath)
|
|
45869
46314
|
)
|
|
45870
46315
|
).all().some(
|
|
45871
|
-
(location) => isStrictlyInside(record.projectPath, location.path) &&
|
|
46316
|
+
(location) => isStrictlyInside(record.projectPath, location.path) && existsSync30(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record.projectId
|
|
45872
46317
|
);
|
|
45873
46318
|
}
|
|
45874
46319
|
function demoteProjectLocation(db, record, state) {
|
|
@@ -45919,7 +46364,7 @@ function rehomeDisplacedRows(db, projectId, projectPath, deviceId, probed) {
|
|
|
45919
46364
|
).orderBy(desc3(projectLocations.lastSeen)).all();
|
|
45920
46365
|
const present = (path2) => {
|
|
45921
46366
|
const holding = probed?.get(holdingKey(row.projectId, path2));
|
|
45922
|
-
return holding === void 0 ?
|
|
46367
|
+
return holding === void 0 ? existsSync30(path2) : holding === "yes";
|
|
45923
46368
|
};
|
|
45924
46369
|
const home = candidates.find(
|
|
45925
46370
|
(c) => present(c.path) && db.select({ projectId: projectRegistry.projectId }).from(projectRegistry).where(eq11(projectRegistry.projectPath, c.path)).all().length === 0
|
|
@@ -45948,7 +46393,7 @@ async function listProjectCheckouts(projectId, opts = {}) {
|
|
|
45948
46393
|
projectHash: generateProjectHash(row.path),
|
|
45949
46394
|
firstSeen: row.firstSeen,
|
|
45950
46395
|
lastSeen: row.lastSeen,
|
|
45951
|
-
exists: local &&
|
|
46396
|
+
exists: local && existsSync30(row.path),
|
|
45952
46397
|
deviceId: local ? deviceId : row.deviceId,
|
|
45953
46398
|
state: row.state
|
|
45954
46399
|
});
|
|
@@ -45977,13 +46422,13 @@ __export(checkout_nonce_exports, {
|
|
|
45977
46422
|
readCheckoutNonce: () => readCheckoutNonce
|
|
45978
46423
|
});
|
|
45979
46424
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
45980
|
-
import { existsSync as
|
|
45981
|
-
import { join as
|
|
46425
|
+
import { existsSync as existsSync31, readFileSync as readFileSync10, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
46426
|
+
import { join as join34 } from "node:path";
|
|
45982
46427
|
function readInfo(projectRoot) {
|
|
45983
|
-
const path2 =
|
|
45984
|
-
if (!
|
|
46428
|
+
const path2 = join34(projectRoot, ".cleo", "project-info.json");
|
|
46429
|
+
if (!existsSync31(path2)) return null;
|
|
45985
46430
|
try {
|
|
45986
|
-
const parsed = JSON.parse(
|
|
46431
|
+
const parsed = JSON.parse(readFileSync10(path2, "utf-8"));
|
|
45987
46432
|
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
45988
46433
|
} catch {
|
|
45989
46434
|
return null;
|
|
@@ -45999,7 +46444,7 @@ function ensureCheckoutNonce(projectRoot) {
|
|
|
45999
46444
|
const info = readInfo(projectRoot);
|
|
46000
46445
|
if (!info) return null;
|
|
46001
46446
|
const nonce = randomBytes2(16).toString("hex");
|
|
46002
|
-
const path2 =
|
|
46447
|
+
const path2 = join34(projectRoot, ".cleo", "project-info.json");
|
|
46003
46448
|
const temp = `${path2}.${randomBytes2(6).toString("hex")}.tmp`;
|
|
46004
46449
|
writeFileSync9(temp, `${JSON.stringify({ ...info, [CHECKOUT_NONCE_FIELD]: nonce }, null, 2)}
|
|
46005
46450
|
`);
|
|
@@ -46074,10 +46519,10 @@ __export(paths_exports, {
|
|
|
46074
46519
|
validateProjectRoot: () => validateProjectRoot,
|
|
46075
46520
|
worktreeScope: () => worktreeScope
|
|
46076
46521
|
});
|
|
46077
|
-
import { existsSync as
|
|
46078
|
-
import { createRequire as
|
|
46522
|
+
import { existsSync as existsSync32, readFileSync as readFileSync11, statSync as statSync9 } from "node:fs";
|
|
46523
|
+
import { createRequire as createRequire11 } from "node:module";
|
|
46079
46524
|
import { homedir as homedir2 } from "node:os";
|
|
46080
|
-
import { basename as basename10, dirname as
|
|
46525
|
+
import { basename as basename10, dirname as dirname19, join as join35, resolve as resolve15 } from "node:path";
|
|
46081
46526
|
import {
|
|
46082
46527
|
getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
|
|
46083
46528
|
getCleoTemplatesTildePath as _getCleoTemplatesTildePath,
|
|
@@ -46087,7 +46532,7 @@ import {
|
|
|
46087
46532
|
resolveCanonicalCleoDir as _resolveCanonicalCleoDir
|
|
46088
46533
|
} from "@cleocode/paths";
|
|
46089
46534
|
function _getDatabaseSyncCtor() {
|
|
46090
|
-
const _require7 =
|
|
46535
|
+
const _require7 = createRequire11(import.meta.url);
|
|
46091
46536
|
const mod = _require7("node:sqlite");
|
|
46092
46537
|
return mod.DatabaseSync;
|
|
46093
46538
|
}
|
|
@@ -46099,20 +46544,20 @@ function runWithWorktreeScopeFromEnv(fn) {
|
|
|
46099
46544
|
}
|
|
46100
46545
|
function isProjectInitialized(projectRoot) {
|
|
46101
46546
|
const root = projectRoot ?? getProjectRoot();
|
|
46102
|
-
const cleoDir =
|
|
46103
|
-
return
|
|
46547
|
+
const cleoDir = join35(root, ".cleo");
|
|
46548
|
+
return existsSync32(cleoDir) && existsSync32(join35(cleoDir, "tasks.db"));
|
|
46104
46549
|
}
|
|
46105
46550
|
function getCleoHome() {
|
|
46106
46551
|
return getPlatformPaths().data;
|
|
46107
46552
|
}
|
|
46108
46553
|
function getCleoTemplatesDir() {
|
|
46109
|
-
return
|
|
46554
|
+
return join35(getCleoHome(), "templates");
|
|
46110
46555
|
}
|
|
46111
46556
|
function getCleoSchemasDir() {
|
|
46112
|
-
return
|
|
46557
|
+
return join35(getCleoHome(), "schemas");
|
|
46113
46558
|
}
|
|
46114
46559
|
function getCleoDocsDir() {
|
|
46115
|
-
return
|
|
46560
|
+
return join35(getCleoHome(), "docs");
|
|
46116
46561
|
}
|
|
46117
46562
|
function getCleoDir(cwd) {
|
|
46118
46563
|
if (cwd) {
|
|
@@ -46161,24 +46606,24 @@ function getCleoDirAbsolute(cwd, opts) {
|
|
|
46161
46606
|
try {
|
|
46162
46607
|
const projectRoot = getProjectRoot(cwd);
|
|
46163
46608
|
const canonical = _resolveCanonicalCleoDir(project.projectId);
|
|
46164
|
-
if (canonical !== null && canonical ===
|
|
46609
|
+
if (canonical !== null && canonical === resolve15(projectRoot, cleoDir)) {
|
|
46165
46610
|
return canonical;
|
|
46166
46611
|
}
|
|
46167
|
-
return
|
|
46612
|
+
return resolve15(projectRoot, cleoDir);
|
|
46168
46613
|
} catch {
|
|
46169
|
-
return
|
|
46614
|
+
return resolve15(project.projectRoot, cleoDir);
|
|
46170
46615
|
}
|
|
46171
46616
|
}
|
|
46172
46617
|
try {
|
|
46173
|
-
return
|
|
46618
|
+
return resolve15(getProjectRoot(cwd), cleoDir);
|
|
46174
46619
|
} catch (err) {
|
|
46175
46620
|
if (opts?.bootstrap) {
|
|
46176
|
-
return
|
|
46621
|
+
return resolve15(cwd ?? process.cwd(), cleoDir);
|
|
46177
46622
|
}
|
|
46178
46623
|
if (_cwdHasGitAncestor(cwd)) {
|
|
46179
46624
|
throw err;
|
|
46180
46625
|
}
|
|
46181
|
-
return
|
|
46626
|
+
return resolve15(cwd ?? process.cwd(), cleoDir);
|
|
46182
46627
|
}
|
|
46183
46628
|
}
|
|
46184
46629
|
function resolveCanonicalCleoDir(projectId) {
|
|
@@ -46205,9 +46650,9 @@ function resolveCanonicalCleoDir(projectId) {
|
|
|
46205
46650
|
function _resolveProjectByCwdFromNexus(cwd) {
|
|
46206
46651
|
try {
|
|
46207
46652
|
const cleoHome = getCleoHome();
|
|
46208
|
-
const globalDbPath =
|
|
46209
|
-
if (!
|
|
46210
|
-
const start =
|
|
46653
|
+
const globalDbPath = join35(cleoHome, "cleo.db");
|
|
46654
|
+
if (!existsSync32(globalDbPath)) return null;
|
|
46655
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46211
46656
|
let current = start;
|
|
46212
46657
|
const DatabaseSync3 = _getDatabaseSyncCtor();
|
|
46213
46658
|
const db = new DatabaseSync3(globalDbPath, { readOnly: true });
|
|
@@ -46220,7 +46665,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
|
|
|
46220
46665
|
if (row && typeof row.project_id === "string" && row.project_id.length > 0) {
|
|
46221
46666
|
return row.project_id;
|
|
46222
46667
|
}
|
|
46223
|
-
const parent =
|
|
46668
|
+
const parent = dirname19(current);
|
|
46224
46669
|
if (parent === current) break;
|
|
46225
46670
|
current = parent;
|
|
46226
46671
|
}
|
|
@@ -46240,18 +46685,18 @@ function _cleoDirEnvOverride() {
|
|
|
46240
46685
|
}
|
|
46241
46686
|
function _findCleoDirRoot(cwd) {
|
|
46242
46687
|
const homeRoot = homedir2();
|
|
46243
|
-
let current =
|
|
46688
|
+
let current = resolve15(cwd ?? process.cwd());
|
|
46244
46689
|
while (true) {
|
|
46245
46690
|
const isDangerousRoot = current === homeRoot || current === "/" || current === "";
|
|
46246
46691
|
if (!isDangerousRoot) {
|
|
46247
46692
|
try {
|
|
46248
|
-
if (statSync9(
|
|
46693
|
+
if (statSync9(join35(current, ".cleo")).isDirectory()) {
|
|
46249
46694
|
return current;
|
|
46250
46695
|
}
|
|
46251
46696
|
} catch {
|
|
46252
46697
|
}
|
|
46253
46698
|
}
|
|
46254
|
-
const parent =
|
|
46699
|
+
const parent = dirname19(current);
|
|
46255
46700
|
if (parent === current) break;
|
|
46256
46701
|
current = parent;
|
|
46257
46702
|
}
|
|
@@ -46270,7 +46715,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46270
46715
|
if (pathsResult !== null) {
|
|
46271
46716
|
return pathsResult.projectId;
|
|
46272
46717
|
}
|
|
46273
|
-
const start =
|
|
46718
|
+
const start = resolve15(from ?? process.cwd());
|
|
46274
46719
|
let current = start;
|
|
46275
46720
|
while (true) {
|
|
46276
46721
|
const mainRepo = _resolveMainRepoFromGitlink(current);
|
|
@@ -46281,7 +46726,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46281
46726
|
}
|
|
46282
46727
|
break;
|
|
46283
46728
|
}
|
|
46284
|
-
const parent =
|
|
46729
|
+
const parent = dirname19(current);
|
|
46285
46730
|
if (parent === current) break;
|
|
46286
46731
|
current = parent;
|
|
46287
46732
|
}
|
|
@@ -46300,7 +46745,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46300
46745
|
function resolveCleoDir(cwd) {
|
|
46301
46746
|
const scope = worktreeScope.getStore();
|
|
46302
46747
|
if (scope !== void 0) {
|
|
46303
|
-
return
|
|
46748
|
+
return join35(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
|
|
46304
46749
|
}
|
|
46305
46750
|
const override = _cleoDirEnvOverride();
|
|
46306
46751
|
if (override !== null) {
|
|
@@ -46308,16 +46753,16 @@ function resolveCleoDir(cwd) {
|
|
|
46308
46753
|
}
|
|
46309
46754
|
const root = _findCleoDirRoot(cwd);
|
|
46310
46755
|
if (root !== null) {
|
|
46311
|
-
return
|
|
46756
|
+
return join35(resolveStoreOwnerRoot(root), ".cleo");
|
|
46312
46757
|
}
|
|
46313
|
-
const start =
|
|
46758
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46314
46759
|
let current = start;
|
|
46315
46760
|
while (true) {
|
|
46316
46761
|
const mainRepo = _resolveMainRepoFromGitlink(current);
|
|
46317
46762
|
if (mainRepo !== null) {
|
|
46318
|
-
return
|
|
46763
|
+
return join35(mainRepo, ".cleo");
|
|
46319
46764
|
}
|
|
46320
|
-
const parent =
|
|
46765
|
+
const parent = dirname19(current);
|
|
46321
46766
|
if (parent === current) {
|
|
46322
46767
|
break;
|
|
46323
46768
|
}
|
|
@@ -46356,25 +46801,25 @@ function _resolveCleoDir(cwd) {
|
|
|
46356
46801
|
const project = _pathsResolveProjectByCwd(cwd);
|
|
46357
46802
|
if (project !== null) {
|
|
46358
46803
|
try {
|
|
46359
|
-
return
|
|
46804
|
+
return resolve15(getProjectRoot(cwd), cleoDir);
|
|
46360
46805
|
} catch {
|
|
46361
|
-
return
|
|
46806
|
+
return resolve15(project.projectRoot, cleoDir);
|
|
46362
46807
|
}
|
|
46363
46808
|
}
|
|
46364
46809
|
return getCleoDirAbsolute(cwd);
|
|
46365
46810
|
}
|
|
46366
46811
|
function _cwdHasGitAncestor(cwd) {
|
|
46367
|
-
const start =
|
|
46812
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46368
46813
|
let current = start;
|
|
46369
46814
|
while (true) {
|
|
46370
|
-
const gitMarker =
|
|
46815
|
+
const gitMarker = join35(current, ".git");
|
|
46371
46816
|
try {
|
|
46372
|
-
if (
|
|
46817
|
+
if (existsSync32(gitMarker)) {
|
|
46373
46818
|
return true;
|
|
46374
46819
|
}
|
|
46375
46820
|
} catch {
|
|
46376
46821
|
}
|
|
46377
|
-
const parent =
|
|
46822
|
+
const parent = dirname19(current);
|
|
46378
46823
|
if (parent === current) return false;
|
|
46379
46824
|
current = parent;
|
|
46380
46825
|
}
|
|
@@ -46401,55 +46846,55 @@ function resolveProjectPath(relativePath, cwd) {
|
|
|
46401
46846
|
return relativePath;
|
|
46402
46847
|
}
|
|
46403
46848
|
if (relativePath.startsWith("~/") || relativePath.startsWith("~\\") || relativePath === "~") {
|
|
46404
|
-
return
|
|
46849
|
+
return resolve15(homedir2(), relativePath.slice(2));
|
|
46405
46850
|
}
|
|
46406
|
-
return
|
|
46851
|
+
return resolve15(getProjectRoot(cwd), relativePath);
|
|
46407
46852
|
}
|
|
46408
46853
|
function getTaskPath(cwd) {
|
|
46409
|
-
return
|
|
46854
|
+
return join35(_resolveCleoDir(cwd), "tasks.db");
|
|
46410
46855
|
}
|
|
46411
46856
|
function getConfigPath(cwd) {
|
|
46412
|
-
return
|
|
46857
|
+
return join35(_resolveCleoDir(cwd), "config.json");
|
|
46413
46858
|
}
|
|
46414
46859
|
function getSessionsPath(cwd) {
|
|
46415
|
-
return
|
|
46860
|
+
return join35(_resolveCleoDir(cwd), "sessions.json");
|
|
46416
46861
|
}
|
|
46417
46862
|
function getArchivePath(cwd) {
|
|
46418
|
-
return
|
|
46863
|
+
return join35(_resolveCleoDir(cwd), "tasks-archive.json");
|
|
46419
46864
|
}
|
|
46420
46865
|
function getLogPath(cwd) {
|
|
46421
|
-
return
|
|
46866
|
+
return join35(_resolveCleoDir(cwd), "logs", "cleo.log");
|
|
46422
46867
|
}
|
|
46423
46868
|
function getBackupDir(cwd) {
|
|
46424
|
-
return
|
|
46869
|
+
return join35(_resolveCleoDir(cwd), "backups", "operational");
|
|
46425
46870
|
}
|
|
46426
46871
|
function getGlobalConfigPath() {
|
|
46427
|
-
return
|
|
46872
|
+
return join35(getCleoHome(), "config.json");
|
|
46428
46873
|
}
|
|
46429
46874
|
function getCleoGlobalRecipesDir() {
|
|
46430
|
-
return
|
|
46875
|
+
return join35(getCleoHome(), "global-recipes");
|
|
46431
46876
|
}
|
|
46432
46877
|
function getCleoGlobalJustfilePath() {
|
|
46433
|
-
return
|
|
46878
|
+
return join35(getCleoGlobalRecipesDir(), "justfile");
|
|
46434
46879
|
}
|
|
46435
46880
|
function getCleoPiExtensionsDir() {
|
|
46436
|
-
return
|
|
46881
|
+
return join35(getCleoHome(), "pi-extensions");
|
|
46437
46882
|
}
|
|
46438
46883
|
function getCleoCantWorkflowsDir() {
|
|
46439
|
-
return
|
|
46884
|
+
return join35(getCleoHome(), "cant-workflows");
|
|
46440
46885
|
}
|
|
46441
46886
|
function getCleoGlobalAgentsDir() {
|
|
46442
|
-
return
|
|
46887
|
+
return join35(getCleoHome(), "agents");
|
|
46443
46888
|
}
|
|
46444
46889
|
function getCleoGlobalCantAgentsDir() {
|
|
46445
|
-
return
|
|
46890
|
+
return join35(getCleoHome(), "cant", "agents");
|
|
46446
46891
|
}
|
|
46447
46892
|
function getAgentOutputsDir(cwd) {
|
|
46448
46893
|
const projectRoot = getProjectRoot(cwd);
|
|
46449
|
-
const configPath =
|
|
46450
|
-
if (
|
|
46894
|
+
const configPath = join35(projectRoot, ".cleo", "config.json");
|
|
46895
|
+
if (existsSync32(configPath)) {
|
|
46451
46896
|
try {
|
|
46452
|
-
const config = JSON.parse(
|
|
46897
|
+
const config = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
46453
46898
|
if (typeof config.agentOutputs === "object" && config.agentOutputs?.directory) {
|
|
46454
46899
|
return config.agentOutputs.directory;
|
|
46455
46900
|
}
|
|
@@ -46472,17 +46917,17 @@ function getAgentOutputsAbsolute(cwd) {
|
|
|
46472
46917
|
if (isAbsolutePath2(dir)) {
|
|
46473
46918
|
return dir;
|
|
46474
46919
|
}
|
|
46475
|
-
return
|
|
46920
|
+
return resolve15(getProjectRoot(cwd), dir);
|
|
46476
46921
|
}
|
|
46477
46922
|
function getManifestPath(cwd) {
|
|
46478
46923
|
const outputDir = getAgentOutputsDir(cwd);
|
|
46479
46924
|
const projectRoot = getProjectRoot(cwd);
|
|
46480
|
-
const configPath =
|
|
46925
|
+
const configPath = join35(projectRoot, ".cleo", "config.json");
|
|
46481
46926
|
const legacyFileName = ["MANIFEST", "jsonl"].join(".");
|
|
46482
46927
|
let manifestFile = legacyFileName;
|
|
46483
|
-
if (
|
|
46928
|
+
if (existsSync32(configPath)) {
|
|
46484
46929
|
try {
|
|
46485
|
-
const config = JSON.parse(
|
|
46930
|
+
const config = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
46486
46931
|
const customFile = config.agentOutputs?.manifestFile ?? config.research?.manifestFile;
|
|
46487
46932
|
if (customFile) {
|
|
46488
46933
|
manifestFile = customFile;
|
|
@@ -46490,12 +46935,12 @@ function getManifestPath(cwd) {
|
|
|
46490
46935
|
} catch {
|
|
46491
46936
|
}
|
|
46492
46937
|
}
|
|
46493
|
-
return
|
|
46938
|
+
return resolve15(projectRoot, outputDir, manifestFile);
|
|
46494
46939
|
}
|
|
46495
46940
|
function getManifestArchivePath(cwd) {
|
|
46496
46941
|
const outputDir = getAgentOutputsDir(cwd);
|
|
46497
46942
|
const projectRoot = getProjectRoot(cwd);
|
|
46498
|
-
return
|
|
46943
|
+
return resolve15(projectRoot, outputDir, "MANIFEST.archive.jsonl");
|
|
46499
46944
|
}
|
|
46500
46945
|
function isAbsolutePath2(path2) {
|
|
46501
46946
|
return _isAbsolutePath(path2);
|
|
@@ -46519,24 +46964,24 @@ function getCanonicalTemplatesTildePath() {
|
|
|
46519
46964
|
return _getCanonicalTemplatesTildePath();
|
|
46520
46965
|
}
|
|
46521
46966
|
function getAgentsHome() {
|
|
46522
|
-
return process.env["AGENTS_HOME"] ??
|
|
46967
|
+
return process.env["AGENTS_HOME"] ?? join35(homedir2(), ".agents");
|
|
46523
46968
|
}
|
|
46524
46969
|
function getClaudeAgentsDir() {
|
|
46525
|
-
const claudeDir = process.env["CLAUDE_HOME"] ??
|
|
46526
|
-
return
|
|
46970
|
+
const claudeDir = process.env["CLAUDE_HOME"] ?? join35(homedir2(), ".claude");
|
|
46971
|
+
return join35(claudeDir, "agents");
|
|
46527
46972
|
}
|
|
46528
46973
|
function getClaudeMemDbPath() {
|
|
46529
|
-
return process.env["CLAUDE_MEM_DB"] ??
|
|
46974
|
+
return process.env["CLAUDE_MEM_DB"] ?? join35(homedir2(), ".claude-mem", "claude-mem.db");
|
|
46530
46975
|
}
|
|
46531
46976
|
function resolveWorktreeRouting(cwdOverride) {
|
|
46532
|
-
const cwd =
|
|
46977
|
+
const cwd = resolve15(cwdOverride ?? process.cwd());
|
|
46533
46978
|
const home = homedir2();
|
|
46534
46979
|
let worktreePath;
|
|
46535
46980
|
let current = cwd;
|
|
46536
46981
|
while (current !== home && current !== "/" && current !== "") {
|
|
46537
|
-
const gitPath =
|
|
46982
|
+
const gitPath = join35(current, ".git");
|
|
46538
46983
|
try {
|
|
46539
|
-
if (
|
|
46984
|
+
if (existsSync32(gitPath)) {
|
|
46540
46985
|
const stat3 = statSync9(gitPath);
|
|
46541
46986
|
if (stat3.isFile()) {
|
|
46542
46987
|
worktreePath = current;
|
|
@@ -46548,7 +46993,7 @@ function resolveWorktreeRouting(cwdOverride) {
|
|
|
46548
46993
|
}
|
|
46549
46994
|
} catch {
|
|
46550
46995
|
}
|
|
46551
|
-
const parent =
|
|
46996
|
+
const parent = dirname19(current);
|
|
46552
46997
|
if (parent === current) break;
|
|
46553
46998
|
current = parent;
|
|
46554
46999
|
}
|
|
@@ -46565,17 +47010,17 @@ function resolveWorktreeRouting(cwdOverride) {
|
|
|
46565
47010
|
}
|
|
46566
47011
|
function resolveWorktreeFilePath(filePath, routing) {
|
|
46567
47012
|
if (!routing.isWorktree || routing.worktreePath === void 0) {
|
|
46568
|
-
return
|
|
47013
|
+
return resolve15(filePath);
|
|
46569
47014
|
}
|
|
46570
|
-
return
|
|
47015
|
+
return resolve15(routing.cwd, filePath);
|
|
46571
47016
|
}
|
|
46572
47017
|
function detectStrayCleoDb(routing) {
|
|
46573
47018
|
if (!routing.isWorktree || routing.worktreePath === void 0) {
|
|
46574
47019
|
return void 0;
|
|
46575
47020
|
}
|
|
46576
|
-
const tasksDbPath =
|
|
47021
|
+
const tasksDbPath = join35(routing.worktreePath, ".cleo", "tasks.db");
|
|
46577
47022
|
try {
|
|
46578
|
-
if (
|
|
47023
|
+
if (existsSync32(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
|
|
46579
47024
|
return tasksDbPath;
|
|
46580
47025
|
}
|
|
46581
47026
|
} catch {
|
|
@@ -46585,7 +47030,7 @@ function detectStrayCleoDb(routing) {
|
|
|
46585
47030
|
async function resolveProjectById(projectId) {
|
|
46586
47031
|
try {
|
|
46587
47032
|
const { getNexusDb: getNexusDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
46588
|
-
if (!
|
|
47033
|
+
if (!existsSync32(getNexusRegistryDbPath2())) return null;
|
|
46589
47034
|
const { eq: eq14 } = await import("drizzle-orm");
|
|
46590
47035
|
const { projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
46591
47036
|
const db = await getNexusDb2();
|
|
@@ -46620,9 +47065,9 @@ function _rowToRegistryEntry(row) {
|
|
|
46620
47065
|
};
|
|
46621
47066
|
}
|
|
46622
47067
|
function _readProjectNameFromInfo(projectRoot) {
|
|
46623
|
-
const infoPath =
|
|
46624
|
-
if (!
|
|
46625
|
-
const raw =
|
|
47068
|
+
const infoPath = join35(projectRoot, ".cleo", "project-info.json");
|
|
47069
|
+
if (!existsSync32(infoPath)) return void 0;
|
|
47070
|
+
const raw = readFileSync11(infoPath, "utf-8");
|
|
46626
47071
|
const data = JSON.parse(raw);
|
|
46627
47072
|
return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
|
|
46628
47073
|
}
|
|
@@ -46673,7 +47118,7 @@ async function recordProjectEncounter(cwd) {
|
|
|
46673
47118
|
if (!shouldAutoRegisterProject(project.projectRoot, cleoHome)) return "ephemeral";
|
|
46674
47119
|
const checkout = captureProjectScope(project.projectRoot, worktreeScope.getStore()).worktreeRoot;
|
|
46675
47120
|
const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
46676
|
-
if (
|
|
47121
|
+
if (existsSync32(getNexusRegistryDbPath2(cleoHome))) {
|
|
46677
47122
|
const { and: and10, eq: eq14 } = await import("drizzle-orm");
|
|
46678
47123
|
const { projectLocations: projectLocations2, projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
46679
47124
|
const { currentDeviceId: currentDeviceId2 } = await Promise.resolve().then(() => (init_path_map(), path_map_exports));
|