@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"],
|
|
@@ -3110,12 +3110,21 @@ var init_operations_registry = __esm({
|
|
|
3110
3110
|
gateway: "query",
|
|
3111
3111
|
domain: "tasks",
|
|
3112
3112
|
operation: "history",
|
|
3113
|
-
description: "Show task work history
|
|
3113
|
+
description: "Show task work history; with taskId, the task audit trail; with ranking, who changed its priority/severity/kind/depends and why (T12693)",
|
|
3114
3114
|
tier: 1,
|
|
3115
3115
|
idempotent: true,
|
|
3116
3116
|
sessionRequired: false,
|
|
3117
3117
|
requiredParams: [],
|
|
3118
|
-
params: [
|
|
3118
|
+
params: [
|
|
3119
|
+
{ name: "taskId", type: "string", required: false, description: "Task to show history for" },
|
|
3120
|
+
{ name: "limit", type: "number", required: false, description: "Maximum entries" },
|
|
3121
|
+
{
|
|
3122
|
+
name: "ranking",
|
|
3123
|
+
type: "boolean",
|
|
3124
|
+
required: false,
|
|
3125
|
+
description: "Only ranking-input changes (actor, session, reason, before/after)"
|
|
3126
|
+
}
|
|
3127
|
+
]
|
|
3119
3128
|
},
|
|
3120
3129
|
{
|
|
3121
3130
|
gateway: "query",
|
|
@@ -5610,6 +5619,32 @@ var init_operations_registry = __esm({
|
|
|
5610
5619
|
],
|
|
5611
5620
|
outputSchema: OUTPUT_CONTRACTS["tasks.assignee"]
|
|
5612
5621
|
},
|
|
5622
|
+
{
|
|
5623
|
+
gateway: "mutate",
|
|
5624
|
+
domain: "tasks",
|
|
5625
|
+
operation: "ranking.revert",
|
|
5626
|
+
description: "tasks.ranking.revert (mutate) \u2014 undo one recorded ranking change (priority/severity/kind/depends) as a new audited change (T12693, D11161)",
|
|
5627
|
+
tier: 1,
|
|
5628
|
+
idempotent: false,
|
|
5629
|
+
sessionRequired: false,
|
|
5630
|
+
requiredParams: ["entryId"],
|
|
5631
|
+
params: [
|
|
5632
|
+
{
|
|
5633
|
+
name: "entryId",
|
|
5634
|
+
type: "string",
|
|
5635
|
+
required: true,
|
|
5636
|
+
description: "ranking_changed audit row id (cleo history ranking <taskId>)",
|
|
5637
|
+
cli: { positional: true }
|
|
5638
|
+
},
|
|
5639
|
+
{ name: "reason", type: "string", required: false, description: "Why it is reverted" },
|
|
5640
|
+
{
|
|
5641
|
+
name: "force",
|
|
5642
|
+
type: "boolean",
|
|
5643
|
+
required: false,
|
|
5644
|
+
description: "Revert even though a field changed again since"
|
|
5645
|
+
}
|
|
5646
|
+
]
|
|
5647
|
+
},
|
|
5613
5648
|
{
|
|
5614
5649
|
gateway: "mutate",
|
|
5615
5650
|
domain: "tasks",
|
|
@@ -10533,7 +10568,7 @@ var init_operations_registry = __esm({
|
|
|
10533
10568
|
type: "string",
|
|
10534
10569
|
required: false,
|
|
10535
10570
|
enum: DOCS_LIFECYCLE_STATUSES,
|
|
10536
|
-
description: `Override the new lifecycle status. Defaults to "draft" on every update. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
|
|
10571
|
+
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("|")}.`
|
|
10537
10572
|
},
|
|
10538
10573
|
{
|
|
10539
10574
|
name: "dryRun",
|
|
@@ -13020,11 +13055,13 @@ var init_evidence_atom_schema = __esm({
|
|
|
13020
13055
|
});
|
|
13021
13056
|
prAtomSchema = z10.object({
|
|
13022
13057
|
kind: z10.literal("pr"),
|
|
13023
|
-
prNumber: z10.number().int().positive("pr atom requires a positive integer PR number")
|
|
13058
|
+
prNumber: z10.number().int().positive("pr atom requires a positive integer PR number"),
|
|
13059
|
+
componentPrNumber: z10.number().int().positive().optional()
|
|
13024
13060
|
});
|
|
13025
13061
|
ciAtomSchema = z10.object({
|
|
13026
13062
|
kind: z10.literal("ci"),
|
|
13027
|
-
prNumber: z10.number().int().positive("ci atom requires a positive integer PR number")
|
|
13063
|
+
prNumber: z10.number().int().positive("ci atom requires a positive integer PR number"),
|
|
13064
|
+
componentPrNumber: z10.number().int().positive().optional()
|
|
13028
13065
|
});
|
|
13029
13066
|
locDropAtomSchema = z10.object({
|
|
13030
13067
|
kind: z10.literal("loc-drop"),
|
|
@@ -13075,7 +13112,10 @@ var init_evidence_atom_schema = __esm({
|
|
|
13075
13112
|
["commit", "note"],
|
|
13076
13113
|
["decision", "files"],
|
|
13077
13114
|
["decision", "note"],
|
|
13078
|
-
["pr", "files"]
|
|
13115
|
+
["pr", "files"],
|
|
13116
|
+
// T12689: a deletion-only PR (no bytes to hash). Contextual validation
|
|
13117
|
+
// accepts this only when every change the PR made is a deletion.
|
|
13118
|
+
["pr", "note"]
|
|
13079
13119
|
]
|
|
13080
13120
|
},
|
|
13081
13121
|
testsPassed: { oneOf: [["test-run"], ["tool"], ["ci"]] },
|
|
@@ -17050,7 +17090,7 @@ var init_collection_keys = __esm({
|
|
|
17050
17090
|
|
|
17051
17091
|
// packages/contracts/src/decide.ts
|
|
17052
17092
|
import { z as z24 } from "zod";
|
|
17053
|
-
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;
|
|
17093
|
+
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;
|
|
17054
17094
|
var init_decide = __esm({
|
|
17055
17095
|
"packages/contracts/src/decide.ts"() {
|
|
17056
17096
|
"use strict";
|
|
@@ -17074,6 +17114,7 @@ var init_decide = __esm({
|
|
|
17074
17114
|
/** Maximum number of levels on a `score` question's scale. */
|
|
17075
17115
|
maxScoreLevels: 10
|
|
17076
17116
|
};
|
|
17117
|
+
DECISION_PROVIDER_KINDS = ["layahost", "jev"];
|
|
17077
17118
|
decisionQuestionTypeSchema = z24.enum(DECISION_QUESTION_TYPES);
|
|
17078
17119
|
decisionOutcomeSourceSchema = z24.enum(DECISION_OUTCOME_SOURCES);
|
|
17079
17120
|
decisionInstructionsSchema = z24.union([z24.string(), z24.record(z24.string(), z24.json())]);
|
|
@@ -17111,6 +17152,8 @@ var init_decide = __esm({
|
|
|
17111
17152
|
]);
|
|
17112
17153
|
decisionRequestSchema = z24.object({
|
|
17113
17154
|
model: z24.string().min(1).optional(),
|
|
17155
|
+
lang: z24.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$/).optional(),
|
|
17156
|
+
cache: z24.boolean().optional(),
|
|
17114
17157
|
state: decisionStateSchema,
|
|
17115
17158
|
questions: z24.record(z24.string().min(1), decisionQuestionSchema).refine(
|
|
17116
17159
|
(questions) => {
|
|
@@ -17151,14 +17194,26 @@ var init_decide = __esm({
|
|
|
17151
17194
|
requestId: z24.string().min(1).optional(),
|
|
17152
17195
|
latencyMs: z24.number().nonnegative(),
|
|
17153
17196
|
costUsd: z24.number().nonnegative().optional(),
|
|
17197
|
+
costMicros: z24.number().int().nonnegative().optional(),
|
|
17198
|
+
balanceMicros: z24.number().int().optional(),
|
|
17199
|
+
checkpoint: z24.string().min(1).optional(),
|
|
17154
17200
|
inputTokens: z24.number().int().nonnegative().optional()
|
|
17155
17201
|
});
|
|
17202
|
+
decisionProviderKindSchema = z24.enum(DECISION_PROVIDER_KINDS);
|
|
17156
17203
|
decisionProviderConfigSchema = z24.object({
|
|
17157
|
-
baseUrl: z24.url()
|
|
17204
|
+
baseUrl: z24.url(),
|
|
17205
|
+
provider: decisionProviderKindSchema.optional()
|
|
17158
17206
|
});
|
|
17159
17207
|
}
|
|
17160
17208
|
});
|
|
17161
17209
|
|
|
17210
|
+
// packages/contracts/src/decide-sites.ts
|
|
17211
|
+
var init_decide_sites = __esm({
|
|
17212
|
+
"packages/contracts/src/decide-sites.ts"() {
|
|
17213
|
+
"use strict";
|
|
17214
|
+
}
|
|
17215
|
+
});
|
|
17216
|
+
|
|
17162
17217
|
// packages/contracts/src/task-id.ts
|
|
17163
17218
|
var init_task_id = __esm({
|
|
17164
17219
|
"packages/contracts/src/task-id.ts"() {
|
|
@@ -17240,6 +17295,7 @@ var init_src = __esm({
|
|
|
17240
17295
|
init_caamp_markers();
|
|
17241
17296
|
init_collection_keys();
|
|
17242
17297
|
init_decide();
|
|
17298
|
+
init_decide_sites();
|
|
17243
17299
|
init_task_id();
|
|
17244
17300
|
}
|
|
17245
17301
|
});
|
|
@@ -18759,6 +18815,37 @@ function linkedWorktreeMainRoot(dir) {
|
|
|
18759
18815
|
if (basename2(commonDir) === ".git") return dirname2(commonDir);
|
|
18760
18816
|
return readCoreWorktree(commonDir);
|
|
18761
18817
|
}
|
|
18818
|
+
function describeWorktreeOwner(dir) {
|
|
18819
|
+
const mainRoot = linkedWorktreeMainRoot(dir);
|
|
18820
|
+
if (mainRoot === null) {
|
|
18821
|
+
const bare = bareRepositoryOfWorktree(dir);
|
|
18822
|
+
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`;
|
|
18823
|
+
}
|
|
18824
|
+
let projectId = null;
|
|
18825
|
+
try {
|
|
18826
|
+
const parsed = JSON.parse(
|
|
18827
|
+
readFileSync2(join3(mainRoot, ".cleo", "project-info.json"), "utf-8")
|
|
18828
|
+
);
|
|
18829
|
+
if (typeof parsed === "object" && parsed !== null && "projectId" in parsed) {
|
|
18830
|
+
const value = parsed.projectId;
|
|
18831
|
+
if (typeof value === "string" && value !== "") projectId = value;
|
|
18832
|
+
}
|
|
18833
|
+
} catch {
|
|
18834
|
+
}
|
|
18835
|
+
return projectId === null ? `owning repository ${mainRoot} (not an initialised CLEO project)` : `owning project ${mainRoot} (projectId ${projectId})`;
|
|
18836
|
+
}
|
|
18837
|
+
function bareRepositoryOfWorktree(dir) {
|
|
18838
|
+
const gitdir = readGitlinkTarget(dir);
|
|
18839
|
+
if (!gitdir || basename2(dirname2(gitdir)) !== "worktrees") return null;
|
|
18840
|
+
const commonDir = dirname2(dirname2(gitdir));
|
|
18841
|
+
try {
|
|
18842
|
+
const config2 = readFileSync2(join3(commonDir, "config"), "utf-8");
|
|
18843
|
+
const core = /^\[core\][^[]*/m.exec(config2)?.[0] ?? "";
|
|
18844
|
+
return /^\s*bare\s*=\s*true\s*$/im.test(core) ? commonDir : null;
|
|
18845
|
+
} catch {
|
|
18846
|
+
return null;
|
|
18847
|
+
}
|
|
18848
|
+
}
|
|
18762
18849
|
function readCoreWorktree(gitDir) {
|
|
18763
18850
|
try {
|
|
18764
18851
|
const config2 = readFileSync2(join3(gitDir, "config"), "utf-8");
|
|
@@ -19208,13 +19295,13 @@ function captureWriteFence(input) {
|
|
|
19208
19295
|
return writeFence;
|
|
19209
19296
|
}
|
|
19210
19297
|
function observeOperation(context, work) {
|
|
19211
|
-
return new Promise((
|
|
19298
|
+
return new Promise((resolve17) => {
|
|
19212
19299
|
let observed = false;
|
|
19213
19300
|
const finish = (result) => {
|
|
19214
19301
|
if (observed) return;
|
|
19215
19302
|
observed = true;
|
|
19216
19303
|
context.signal.removeEventListener("abort", abort);
|
|
19217
|
-
|
|
19304
|
+
resolve17(result);
|
|
19218
19305
|
};
|
|
19219
19306
|
const abort = () => {
|
|
19220
19307
|
const reason = context.signal.reason;
|
|
@@ -19848,7 +19935,7 @@ var init_sql = __esm({
|
|
|
19848
19935
|
return new SQL([new StringChunk(str)]);
|
|
19849
19936
|
}
|
|
19850
19937
|
_sql.raw = raw;
|
|
19851
|
-
function
|
|
19938
|
+
function join50(chunks, separator) {
|
|
19852
19939
|
const result = [];
|
|
19853
19940
|
for (const [i, chunk] of chunks.entries()) {
|
|
19854
19941
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -19856,7 +19943,7 @@ var init_sql = __esm({
|
|
|
19856
19943
|
}
|
|
19857
19944
|
return new SQL(result);
|
|
19858
19945
|
}
|
|
19859
|
-
_sql.join =
|
|
19946
|
+
_sql.join = join50;
|
|
19860
19947
|
function identifier2(value) {
|
|
19861
19948
|
return new Name(value);
|
|
19862
19949
|
}
|
|
@@ -21871,7 +21958,7 @@ var init_select = __esm({
|
|
|
21871
21958
|
const baseTableName = this.tableName;
|
|
21872
21959
|
const tableName = getTableLikeName(table);
|
|
21873
21960
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
21874
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
21961
|
+
if (typeof tableName === "string" && this.config.joins?.some((join50) => join50.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
21875
21962
|
if (!this.isPartialSelect) {
|
|
21876
21963
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
21877
21964
|
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
@@ -23468,7 +23555,7 @@ var init_dialect = __esm({
|
|
|
23468
23555
|
if (!joins2) return;
|
|
23469
23556
|
const withEntries = Object.entries(joins2).filter(([_, v]) => v);
|
|
23470
23557
|
if (!withEntries.length) return;
|
|
23471
|
-
return sql.join(withEntries.map(([k,
|
|
23558
|
+
return sql.join(withEntries.map(([k, join50]) => {
|
|
23472
23559
|
const relation = tableConfig.relations[k];
|
|
23473
23560
|
const isSingle2 = is(relation, One);
|
|
23474
23561
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -23479,7 +23566,7 @@ var init_dialect = __esm({
|
|
|
23479
23566
|
table: targetTable,
|
|
23480
23567
|
mode: isSingle2 ? "first" : "many",
|
|
23481
23568
|
schema,
|
|
23482
|
-
queryConfig:
|
|
23569
|
+
queryConfig: join50,
|
|
23483
23570
|
tableConfig: schema[relation.targetTableName],
|
|
23484
23571
|
relationWhere: filter2,
|
|
23485
23572
|
isNested: true,
|
|
@@ -23493,7 +23580,7 @@ var init_dialect = __esm({
|
|
|
23493
23580
|
key: k,
|
|
23494
23581
|
selection: innerQuery.selection,
|
|
23495
23582
|
isArray: !isSingle2,
|
|
23496
|
-
isOptional: (relation.optional ?? false) ||
|
|
23583
|
+
isOptional: (relation.optional ?? false) || join50 !== true && !!join50.where
|
|
23497
23584
|
});
|
|
23498
23585
|
const jsonColumns = sql.join(innerQuery.selection.map((s) => {
|
|
23499
23586
|
return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
|
|
@@ -23915,7 +24002,7 @@ var init_update = __esm({
|
|
|
23915
24002
|
createJoin(joinType) {
|
|
23916
24003
|
return ((table, on) => {
|
|
23917
24004
|
const tableName = getTableLikeName(table);
|
|
23918
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
24005
|
+
if (typeof tableName === "string" && this.config.joins.some((join50) => join50.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
23919
24006
|
if (typeof on === "function") {
|
|
23920
24007
|
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;
|
|
23921
24008
|
on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -25063,7 +25150,7 @@ async function withWriteRetry(fn, opts = {}) {
|
|
|
25063
25150
|
throw contentionErr;
|
|
25064
25151
|
}
|
|
25065
25152
|
function sleep(ms) {
|
|
25066
|
-
return new Promise((
|
|
25153
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
25067
25154
|
}
|
|
25068
25155
|
var DEFAULT_MAX_ATTEMPTS, DEFAULT_BASE_DELAY_MS, DEFAULT_JITTER_MS;
|
|
25069
25156
|
var init_with_retry = __esm({
|
|
@@ -25075,9 +25162,250 @@ var init_with_retry = __esm({
|
|
|
25075
25162
|
}
|
|
25076
25163
|
});
|
|
25077
25164
|
|
|
25165
|
+
// packages/core/src/store/worktree-build-guard.ts
|
|
25166
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
25167
|
+
import { createRequire } from "node:module";
|
|
25168
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
25169
|
+
import { fileURLToPath } from "node:url";
|
|
25170
|
+
function realOrResolved(path) {
|
|
25171
|
+
try {
|
|
25172
|
+
return realpathSync3(path);
|
|
25173
|
+
} catch {
|
|
25174
|
+
return resolve2(path);
|
|
25175
|
+
}
|
|
25176
|
+
}
|
|
25177
|
+
function isWithin(root, path) {
|
|
25178
|
+
const local = relative2(root, path);
|
|
25179
|
+
return local === "" || !isAbsolute3(local) && local !== ".." && !local.startsWith(`..${sep2}`);
|
|
25180
|
+
}
|
|
25181
|
+
function insideGitCheckout(dir) {
|
|
25182
|
+
let current = dir;
|
|
25183
|
+
for (; ; ) {
|
|
25184
|
+
if (existsSync4(join5(current, ".git"))) return true;
|
|
25185
|
+
const parent = dirname3(current);
|
|
25186
|
+
if (parent === current) return false;
|
|
25187
|
+
current = parent;
|
|
25188
|
+
}
|
|
25189
|
+
}
|
|
25190
|
+
function insideTestSandbox(path) {
|
|
25191
|
+
let dir = dirname3(path);
|
|
25192
|
+
for (; ; ) {
|
|
25193
|
+
if (existsSync4(join5(dir, TEST_SANDBOX_MARKER))) return !insideGitCheckout(dir);
|
|
25194
|
+
const parent = dirname3(dir);
|
|
25195
|
+
if (parent === dir) return false;
|
|
25196
|
+
dir = parent;
|
|
25197
|
+
}
|
|
25198
|
+
}
|
|
25199
|
+
function linkedWorktreeRootOf(path) {
|
|
25200
|
+
let dir = realOrResolved(path);
|
|
25201
|
+
for (; ; ) {
|
|
25202
|
+
if (isGitLinkedCheckout(dir)) return dir;
|
|
25203
|
+
if (existsSync4(join5(dir, ".git"))) return null;
|
|
25204
|
+
const parent = dirname3(dir);
|
|
25205
|
+
if (parent === dir) return null;
|
|
25206
|
+
dir = parent;
|
|
25207
|
+
}
|
|
25208
|
+
}
|
|
25209
|
+
function readBuildProvenance(codePath) {
|
|
25210
|
+
let dir = dirname3(codePath);
|
|
25211
|
+
for (; ; ) {
|
|
25212
|
+
const stamp = join5(dir, "build-provenance.json");
|
|
25213
|
+
if (existsSync4(stamp)) {
|
|
25214
|
+
try {
|
|
25215
|
+
const parsed = JSON.parse(readFileSync3(stamp, "utf8"));
|
|
25216
|
+
if (typeof parsed === "object" && parsed !== null && "linkedWorktree" in parsed) {
|
|
25217
|
+
const value = parsed.linkedWorktree;
|
|
25218
|
+
if (value === null || typeof value === "string") return { linkedWorktree: value };
|
|
25219
|
+
}
|
|
25220
|
+
} catch {
|
|
25221
|
+
}
|
|
25222
|
+
return null;
|
|
25223
|
+
}
|
|
25224
|
+
if (existsSync4(join5(dir, "package.json"))) return null;
|
|
25225
|
+
const parent = dirname3(dir);
|
|
25226
|
+
if (parent === dir) return null;
|
|
25227
|
+
dir = parent;
|
|
25228
|
+
}
|
|
25229
|
+
}
|
|
25230
|
+
function devBuildWorktree(options = {}) {
|
|
25231
|
+
const codePath = options.codePath ?? overrides?.codePath ?? fileURLToPath(import.meta.url);
|
|
25232
|
+
const provenance = options.provenance !== void 0 ? options.provenance : overrides?.provenance !== void 0 ? overrides.provenance : readBuildProvenance(codePath);
|
|
25233
|
+
if (provenance) return provenance.linkedWorktree;
|
|
25234
|
+
if (codePath.split(/[\\/]/).includes("node_modules")) return null;
|
|
25235
|
+
return linkedWorktreeRootOf(codePath);
|
|
25236
|
+
}
|
|
25237
|
+
function schemaWriteRefusal(dbPath, options = {}) {
|
|
25238
|
+
const env = options.env ?? overrides?.env ?? process.env;
|
|
25239
|
+
const buildWorktree = devBuildWorktree(options);
|
|
25240
|
+
if (buildWorktree === null) return null;
|
|
25241
|
+
const store = realOrResolved(dbPath);
|
|
25242
|
+
if (isWithin(realOrResolved(buildWorktree), store)) return null;
|
|
25243
|
+
if (env["VITEST"]) return null;
|
|
25244
|
+
const honourTestSandbox = options.honourTestSandbox ?? overrides?.honourTestSandbox ?? true;
|
|
25245
|
+
if (honourTestSandbox && insideTestSandbox(store)) return null;
|
|
25246
|
+
if (env[ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV] === "1") return null;
|
|
25247
|
+
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).`;
|
|
25248
|
+
}
|
|
25249
|
+
function decisionFor(dbPath) {
|
|
25250
|
+
const key = realOrResolved(dbPath);
|
|
25251
|
+
if (!decisions.has(key)) decisions.set(key, schemaWriteRefusal(key));
|
|
25252
|
+
return decisions.get(key) ?? null;
|
|
25253
|
+
}
|
|
25254
|
+
function isWorktreeBuildSchemaError(error48) {
|
|
25255
|
+
return error48 instanceof Error && error48.message.includes(E_WORKTREE_BUILD_SCHEMA);
|
|
25256
|
+
}
|
|
25257
|
+
function codes() {
|
|
25258
|
+
if (authorizerCodes) return authorizerCodes;
|
|
25259
|
+
const sqlite = createRequire(import.meta.url)("node:sqlite").constants;
|
|
25260
|
+
authorizerCodes = {
|
|
25261
|
+
sqlite,
|
|
25262
|
+
creates: /* @__PURE__ */ new Map([
|
|
25263
|
+
[sqlite.SQLITE_CREATE_TABLE, "table"],
|
|
25264
|
+
[sqlite.SQLITE_CREATE_VTABLE, "table"],
|
|
25265
|
+
[sqlite.SQLITE_CREATE_INDEX, "index"],
|
|
25266
|
+
[sqlite.SQLITE_CREATE_TRIGGER, "trigger"],
|
|
25267
|
+
[sqlite.SQLITE_CREATE_VIEW, "view"]
|
|
25268
|
+
]),
|
|
25269
|
+
changes: /* @__PURE__ */ new Set([
|
|
25270
|
+
sqlite.SQLITE_ALTER_TABLE,
|
|
25271
|
+
sqlite.SQLITE_DROP_TABLE,
|
|
25272
|
+
sqlite.SQLITE_DROP_INDEX,
|
|
25273
|
+
sqlite.SQLITE_DROP_TRIGGER,
|
|
25274
|
+
sqlite.SQLITE_DROP_VIEW,
|
|
25275
|
+
sqlite.SQLITE_DROP_VTABLE
|
|
25276
|
+
])
|
|
25277
|
+
};
|
|
25278
|
+
return authorizerCodes;
|
|
25279
|
+
}
|
|
25280
|
+
function attachRefusal(name15) {
|
|
25281
|
+
if (name15 === "" || name15 === ":memory:") return null;
|
|
25282
|
+
if (typeof name15 !== "string" || /^file:/i.test(name15) || name15.includes("?")) {
|
|
25283
|
+
return UNKNOWN_ATTACH_REFUSAL;
|
|
25284
|
+
}
|
|
25285
|
+
return decisionFor(name15);
|
|
25286
|
+
}
|
|
25287
|
+
function readSchemas(nativeDb) {
|
|
25288
|
+
const schemas = /* @__PURE__ */ new Map();
|
|
25289
|
+
const list = nativeDb.prepare("PRAGMA database_list").all();
|
|
25290
|
+
for (const { name: name15, file: file2 } of list) {
|
|
25291
|
+
if (name15 === "temp") continue;
|
|
25292
|
+
const rows = nativeDb.prepare(`SELECT type, name FROM "${name15.replaceAll('"', '""')}".sqlite_master`).all();
|
|
25293
|
+
schemas.set(name15.toLowerCase(), {
|
|
25294
|
+
refusal: file2 ? decisionFor(file2) : null,
|
|
25295
|
+
// '' = in-memory
|
|
25296
|
+
objects: new Set(rows.map((r) => `${r.type}:${r.name}`))
|
|
25297
|
+
});
|
|
25298
|
+
}
|
|
25299
|
+
return schemas;
|
|
25300
|
+
}
|
|
25301
|
+
function guardActive() {
|
|
25302
|
+
const env = overrides?.env ?? process.env;
|
|
25303
|
+
if (env["VITEST"]) return false;
|
|
25304
|
+
if (overrides) return devBuildWorktree() !== null;
|
|
25305
|
+
if (processBuildWorktree === void 0) processBuildWorktree = devBuildWorktree();
|
|
25306
|
+
return processBuildWorktree !== null;
|
|
25307
|
+
}
|
|
25308
|
+
function installSchemaWriteGuard(nativeDb) {
|
|
25309
|
+
if (!guardActive()) return false;
|
|
25310
|
+
const location = nativeDb.location();
|
|
25311
|
+
const mainRefusal = location ? decisionFor(location) : null;
|
|
25312
|
+
if (typeof nativeDb.setAuthorizer !== "function") {
|
|
25313
|
+
if (mainRefusal) throw new WorktreeBuildSchemaError(mainRefusal);
|
|
25314
|
+
return false;
|
|
25315
|
+
}
|
|
25316
|
+
const state = {
|
|
25317
|
+
schemas: readSchemas(nativeDb),
|
|
25318
|
+
unmappedAttachRefusal: null,
|
|
25319
|
+
stale: false,
|
|
25320
|
+
lastDenied: null
|
|
25321
|
+
};
|
|
25322
|
+
guards.set(nativeDb, state);
|
|
25323
|
+
const { sqlite, creates, changes } = codes();
|
|
25324
|
+
nativeDb.setAuthorizer((action, arg1, arg2, dbName) => {
|
|
25325
|
+
if (action === sqlite.SQLITE_ATTACH) {
|
|
25326
|
+
const refusal2 = attachRefusal(arg1);
|
|
25327
|
+
if (refusal2 && !state.unmappedAttachRefusal) state.unmappedAttachRefusal = refusal2;
|
|
25328
|
+
return sqlite.SQLITE_OK;
|
|
25329
|
+
}
|
|
25330
|
+
if (action === sqlite.SQLITE_DETACH) {
|
|
25331
|
+
state.stale = true;
|
|
25332
|
+
return sqlite.SQLITE_OK;
|
|
25333
|
+
}
|
|
25334
|
+
const createType = creates.get(action);
|
|
25335
|
+
if (createType === void 0 && !changes.has(action)) return sqlite.SQLITE_OK;
|
|
25336
|
+
const schema = ((action === sqlite.SQLITE_ALTER_TABLE ? arg1 : dbName) ?? "main").toLowerCase();
|
|
25337
|
+
if (schema === "temp") return sqlite.SQLITE_OK;
|
|
25338
|
+
const mapped = state.schemas.get(schema);
|
|
25339
|
+
const policy = state.stale ? void 0 : mapped;
|
|
25340
|
+
const refusal = policy ? policy.refusal : (mapped?.refusal ?? null) || state.unmappedAttachRefusal;
|
|
25341
|
+
if (refusal === null) return sqlite.SQLITE_OK;
|
|
25342
|
+
if (createType !== void 0 && policy?.objects.has(`${createType}:${arg1}`)) {
|
|
25343
|
+
return sqlite.SQLITE_OK;
|
|
25344
|
+
}
|
|
25345
|
+
state.lastDenied = {
|
|
25346
|
+
what: createType !== void 0 ? `CREATE ${createType} ${schema}.${arg1}` : `schema change on ${schema}.${(action === sqlite.SQLITE_ALTER_TABLE ? arg2 : arg1) ?? ""}`,
|
|
25347
|
+
refusal
|
|
25348
|
+
};
|
|
25349
|
+
return sqlite.SQLITE_DENY;
|
|
25350
|
+
});
|
|
25351
|
+
return mainRefusal !== null;
|
|
25352
|
+
}
|
|
25353
|
+
function refreshSchemaWriteGuard(nativeDb) {
|
|
25354
|
+
const state = guards.get(nativeDb);
|
|
25355
|
+
if (!state) return;
|
|
25356
|
+
state.schemas = readSchemas(nativeDb);
|
|
25357
|
+
state.unmappedAttachRefusal = null;
|
|
25358
|
+
state.stale = false;
|
|
25359
|
+
}
|
|
25360
|
+
function explainSchemaWriteDenial(nativeDb, error48) {
|
|
25361
|
+
if (!(error48 instanceof Error) || !/not authorized/i.test(error48.message)) return error48;
|
|
25362
|
+
const denied = guards.get(nativeDb)?.lastDenied;
|
|
25363
|
+
if (!denied) return error48;
|
|
25364
|
+
return new WorktreeBuildSchemaError(`${denied.refusal} Denied: ${denied.what}.`);
|
|
25365
|
+
}
|
|
25366
|
+
function pendingMigrations(nativeDb, migrations) {
|
|
25367
|
+
const hasJournal = nativeDb.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '__drizzle_migrations'").get();
|
|
25368
|
+
const applied = hasJournal ? new Set(
|
|
25369
|
+
nativeDb.prepare('SELECT hash FROM main."__drizzle_migrations"').all().map((row) => row.hash)
|
|
25370
|
+
) : /* @__PURE__ */ new Set();
|
|
25371
|
+
return migrations.filter((m) => !applied.has(m.hash)).map((m) => m.name ?? m.hash);
|
|
25372
|
+
}
|
|
25373
|
+
function assertNoPendingMigrationsForWorktreeBuild(nativeDb, migrations) {
|
|
25374
|
+
const dbPath = nativeDb.location();
|
|
25375
|
+
if (!dbPath) return;
|
|
25376
|
+
const refusal = decisionFor(dbPath);
|
|
25377
|
+
if (refusal === null) return;
|
|
25378
|
+
const pending = pendingMigrations(nativeDb, migrations);
|
|
25379
|
+
if (pending.length === 0) return;
|
|
25380
|
+
throw new WorktreeBuildSchemaError(`${refusal} Pending migrations: ${pending.join(", ")}.`);
|
|
25381
|
+
}
|
|
25382
|
+
var ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV, TEST_SANDBOX_MARKER, E_WORKTREE_BUILD_SCHEMA, overrides, decisions, WorktreeBuildSchemaError, authorizerCodes, guards, UNKNOWN_ATTACH_REFUSAL, processBuildWorktree;
|
|
25383
|
+
var init_worktree_build_guard = __esm({
|
|
25384
|
+
"packages/core/src/store/worktree-build-guard.ts"() {
|
|
25385
|
+
"use strict";
|
|
25386
|
+
init_src();
|
|
25387
|
+
init_errors2();
|
|
25388
|
+
init_project_scope();
|
|
25389
|
+
ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV = "CLEO_ALLOW_WORKTREE_BUILD_MIGRATIONS";
|
|
25390
|
+
TEST_SANDBOX_MARKER = ".cleo-test-sandbox";
|
|
25391
|
+
E_WORKTREE_BUILD_SCHEMA = "E_WORKTREE_BUILD_SCHEMA";
|
|
25392
|
+
overrides = null;
|
|
25393
|
+
decisions = /* @__PURE__ */ new Map();
|
|
25394
|
+
WorktreeBuildSchemaError = class extends CleoError {
|
|
25395
|
+
constructor(message) {
|
|
25396
|
+
super(8 /* CONFIG_ERROR */, `${E_WORKTREE_BUILD_SCHEMA}: ${message}`, {
|
|
25397
|
+
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.`
|
|
25398
|
+
});
|
|
25399
|
+
}
|
|
25400
|
+
};
|
|
25401
|
+
guards = /* @__PURE__ */ new WeakMap();
|
|
25402
|
+
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";
|
|
25403
|
+
}
|
|
25404
|
+
});
|
|
25405
|
+
|
|
25078
25406
|
// packages/core/src/store/migration-manager.ts
|
|
25079
|
-
import { copyFileSync, existsSync as
|
|
25080
|
-
import { dirname as
|
|
25407
|
+
import { copyFileSync, existsSync as existsSync5 } from "node:fs";
|
|
25408
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
25081
25409
|
function stripSqlComments(sql29) {
|
|
25082
25410
|
return sql29.replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
25083
25411
|
}
|
|
@@ -25116,10 +25444,10 @@ function computeEliminatedTables(migrations) {
|
|
|
25116
25444
|
return eliminated;
|
|
25117
25445
|
}
|
|
25118
25446
|
function resolveConsolidationCutoverPrefix(migrationsFolder) {
|
|
25119
|
-
const parent =
|
|
25447
|
+
const parent = dirname4(migrationsFolder);
|
|
25120
25448
|
for (const setName of ["drizzle-cleo-project", "drizzle-cleo-global"]) {
|
|
25121
|
-
const folder =
|
|
25122
|
-
if (!
|
|
25449
|
+
const folder = join6(parent, setName);
|
|
25450
|
+
if (!existsSync5(folder)) continue;
|
|
25123
25451
|
try {
|
|
25124
25452
|
const consolidation = readMigrationFiles({ migrationsFolder: folder }).find(
|
|
25125
25453
|
(m) => /-consolidation-cleo-/.test(m.name ?? "")
|
|
@@ -25143,7 +25471,7 @@ function tableExists(nativeDb, tableName) {
|
|
|
25143
25471
|
}
|
|
25144
25472
|
function createSafetyBackup(dbPath) {
|
|
25145
25473
|
const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
|
|
25146
|
-
if (!
|
|
25474
|
+
if (!existsSync5(backupPath)) {
|
|
25147
25475
|
try {
|
|
25148
25476
|
copyFileSync(dbPath, backupPath);
|
|
25149
25477
|
} catch {
|
|
@@ -25261,6 +25589,16 @@ function readSiblingMigrationHashes(siblingFolder) {
|
|
|
25261
25589
|
return /* @__PURE__ */ new Set();
|
|
25262
25590
|
}
|
|
25263
25591
|
}
|
|
25592
|
+
function readSiblingNewestMillis(siblingFolder) {
|
|
25593
|
+
try {
|
|
25594
|
+
return Math.max(
|
|
25595
|
+
0,
|
|
25596
|
+
...readMigrationFiles({ migrationsFolder: siblingFolder }).map((m) => m.folderMillis)
|
|
25597
|
+
);
|
|
25598
|
+
} catch {
|
|
25599
|
+
return 0;
|
|
25600
|
+
}
|
|
25601
|
+
}
|
|
25264
25602
|
function ensureJournalHashUnique(nativeDb) {
|
|
25265
25603
|
if (!tableExists(nativeDb, "__drizzle_migrations")) return;
|
|
25266
25604
|
try {
|
|
@@ -25309,6 +25647,7 @@ function upgradeSharedJournalFormat(nativeDb, lineageFolders) {
|
|
|
25309
25647
|
return { named, unnamed: rows.length - named };
|
|
25310
25648
|
}
|
|
25311
25649
|
function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsystem, siblingMigrationsFolders = []) {
|
|
25650
|
+
assertNoPendingMigrationsForWorktreeBuild(nativeDb, readMigrationFiles({ migrationsFolder }));
|
|
25312
25651
|
const eliminatedTables = computeEliminatedTables(readMigrationFiles({ migrationsFolder }));
|
|
25313
25652
|
const cutoverPrefix = resolveConsolidationCutoverPrefix(migrationsFolder);
|
|
25314
25653
|
if (siblingMigrationsFolders.length > 0)
|
|
@@ -25340,8 +25679,15 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
|
|
|
25340
25679
|
knownHashes.add(m);
|
|
25341
25680
|
}
|
|
25342
25681
|
}
|
|
25343
|
-
const
|
|
25344
|
-
|
|
25682
|
+
const newestKnownMillis = Math.max(
|
|
25683
|
+
0,
|
|
25684
|
+
...localMigrations.map((m) => m.folderMillis),
|
|
25685
|
+
...siblingMigrationsFolders.filter((folder) => folder !== migrationsFolder).map(readSiblingNewestMillis)
|
|
25686
|
+
);
|
|
25687
|
+
const dbEntries = nativeDb.prepare('SELECT id, hash, created_at FROM "__drizzle_migrations"').all();
|
|
25688
|
+
const orphanedEntries = dbEntries.filter(
|
|
25689
|
+
(e) => !knownHashes.has(e.hash) && !(Number(e.created_at) > newestKnownMillis)
|
|
25690
|
+
);
|
|
25345
25691
|
const hasOrphanedEntries = orphanedEntries.length > 0;
|
|
25346
25692
|
if (hasOrphanedEntries) {
|
|
25347
25693
|
const dbHashes = new Set(dbEntries.map((e) => e.hash));
|
|
@@ -25583,6 +25929,8 @@ function sanitizeMigrationStatements(migrations) {
|
|
|
25583
25929
|
}
|
|
25584
25930
|
function migrateSanitized(db, config2) {
|
|
25585
25931
|
const raw = readMigrationFiles(config2);
|
|
25932
|
+
const client = db.$client;
|
|
25933
|
+
if (client) assertNoPendingMigrationsForWorktreeBuild(client, raw);
|
|
25586
25934
|
const sanitized = sanitizeMigrationStatements(raw);
|
|
25587
25935
|
migrateSync(sanitized, db._.session, config2);
|
|
25588
25936
|
}
|
|
@@ -25646,6 +25994,7 @@ var init_migration_manager = __esm({
|
|
|
25646
25994
|
init_sqlite_core();
|
|
25647
25995
|
init_logger2();
|
|
25648
25996
|
init_with_retry();
|
|
25997
|
+
init_worktree_build_guard();
|
|
25649
25998
|
MAX_MIGRATION_RETRIES = 5;
|
|
25650
25999
|
MIGRATION_RETRY_BASE_DELAY_MS = 100;
|
|
25651
26000
|
MIGRATION_RETRY_MAX_DELAY_MS = 2e3;
|
|
@@ -25655,13 +26004,13 @@ var init_migration_manager = __esm({
|
|
|
25655
26004
|
});
|
|
25656
26005
|
|
|
25657
26006
|
// packages/core/src/store/relocated-store-guard.ts
|
|
25658
|
-
import { existsSync as
|
|
25659
|
-
import { createRequire } from "node:module";
|
|
25660
|
-
import { basename as basename3, dirname as
|
|
26007
|
+
import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
26008
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
26009
|
+
import { basename as basename3, dirname as dirname5 } from "node:path";
|
|
25661
26010
|
import { readDeclaredProjectIdentity as readDeclaredProjectIdentity2, readPortableProjectId } from "@cleocode/paths";
|
|
25662
26011
|
function real2(p) {
|
|
25663
26012
|
try {
|
|
25664
|
-
return
|
|
26013
|
+
return realpathSync4(p);
|
|
25665
26014
|
} catch {
|
|
25666
26015
|
return p;
|
|
25667
26016
|
}
|
|
@@ -25678,7 +26027,7 @@ function liveElsewhere(globalDbPath, projectId, root) {
|
|
|
25678
26027
|
"SELECT project_path AS projectPath FROM nexus_project_registry WHERE project_id = ?"
|
|
25679
26028
|
).get(projectId);
|
|
25680
26029
|
const live = row?.projectPath;
|
|
25681
|
-
if (!live || paths.has(live) || !
|
|
26030
|
+
if (!live || paths.has(live) || !existsSync6(live)) return null;
|
|
25682
26031
|
if (!isStrictlyInsideDir(root, live)) return null;
|
|
25683
26032
|
return readDeclaredProjectIdentity2(live)?.projectId === projectId ? live : null;
|
|
25684
26033
|
} catch {
|
|
@@ -25692,14 +26041,14 @@ function detectRelocatedRoot(root, globalDbPath) {
|
|
|
25692
26041
|
if (tombstone)
|
|
25693
26042
|
return { projectId: tombstone.projectId, movedTo: tombstone.movedTo, via: "tombstone" };
|
|
25694
26043
|
const declared = readPortableProjectId(root);
|
|
25695
|
-
if (declared.status !== "valid" || !
|
|
26044
|
+
if (declared.status !== "valid" || !existsSync6(globalDbPath)) return null;
|
|
25696
26045
|
const movedTo = liveElsewhere(globalDbPath, declared.projectId, root);
|
|
25697
26046
|
return movedTo ? { projectId: declared.projectId, movedTo, via: "registry" } : null;
|
|
25698
26047
|
}
|
|
25699
26048
|
function assertStoreNotRelocated(dbPath, globalDbPath) {
|
|
25700
|
-
if (basename3(dbPath) !== "cleo.db" || basename3(
|
|
25701
|
-
if (
|
|
25702
|
-
const root =
|
|
26049
|
+
if (basename3(dbPath) !== "cleo.db" || basename3(dirname5(dbPath)) !== ".cleo") return;
|
|
26050
|
+
if (existsSync6(dbPath) || globalDbPath === dbPath) return;
|
|
26051
|
+
const root = dirname5(dirname5(dbPath));
|
|
25703
26052
|
if (_adopted.has(root)) return;
|
|
25704
26053
|
const moved = detectRelocatedRoot(root, globalDbPath);
|
|
25705
26054
|
if (moved) throw projectMovedError(root, moved, void 0, moved.via);
|
|
@@ -25709,17 +26058,17 @@ var init_relocated_store_guard = __esm({
|
|
|
25709
26058
|
"packages/core/src/store/relocated-store-guard.ts"() {
|
|
25710
26059
|
"use strict";
|
|
25711
26060
|
init_project_tombstone();
|
|
25712
|
-
_require =
|
|
26061
|
+
_require = createRequire2(import.meta.url);
|
|
25713
26062
|
_adopted = /* @__PURE__ */ new Set();
|
|
25714
26063
|
}
|
|
25715
26064
|
});
|
|
25716
26065
|
|
|
25717
26066
|
// packages/core/src/store/resolve-migrations-folder.ts
|
|
25718
|
-
import { createRequire as
|
|
25719
|
-
import { dirname as
|
|
25720
|
-
import { fileURLToPath } from "node:url";
|
|
26067
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
26068
|
+
import { dirname as dirname6, join as join7 } from "node:path";
|
|
26069
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
25721
26070
|
function coreRootFromEntry(entryPath) {
|
|
25722
|
-
return
|
|
26071
|
+
return dirname6(dirname6(entryPath));
|
|
25723
26072
|
}
|
|
25724
26073
|
function resolveConsolidatedJournalSiblings(ownSetName) {
|
|
25725
26074
|
return CONSOLIDATED_JOURNAL_LINEAGES.filter((name15) => name15 !== ownSetName).map(
|
|
@@ -25729,14 +26078,14 @@ function resolveConsolidatedJournalSiblings(ownSetName) {
|
|
|
25729
26078
|
function resolveCorePackageMigrationsFolder(setName) {
|
|
25730
26079
|
try {
|
|
25731
26080
|
const resolved = import.meta.resolve("@cleocode/core", import.meta.url);
|
|
25732
|
-
const entryPath =
|
|
25733
|
-
return
|
|
26081
|
+
const entryPath = fileURLToPath2(resolved);
|
|
26082
|
+
return join7(coreRootFromEntry(entryPath), "migrations", setName);
|
|
25734
26083
|
} catch {
|
|
25735
26084
|
}
|
|
25736
|
-
const _require7 =
|
|
26085
|
+
const _require7 = createRequire3(import.meta.url);
|
|
25737
26086
|
try {
|
|
25738
26087
|
const entryPath = _require7.resolve("@cleocode/core");
|
|
25739
|
-
return
|
|
26088
|
+
return join7(coreRootFromEntry(entryPath), "migrations", setName);
|
|
25740
26089
|
} catch (err) {
|
|
25741
26090
|
throw new Error(
|
|
25742
26091
|
`resolveCorePackageMigrationsFolder("${setName}"): cannot locate @cleocode/core from "${import.meta.url}". Ensure @cleocode/core is installed (workspace or npm). Original error: ${err.message}`
|
|
@@ -25832,11 +26181,11 @@ var init_sqlite_pragmas = __esm({
|
|
|
25832
26181
|
});
|
|
25833
26182
|
|
|
25834
26183
|
// packages/core/src/store/worktree-isolation-guard.ts
|
|
25835
|
-
import { basename as basename4, dirname as
|
|
26184
|
+
import { basename as basename4, dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
|
|
25836
26185
|
function assertStorePathIsNotWorktreeResident(role, dbPath) {
|
|
25837
|
-
const cleoDir =
|
|
26186
|
+
const cleoDir = dirname7(dbPath);
|
|
25838
26187
|
if (basename4(cleoDir) !== ".cleo") return;
|
|
25839
|
-
const projectRoot =
|
|
26188
|
+
const projectRoot = dirname7(cleoDir);
|
|
25840
26189
|
if (!isGitLinkedCheckout(projectRoot)) return;
|
|
25841
26190
|
if (process.env["CLEO_ALLOW_WORKTREE_DB_CREATE"] === "1") {
|
|
25842
26191
|
process.stderr.write(
|
|
@@ -25845,9 +26194,10 @@ function assertStorePathIsNotWorktreeResident(role, dbPath) {
|
|
|
25845
26194
|
);
|
|
25846
26195
|
return;
|
|
25847
26196
|
}
|
|
26197
|
+
const owner = describeWorktreeOwner(projectRoot);
|
|
25848
26198
|
throw new CleoError(
|
|
25849
26199
|
8 /* CONFIG_ERROR */,
|
|
25850
|
-
`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.`,
|
|
26200
|
+
`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.`,
|
|
25851
26201
|
{
|
|
25852
26202
|
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.`
|
|
25853
26203
|
}
|
|
@@ -25860,7 +26210,7 @@ function assertDbPathIsNotWorktreeResident(role, cwd) {
|
|
|
25860
26210
|
} catch {
|
|
25861
26211
|
return;
|
|
25862
26212
|
}
|
|
25863
|
-
assertStorePathIsNotWorktreeResident(role,
|
|
26213
|
+
assertStorePathIsNotWorktreeResident(role, join8(cleoDir, PROJECT_STORE_FILENAME2));
|
|
25864
26214
|
}
|
|
25865
26215
|
var PROJECT_STORE_FILENAME2;
|
|
25866
26216
|
var init_worktree_isolation_guard = __esm({
|
|
@@ -25880,10 +26230,10 @@ __export(sqlite_native_exports, {
|
|
|
25880
26230
|
getDbSyncConstructor: () => getDbSyncConstructor,
|
|
25881
26231
|
openNativeDatabase: () => openNativeDatabase
|
|
25882
26232
|
});
|
|
25883
|
-
import { realpathSync as
|
|
25884
|
-
import { createRequire as
|
|
26233
|
+
import { realpathSync as realpathSync5 } from "node:fs";
|
|
26234
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
25885
26235
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
25886
|
-
import { delimiter, dirname as
|
|
26236
|
+
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute4, join as join9, resolve as resolve4, sep as sep3 } from "node:path";
|
|
25887
26237
|
function getDbSyncConstructor() {
|
|
25888
26238
|
if (_ctor === null) {
|
|
25889
26239
|
const mod = _require2("node:sqlite");
|
|
@@ -25892,19 +26242,19 @@ function getDbSyncConstructor() {
|
|
|
25892
26242
|
return _ctor;
|
|
25893
26243
|
}
|
|
25894
26244
|
function resolveAbsoluteSafe(p) {
|
|
25895
|
-
const abs =
|
|
26245
|
+
const abs = isAbsolute4(p) ? p : resolve4(p);
|
|
25896
26246
|
try {
|
|
25897
|
-
return
|
|
26247
|
+
return realpathSync5(abs);
|
|
25898
26248
|
} catch {
|
|
25899
26249
|
const missingParts = [];
|
|
25900
26250
|
let cursor = abs;
|
|
25901
26251
|
while (true) {
|
|
25902
|
-
const parent =
|
|
26252
|
+
const parent = dirname8(cursor);
|
|
25903
26253
|
if (parent === cursor) return abs;
|
|
25904
|
-
missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(
|
|
26254
|
+
missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep3) ? 0 : 1)));
|
|
25905
26255
|
cursor = parent;
|
|
25906
26256
|
try {
|
|
25907
|
-
return
|
|
26257
|
+
return join9(realpathSync5(cursor), ...missingParts);
|
|
25908
26258
|
} catch {
|
|
25909
26259
|
}
|
|
25910
26260
|
}
|
|
@@ -25912,7 +26262,7 @@ function resolveAbsoluteSafe(p) {
|
|
|
25912
26262
|
}
|
|
25913
26263
|
function isPathUnder(child, parent) {
|
|
25914
26264
|
if (child === parent) return true;
|
|
25915
|
-
const withSep = parent.endsWith(
|
|
26265
|
+
const withSep = parent.endsWith(sep3) ? parent : parent + sep3;
|
|
25916
26266
|
return child.startsWith(withSep);
|
|
25917
26267
|
}
|
|
25918
26268
|
function assertVitestSafePath(path) {
|
|
@@ -25935,6 +26285,7 @@ function openNativeDatabase(path, options) {
|
|
|
25935
26285
|
assertVitestSafePath(path);
|
|
25936
26286
|
const DatabaseSyncCtor = getDbSyncConstructor();
|
|
25937
26287
|
const db = new DatabaseSyncCtor(path, {
|
|
26288
|
+
// schema-guard-exempt: the native chokepoint; every writable caller installs the guard
|
|
25938
26289
|
enableForeignKeyConstraints: true,
|
|
25939
26290
|
readOnly: options?.readonly ?? false,
|
|
25940
26291
|
// Default handle-open lock timeout mirrors the SSoT busy_timeout
|
|
@@ -25986,7 +26337,7 @@ var init_sqlite_native = __esm({
|
|
|
25986
26337
|
"packages/core/src/store/sqlite-native.ts"() {
|
|
25987
26338
|
"use strict";
|
|
25988
26339
|
init_sqlite_pragmas();
|
|
25989
|
-
_require2 =
|
|
26340
|
+
_require2 = createRequire4(import.meta.url);
|
|
25990
26341
|
_ctor = null;
|
|
25991
26342
|
}
|
|
25992
26343
|
});
|
|
@@ -26060,7 +26411,7 @@ var init_writer_lease_schema = __esm({
|
|
|
26060
26411
|
// packages/core/src/store/writer-lease.ts
|
|
26061
26412
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
26062
26413
|
import { randomUUID } from "node:crypto";
|
|
26063
|
-
import { realpathSync as
|
|
26414
|
+
import { realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
26064
26415
|
import { resolve as resolvePath } from "node:path";
|
|
26065
26416
|
function log() {
|
|
26066
26417
|
if (_log === null) _log = getLogger("writer-lease");
|
|
@@ -26150,7 +26501,7 @@ function resolveDbIdentity(db) {
|
|
|
26150
26501
|
return identity;
|
|
26151
26502
|
}
|
|
26152
26503
|
function sleepAsync(ms) {
|
|
26153
|
-
return new Promise((
|
|
26504
|
+
return new Promise((resolve17) => setTimeout(resolve17, Math.max(0, Math.round(ms))));
|
|
26154
26505
|
}
|
|
26155
26506
|
function isPidAlive(pid) {
|
|
26156
26507
|
try {
|
|
@@ -26489,7 +26840,7 @@ function assertColdOpenFile(frame) {
|
|
|
26489
26840
|
async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
|
|
26490
26841
|
opts.execution?.assertActive();
|
|
26491
26842
|
const captured = opts.requiredIdentity;
|
|
26492
|
-
const path =
|
|
26843
|
+
const path = realpathSync6(captured.dbPath);
|
|
26493
26844
|
const identity = statSync2(path, { bigint: true });
|
|
26494
26845
|
if (captured.scope !== scope || captured.fileDevice !== String(identity.dev) || captured.fileInode !== String(identity.ino)) {
|
|
26495
26846
|
throw new LeaseUnavailableError(
|
|
@@ -26522,6 +26873,7 @@ async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
|
|
|
26522
26873
|
}
|
|
26523
26874
|
const remaining = opts.execution ? Math.max(1, opts.execution.deadlineAt - Date.now()) : ACQUIRE_DEADLINE_MS;
|
|
26524
26875
|
const owned = openNativeDatabase(path, { timeout: Math.min(ACQUIRE_DEADLINE_MS, remaining) });
|
|
26876
|
+
installSchemaWriteGuard(owned);
|
|
26525
26877
|
try {
|
|
26526
26878
|
opts.execution?.assertActive();
|
|
26527
26879
|
const afterOpen = statSync2(path, { bigint: true });
|
|
@@ -26715,6 +27067,7 @@ var init_writer_lease = __esm({
|
|
|
26715
27067
|
init_background_ops();
|
|
26716
27068
|
init_dual_scope_db();
|
|
26717
27069
|
init_sqlite_native();
|
|
27070
|
+
init_worktree_build_guard();
|
|
26718
27071
|
init_writer_lease_schema();
|
|
26719
27072
|
DEFAULT_TTL_MS = 3e4;
|
|
26720
27073
|
DEFAULT_PRIORITY = 100;
|
|
@@ -27257,10 +27610,10 @@ var init_monitor = __esm({
|
|
|
27257
27610
|
|
|
27258
27611
|
// packages/core/src/resources/supervisor-admit.ts
|
|
27259
27612
|
import { connect } from "node:net";
|
|
27260
|
-
import { join as
|
|
27613
|
+
import { join as join10 } from "node:path";
|
|
27261
27614
|
import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
|
|
27262
27615
|
function resolveSupervisorSocketPath() {
|
|
27263
|
-
return process.env.CLEO_SUPERVISOR_SOCKET ??
|
|
27616
|
+
return process.env.CLEO_SUPERVISOR_SOCKET ?? join10(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
|
|
27264
27617
|
}
|
|
27265
27618
|
async function sendResourceAdmit(socketPath, cls, holderId, budget) {
|
|
27266
27619
|
const result = await sendLeaseRequest(
|
|
@@ -27283,7 +27636,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
|
|
|
27283
27636
|
return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
|
|
27284
27637
|
}
|
|
27285
27638
|
function sendLeaseRequest(socketPath, request, expectedKind) {
|
|
27286
|
-
return new Promise((
|
|
27639
|
+
return new Promise((resolve17) => {
|
|
27287
27640
|
const id = `ra-${process.pid}-${request.kind}`;
|
|
27288
27641
|
const envelope = LeaseIpcRequestEnvelopeSchema.parse({
|
|
27289
27642
|
protocol_version: LEASE_IPC_PROTOCOL_VERSION,
|
|
@@ -27301,7 +27654,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
|
|
|
27301
27654
|
settled = true;
|
|
27302
27655
|
socket.removeAllListeners();
|
|
27303
27656
|
socket.destroy();
|
|
27304
|
-
|
|
27657
|
+
resolve17(value);
|
|
27305
27658
|
};
|
|
27306
27659
|
const degrade = (reason) => done({ unavailable: true, reason });
|
|
27307
27660
|
socket.setTimeout(REQUEST_TIMEOUT_MS);
|
|
@@ -27372,9 +27725,9 @@ __export(governor_exports, {
|
|
|
27372
27725
|
resolveGovernorMode: () => resolveGovernorMode,
|
|
27373
27726
|
slotFileCount: () => slotFileCount
|
|
27374
27727
|
});
|
|
27375
|
-
import { existsSync as
|
|
27728
|
+
import { existsSync as existsSync7, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
27376
27729
|
import { availableParallelism, totalmem } from "node:os";
|
|
27377
|
-
import { join as
|
|
27730
|
+
import { join as join11 } from "node:path";
|
|
27378
27731
|
import lockfile from "proper-lockfile";
|
|
27379
27732
|
function log2() {
|
|
27380
27733
|
if (_log2 === null) _log2 = getLogger("resource-governor");
|
|
@@ -27443,14 +27796,14 @@ function clamp(lo, v, hi) {
|
|
|
27443
27796
|
return Math.max(lo, Math.min(v, hi));
|
|
27444
27797
|
}
|
|
27445
27798
|
function governorSlotDir(cls) {
|
|
27446
|
-
return
|
|
27799
|
+
return join11(getCleoHome(), "locks", `resource-${cls}`);
|
|
27447
27800
|
}
|
|
27448
27801
|
function ensureSlotFiles(dir, count) {
|
|
27449
|
-
if (!
|
|
27802
|
+
if (!existsSync7(dir)) mkdirSync(dir, { recursive: true });
|
|
27450
27803
|
const paths = [];
|
|
27451
27804
|
for (let i = 0; i < count; i++) {
|
|
27452
|
-
const p =
|
|
27453
|
-
if (!
|
|
27805
|
+
const p = join11(dir, `slot-${i}.lock`);
|
|
27806
|
+
if (!existsSync7(p)) writeFileSync3(p, "", { flag: "a" });
|
|
27454
27807
|
paths.push(p);
|
|
27455
27808
|
}
|
|
27456
27809
|
return paths;
|
|
@@ -27490,7 +27843,7 @@ function shuffledIndices(n) {
|
|
|
27490
27843
|
}
|
|
27491
27844
|
async function countHeldSlots(cls, budget) {
|
|
27492
27845
|
const dir = governorSlotDir(cls);
|
|
27493
|
-
if (!
|
|
27846
|
+
if (!existsSync7(dir)) return 0;
|
|
27494
27847
|
const slots = ensureSlotFiles(dir, budget);
|
|
27495
27848
|
let held = 0;
|
|
27496
27849
|
for (const path of slots) {
|
|
@@ -27505,7 +27858,7 @@ async function countHeldSlots(cls, budget) {
|
|
|
27505
27858
|
}
|
|
27506
27859
|
function slotFileCount(cls) {
|
|
27507
27860
|
const dir = governorSlotDir(cls);
|
|
27508
|
-
if (!
|
|
27861
|
+
if (!existsSync7(dir)) return 0;
|
|
27509
27862
|
return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
|
|
27510
27863
|
}
|
|
27511
27864
|
var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
|
|
@@ -27705,11 +28058,11 @@ var init_lock = __esm({
|
|
|
27705
28058
|
|
|
27706
28059
|
// packages/core/src/store/atomic.ts
|
|
27707
28060
|
import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
|
|
27708
|
-
import { dirname as
|
|
28061
|
+
import { dirname as dirname9 } from "node:path";
|
|
27709
28062
|
import writeFileAtomic from "write-file-atomic";
|
|
27710
28063
|
async function atomicWrite(filePath, data, options) {
|
|
27711
28064
|
try {
|
|
27712
|
-
await mkdir(
|
|
28065
|
+
await mkdir(dirname9(filePath), { recursive: true });
|
|
27713
28066
|
await writeFileAtomic(filePath, data, {
|
|
27714
28067
|
encoding: options?.encoding ?? "utf8",
|
|
27715
28068
|
mode: options?.mode
|
|
@@ -27742,7 +28095,7 @@ var init_atomic = __esm({
|
|
|
27742
28095
|
|
|
27743
28096
|
// packages/core/src/store/backup.ts
|
|
27744
28097
|
import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
27745
|
-
import { basename as basename5, join as
|
|
28098
|
+
import { basename as basename5, dirname as dirname10, join as join12 } from "node:path";
|
|
27746
28099
|
async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
|
|
27747
28100
|
try {
|
|
27748
28101
|
await mkdir2(backupDir, { recursive: true });
|
|
@@ -27753,14 +28106,14 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
|
|
|
27753
28106
|
throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
|
|
27754
28107
|
}
|
|
27755
28108
|
for (let i = maxBackups; i >= 1; i--) {
|
|
27756
|
-
const current =
|
|
28109
|
+
const current = join12(backupDir, `${fileName}.${i}`);
|
|
27757
28110
|
if (i === maxBackups) {
|
|
27758
28111
|
try {
|
|
27759
28112
|
await unlink2(current);
|
|
27760
28113
|
} catch {
|
|
27761
28114
|
}
|
|
27762
28115
|
} else {
|
|
27763
|
-
const next =
|
|
28116
|
+
const next = join12(backupDir, `${fileName}.${i + 1}`);
|
|
27764
28117
|
try {
|
|
27765
28118
|
await stat2(current);
|
|
27766
28119
|
await fsRename(current, next);
|
|
@@ -27768,7 +28121,7 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
|
|
|
27768
28121
|
}
|
|
27769
28122
|
}
|
|
27770
28123
|
}
|
|
27771
|
-
const backupPath =
|
|
28124
|
+
const backupPath = join12(backupDir, `${fileName}.1`);
|
|
27772
28125
|
await copyFile(filePath, backupPath);
|
|
27773
28126
|
return backupPath;
|
|
27774
28127
|
} catch (err) {
|
|
@@ -27782,6 +28135,7 @@ var init_backup = __esm({
|
|
|
27782
28135
|
"use strict";
|
|
27783
28136
|
init_src();
|
|
27784
28137
|
init_errors2();
|
|
28138
|
+
init_worktree_isolation_guard();
|
|
27785
28139
|
DEFAULT_MAX_BACKUPS = 5;
|
|
27786
28140
|
}
|
|
27787
28141
|
});
|
|
@@ -28066,7 +28420,7 @@ __export(identity_exports, {
|
|
|
28066
28420
|
import { execFile } from "node:child_process";
|
|
28067
28421
|
import { createHash as createHash2 } from "node:crypto";
|
|
28068
28422
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
28069
|
-
import { join as
|
|
28423
|
+
import { join as join13, resolve as resolve5 } from "node:path";
|
|
28070
28424
|
import { promisify } from "node:util";
|
|
28071
28425
|
import { legacyProjectId } from "@cleocode/paths";
|
|
28072
28426
|
import { legacyProjectId as legacyProjectId2 } from "@cleocode/paths";
|
|
@@ -28074,14 +28428,14 @@ async function findGitRoot(fromPath, execution) {
|
|
|
28074
28428
|
execution?.assertActive();
|
|
28075
28429
|
try {
|
|
28076
28430
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
28077
|
-
cwd:
|
|
28431
|
+
cwd: resolve5(fromPath),
|
|
28078
28432
|
signal: execution?.signal,
|
|
28079
28433
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
28080
28434
|
killSignal: "SIGKILL",
|
|
28081
28435
|
maxBuffer: 64 * 1024
|
|
28082
28436
|
});
|
|
28083
28437
|
execution?.assertActive();
|
|
28084
|
-
return
|
|
28438
|
+
return resolve5(stdout.trim());
|
|
28085
28439
|
} catch {
|
|
28086
28440
|
execution?.assertActive();
|
|
28087
28441
|
return null;
|
|
@@ -28091,7 +28445,7 @@ async function findGitRemoteUrl(fromPath, execution) {
|
|
|
28091
28445
|
execution?.assertActive();
|
|
28092
28446
|
try {
|
|
28093
28447
|
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
|
|
28094
|
-
cwd:
|
|
28448
|
+
cwd: resolve5(fromPath),
|
|
28095
28449
|
signal: execution?.signal,
|
|
28096
28450
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
28097
28451
|
killSignal: "SIGKILL",
|
|
@@ -28121,7 +28475,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
|
|
|
28121
28475
|
try {
|
|
28122
28476
|
const args = ["--no-replace-objects", "rev-list", "--max-parents=0", "HEAD"];
|
|
28123
28477
|
const { stdout } = await execFileAsync("git", args, {
|
|
28124
|
-
cwd:
|
|
28478
|
+
cwd: resolve5(fromPath),
|
|
28125
28479
|
signal: execution?.signal,
|
|
28126
28480
|
timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
|
|
28127
28481
|
killSignal: "SIGKILL",
|
|
@@ -28144,7 +28498,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
|
|
|
28144
28498
|
async function readProjectInfoName(repoRoot, execution) {
|
|
28145
28499
|
execution?.assertActive();
|
|
28146
28500
|
try {
|
|
28147
|
-
const raw = await readFile3(
|
|
28501
|
+
const raw = await readFile3(join13(repoRoot, ".cleo", "project-info.json"), {
|
|
28148
28502
|
encoding: "utf8",
|
|
28149
28503
|
signal: execution?.signal
|
|
28150
28504
|
});
|
|
@@ -28159,7 +28513,7 @@ async function readProjectInfoName(repoRoot, execution) {
|
|
|
28159
28513
|
}
|
|
28160
28514
|
async function projectPathFingerprint(repoPath, execution) {
|
|
28161
28515
|
execution?.assertActive();
|
|
28162
|
-
const realRepoPath =
|
|
28516
|
+
const realRepoPath = resolve5(repoPath);
|
|
28163
28517
|
const results = await Promise.allSettled([
|
|
28164
28518
|
findGitRoot(realRepoPath, execution),
|
|
28165
28519
|
findGitRemoteUrl(realRepoPath, execution)
|
|
@@ -28183,9 +28537,9 @@ async function projectPathFingerprint(repoPath, execution) {
|
|
|
28183
28537
|
}
|
|
28184
28538
|
function computeLegacyAliases(repoPath, additionalPaths) {
|
|
28185
28539
|
const aliases = /* @__PURE__ */ new Set();
|
|
28186
|
-
aliases.add(legacyProjectId(
|
|
28540
|
+
aliases.add(legacyProjectId(resolve5(repoPath)));
|
|
28187
28541
|
for (const p of additionalPaths ?? []) {
|
|
28188
|
-
aliases.add(legacyProjectId(
|
|
28542
|
+
aliases.add(legacyProjectId(resolve5(p)));
|
|
28189
28543
|
}
|
|
28190
28544
|
return [...aliases];
|
|
28191
28545
|
}
|
|
@@ -28219,17 +28573,17 @@ var init_project_identity = __esm({
|
|
|
28219
28573
|
});
|
|
28220
28574
|
|
|
28221
28575
|
// packages/core/src/scaffold/ensure-config.ts
|
|
28222
|
-
import { existsSync as
|
|
28223
|
-
import { basename as basename6, dirname as
|
|
28224
|
-
import { fileURLToPath as
|
|
28576
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
28577
|
+
import { basename as basename6, dirname as dirname11, join as join14, resolve as resolve6 } from "node:path";
|
|
28578
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
28225
28579
|
function getPackageRoot() {
|
|
28226
|
-
const thisFile =
|
|
28227
|
-
return
|
|
28580
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
28581
|
+
return resolve6(dirname11(thisFile), "..", "..");
|
|
28228
28582
|
}
|
|
28229
28583
|
function getCleoVersion() {
|
|
28230
28584
|
try {
|
|
28231
|
-
const pkgPath =
|
|
28232
|
-
const pkg = JSON.parse(
|
|
28585
|
+
const pkgPath = join14(getPackageRoot(), "package.json");
|
|
28586
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
28233
28587
|
return pkg.version ?? "0.0.0";
|
|
28234
28588
|
} catch {
|
|
28235
28589
|
return "0.0.0";
|
|
@@ -28588,25 +28942,25 @@ var init_recovery = __esm({
|
|
|
28588
28942
|
// packages/core/src/store/exodus/archive.ts
|
|
28589
28943
|
import {
|
|
28590
28944
|
copyFileSync as copyFileSync2,
|
|
28591
|
-
existsSync as
|
|
28945
|
+
existsSync as existsSync9,
|
|
28592
28946
|
mkdirSync as mkdirSync2,
|
|
28593
|
-
readFileSync as
|
|
28947
|
+
readFileSync as readFileSync5,
|
|
28594
28948
|
renameSync as renameSync3,
|
|
28595
28949
|
unlinkSync,
|
|
28596
28950
|
writeFileSync as writeFileSync4
|
|
28597
28951
|
} from "node:fs";
|
|
28598
|
-
import { basename as basename7, dirname as
|
|
28952
|
+
import { basename as basename7, dirname as dirname12, join as join15, resolve as resolve7 } from "node:path";
|
|
28599
28953
|
import { z as z26 } from "zod";
|
|
28600
28954
|
function scopeBaseDir(scope, cwd, targetDbPath) {
|
|
28601
|
-
if (targetDbPath !== void 0) return
|
|
28955
|
+
if (targetDbPath !== void 0) return dirname12(targetDbPath);
|
|
28602
28956
|
return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
|
|
28603
28957
|
}
|
|
28604
28958
|
function exodusArchiveDir(scope, cwd, targetDbPath) {
|
|
28605
|
-
return
|
|
28959
|
+
return join15(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
|
|
28606
28960
|
}
|
|
28607
28961
|
function exodusMarkerPath(scope, cwd, targetDbPath) {
|
|
28608
28962
|
const marker16 = targetDbPath !== void 0 && basename7(targetDbPath) !== "cleo.db" ? `${basename7(targetDbPath)}.${MARKER_FILENAME_BY_SCOPE[scope]}` : MARKER_FILENAME_BY_SCOPE[scope];
|
|
28609
|
-
return
|
|
28963
|
+
return join15(scopeBaseDir(scope, cwd, targetDbPath), marker16);
|
|
28610
28964
|
}
|
|
28611
28965
|
function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
|
|
28612
28966
|
let markerPath;
|
|
@@ -28616,13 +28970,13 @@ function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
|
|
|
28616
28970
|
if (targetDbPath) throw error48;
|
|
28617
28971
|
return false;
|
|
28618
28972
|
}
|
|
28619
|
-
if (!
|
|
28620
|
-
const marker16 = markerIdentity.parse(JSON.parse(
|
|
28973
|
+
if (!existsSync9(markerPath)) return false;
|
|
28974
|
+
const marker16 = markerIdentity.parse(JSON.parse(readFileSync5(markerPath, "utf8")));
|
|
28621
28975
|
if (nativeDb && (!marker16.databaseIdentity || !hasExodusDatabaseIdentity(nativeDb, marker16.databaseIdentity)))
|
|
28622
28976
|
throw new Error(
|
|
28623
28977
|
"Exodus completion marker does not certify this database generation; assessment required"
|
|
28624
28978
|
);
|
|
28625
|
-
return marker16.scope === scope && (!targetDbPath || !marker16.targetDbPath ||
|
|
28979
|
+
return marker16.scope === scope && (!targetDbPath || !marker16.targetDbPath || resolve7(marker16.targetDbPath) === resolve7(targetDbPath));
|
|
28626
28980
|
}
|
|
28627
28981
|
function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, databaseIdentity) {
|
|
28628
28982
|
const markerPath = exodusMarkerPath(scope, cwd, targetDbPath);
|
|
@@ -28634,7 +28988,7 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
|
|
|
28634
28988
|
cleoVersion: getCleoVersion(),
|
|
28635
28989
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28636
28990
|
archivedSources: [...archivedSources],
|
|
28637
|
-
targetDbPath:
|
|
28991
|
+
targetDbPath: resolve7(targetDbPath ?? join15(baseDir, "cleo.db")),
|
|
28638
28992
|
...databaseIdentity ? { databaseIdentity } : {}
|
|
28639
28993
|
};
|
|
28640
28994
|
const tmpPath = `${markerPath}.tmp`;
|
|
@@ -28645,10 +28999,10 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
|
|
|
28645
28999
|
}
|
|
28646
29000
|
function moveFileInto(srcPath, destDir) {
|
|
28647
29001
|
mkdirSync2(destDir, { recursive: true });
|
|
28648
|
-
let dest =
|
|
28649
|
-
if (
|
|
29002
|
+
let dest = join15(destDir, basename7(srcPath));
|
|
29003
|
+
if (existsSync9(dest)) {
|
|
28650
29004
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
|
|
28651
|
-
dest =
|
|
29005
|
+
dest = join15(destDir, `${basename7(srcPath)}.${stamp}`);
|
|
28652
29006
|
}
|
|
28653
29007
|
try {
|
|
28654
29008
|
renameSync3(srcPath, dest);
|
|
@@ -28659,14 +29013,14 @@ function moveFileInto(srcPath, destDir) {
|
|
|
28659
29013
|
return dest;
|
|
28660
29014
|
}
|
|
28661
29015
|
function archiveSourceDb(source, cwd, targetDbPath) {
|
|
28662
|
-
if (!
|
|
29016
|
+
if (!existsSync9(source.path)) {
|
|
28663
29017
|
return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
|
|
28664
29018
|
}
|
|
28665
29019
|
const destDir = exodusArchiveDir(source.targetScope, cwd, targetDbPath);
|
|
28666
29020
|
const archivedTo = moveFileInto(source.path, destDir);
|
|
28667
29021
|
for (const suffix of SIDECAR_SUFFIXES) {
|
|
28668
29022
|
const sidecar = `${source.path}${suffix}`;
|
|
28669
|
-
if (
|
|
29023
|
+
if (existsSync9(sidecar)) {
|
|
28670
29024
|
try {
|
|
28671
29025
|
moveFileInto(sidecar, destDir);
|
|
28672
29026
|
} catch (err) {
|
|
@@ -28714,7 +29068,7 @@ function detectStrandedResidue(sources, cwd) {
|
|
|
28714
29068
|
const stranded = [];
|
|
28715
29069
|
for (const source of sources) {
|
|
28716
29070
|
if (!markedScopes.has(source.targetScope)) continue;
|
|
28717
|
-
if (
|
|
29071
|
+
if (existsSync9(source.path)) {
|
|
28718
29072
|
stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
|
|
28719
29073
|
}
|
|
28720
29074
|
}
|
|
@@ -28779,7 +29133,7 @@ __export(open_cleo_db_exports, {
|
|
|
28779
29133
|
openCleoDbSnapshot: () => openCleoDbSnapshot,
|
|
28780
29134
|
validateProjectIdConsistency: () => validateProjectIdConsistency
|
|
28781
29135
|
});
|
|
28782
|
-
import { createRequire as
|
|
29136
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
28783
29137
|
function unwrapNativeSqliteDb(db) {
|
|
28784
29138
|
if (db && typeof db === "object" && "$client" in db) {
|
|
28785
29139
|
return db.$client ?? db;
|
|
@@ -28843,9 +29197,10 @@ async function openCleoDb(role, cwd) {
|
|
|
28843
29197
|
}
|
|
28844
29198
|
function openCleoDbSnapshot(path, options = {}) {
|
|
28845
29199
|
const { readOnly = true, applyPragmas = true } = options;
|
|
28846
|
-
const _require7 =
|
|
29200
|
+
const _require7 = createRequire5(import.meta.url);
|
|
28847
29201
|
const { DatabaseSync: DatabaseSyncCtor } = _require7("node:sqlite");
|
|
28848
29202
|
const db = new DatabaseSyncCtor(path, { readOnly });
|
|
29203
|
+
if (!readOnly) installSchemaWriteGuard(db);
|
|
28849
29204
|
if (applyPragmas) {
|
|
28850
29205
|
applyPerfPragmas(db, { enableWal: !readOnly });
|
|
28851
29206
|
}
|
|
@@ -28873,6 +29228,7 @@ var init_open_cleo_db = __esm({
|
|
|
28873
29228
|
init_project_info();
|
|
28874
29229
|
init_dual_scope_db();
|
|
28875
29230
|
init_sqlite_pragmas();
|
|
29231
|
+
init_worktree_build_guard();
|
|
28876
29232
|
init_worktree_isolation_guard();
|
|
28877
29233
|
PROJECT_ID_TRACKING_ROLES = /* @__PURE__ */ new Set(["global"]);
|
|
28878
29234
|
}
|
|
@@ -29212,7 +29568,7 @@ var init_table_name_map = __esm({
|
|
|
29212
29568
|
});
|
|
29213
29569
|
|
|
29214
29570
|
// packages/core/src/store/exodus/count-parity.ts
|
|
29215
|
-
import { existsSync as
|
|
29571
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
29216
29572
|
function listTables(db) {
|
|
29217
29573
|
return db.prepare(
|
|
29218
29574
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
|
|
@@ -29233,14 +29589,14 @@ function rowCount(db, tableName) {
|
|
|
29233
29589
|
function computeCountParity(sources, projectDbPath, globalDbPath) {
|
|
29234
29590
|
const entries = [];
|
|
29235
29591
|
let skipped = 0;
|
|
29236
|
-
if (!
|
|
29592
|
+
if (!existsSync10(projectDbPath) || !existsSync10(globalDbPath)) {
|
|
29237
29593
|
return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
29238
29594
|
}
|
|
29239
29595
|
const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
|
|
29240
29596
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
29241
29597
|
try {
|
|
29242
29598
|
for (const src of sources) {
|
|
29243
|
-
if (!
|
|
29599
|
+
if (!existsSync10(src.path)) continue;
|
|
29244
29600
|
const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
29245
29601
|
try {
|
|
29246
29602
|
for (const legacyTable of listTables(srcSnap.db)) {
|
|
@@ -29298,8 +29654,8 @@ var init_count_parity = __esm({
|
|
|
29298
29654
|
});
|
|
29299
29655
|
|
|
29300
29656
|
// packages/core/src/store/exodus/plan.ts
|
|
29301
|
-
import { existsSync as
|
|
29302
|
-
import { join as
|
|
29657
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
|
|
29658
|
+
import { join as join16 } from "node:path";
|
|
29303
29659
|
function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
|
|
29304
29660
|
return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
|
|
29305
29661
|
}
|
|
@@ -29310,33 +29666,33 @@ function buildSourceDescriptors(cwd) {
|
|
|
29310
29666
|
// Project-tier — go into consolidated project-scope cleo.db
|
|
29311
29667
|
{
|
|
29312
29668
|
name: "tasks",
|
|
29313
|
-
path:
|
|
29669
|
+
path: join16(cleoDir, "tasks.db"),
|
|
29314
29670
|
targetScope: "project"
|
|
29315
29671
|
},
|
|
29316
29672
|
{
|
|
29317
29673
|
name: "brain (project)",
|
|
29318
|
-
path:
|
|
29674
|
+
path: join16(cleoDir, "brain.db"),
|
|
29319
29675
|
targetScope: "project"
|
|
29320
29676
|
},
|
|
29321
29677
|
{
|
|
29322
29678
|
name: "conduit",
|
|
29323
|
-
path:
|
|
29679
|
+
path: join16(cleoDir, "conduit.db"),
|
|
29324
29680
|
targetScope: "project"
|
|
29325
29681
|
},
|
|
29326
29682
|
// Global-tier — go into consolidated global-scope cleo.db
|
|
29327
29683
|
{
|
|
29328
29684
|
name: "nexus",
|
|
29329
|
-
path:
|
|
29685
|
+
path: join16(cleoHome, "nexus.db"),
|
|
29330
29686
|
targetScope: "global"
|
|
29331
29687
|
},
|
|
29332
29688
|
{
|
|
29333
29689
|
name: "signaldock",
|
|
29334
|
-
path:
|
|
29690
|
+
path: join16(cleoHome, "signaldock.db"),
|
|
29335
29691
|
targetScope: "global"
|
|
29336
29692
|
},
|
|
29337
29693
|
{
|
|
29338
29694
|
name: "skills",
|
|
29339
|
-
path:
|
|
29695
|
+
path: join16(cleoHome, "skills.db"),
|
|
29340
29696
|
targetScope: "global"
|
|
29341
29697
|
}
|
|
29342
29698
|
];
|
|
@@ -29365,7 +29721,7 @@ function findExistingStaging(cleoDir) {
|
|
|
29365
29721
|
const entries = readdirSync3(cleoDir, { withFileTypes: true });
|
|
29366
29722
|
const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
|
|
29367
29723
|
if (stagingDirs.length > 0) {
|
|
29368
|
-
return
|
|
29724
|
+
return join16(cleoDir, stagingDirs[0]);
|
|
29369
29725
|
}
|
|
29370
29726
|
} catch {
|
|
29371
29727
|
}
|
|
@@ -29381,7 +29737,7 @@ function buildExodusPlan(cwd) {
|
|
|
29381
29737
|
const availableBytes = getAvailableBytes(cleoDir);
|
|
29382
29738
|
const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
|
|
29383
29739
|
const existingStaging = findExistingStaging(cleoDir);
|
|
29384
|
-
const stagingDir = existingStaging ??
|
|
29740
|
+
const stagingDir = existingStaging ?? join16(cleoDir, deriveStagingDirName());
|
|
29385
29741
|
const resumeFromStaging = existingStaging !== null;
|
|
29386
29742
|
const projectDbPath = resolveDualScopeDbPath("project", cwd);
|
|
29387
29743
|
const globalDbPath = resolveDualScopeDbPath("global");
|
|
@@ -29400,7 +29756,7 @@ function buildExodusPlan(cwd) {
|
|
|
29400
29756
|
};
|
|
29401
29757
|
}
|
|
29402
29758
|
function sourcesPresent(sources) {
|
|
29403
|
-
return sources.some((s) =>
|
|
29759
|
+
return sources.some((s) => existsSync11(s.path));
|
|
29404
29760
|
}
|
|
29405
29761
|
var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
|
|
29406
29762
|
var init_plan2 = __esm({
|
|
@@ -29414,18 +29770,18 @@ var init_plan2 = __esm({
|
|
|
29414
29770
|
});
|
|
29415
29771
|
|
|
29416
29772
|
// packages/core/src/store/exodus/health.ts
|
|
29417
|
-
import { existsSync as
|
|
29773
|
+
import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
|
|
29418
29774
|
function buildExodusHealth(cwd) {
|
|
29419
29775
|
const plan = buildExodusPlan(cwd);
|
|
29420
|
-
const anyLegacyPresent = plan.sources.some((s) =>
|
|
29776
|
+
const anyLegacyPresent = plan.sources.some((s) => existsSync12(s.path));
|
|
29421
29777
|
const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
29422
29778
|
const consolidatedExistsByScope = {
|
|
29423
|
-
project:
|
|
29424
|
-
global:
|
|
29779
|
+
project: existsSync12(plan.projectDbPath),
|
|
29780
|
+
global: existsSync12(plan.globalDbPath)
|
|
29425
29781
|
};
|
|
29426
29782
|
const buildScope = (scope) => {
|
|
29427
29783
|
const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
|
|
29428
|
-
const present =
|
|
29784
|
+
const present = existsSync12(s.path);
|
|
29429
29785
|
let bytes = 0;
|
|
29430
29786
|
if (present) {
|
|
29431
29787
|
try {
|
|
@@ -29777,8 +30133,8 @@ var init_types = __esm({
|
|
|
29777
30133
|
});
|
|
29778
30134
|
|
|
29779
30135
|
// packages/core/src/store/backup-sidecar.ts
|
|
29780
|
-
import { existsSync as
|
|
29781
|
-
import { join as
|
|
30136
|
+
import { existsSync as existsSync13, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
30137
|
+
import { join as join17 } from "node:path";
|
|
29782
30138
|
function formatBackupTimestamp(d) {
|
|
29783
30139
|
const pad = (n, len = 2) => String(n).padStart(len, "0");
|
|
29784
30140
|
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
@@ -29789,8 +30145,8 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29789
30145
|
const ownedPattern = new RegExp(`\\.${escapedType}-`);
|
|
29790
30146
|
const files = readdirSync4(backupDir).filter((f) => !f.endsWith(".meta.json") && !f.endsWith(".tmp") && ownedPattern.test(f)).map((f) => ({
|
|
29791
30147
|
name: f,
|
|
29792
|
-
path:
|
|
29793
|
-
mtimeMs: statSync5(
|
|
30148
|
+
path: join17(backupDir, f),
|
|
30149
|
+
mtimeMs: statSync5(join17(backupDir, f)).mtimeMs
|
|
29794
30150
|
})).sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
29795
30151
|
while (files.length > maxSnapshots) {
|
|
29796
30152
|
const oldest = files.shift();
|
|
@@ -29798,7 +30154,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29798
30154
|
try {
|
|
29799
30155
|
unlinkSync2(oldest.path);
|
|
29800
30156
|
const metaPath = `${oldest.path}.meta.json`;
|
|
29801
|
-
if (
|
|
30157
|
+
if (existsSync13(metaPath)) unlinkSync2(metaPath);
|
|
29802
30158
|
} catch {
|
|
29803
30159
|
}
|
|
29804
30160
|
}
|
|
@@ -29806,7 +30162,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
|
|
|
29806
30162
|
}
|
|
29807
30163
|
}
|
|
29808
30164
|
function writeBackupSidecar(backupDir, sidecar) {
|
|
29809
|
-
const dest =
|
|
30165
|
+
const dest = join17(backupDir, `${sidecar.backupId}.meta.json`);
|
|
29810
30166
|
const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
|
|
29811
30167
|
writeFileSync5(tmp, JSON.stringify(sidecar, null, 2));
|
|
29812
30168
|
renameSync4(tmp, dest);
|
|
@@ -29818,23 +30174,23 @@ var init_backup_sidecar = __esm({
|
|
|
29818
30174
|
});
|
|
29819
30175
|
|
|
29820
30176
|
// packages/core/src/store/pre-repair-snapshot.ts
|
|
29821
|
-
import { existsSync as
|
|
29822
|
-
import { dirname as
|
|
30177
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
|
|
30178
|
+
import { dirname as dirname13, join as join18 } from "node:path";
|
|
29823
30179
|
function writePreRepairSnapshot(nativeDb, dbPath, label) {
|
|
29824
30180
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
29825
|
-
const backupDir =
|
|
30181
|
+
const backupDir = join18(dirname13(dbPath), "backups");
|
|
29826
30182
|
mkdirSync3(backupDir, { recursive: true });
|
|
29827
|
-
const snapshotPath =
|
|
30183
|
+
const snapshotPath = join18(backupDir, `cleo-pre-${label}-${stamp}.db`);
|
|
29828
30184
|
nativeDb.exec(`VACUUM INTO '${snapshotPath.replace(/'/g, "''")}'`);
|
|
29829
30185
|
return snapshotPath;
|
|
29830
30186
|
}
|
|
29831
30187
|
function existingAncestor(path) {
|
|
29832
30188
|
let p = path;
|
|
29833
|
-
while (!
|
|
30189
|
+
while (!existsSync14(p) && dirname13(p) !== p) p = dirname13(p);
|
|
29834
30190
|
return p;
|
|
29835
30191
|
}
|
|
29836
30192
|
function planMigrationSnapshot(nativeDb, dbPath) {
|
|
29837
|
-
const backupDir =
|
|
30193
|
+
const backupDir = join18(dirname13(dbPath), "backups", "sqlite");
|
|
29838
30194
|
const pragma = (name15) => Number(nativeDb.prepare(`PRAGMA main.${name15}`).get()[name15] ?? 0);
|
|
29839
30195
|
const liveBytes = (pragma("page_count") - pragma("freelist_count")) * pragma("page_size");
|
|
29840
30196
|
let availableBytes = null;
|
|
@@ -29846,13 +30202,13 @@ function planMigrationSnapshot(nativeDb, dbPath) {
|
|
|
29846
30202
|
}
|
|
29847
30203
|
const base = `migration-${formatBackupTimestamp(/* @__PURE__ */ new Date())}`;
|
|
29848
30204
|
let backupId = base;
|
|
29849
|
-
for (let n = 2;
|
|
30205
|
+
for (let n = 2; existsSync14(join18(backupDir, `${backupId}.meta.json`)); n++) {
|
|
29850
30206
|
backupId = `${base}-${n}`;
|
|
29851
30207
|
}
|
|
29852
30208
|
return {
|
|
29853
30209
|
backupDir,
|
|
29854
30210
|
backupId,
|
|
29855
|
-
snapshotPath:
|
|
30211
|
+
snapshotPath: join18(backupDir, `cleo.db.${backupId}`),
|
|
29856
30212
|
requiredBytes: liveBytes + SNAPSHOT_HEADROOM_BYTES,
|
|
29857
30213
|
availableBytes
|
|
29858
30214
|
};
|
|
@@ -30092,7 +30448,7 @@ var init_legacy_tasks_lineage = __esm({
|
|
|
30092
30448
|
|
|
30093
30449
|
// packages/core/src/store/ports/domain-binding.ts
|
|
30094
30450
|
import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
|
|
30095
|
-
import { resolve as
|
|
30451
|
+
import { resolve as resolve8 } from "node:path";
|
|
30096
30452
|
function getCleoRuntime() {
|
|
30097
30453
|
if (!_runtime) {
|
|
30098
30454
|
_runtime = createCleoRuntime();
|
|
@@ -30160,6 +30516,8 @@ async function bindAgainst(key, store, establish) {
|
|
|
30160
30516
|
() => establish(native, store)
|
|
30161
30517
|
);
|
|
30162
30518
|
return { store, native, db };
|
|
30519
|
+
} catch (error48) {
|
|
30520
|
+
throw explainSchemaWriteDenial(native, error48);
|
|
30163
30521
|
} finally {
|
|
30164
30522
|
membership.active = false;
|
|
30165
30523
|
}
|
|
@@ -30209,7 +30567,7 @@ async function bindLive(scope, key, dbPath, openStore, establish) {
|
|
|
30209
30567
|
);
|
|
30210
30568
|
}
|
|
30211
30569
|
async function bindProjectDomain(domain2, cwd, establish) {
|
|
30212
|
-
const dbPath =
|
|
30570
|
+
const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
|
|
30213
30571
|
const row = await bindLive(
|
|
30214
30572
|
"project",
|
|
30215
30573
|
bindingKey("project", dbPath, domain2),
|
|
@@ -30220,7 +30578,7 @@ async function bindProjectDomain(domain2, cwd, establish) {
|
|
|
30220
30578
|
return row;
|
|
30221
30579
|
}
|
|
30222
30580
|
async function bindGlobalDomain(domain2, establish, cwd) {
|
|
30223
|
-
const dbPath =
|
|
30581
|
+
const dbPath = resolve8(resolveDualScopeDbPath("global"));
|
|
30224
30582
|
const row = await bindLive(
|
|
30225
30583
|
"global",
|
|
30226
30584
|
bindingKey("global", dbPath, domain2),
|
|
@@ -30231,7 +30589,7 @@ async function bindGlobalDomain(domain2, establish, cwd) {
|
|
|
30231
30589
|
return row;
|
|
30232
30590
|
}
|
|
30233
30591
|
async function bindGlobalDomainAtPath(domain2, dbPath, establish) {
|
|
30234
|
-
const normalized =
|
|
30592
|
+
const normalized = resolve8(dbPath);
|
|
30235
30593
|
const row = await bindLive(
|
|
30236
30594
|
"global",
|
|
30237
30595
|
bindingKey("global", normalized, domain2),
|
|
@@ -30242,7 +30600,7 @@ async function bindGlobalDomainAtPath(domain2, dbPath, establish) {
|
|
|
30242
30600
|
return row;
|
|
30243
30601
|
}
|
|
30244
30602
|
function peekDomainAtPath(scope, dbPath, domain2) {
|
|
30245
|
-
const row = _bindings.get(bindingKey(scope,
|
|
30603
|
+
const row = _bindings.get(bindingKey(scope, resolve8(dbPath), domain2));
|
|
30246
30604
|
if (!row?.native.isOpen) return null;
|
|
30247
30605
|
return row;
|
|
30248
30606
|
}
|
|
@@ -30251,12 +30609,12 @@ function releaseDomainBindings(filter2) {
|
|
|
30251
30609
|
_bindings.clear();
|
|
30252
30610
|
return;
|
|
30253
30611
|
}
|
|
30254
|
-
const wantPath = filter2.dbPath === void 0 ? void 0 :
|
|
30612
|
+
const wantPath = filter2.dbPath === void 0 ? void 0 : resolve8(filter2.dbPath);
|
|
30255
30613
|
for (const key of [..._bindings.keys()]) {
|
|
30256
|
-
const
|
|
30614
|
+
const sep6 = key.indexOf("::");
|
|
30257
30615
|
const lastSep = key.lastIndexOf("::");
|
|
30258
|
-
const scope = key.slice(0,
|
|
30259
|
-
const dbPath = key.slice(
|
|
30616
|
+
const scope = key.slice(0, sep6);
|
|
30617
|
+
const dbPath = key.slice(sep6 + 2, lastSep);
|
|
30260
30618
|
const domain2 = key.slice(lastSep + 2);
|
|
30261
30619
|
if (filter2.scope !== void 0 && scope !== filter2.scope) continue;
|
|
30262
30620
|
if (wantPath !== void 0 && dbPath !== wantPath) continue;
|
|
@@ -30271,7 +30629,7 @@ function boundProjectNative(domain2, cwd) {
|
|
|
30271
30629
|
return peekProjectDomain(domain2, cwd)?.native ?? null;
|
|
30272
30630
|
}
|
|
30273
30631
|
function peekProjectDomain(domain2, cwd) {
|
|
30274
|
-
const dbPath =
|
|
30632
|
+
const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
|
|
30275
30633
|
const row = _bindings.get(bindingKey("project", dbPath, domain2));
|
|
30276
30634
|
if (row?.native.isOpen) return row;
|
|
30277
30635
|
if (cwd !== void 0) return null;
|
|
@@ -30286,7 +30644,7 @@ function peekProjectDomain(domain2, cwd) {
|
|
|
30286
30644
|
return sole ?? null;
|
|
30287
30645
|
}
|
|
30288
30646
|
function peekGlobalDomain(domain2) {
|
|
30289
|
-
const dbPath =
|
|
30647
|
+
const dbPath = resolve8(resolveDualScopeDbPath("global"));
|
|
30290
30648
|
const row = _bindings.get(bindingKey("global", dbPath, domain2));
|
|
30291
30649
|
if (!row || !row.native.isOpen) return null;
|
|
30292
30650
|
return row;
|
|
@@ -30297,6 +30655,7 @@ var init_domain_binding = __esm({
|
|
|
30297
30655
|
"use strict";
|
|
30298
30656
|
init_project_scope();
|
|
30299
30657
|
init_dual_scope_db();
|
|
30658
|
+
init_worktree_build_guard();
|
|
30300
30659
|
_runtime = null;
|
|
30301
30660
|
_bindings = /* @__PURE__ */ new Map();
|
|
30302
30661
|
_inflight = /* @__PURE__ */ new Map();
|
|
@@ -30307,9 +30666,9 @@ var init_domain_binding = __esm({
|
|
|
30307
30666
|
|
|
30308
30667
|
// packages/core/src/telemetry/sqlite.ts
|
|
30309
30668
|
import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
30310
|
-
import { dirname as
|
|
30669
|
+
import { dirname as dirname14, join as join19 } from "node:path";
|
|
30311
30670
|
function getTelemetryDbPath() {
|
|
30312
|
-
return
|
|
30671
|
+
return join19(getCleoHome(), DB_FILENAME);
|
|
30313
30672
|
}
|
|
30314
30673
|
function resolveTelemetryMigrationsFolder() {
|
|
30315
30674
|
return resolveCorePackageMigrationsFolder("drizzle-telemetry");
|
|
@@ -30357,8 +30716,9 @@ async function getTelemetryDb() {
|
|
|
30357
30716
|
_initPromise = (async () => {
|
|
30358
30717
|
const dbPath = requestedPath;
|
|
30359
30718
|
_dbPath = dbPath;
|
|
30360
|
-
mkdirSync4(
|
|
30719
|
+
mkdirSync4(dirname14(dbPath), { recursive: true });
|
|
30361
30720
|
const nativeDb = openNativeDatabase(dbPath);
|
|
30721
|
+
installSchemaWriteGuard(nativeDb);
|
|
30362
30722
|
_nativeDb = nativeDb;
|
|
30363
30723
|
const db = drizzle({ client: nativeDb });
|
|
30364
30724
|
runTelemetryMigrations(nativeDb, db);
|
|
@@ -30379,6 +30739,7 @@ var init_sqlite2 = __esm({
|
|
|
30379
30739
|
init_migration_manager();
|
|
30380
30740
|
init_resolve_migrations_folder();
|
|
30381
30741
|
init_sqlite3();
|
|
30742
|
+
init_worktree_build_guard();
|
|
30382
30743
|
DB_FILENAME = "telemetry.db";
|
|
30383
30744
|
TELEMETRY_SCHEMA_VERSION = "1.0.0";
|
|
30384
30745
|
_db = null;
|
|
@@ -30389,11 +30750,11 @@ var init_sqlite2 = __esm({
|
|
|
30389
30750
|
});
|
|
30390
30751
|
|
|
30391
30752
|
// packages/core/src/store/agent-registry-store.ts
|
|
30392
|
-
import { existsSync as
|
|
30393
|
-
import { join as
|
|
30753
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
30754
|
+
import { join as join20 } from "node:path";
|
|
30394
30755
|
function getGlobalAgentRegistryDbPath() {
|
|
30395
30756
|
const cleoHome = getCleoHome();
|
|
30396
|
-
const dbPath =
|
|
30757
|
+
const dbPath = join20(cleoHome, "cleo.db");
|
|
30397
30758
|
if (!dbPath.startsWith(cleoHome)) {
|
|
30398
30759
|
throw new Error(
|
|
30399
30760
|
`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.`
|
|
@@ -30460,7 +30821,7 @@ function establishAgentRegistrySchema(native) {
|
|
|
30460
30821
|
}
|
|
30461
30822
|
async function ensureGlobalAgentRegistryDb() {
|
|
30462
30823
|
const dbPath = getGlobalAgentRegistryDbPath();
|
|
30463
|
-
const alreadyExists =
|
|
30824
|
+
const alreadyExists = existsSync15(dbPath);
|
|
30464
30825
|
let created = false;
|
|
30465
30826
|
const { native: nativeDb } = await bindGlobalDomainAtPath(
|
|
30466
30827
|
AGENT_REGISTRY_DOMAIN,
|
|
@@ -30505,8 +30866,8 @@ var init_agent_registry_store = __esm({
|
|
|
30505
30866
|
});
|
|
30506
30867
|
|
|
30507
30868
|
// packages/core/src/store/conduit-sqlite.ts
|
|
30508
|
-
import { existsSync as
|
|
30509
|
-
import { createRequire as
|
|
30869
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
30870
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
30510
30871
|
function _getDrizzle() {
|
|
30511
30872
|
if (_drizzle === null) {
|
|
30512
30873
|
const mod = _require3("drizzle-orm/node-sqlite");
|
|
@@ -30534,7 +30895,7 @@ function runConduitMigrations(nativeDb) {
|
|
|
30534
30895
|
}
|
|
30535
30896
|
async function ensureConduitDb(projectRoot) {
|
|
30536
30897
|
const dbPath = getConduitDbPath(projectRoot);
|
|
30537
|
-
const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null ||
|
|
30898
|
+
const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync16(dbPath);
|
|
30538
30899
|
await bindConduitDomain(projectRoot);
|
|
30539
30900
|
return { action: alreadyExists ? "exists" : "created", path: dbPath };
|
|
30540
30901
|
}
|
|
@@ -30560,7 +30921,8 @@ var init_conduit_sqlite = __esm({
|
|
|
30560
30921
|
init_domain_binding();
|
|
30561
30922
|
init_resolve_migrations_folder();
|
|
30562
30923
|
init_sqlite_pragmas();
|
|
30563
|
-
|
|
30924
|
+
init_worktree_build_guard();
|
|
30925
|
+
_require3 = createRequire6(import.meta.url);
|
|
30564
30926
|
({ DatabaseSync: DatabaseSync2 } = _require3("node:sqlite"));
|
|
30565
30927
|
_drizzle = null;
|
|
30566
30928
|
CONDUIT_SCHEMA_VERSION = "2026.4.23";
|
|
@@ -32434,216 +32796,6 @@ var init_memory_schema = __esm({
|
|
|
32434
32796
|
}
|
|
32435
32797
|
});
|
|
32436
32798
|
|
|
32437
|
-
// packages/core/src/store/snapshot-gate.ts
|
|
32438
|
-
import { join as join20 } from "node:path";
|
|
32439
|
-
function readGateState(db) {
|
|
32440
|
-
const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
|
|
32441
|
-
const state = { generation: 0, prefixes: {} };
|
|
32442
|
-
if (!row) return state;
|
|
32443
|
-
try {
|
|
32444
|
-
const parsed = JSON.parse(row.value);
|
|
32445
|
-
if (parsed === null || typeof parsed !== "object") return state;
|
|
32446
|
-
if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
|
|
32447
|
-
state.generation = parsed.generation;
|
|
32448
|
-
}
|
|
32449
|
-
for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
|
|
32450
|
-
if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
|
|
32451
|
-
state.prefixes[prefix] = {
|
|
32452
|
-
generation: e.generation,
|
|
32453
|
-
startedAt: e.startedAt,
|
|
32454
|
-
completedAt: e.completedAt
|
|
32455
|
-
};
|
|
32456
|
-
}
|
|
32457
|
-
}
|
|
32458
|
-
} catch {
|
|
32459
|
-
}
|
|
32460
|
-
return state;
|
|
32461
|
-
}
|
|
32462
|
-
function writeGateState(db, state) {
|
|
32463
|
-
db.prepare(
|
|
32464
|
-
"INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
32465
|
-
).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
|
|
32466
|
-
}
|
|
32467
|
-
function tryReadGateState(db) {
|
|
32468
|
-
if (!db) return null;
|
|
32469
|
-
try {
|
|
32470
|
-
return readGateState(db);
|
|
32471
|
-
} catch {
|
|
32472
|
-
return null;
|
|
32473
|
-
}
|
|
32474
|
-
}
|
|
32475
|
-
function needsSnapshot(entry, mode, nowMs, seenGeneration) {
|
|
32476
|
-
if (!entry) return true;
|
|
32477
|
-
if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
|
|
32478
|
-
const elapsed = nowMs - entry.startedAt;
|
|
32479
|
-
return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
|
|
32480
|
-
}
|
|
32481
|
-
async function runGatedSnapshot(opts, snapshot) {
|
|
32482
|
-
const now = opts.now ?? Date.now;
|
|
32483
|
-
const mode = opts.mode ?? "routine";
|
|
32484
|
-
const db = opts.stateDb;
|
|
32485
|
-
const none = (skipped, error48) => ({
|
|
32486
|
-
snapshotted: [],
|
|
32487
|
-
linked: [],
|
|
32488
|
-
absent: [],
|
|
32489
|
-
failed: [],
|
|
32490
|
-
skipped,
|
|
32491
|
-
...error48 !== void 0 && { error: error48 }
|
|
32492
|
-
});
|
|
32493
|
-
const entryState = tryReadGateState(db);
|
|
32494
|
-
const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
|
|
32495
|
-
if (mode === "routine") {
|
|
32496
|
-
if (!entryState) return none("state-unavailable");
|
|
32497
|
-
const nowMs = now();
|
|
32498
|
-
if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
|
|
32499
|
-
return none("debounced");
|
|
32500
|
-
}
|
|
32501
|
-
}
|
|
32502
|
-
const lockPath2 = join20(opts.backupDir, GATE_LOCK_BASENAME);
|
|
32503
|
-
let release;
|
|
32504
|
-
try {
|
|
32505
|
-
release = await acquireLock(lockPath2, {
|
|
32506
|
-
retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
|
|
32507
|
-
stale: SNAPSHOT_LOCK_STALE_MS,
|
|
32508
|
-
// A compromised lock (e.g. the backup dir was removed) must not throw
|
|
32509
|
-
// from a timer and crash the host process.
|
|
32510
|
-
onCompromised: () => {
|
|
32511
|
-
}
|
|
32512
|
-
});
|
|
32513
|
-
} catch {
|
|
32514
|
-
if (mode === "routine") return none("in-flight");
|
|
32515
|
-
return none(
|
|
32516
|
-
"lock-timeout",
|
|
32517
|
-
`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.`
|
|
32518
|
-
);
|
|
32519
|
-
}
|
|
32520
|
-
try {
|
|
32521
|
-
try {
|
|
32522
|
-
opts.onLockAcquired?.();
|
|
32523
|
-
} catch {
|
|
32524
|
-
}
|
|
32525
|
-
const state = tryReadGateState(db);
|
|
32526
|
-
if (!state && mode === "routine") return none("state-unavailable");
|
|
32527
|
-
const startMs = now();
|
|
32528
|
-
const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
|
|
32529
|
-
(p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
|
|
32530
|
-
);
|
|
32531
|
-
if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
|
|
32532
|
-
const generation = (state?.generation ?? 0) + 1;
|
|
32533
|
-
let claimed = false;
|
|
32534
|
-
if (db && state) {
|
|
32535
|
-
try {
|
|
32536
|
-
writeGateState(db, { ...state, generation });
|
|
32537
|
-
claimed = true;
|
|
32538
|
-
} catch {
|
|
32539
|
-
}
|
|
32540
|
-
}
|
|
32541
|
-
const snapshotted = [];
|
|
32542
|
-
const linked = [];
|
|
32543
|
-
const absent = [];
|
|
32544
|
-
const failed = [];
|
|
32545
|
-
for (const prefix of admitted) {
|
|
32546
|
-
try {
|
|
32547
|
-
const outcome = await snapshot(prefix);
|
|
32548
|
-
if (outcome === "absent") absent.push(prefix);
|
|
32549
|
-
else {
|
|
32550
|
-
snapshotted.push(prefix);
|
|
32551
|
-
if (outcome === "linked") linked.push(prefix);
|
|
32552
|
-
}
|
|
32553
|
-
} catch {
|
|
32554
|
-
failed.push(prefix);
|
|
32555
|
-
}
|
|
32556
|
-
}
|
|
32557
|
-
const satisfied = [...snapshotted, ...absent];
|
|
32558
|
-
if (db && claimed && satisfied.length > 0) {
|
|
32559
|
-
try {
|
|
32560
|
-
const latest = readGateState(db);
|
|
32561
|
-
const completedAt = now();
|
|
32562
|
-
latest.generation = Math.max(latest.generation, generation);
|
|
32563
|
-
for (const p of satisfied) {
|
|
32564
|
-
latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
|
|
32565
|
-
}
|
|
32566
|
-
writeGateState(db, latest);
|
|
32567
|
-
} catch {
|
|
32568
|
-
}
|
|
32569
|
-
}
|
|
32570
|
-
return { snapshotted, linked, absent, failed, skipped: null };
|
|
32571
|
-
} finally {
|
|
32572
|
-
await release().catch(() => {
|
|
32573
|
-
});
|
|
32574
|
-
}
|
|
32575
|
-
}
|
|
32576
|
-
function isValidStamp(ymd, hms) {
|
|
32577
|
-
const y = Number(ymd.slice(0, 4));
|
|
32578
|
-
const mo = Number(ymd.slice(4, 6));
|
|
32579
|
-
const d = Number(ymd.slice(6, 8));
|
|
32580
|
-
const h = Number(hms.slice(0, 2));
|
|
32581
|
-
const mi = Number(hms.slice(2, 4));
|
|
32582
|
-
const se = Number(hms.slice(4, 6));
|
|
32583
|
-
if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
|
|
32584
|
-
const probe = new Date(Date.UTC(y, mo - 1, d));
|
|
32585
|
-
return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
|
|
32586
|
-
}
|
|
32587
|
-
function selectSnapshotsToKeep(names, ctx = {}) {
|
|
32588
|
-
const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
|
|
32589
|
-
const keep = /* @__PURE__ */ new Set();
|
|
32590
|
-
const stamped = [];
|
|
32591
|
-
for (const name15 of names) {
|
|
32592
|
-
const m = STAMP_PATTERN.exec(name15);
|
|
32593
|
-
const ymd = m?.[1];
|
|
32594
|
-
const hms = m?.[2];
|
|
32595
|
-
if (!ymd || !hms || !isValidStamp(ymd, hms)) {
|
|
32596
|
-
keep.add(name15);
|
|
32597
|
-
continue;
|
|
32598
|
-
}
|
|
32599
|
-
const stamp = `${ymd}-${hms}`;
|
|
32600
|
-
if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
|
|
32601
|
-
keep.add(name15);
|
|
32602
|
-
continue;
|
|
32603
|
-
}
|
|
32604
|
-
stamped.push({ name: name15, stamp });
|
|
32605
|
-
}
|
|
32606
|
-
if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
|
|
32607
|
-
stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
|
|
32608
|
-
for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
|
|
32609
|
-
const keepNewestPerBucket = (bucketOf, slots) => {
|
|
32610
|
-
const seen = /* @__PURE__ */ new Set();
|
|
32611
|
-
for (const s of stamped) {
|
|
32612
|
-
const bucket = bucketOf(s.stamp);
|
|
32613
|
-
if (seen.has(bucket)) continue;
|
|
32614
|
-
if (seen.size >= slots) break;
|
|
32615
|
-
seen.add(bucket);
|
|
32616
|
-
keep.add(s.name);
|
|
32617
|
-
}
|
|
32618
|
-
};
|
|
32619
|
-
keepNewestPerBucket(
|
|
32620
|
-
(stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
|
|
32621
|
-
policy.quarterHourly
|
|
32622
|
-
);
|
|
32623
|
-
keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
|
|
32624
|
-
keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
|
|
32625
|
-
return keep;
|
|
32626
|
-
}
|
|
32627
|
-
var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
|
|
32628
|
-
var init_snapshot_gate = __esm({
|
|
32629
|
-
"packages/core/src/store/snapshot-gate.ts"() {
|
|
32630
|
-
"use strict";
|
|
32631
|
-
init_lock();
|
|
32632
|
-
SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
|
|
32633
|
-
SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
|
|
32634
|
-
SNAPSHOT_LOCK_WAIT_RETRIES = 90;
|
|
32635
|
-
SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
|
|
32636
|
-
GATE_LOCK_BASENAME = ".snapshot-gate";
|
|
32637
|
-
DEFAULT_SNAPSHOT_RETENTION = {
|
|
32638
|
-
latest: 1,
|
|
32639
|
-
quarterHourly: 3,
|
|
32640
|
-
hourly: 3,
|
|
32641
|
-
daily: 3
|
|
32642
|
-
};
|
|
32643
|
-
STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
|
|
32644
|
-
}
|
|
32645
|
-
});
|
|
32646
|
-
|
|
32647
32799
|
// packages/core/src/store/twin-collapse.ts
|
|
32648
32800
|
import { createHash as createHash3 } from "node:crypto";
|
|
32649
32801
|
function hasMainTable(db, name15) {
|
|
@@ -32720,6 +32872,22 @@ function mergeSchemaMetaValue(key, bare, twin) {
|
|
|
32720
32872
|
const field = SCHEMA_META_COUNTER_FIELDS[key];
|
|
32721
32873
|
return field === void 0 ? bare : withMaxCounter(bare, twin, field);
|
|
32722
32874
|
}
|
|
32875
|
+
function mirrorCounterToBare(db, key) {
|
|
32876
|
+
if (SCHEMA_META_COUNTER_FIELDS[key] === void 0) return;
|
|
32877
|
+
if (!hasMainTable(db, "schema_meta")) return;
|
|
32878
|
+
const twin = readKv(db, "tasks_schema_meta", key);
|
|
32879
|
+
if (twin === void 0) return;
|
|
32880
|
+
const bare = readKv(db, "schema_meta", key);
|
|
32881
|
+
const next = bare === void 0 ? twin : mergeSchemaMetaValue(key, bare, twin);
|
|
32882
|
+
if (next === null || next === bare) return;
|
|
32883
|
+
writeKv(db, "schema_meta", key, next);
|
|
32884
|
+
}
|
|
32885
|
+
function bareCounterOf(db, key) {
|
|
32886
|
+
const name15 = SCHEMA_META_COUNTER_FIELDS[key];
|
|
32887
|
+
if (name15 === void 0 || !hasMainTable(db, "schema_meta")) return 0;
|
|
32888
|
+
const bare = readKv(db, "schema_meta", key);
|
|
32889
|
+
return (bare === void 0 ? void 0 : counterOf(bare, name15)) ?? 0;
|
|
32890
|
+
}
|
|
32723
32891
|
function kvRows(db, table, schema = "main") {
|
|
32724
32892
|
const rows = db.prepare(`SELECT key, value FROM ${schema}.${table}`).all();
|
|
32725
32893
|
return new Map(rows.map((r) => [r.key, r.value]));
|
|
@@ -32852,6 +33020,39 @@ function applyStickyRows(db, schema, plan) {
|
|
|
32852
33020
|
}
|
|
32853
33021
|
return { inserted, replaced: 0, deleted };
|
|
32854
33022
|
}
|
|
33023
|
+
function tagsOf(tagsJson) {
|
|
33024
|
+
if (!tagsJson) return [];
|
|
33025
|
+
try {
|
|
33026
|
+
const parsed = JSON.parse(tagsJson);
|
|
33027
|
+
if (!Array.isArray(parsed)) return [];
|
|
33028
|
+
return [...new Set(parsed.filter((t) => typeof t === "string" && t.length > 0))];
|
|
33029
|
+
} catch {
|
|
33030
|
+
return [];
|
|
33031
|
+
}
|
|
33032
|
+
}
|
|
33033
|
+
function syncStickyJunction(db, schema) {
|
|
33034
|
+
const notes = db.prepare("SELECT id, tags_json FROM main.brain_sticky_notes").all();
|
|
33035
|
+
const have = /* @__PURE__ */ new Map();
|
|
33036
|
+
for (const r of db.prepare(`SELECT sticky_id, tag FROM ${schema}.brain_sticky_tags`).all()) {
|
|
33037
|
+
const set2 = have.get(r.sticky_id) ?? /* @__PURE__ */ new Set();
|
|
33038
|
+
set2.add(r.tag);
|
|
33039
|
+
have.set(r.sticky_id, set2);
|
|
33040
|
+
}
|
|
33041
|
+
const insert = db.prepare(
|
|
33042
|
+
`INSERT OR IGNORE INTO ${schema}.brain_sticky_tags (sticky_id, tag) VALUES (?, ?)`
|
|
33043
|
+
);
|
|
33044
|
+
const del = db.prepare(`DELETE FROM ${schema}.brain_sticky_tags WHERE sticky_id = ? AND tag = ?`);
|
|
33045
|
+
let inserted = 0;
|
|
33046
|
+
let deleted = 0;
|
|
33047
|
+
for (const note of notes) {
|
|
33048
|
+
const want = new Set(tagsOf(note.tags_json));
|
|
33049
|
+
const current = have.get(note.id) ?? /* @__PURE__ */ new Set();
|
|
33050
|
+
for (const tag of want)
|
|
33051
|
+
if (!current.has(tag)) inserted += Number(insert.run(note.id, tag).changes);
|
|
33052
|
+
for (const tag of current) if (!want.has(tag)) deleted += Number(del.run(note.id, tag).changes);
|
|
33053
|
+
}
|
|
33054
|
+
return { inserted, deleted };
|
|
33055
|
+
}
|
|
32855
33056
|
function twinCollapseFailureOf(db) {
|
|
32856
33057
|
return degraded.get(db);
|
|
32857
33058
|
}
|
|
@@ -33061,7 +33262,7 @@ function collapseTwinTables(nativeDb, dbPath, options = {}) {
|
|
|
33061
33262
|
}
|
|
33062
33263
|
return inOrder();
|
|
33063
33264
|
}
|
|
33064
|
-
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;
|
|
33265
|
+
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;
|
|
33065
33266
|
var init_twin_collapse = __esm({
|
|
33066
33267
|
"packages/core/src/store/twin-collapse.ts"() {
|
|
33067
33268
|
"use strict";
|
|
@@ -33069,18 +33270,18 @@ var init_twin_collapse = __esm({
|
|
|
33069
33270
|
init_errors2();
|
|
33070
33271
|
init_logger2();
|
|
33071
33272
|
init_pre_repair_snapshot();
|
|
33072
|
-
init_snapshot_gate();
|
|
33073
33273
|
log6 = getLogger("twin-collapse");
|
|
33074
33274
|
TWIN_COLLAPSE_MARKER_PREFIX = "twin_collapse:";
|
|
33075
33275
|
TWIN_COLLAPSE_FAILURE_PREFIX = "twin_collapse_failed:";
|
|
33276
|
+
SNAPSHOT_GATE_KEY = "sqlite_snapshot_gate";
|
|
33076
33277
|
SCHEMA_META_COUNTER_FIELDS = {
|
|
33077
33278
|
task_id_sequence: "counter",
|
|
33078
|
-
[
|
|
33279
|
+
[SNAPSHOT_GATE_KEY]: "generation",
|
|
33079
33280
|
file_meta: "generation"
|
|
33080
33281
|
};
|
|
33081
33282
|
SCHEMA_META_NEVER_DELETED = /* @__PURE__ */ new Set([
|
|
33082
33283
|
"task_id_sequence",
|
|
33083
|
-
|
|
33284
|
+
SNAPSHOT_GATE_KEY
|
|
33084
33285
|
]);
|
|
33085
33286
|
MAX_CONFLICTS = 50;
|
|
33086
33287
|
sha = (value) => createHash3("sha256").update(value).digest("hex");
|
|
@@ -33145,7 +33346,12 @@ var init_twin_collapse = __esm({
|
|
|
33145
33346
|
throw new Error(
|
|
33146
33347
|
`sticky_tags collapse did not verify: ${missing} missing, ${lingering} not removed`
|
|
33147
33348
|
);
|
|
33148
|
-
|
|
33349
|
+
const synced = syncStickyJunction(db, "main");
|
|
33350
|
+
return {
|
|
33351
|
+
inserted: counts.inserted + synced.inserted,
|
|
33352
|
+
replaced: 0,
|
|
33353
|
+
deleted: counts.deleted + synced.deleted
|
|
33354
|
+
};
|
|
33149
33355
|
},
|
|
33150
33356
|
shadow(db, plan) {
|
|
33151
33357
|
db.exec(
|
|
@@ -33156,6 +33362,7 @@ var init_twin_collapse = __esm({
|
|
|
33156
33362
|
"INSERT INTO temp.brain_sticky_tags (sticky_id, tag) SELECT sticky_id, tag FROM main.brain_sticky_tags"
|
|
33157
33363
|
);
|
|
33158
33364
|
applyStickyRows(db, "temp", plan);
|
|
33365
|
+
syncStickyJunction(db, "temp");
|
|
33159
33366
|
}
|
|
33160
33367
|
};
|
|
33161
33368
|
PAIRS = [SCHEMA_META, STICKY_TAGS];
|
|
@@ -33187,7 +33394,7 @@ __export(config_exports, {
|
|
|
33187
33394
|
parseConfigValue: () => parseConfigValue,
|
|
33188
33395
|
setConfigValue: () => setConfigValue
|
|
33189
33396
|
});
|
|
33190
|
-
import { existsSync as
|
|
33397
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
33191
33398
|
function getNestedValue(obj, path) {
|
|
33192
33399
|
const parts = path.split(".");
|
|
33193
33400
|
let current = obj;
|
|
@@ -33309,7 +33516,7 @@ function parseConfigValue(value) {
|
|
|
33309
33516
|
}
|
|
33310
33517
|
async function setConfigValue(key, value, cwd, opts) {
|
|
33311
33518
|
const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
|
|
33312
|
-
if (!
|
|
33519
|
+
if (!existsSync17(configPath)) {
|
|
33313
33520
|
await atomicWriteJson(configPath, {});
|
|
33314
33521
|
}
|
|
33315
33522
|
const config2 = await readJson(configPath) ?? {};
|
|
@@ -33321,7 +33528,7 @@ async function setConfigValue(key, value, cwd, opts) {
|
|
|
33321
33528
|
async function applyStrictnessPreset(preset, cwd, opts) {
|
|
33322
33529
|
const definition = STRICTNESS_PRESETS[preset];
|
|
33323
33530
|
const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
|
|
33324
|
-
if (!
|
|
33531
|
+
if (!existsSync17(configPath)) {
|
|
33325
33532
|
await atomicWriteJson(configPath, {});
|
|
33326
33533
|
}
|
|
33327
33534
|
const config2 = await readJson(configPath) ?? {};
|
|
@@ -33898,6 +34105,7 @@ var init_cross_db_cleanup = __esm({
|
|
|
33898
34105
|
"use strict";
|
|
33899
34106
|
init_memory_sqlite();
|
|
33900
34107
|
init_memory_schema();
|
|
34108
|
+
init_worktree_build_guard();
|
|
33901
34109
|
}
|
|
33902
34110
|
});
|
|
33903
34111
|
|
|
@@ -38590,7 +38798,7 @@ __export(sqlite_data_accessor_exports, {
|
|
|
38590
38798
|
setMetaValue: () => setMetaValue
|
|
38591
38799
|
});
|
|
38592
38800
|
import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
|
|
38593
|
-
import { resolve as
|
|
38801
|
+
import { resolve as resolve9 } from "node:path";
|
|
38594
38802
|
import {
|
|
38595
38803
|
and as and5,
|
|
38596
38804
|
eq as eq6,
|
|
@@ -38630,9 +38838,12 @@ async function writeMetaValue(cwd, key, value) {
|
|
|
38630
38838
|
target: tasksSchemaMeta.key,
|
|
38631
38839
|
set: { value: json2 }
|
|
38632
38840
|
}).run();
|
|
38841
|
+
const native = getNativeTasksDb(cwd);
|
|
38842
|
+
if (native) mirrorCounterToBare(native, key);
|
|
38633
38843
|
}
|
|
38634
38844
|
function advanceTaskIdSequence(nativeDb, floor) {
|
|
38635
38845
|
assertTwinCollapseWritable(nativeDb);
|
|
38846
|
+
const lowest = Math.max(floor, bareCounterOf(nativeDb, "task_id_sequence"));
|
|
38636
38847
|
nativeDb.prepare(`
|
|
38637
38848
|
UPDATE tasks_schema_meta
|
|
38638
38849
|
SET value = json_set(value,
|
|
@@ -38641,7 +38852,8 @@ function advanceTaskIdSequence(nativeDb, floor) {
|
|
|
38641
38852
|
'$.checksum', 'alloc-' || strftime('%s','now')
|
|
38642
38853
|
)
|
|
38643
38854
|
WHERE key = 'task_id_sequence'
|
|
38644
|
-
`).run(
|
|
38855
|
+
`).run(lowest, lowest);
|
|
38856
|
+
mirrorCounterToBare(nativeDb, "task_id_sequence");
|
|
38645
38857
|
const row = nativeDb.prepare(`
|
|
38646
38858
|
SELECT json_extract(value, '$.counter') AS counter
|
|
38647
38859
|
FROM tasks_schema_meta WHERE key = 'task_id_sequence'
|
|
@@ -38695,7 +38907,7 @@ function bindTaskAccessorScope(accessor, scope) {
|
|
|
38695
38907
|
}
|
|
38696
38908
|
async function createSqliteDataAccessor(cwd) {
|
|
38697
38909
|
const scope = captureProjectScope(
|
|
38698
|
-
|
|
38910
|
+
resolve9(cwd ?? getProjectRoot()),
|
|
38699
38911
|
worktreeScope.getStore()
|
|
38700
38912
|
);
|
|
38701
38913
|
return worktreeScope.run(
|
|
@@ -38810,7 +39022,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38810
39022
|
actor: entry.actor ?? "system",
|
|
38811
39023
|
detailsJson: entry.details ? JSON.stringify(entry.details) : "{}",
|
|
38812
39024
|
beforeJson: entry.before ? JSON.stringify(entry.before) : null,
|
|
38813
|
-
afterJson: entry.after ? JSON.stringify(entry.after) : null
|
|
39025
|
+
afterJson: entry.after ? JSON.stringify(entry.after) : null,
|
|
39026
|
+
// T12693: the session a ranking change ran in.
|
|
39027
|
+
sessionId: typeof entry.sessionId === "string" ? entry.sessionId : null
|
|
38814
39028
|
}).run()
|
|
38815
39029
|
);
|
|
38816
39030
|
});
|
|
@@ -38818,6 +39032,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38818
39032
|
async queryAuditLog(query) {
|
|
38819
39033
|
const db = await getDb(cwd);
|
|
38820
39034
|
const conditions = [];
|
|
39035
|
+
if (query.ids && query.ids.length > 0) {
|
|
39036
|
+
conditions.push(inArray4(tasksAuditLog.id, [...query.ids]));
|
|
39037
|
+
}
|
|
38821
39038
|
if (query.taskIds && query.taskIds.length > 0) {
|
|
38822
39039
|
conditions.push(inArray4(tasksAuditLog.taskId, [...query.taskIds]));
|
|
38823
39040
|
}
|
|
@@ -38836,7 +39053,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38836
39053
|
actor: tasksAuditLog.actor,
|
|
38837
39054
|
detailsJson: tasksAuditLog.detailsJson,
|
|
38838
39055
|
beforeJson: tasksAuditLog.beforeJson,
|
|
38839
|
-
afterJson: tasksAuditLog.afterJson
|
|
39056
|
+
afterJson: tasksAuditLog.afterJson,
|
|
39057
|
+
sessionId: tasksAuditLog.sessionId
|
|
38840
39058
|
}).from(tasksAuditLog).where(conditions.length > 0 ? and5(...conditions) : void 0).orderBy(sql26`${tasksAuditLog.timestamp} DESC`).limit(limit).all();
|
|
38841
39059
|
return rows.map((row) => ({
|
|
38842
39060
|
id: row.id,
|
|
@@ -38846,7 +39064,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
38846
39064
|
actor: row.actor,
|
|
38847
39065
|
detailsJson: row.detailsJson ?? null,
|
|
38848
39066
|
beforeJson: row.beforeJson ?? null,
|
|
38849
|
-
afterJson: row.afterJson ?? null
|
|
39067
|
+
afterJson: row.afterJson ?? null,
|
|
39068
|
+
sessionId: row.sessionId ?? null
|
|
38850
39069
|
}));
|
|
38851
39070
|
},
|
|
38852
39071
|
// ---- Fine-grained task operations (T5034) ----
|
|
@@ -39684,7 +39903,7 @@ var init_sqlite_data_accessor = __esm({
|
|
|
39684
39903
|
});
|
|
39685
39904
|
|
|
39686
39905
|
// packages/core/src/sequence/index.ts
|
|
39687
|
-
import { existsSync as
|
|
39906
|
+
import { existsSync as existsSync18, readFileSync as readFileSync6, renameSync as renameSync5 } from "node:fs";
|
|
39688
39907
|
import { join as join21 } from "node:path";
|
|
39689
39908
|
function getLegacySequenceJsonPath(cwd) {
|
|
39690
39909
|
return join21(resolveOrCwd(cwd), ".cleo", ".sequence.json");
|
|
@@ -39701,19 +39920,19 @@ function isSeedSequence(value) {
|
|
|
39701
39920
|
return value.counter === 0 && value.lastId === "T000" && value.checksum === "seed";
|
|
39702
39921
|
}
|
|
39703
39922
|
function readLegacySequenceFile(path) {
|
|
39704
|
-
if (!
|
|
39923
|
+
if (!existsSync18(path)) return null;
|
|
39705
39924
|
try {
|
|
39706
|
-
const parsed = JSON.parse(
|
|
39925
|
+
const parsed = JSON.parse(readFileSync6(path, "utf-8"));
|
|
39707
39926
|
return isValidSequenceState(parsed) ? parsed : null;
|
|
39708
39927
|
} catch {
|
|
39709
39928
|
return null;
|
|
39710
39929
|
}
|
|
39711
39930
|
}
|
|
39712
39931
|
function renameLegacyFile(path) {
|
|
39713
|
-
if (!
|
|
39932
|
+
if (!existsSync18(path)) return;
|
|
39714
39933
|
const migratedPath = `${path}.migrated`;
|
|
39715
39934
|
try {
|
|
39716
|
-
if (!
|
|
39935
|
+
if (!existsSync18(migratedPath)) {
|
|
39717
39936
|
renameSync5(path, migratedPath);
|
|
39718
39937
|
return;
|
|
39719
39938
|
}
|
|
@@ -39879,12 +40098,12 @@ var init_checkpoint_git_dir = __esm({
|
|
|
39879
40098
|
|
|
39880
40099
|
// packages/core/src/store/git-checkpoint.ts
|
|
39881
40100
|
import { execFile as execFile2 } from "node:child_process";
|
|
39882
|
-
import { existsSync as
|
|
40101
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
39883
40102
|
import { readFile as readFile4, writeFile } from "node:fs/promises";
|
|
39884
|
-
import { join as join23, resolve as
|
|
40103
|
+
import { join as join23, resolve as resolve10 } from "node:path";
|
|
39885
40104
|
import { promisify as promisify2 } from "node:util";
|
|
39886
40105
|
function makeCleoGitEnv(cleoDir) {
|
|
39887
|
-
const abs =
|
|
40106
|
+
const abs = resolve10(cleoDir);
|
|
39888
40107
|
return {
|
|
39889
40108
|
...process.env,
|
|
39890
40109
|
GIT_DIR: checkpointGitDir(abs),
|
|
@@ -39894,7 +40113,7 @@ function makeCleoGitEnv(cleoDir) {
|
|
|
39894
40113
|
async function cleoGitCommand(args, cleoDir) {
|
|
39895
40114
|
try {
|
|
39896
40115
|
const result = await execFileAsync2("git", args, {
|
|
39897
|
-
cwd:
|
|
40116
|
+
cwd: resolve10(cleoDir),
|
|
39898
40117
|
// absolute cwd so relative paths in args resolve correctly
|
|
39899
40118
|
env: makeCleoGitEnv(cleoDir),
|
|
39900
40119
|
timeout: 1e4
|
|
@@ -39905,7 +40124,7 @@ async function cleoGitCommand(args, cleoDir) {
|
|
|
39905
40124
|
}
|
|
39906
40125
|
}
|
|
39907
40126
|
function isCleoGitInitialized(cleoDir) {
|
|
39908
|
-
return
|
|
40127
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "HEAD"));
|
|
39909
40128
|
}
|
|
39910
40129
|
async function loadStateFileAllowlist(cwd) {
|
|
39911
40130
|
try {
|
|
@@ -39949,14 +40168,14 @@ async function isCleoGitRepo(cleoDir) {
|
|
|
39949
40168
|
return result.success && (result.stdout === "true" || isCleoGitInitialized(cleoDir));
|
|
39950
40169
|
}
|
|
39951
40170
|
function isMergeInProgress(cleoDir) {
|
|
39952
|
-
return
|
|
40171
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
|
|
39953
40172
|
}
|
|
39954
40173
|
async function isDetachedHead(cleoDir) {
|
|
39955
40174
|
const result = await cleoGitCommand(["symbolic-ref", "HEAD"], cleoDir);
|
|
39956
40175
|
return !result.success;
|
|
39957
40176
|
}
|
|
39958
40177
|
function isRebaseInProgress(cleoDir) {
|
|
39959
|
-
return
|
|
40178
|
+
return existsSync19(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync19(join23(checkpointGitDir(cleoDir), "rebase-apply"));
|
|
39960
40179
|
}
|
|
39961
40180
|
async function recordCheckpointTime(cleoDir) {
|
|
39962
40181
|
try {
|
|
@@ -39980,7 +40199,7 @@ async function getChangedStateFiles(cleoDir, cwd) {
|
|
|
39980
40199
|
const allStateFiles = await getAllStateFiles(cwd);
|
|
39981
40200
|
for (const stateFile of allStateFiles) {
|
|
39982
40201
|
const fullPath = join23(cleoDir, stateFile);
|
|
39983
|
-
if (!
|
|
40202
|
+
if (!existsSync19(fullPath)) continue;
|
|
39984
40203
|
const diffResult = await cleoGitCommand(["diff", "--quiet", "--", stateFile], cleoDir);
|
|
39985
40204
|
const cachedResult = await cleoGitCommand(
|
|
39986
40205
|
["diff", "--cached", "--quiet", "--", stateFile],
|
|
@@ -40007,7 +40226,7 @@ async function shouldCheckpoint(options) {
|
|
|
40007
40226
|
const config2 = await loadCheckpointConfig(cwd);
|
|
40008
40227
|
if (!config2.enabled) return false;
|
|
40009
40228
|
const cleoDir = getCleoDir(cwd);
|
|
40010
|
-
if (!
|
|
40229
|
+
if (!existsSync19(cleoDir)) return false;
|
|
40011
40230
|
if (!isCleoGitInitialized(cleoDir)) return false;
|
|
40012
40231
|
if (!await isCleoGitRepo(cleoDir)) return false;
|
|
40013
40232
|
if (isMergeInProgress(cleoDir)) return false;
|
|
@@ -40080,6 +40299,218 @@ var init_git_checkpoint = __esm({
|
|
|
40080
40299
|
}
|
|
40081
40300
|
});
|
|
40082
40301
|
|
|
40302
|
+
// packages/core/src/store/snapshot-gate.ts
|
|
40303
|
+
import { join as join24 } from "node:path";
|
|
40304
|
+
function readGateState(db) {
|
|
40305
|
+
const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
|
|
40306
|
+
const state = { generation: 0, prefixes: {} };
|
|
40307
|
+
if (!row) return state;
|
|
40308
|
+
try {
|
|
40309
|
+
const parsed = JSON.parse(row.value);
|
|
40310
|
+
if (parsed === null || typeof parsed !== "object") return state;
|
|
40311
|
+
if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
|
|
40312
|
+
state.generation = parsed.generation;
|
|
40313
|
+
}
|
|
40314
|
+
for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
|
|
40315
|
+
if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
|
|
40316
|
+
state.prefixes[prefix] = {
|
|
40317
|
+
generation: e.generation,
|
|
40318
|
+
startedAt: e.startedAt,
|
|
40319
|
+
completedAt: e.completedAt
|
|
40320
|
+
};
|
|
40321
|
+
}
|
|
40322
|
+
}
|
|
40323
|
+
} catch {
|
|
40324
|
+
}
|
|
40325
|
+
return state;
|
|
40326
|
+
}
|
|
40327
|
+
function writeGateState(db, state) {
|
|
40328
|
+
db.prepare(
|
|
40329
|
+
"INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
40330
|
+
).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
|
|
40331
|
+
mirrorCounterToBare(db, SNAPSHOT_GATE_META_KEY);
|
|
40332
|
+
}
|
|
40333
|
+
function tryReadGateState(db) {
|
|
40334
|
+
if (!db) return null;
|
|
40335
|
+
try {
|
|
40336
|
+
return readGateState(db);
|
|
40337
|
+
} catch {
|
|
40338
|
+
return null;
|
|
40339
|
+
}
|
|
40340
|
+
}
|
|
40341
|
+
function needsSnapshot(entry, mode, nowMs, seenGeneration) {
|
|
40342
|
+
if (!entry) return true;
|
|
40343
|
+
if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
|
|
40344
|
+
const elapsed = nowMs - entry.startedAt;
|
|
40345
|
+
return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
|
|
40346
|
+
}
|
|
40347
|
+
async function runGatedSnapshot(opts, snapshot) {
|
|
40348
|
+
const now = opts.now ?? Date.now;
|
|
40349
|
+
const mode = opts.mode ?? "routine";
|
|
40350
|
+
const db = opts.stateDb;
|
|
40351
|
+
const none = (skipped, error48) => ({
|
|
40352
|
+
snapshotted: [],
|
|
40353
|
+
linked: [],
|
|
40354
|
+
absent: [],
|
|
40355
|
+
failed: [],
|
|
40356
|
+
skipped,
|
|
40357
|
+
...error48 !== void 0 && { error: error48 }
|
|
40358
|
+
});
|
|
40359
|
+
const entryState = tryReadGateState(db);
|
|
40360
|
+
const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
|
|
40361
|
+
if (mode === "routine") {
|
|
40362
|
+
if (!entryState) return none("state-unavailable");
|
|
40363
|
+
const nowMs = now();
|
|
40364
|
+
if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
|
|
40365
|
+
return none("debounced");
|
|
40366
|
+
}
|
|
40367
|
+
}
|
|
40368
|
+
const lockPath2 = join24(opts.backupDir, GATE_LOCK_BASENAME);
|
|
40369
|
+
let release;
|
|
40370
|
+
try {
|
|
40371
|
+
release = await acquireLock(lockPath2, {
|
|
40372
|
+
retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
|
|
40373
|
+
stale: SNAPSHOT_LOCK_STALE_MS,
|
|
40374
|
+
// A compromised lock (e.g. the backup dir was removed) must not throw
|
|
40375
|
+
// from a timer and crash the host process.
|
|
40376
|
+
onCompromised: () => {
|
|
40377
|
+
}
|
|
40378
|
+
});
|
|
40379
|
+
} catch {
|
|
40380
|
+
if (mode === "routine") return none("in-flight");
|
|
40381
|
+
return none(
|
|
40382
|
+
"lock-timeout",
|
|
40383
|
+
`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.`
|
|
40384
|
+
);
|
|
40385
|
+
}
|
|
40386
|
+
try {
|
|
40387
|
+
try {
|
|
40388
|
+
opts.onLockAcquired?.();
|
|
40389
|
+
} catch {
|
|
40390
|
+
}
|
|
40391
|
+
const state = tryReadGateState(db);
|
|
40392
|
+
if (!state && mode === "routine") return none("state-unavailable");
|
|
40393
|
+
const startMs = now();
|
|
40394
|
+
const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
|
|
40395
|
+
(p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
|
|
40396
|
+
);
|
|
40397
|
+
if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
|
|
40398
|
+
const generation = (state?.generation ?? 0) + 1;
|
|
40399
|
+
let claimed = false;
|
|
40400
|
+
if (db && state) {
|
|
40401
|
+
try {
|
|
40402
|
+
writeGateState(db, { ...state, generation });
|
|
40403
|
+
claimed = true;
|
|
40404
|
+
} catch {
|
|
40405
|
+
}
|
|
40406
|
+
}
|
|
40407
|
+
const snapshotted = [];
|
|
40408
|
+
const linked = [];
|
|
40409
|
+
const absent = [];
|
|
40410
|
+
const failed = [];
|
|
40411
|
+
for (const prefix of admitted) {
|
|
40412
|
+
try {
|
|
40413
|
+
const outcome = await snapshot(prefix);
|
|
40414
|
+
if (outcome === "absent") absent.push(prefix);
|
|
40415
|
+
else {
|
|
40416
|
+
snapshotted.push(prefix);
|
|
40417
|
+
if (outcome === "linked") linked.push(prefix);
|
|
40418
|
+
}
|
|
40419
|
+
} catch {
|
|
40420
|
+
failed.push(prefix);
|
|
40421
|
+
}
|
|
40422
|
+
}
|
|
40423
|
+
const satisfied = [...snapshotted, ...absent];
|
|
40424
|
+
if (db && claimed && satisfied.length > 0) {
|
|
40425
|
+
try {
|
|
40426
|
+
const latest = readGateState(db);
|
|
40427
|
+
const completedAt = now();
|
|
40428
|
+
latest.generation = Math.max(latest.generation, generation);
|
|
40429
|
+
for (const p of satisfied) {
|
|
40430
|
+
latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
|
|
40431
|
+
}
|
|
40432
|
+
writeGateState(db, latest);
|
|
40433
|
+
} catch {
|
|
40434
|
+
}
|
|
40435
|
+
}
|
|
40436
|
+
return { snapshotted, linked, absent, failed, skipped: null };
|
|
40437
|
+
} finally {
|
|
40438
|
+
await release().catch(() => {
|
|
40439
|
+
});
|
|
40440
|
+
}
|
|
40441
|
+
}
|
|
40442
|
+
function isValidStamp(ymd, hms) {
|
|
40443
|
+
const y = Number(ymd.slice(0, 4));
|
|
40444
|
+
const mo = Number(ymd.slice(4, 6));
|
|
40445
|
+
const d = Number(ymd.slice(6, 8));
|
|
40446
|
+
const h = Number(hms.slice(0, 2));
|
|
40447
|
+
const mi = Number(hms.slice(2, 4));
|
|
40448
|
+
const se = Number(hms.slice(4, 6));
|
|
40449
|
+
if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
|
|
40450
|
+
const probe = new Date(Date.UTC(y, mo - 1, d));
|
|
40451
|
+
return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
|
|
40452
|
+
}
|
|
40453
|
+
function selectSnapshotsToKeep(names, ctx = {}) {
|
|
40454
|
+
const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
|
|
40455
|
+
const keep = /* @__PURE__ */ new Set();
|
|
40456
|
+
const stamped = [];
|
|
40457
|
+
for (const name15 of names) {
|
|
40458
|
+
const m = STAMP_PATTERN.exec(name15);
|
|
40459
|
+
const ymd = m?.[1];
|
|
40460
|
+
const hms = m?.[2];
|
|
40461
|
+
if (!ymd || !hms || !isValidStamp(ymd, hms)) {
|
|
40462
|
+
keep.add(name15);
|
|
40463
|
+
continue;
|
|
40464
|
+
}
|
|
40465
|
+
const stamp = `${ymd}-${hms}`;
|
|
40466
|
+
if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
|
|
40467
|
+
keep.add(name15);
|
|
40468
|
+
continue;
|
|
40469
|
+
}
|
|
40470
|
+
stamped.push({ name: name15, stamp });
|
|
40471
|
+
}
|
|
40472
|
+
if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
|
|
40473
|
+
stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
|
|
40474
|
+
for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
|
|
40475
|
+
const keepNewestPerBucket = (bucketOf, slots) => {
|
|
40476
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40477
|
+
for (const s of stamped) {
|
|
40478
|
+
const bucket = bucketOf(s.stamp);
|
|
40479
|
+
if (seen.has(bucket)) continue;
|
|
40480
|
+
if (seen.size >= slots) break;
|
|
40481
|
+
seen.add(bucket);
|
|
40482
|
+
keep.add(s.name);
|
|
40483
|
+
}
|
|
40484
|
+
};
|
|
40485
|
+
keepNewestPerBucket(
|
|
40486
|
+
(stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
|
|
40487
|
+
policy.quarterHourly
|
|
40488
|
+
);
|
|
40489
|
+
keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
|
|
40490
|
+
keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
|
|
40491
|
+
return keep;
|
|
40492
|
+
}
|
|
40493
|
+
var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
|
|
40494
|
+
var init_snapshot_gate = __esm({
|
|
40495
|
+
"packages/core/src/store/snapshot-gate.ts"() {
|
|
40496
|
+
"use strict";
|
|
40497
|
+
init_lock();
|
|
40498
|
+
init_twin_collapse();
|
|
40499
|
+
SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
|
|
40500
|
+
SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
|
|
40501
|
+
SNAPSHOT_LOCK_WAIT_RETRIES = 90;
|
|
40502
|
+
SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
|
|
40503
|
+
GATE_LOCK_BASENAME = ".snapshot-gate";
|
|
40504
|
+
DEFAULT_SNAPSHOT_RETENTION = {
|
|
40505
|
+
latest: 1,
|
|
40506
|
+
quarterHourly: 3,
|
|
40507
|
+
hourly: 3,
|
|
40508
|
+
daily: 3
|
|
40509
|
+
};
|
|
40510
|
+
STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
|
|
40511
|
+
}
|
|
40512
|
+
});
|
|
40513
|
+
|
|
40083
40514
|
// packages/core/src/store/data-safety-central.ts
|
|
40084
40515
|
import { eq as eq7 } from "drizzle-orm";
|
|
40085
40516
|
function inSafetyScope(cwd, operation) {
|
|
@@ -40490,7 +40921,7 @@ __export(data_accessor_exports, {
|
|
|
40490
40921
|
getAccessorDb: () => getAccessorDb,
|
|
40491
40922
|
getTaskAccessor: () => getTaskAccessor
|
|
40492
40923
|
});
|
|
40493
|
-
import { resolve as
|
|
40924
|
+
import { resolve as resolve11 } from "node:path";
|
|
40494
40925
|
function assertTestEnv(dbPath) {
|
|
40495
40926
|
const testMode = process.env["CLEO_TEST_MODE"];
|
|
40496
40927
|
if (testMode !== "1") return;
|
|
@@ -40511,7 +40942,7 @@ function assertTestEnv(dbPath) {
|
|
|
40511
40942
|
}
|
|
40512
40943
|
}
|
|
40513
40944
|
async function createDataAccessor(cwd) {
|
|
40514
|
-
const root =
|
|
40945
|
+
const root = resolve11(cwd ?? getProjectRoot());
|
|
40515
40946
|
const inherited = worktreeScope.getStore();
|
|
40516
40947
|
const captured = inherited ? { ...inherited } : void 0;
|
|
40517
40948
|
captured?.execution?.assertActive();
|
|
@@ -40555,7 +40986,7 @@ __export(memory_sqlite_exports, {
|
|
|
40555
40986
|
resetBrainDbState: () => resetBrainDbState,
|
|
40556
40987
|
resolveBrainMigrationsFolder: () => resolveBrainMigrationsFolder
|
|
40557
40988
|
});
|
|
40558
|
-
import { createRequire as
|
|
40989
|
+
import { createRequire as createRequire7 } from "node:module";
|
|
40559
40990
|
function _getDrizzle2() {
|
|
40560
40991
|
if (_drizzle2 === null) {
|
|
40561
40992
|
const mod = _require4("drizzle-orm/node-sqlite");
|
|
@@ -40692,7 +41123,7 @@ var init_memory_sqlite = __esm({
|
|
|
40692
41123
|
init_resolve_migrations_folder();
|
|
40693
41124
|
init_memory_schema();
|
|
40694
41125
|
init_twin_collapse();
|
|
40695
|
-
_require4 =
|
|
41126
|
+
_require4 = createRequire7(import.meta.url);
|
|
40696
41127
|
_drizzle2 = null;
|
|
40697
41128
|
BRAIN_SCHEMA_VERSION = "1.0.0";
|
|
40698
41129
|
CONSOLIDATED_BRAIN_TABLES = [
|
|
@@ -40880,11 +41311,11 @@ var init_skills_schema = __esm({
|
|
|
40880
41311
|
});
|
|
40881
41312
|
|
|
40882
41313
|
// packages/core/src/store/skills-db.ts
|
|
40883
|
-
import { join as
|
|
41314
|
+
import { join as join25 } from "node:path";
|
|
40884
41315
|
import { and as and6, eq as eq8 } from "drizzle-orm";
|
|
40885
41316
|
function getDefaultSkillsDbPath() {
|
|
40886
41317
|
const cleoHome = getCleoHome();
|
|
40887
|
-
const dbPath =
|
|
41318
|
+
const dbPath = join25(cleoHome, "cleo.db");
|
|
40888
41319
|
if (!dbPath.startsWith(cleoHome)) {
|
|
40889
41320
|
throw new Error(
|
|
40890
41321
|
`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.`
|
|
@@ -40932,19 +41363,19 @@ import {
|
|
|
40932
41363
|
chmodSync,
|
|
40933
41364
|
closeSync,
|
|
40934
41365
|
copyFileSync as copyFileSync3,
|
|
40935
|
-
existsSync as
|
|
41366
|
+
existsSync as existsSync20,
|
|
40936
41367
|
fsyncSync,
|
|
40937
41368
|
linkSync,
|
|
40938
41369
|
mkdirSync as mkdirSync5,
|
|
40939
41370
|
openSync,
|
|
40940
41371
|
readdirSync as readdirSync5,
|
|
40941
|
-
realpathSync as
|
|
41372
|
+
realpathSync as realpathSync7,
|
|
40942
41373
|
renameSync as renameSync6,
|
|
40943
41374
|
rmSync,
|
|
40944
41375
|
statSync as statSync6,
|
|
40945
41376
|
unlinkSync as unlinkSync3
|
|
40946
41377
|
} from "node:fs";
|
|
40947
|
-
import { dirname as
|
|
41378
|
+
import { dirname as dirname15, join as join26, sep as sep4 } from "node:path";
|
|
40948
41379
|
function resolveInventoryPath(entry, cwd) {
|
|
40949
41380
|
try {
|
|
40950
41381
|
if (entry.tier === "global") {
|
|
@@ -40980,8 +41411,8 @@ async function openAgentRegistryDbForSnapshot() {
|
|
|
40980
41411
|
}
|
|
40981
41412
|
async function openTelemetryDbForSnapshot() {
|
|
40982
41413
|
try {
|
|
40983
|
-
const path =
|
|
40984
|
-
if (!
|
|
41414
|
+
const path = join26(getCleoHome(), "telemetry.db");
|
|
41415
|
+
if (!existsSync20(path)) return null;
|
|
40985
41416
|
} catch {
|
|
40986
41417
|
return null;
|
|
40987
41418
|
}
|
|
@@ -41093,7 +41524,7 @@ function rotateSnapshots(backupDir, prefix, justWritten) {
|
|
|
41093
41524
|
for (const name15 of names) {
|
|
41094
41525
|
if (keep.has(name15)) continue;
|
|
41095
41526
|
try {
|
|
41096
|
-
unlinkSync3(
|
|
41527
|
+
unlinkSync3(join26(backupDir, name15));
|
|
41097
41528
|
} catch {
|
|
41098
41529
|
}
|
|
41099
41530
|
}
|
|
@@ -41115,7 +41546,7 @@ async function snapshotProjectTargetsGated(targets, opts) {
|
|
|
41115
41546
|
let backupDir;
|
|
41116
41547
|
try {
|
|
41117
41548
|
const cleoDir = getCleoDir(cwd);
|
|
41118
|
-
backupDir =
|
|
41549
|
+
backupDir = join26(cleoDir, "backups", "sqlite");
|
|
41119
41550
|
mkdirSync5(backupDir, { recursive: true });
|
|
41120
41551
|
} catch {
|
|
41121
41552
|
return null;
|
|
@@ -41147,7 +41578,7 @@ function sourceFileOf(db) {
|
|
|
41147
41578
|
const location = db.location();
|
|
41148
41579
|
if (!location) return null;
|
|
41149
41580
|
try {
|
|
41150
|
-
return
|
|
41581
|
+
return realpathSync7(location);
|
|
41151
41582
|
} catch {
|
|
41152
41583
|
return location;
|
|
41153
41584
|
}
|
|
@@ -41158,10 +41589,10 @@ function hasLocation(db) {
|
|
|
41158
41589
|
function assertOwnedByProject(source, prefix, cwd) {
|
|
41159
41590
|
let cleoDir = getCleoDir(cwd);
|
|
41160
41591
|
try {
|
|
41161
|
-
cleoDir =
|
|
41592
|
+
cleoDir = realpathSync7(cleoDir);
|
|
41162
41593
|
} catch {
|
|
41163
41594
|
}
|
|
41164
|
-
if (!source.startsWith(cleoDir +
|
|
41595
|
+
if (!source.startsWith(cleoDir + sep4)) {
|
|
41165
41596
|
throw new Error(
|
|
41166
41597
|
`refusing to snapshot ${prefix}: its database ${source} is not inside ${cleoDir}`
|
|
41167
41598
|
);
|
|
@@ -41190,7 +41621,7 @@ function commitSnapshotFile(tmp, dest) {
|
|
|
41190
41621
|
}
|
|
41191
41622
|
renameSync6(tmp, dest);
|
|
41192
41623
|
try {
|
|
41193
|
-
const dirFd = openSync(
|
|
41624
|
+
const dirFd = openSync(dirname15(dest), "r");
|
|
41194
41625
|
try {
|
|
41195
41626
|
fsyncSync(dirFd);
|
|
41196
41627
|
} finally {
|
|
@@ -41213,7 +41644,7 @@ function removeDeadTempSnapshots(backupDir) {
|
|
|
41213
41644
|
const m = TEMP_SNAPSHOT_RE.exec(name15);
|
|
41214
41645
|
if (!m) continue;
|
|
41215
41646
|
const pid = Number(m[1]);
|
|
41216
|
-
const path =
|
|
41647
|
+
const path = join26(backupDir, name15);
|
|
41217
41648
|
const stale = pid !== process.pid && (!isPidAlive2(pid) || Date.now() - statSync6(path).mtimeMs > TEMP_SNAPSHOT_MAX_AGE_MS);
|
|
41218
41649
|
if (stale) rmSync(path, { force: true });
|
|
41219
41650
|
}
|
|
@@ -41223,7 +41654,7 @@ function removeDeadTempSnapshots(backupDir) {
|
|
|
41223
41654
|
async function freeSnapshotName(backupDir, prefix) {
|
|
41224
41655
|
for (let attempt = 0; attempt < SNAPSHOT_NAME_ATTEMPTS; attempt++) {
|
|
41225
41656
|
const name15 = `${prefix}-${formatTimestamp(/* @__PURE__ */ new Date())}.db`;
|
|
41226
|
-
if (!
|
|
41657
|
+
if (!existsSync20(join26(backupDir, name15))) return name15;
|
|
41227
41658
|
await new Promise((r) => setTimeout(r, 1e3 - Date.now() % 1e3 + 5));
|
|
41228
41659
|
}
|
|
41229
41660
|
throw new Error(`no free snapshot filename for ${prefix} in ${backupDir}`);
|
|
@@ -41251,7 +41682,7 @@ async function snapshotOne(target, backupDir, writtenBySource, cwd) {
|
|
|
41251
41682
|
if (opened && target.closeDb) target.closeDb(opened);
|
|
41252
41683
|
throw err;
|
|
41253
41684
|
}
|
|
41254
|
-
const dest =
|
|
41685
|
+
const dest = join26(backupDir, destName);
|
|
41255
41686
|
removeDeadTempSnapshots(backupDir);
|
|
41256
41687
|
const existing = source !== null ? writtenBySource.get(source) : void 0;
|
|
41257
41688
|
if (existing !== void 0) {
|
|
@@ -41305,13 +41736,13 @@ async function vacuumIntoBackup(opts = {}) {
|
|
|
41305
41736
|
function listSqliteBackupsForPrefix(prefix, cwd) {
|
|
41306
41737
|
try {
|
|
41307
41738
|
const cleoDir = getCleoDir(cwd);
|
|
41308
|
-
const backupDir =
|
|
41309
|
-
if (!
|
|
41739
|
+
const backupDir = join26(cleoDir, "backups", "sqlite");
|
|
41740
|
+
if (!existsSync20(backupDir)) return [];
|
|
41310
41741
|
const pattern = snapshotPattern(prefix);
|
|
41311
41742
|
return readdirSync5(backupDir).filter((f) => pattern.test(f)).map((f) => ({
|
|
41312
41743
|
name: f,
|
|
41313
|
-
path:
|
|
41314
|
-
mtimeMs: statSync6(
|
|
41744
|
+
path: join26(backupDir, f),
|
|
41745
|
+
mtimeMs: statSync6(join26(backupDir, f)).mtimeMs
|
|
41315
41746
|
})).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
41316
41747
|
} catch {
|
|
41317
41748
|
return [];
|
|
@@ -41381,15 +41812,16 @@ __export(sqlite_exports, {
|
|
|
41381
41812
|
resetDbState: () => resetDbState,
|
|
41382
41813
|
resolveMigrationsFolder: () => resolveMigrationsFolder,
|
|
41383
41814
|
schema: () => tasks_schema_exports,
|
|
41384
|
-
seedTasksMeta: () => seedTasksMeta
|
|
41815
|
+
seedTasksMeta: () => seedTasksMeta,
|
|
41816
|
+
worktreeRecoveryRefusal: () => worktreeRecoveryRefusal
|
|
41385
41817
|
});
|
|
41386
|
-
import { copyFileSync as copyFileSync4, existsSync as
|
|
41387
|
-
import { createRequire as
|
|
41388
|
-
import { basename as basename8, dirname as
|
|
41818
|
+
import { copyFileSync as copyFileSync4, existsSync as existsSync21, realpathSync as realpathSync8, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41819
|
+
import { createRequire as createRequire8 } from "node:module";
|
|
41820
|
+
import { basename as basename8, dirname as dirname16, resolve as resolve12 } from "node:path";
|
|
41389
41821
|
import { eq as eq9 } from "drizzle-orm";
|
|
41390
41822
|
function _getDrizzle3() {
|
|
41391
41823
|
if (_drizzle3 === null) {
|
|
41392
|
-
const _require7 =
|
|
41824
|
+
const _require7 = createRequire8(import.meta.url);
|
|
41393
41825
|
const mod = _require7("drizzle-orm/node-sqlite");
|
|
41394
41826
|
_drizzle3 = mod.drizzle;
|
|
41395
41827
|
}
|
|
@@ -41425,13 +41857,19 @@ function countBackupTasks(backupDb) {
|
|
|
41425
41857
|
return 0;
|
|
41426
41858
|
}
|
|
41427
41859
|
function isSameDirectory(a, b) {
|
|
41428
|
-
if (
|
|
41860
|
+
if (resolve12(a) === resolve12(b)) return true;
|
|
41429
41861
|
try {
|
|
41430
|
-
return
|
|
41862
|
+
return realpathSync8(a) === realpathSync8(b);
|
|
41431
41863
|
} catch {
|
|
41432
41864
|
return false;
|
|
41433
41865
|
}
|
|
41434
41866
|
}
|
|
41867
|
+
function worktreeRecoveryRefusal(dbPath) {
|
|
41868
|
+
const storeCleoDir = dirname16(dbPath);
|
|
41869
|
+
const root = dirname16(storeCleoDir);
|
|
41870
|
+
if (basename8(storeCleoDir) !== ".cleo" || !isGitLinkedCheckout(root)) return null;
|
|
41871
|
+
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).`;
|
|
41872
|
+
}
|
|
41435
41873
|
async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
41436
41874
|
const { openNativeDatabase: openNativeDatabase2 } = await Promise.resolve().then(() => (init_sqlite_native(), sqlite_native_exports));
|
|
41437
41875
|
const log15 = getLogger("sqlite");
|
|
@@ -41440,12 +41878,10 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
41440
41878
|
const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks_tasks").get();
|
|
41441
41879
|
const taskCount = countResult?.cnt ?? 0;
|
|
41442
41880
|
if (taskCount > 0) return false;
|
|
41443
|
-
const storeCleoDir =
|
|
41444
|
-
|
|
41445
|
-
|
|
41446
|
-
|
|
41447
|
-
"Auto-recovery refused: the empty store lives inside a git worktree (T12460). Worktrees must resolve the parent project store."
|
|
41448
|
-
);
|
|
41881
|
+
const storeCleoDir = dirname16(dbPath);
|
|
41882
|
+
const worktreeRefusal = worktreeRecoveryRefusal(dbPath);
|
|
41883
|
+
if (worktreeRefusal !== null) {
|
|
41884
|
+
log15.warn({ dbPath }, worktreeRefusal);
|
|
41449
41885
|
return false;
|
|
41450
41886
|
}
|
|
41451
41887
|
const backups = listSqliteBackups(cwd);
|
|
@@ -41453,7 +41889,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
41453
41889
|
return false;
|
|
41454
41890
|
}
|
|
41455
41891
|
const newestBackup = backups[0];
|
|
41456
|
-
const backupCleoDir =
|
|
41892
|
+
const backupCleoDir = dirname16(dirname16(dirname16(newestBackup.path)));
|
|
41457
41893
|
if (!isSameDirectory(backupCleoDir, storeCleoDir)) {
|
|
41458
41894
|
log15.warn(
|
|
41459
41895
|
{ dbPath, backupPath: newestBackup.path },
|
|
@@ -41575,6 +42011,7 @@ function runMigrations(nativeDb, db, dbPath) {
|
|
|
41575
42011
|
try {
|
|
41576
42012
|
migrateWithRetry(db, migrationsFolder, nativeDb, "tasks", "sqlite");
|
|
41577
42013
|
} catch (error48) {
|
|
42014
|
+
if (isWorktreeBuildSchemaError(error48)) throw error48;
|
|
41578
42015
|
if (isSqliteBusy(error48) || !tableExists(nativeDb, "tasks_tasks")) throw error48;
|
|
41579
42016
|
try {
|
|
41580
42017
|
rebuildLegacyTasksLineage(
|
|
@@ -41616,7 +42053,7 @@ async function getSchemaVersion(cwd) {
|
|
|
41616
42053
|
return result[0]?.value ?? null;
|
|
41617
42054
|
}
|
|
41618
42055
|
function dbExists(cwd) {
|
|
41619
|
-
return
|
|
42056
|
+
return existsSync21(resolveDualScopeDbPath("project", cwd));
|
|
41620
42057
|
}
|
|
41621
42058
|
function getNativeDb(cwd) {
|
|
41622
42059
|
return boundProjectNative("tasks", cwd);
|
|
@@ -41652,6 +42089,7 @@ var init_sqlite3 = __esm({
|
|
|
41652
42089
|
init_resolve_migrations_folder();
|
|
41653
42090
|
init_sqlite_backup();
|
|
41654
42091
|
init_twin_collapse();
|
|
42092
|
+
init_worktree_build_guard();
|
|
41655
42093
|
init_worktree_isolation_guard();
|
|
41656
42094
|
init_sqlite_native();
|
|
41657
42095
|
init_tasks_schema();
|
|
@@ -41680,15 +42118,15 @@ var init_sqlite3 = __esm({
|
|
|
41680
42118
|
// packages/core/src/store/exodus/migrate.ts
|
|
41681
42119
|
import {
|
|
41682
42120
|
copyFileSync as copyFileSync5,
|
|
41683
|
-
existsSync as
|
|
42121
|
+
existsSync as existsSync22,
|
|
41684
42122
|
mkdirSync as mkdirSync6,
|
|
41685
|
-
readFileSync as
|
|
42123
|
+
readFileSync as readFileSync7,
|
|
41686
42124
|
renameSync as renameSync8,
|
|
41687
42125
|
statSync as statSync7,
|
|
41688
42126
|
unlinkSync as unlinkSync5,
|
|
41689
42127
|
writeFileSync as writeFileSync6
|
|
41690
42128
|
} from "node:fs";
|
|
41691
|
-
import { join as
|
|
42129
|
+
import { join as join27 } from "node:path";
|
|
41692
42130
|
function getSqliteVersion(db) {
|
|
41693
42131
|
try {
|
|
41694
42132
|
const row = db.prepare("SELECT sqlite_version() AS v").get();
|
|
@@ -41719,24 +42157,24 @@ function restoreGrandfatheredGuards(db, suspended) {
|
|
|
41719
42157
|
}
|
|
41720
42158
|
}
|
|
41721
42159
|
function writeJournal(stagingDir, journal) {
|
|
41722
|
-
const journalPath =
|
|
42160
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
41723
42161
|
const tmpPath = `${journalPath}.tmp`;
|
|
41724
42162
|
writeFileSync6(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
|
|
41725
42163
|
renameSync8(tmpPath, journalPath);
|
|
41726
42164
|
}
|
|
41727
42165
|
function readJournal(stagingDir) {
|
|
41728
|
-
const journalPath =
|
|
41729
|
-
if (!
|
|
42166
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
42167
|
+
if (!existsSync22(journalPath)) return null;
|
|
41730
42168
|
try {
|
|
41731
|
-
return JSON.parse(
|
|
42169
|
+
return JSON.parse(readFileSync7(journalPath, "utf8"));
|
|
41732
42170
|
} catch {
|
|
41733
42171
|
return null;
|
|
41734
42172
|
}
|
|
41735
42173
|
}
|
|
41736
42174
|
function clearExodusJournal(stagingDir) {
|
|
41737
|
-
const journalPath =
|
|
42175
|
+
const journalPath = join27(stagingDir, JOURNAL_FILENAME);
|
|
41738
42176
|
try {
|
|
41739
|
-
if (!
|
|
42177
|
+
if (!existsSync22(journalPath)) return false;
|
|
41740
42178
|
unlinkSync5(journalPath);
|
|
41741
42179
|
log10.info(
|
|
41742
42180
|
{ stagingDir },
|
|
@@ -42032,7 +42470,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
42032
42470
|
mkdirSync6(stagingDir, { recursive: true });
|
|
42033
42471
|
let sqliteVersion = "unknown";
|
|
42034
42472
|
for (const src of sources) {
|
|
42035
|
-
if (
|
|
42473
|
+
if (existsSync22(src.path)) {
|
|
42036
42474
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
42037
42475
|
sqliteVersion = getSqliteVersion(snap.db);
|
|
42038
42476
|
snap.close();
|
|
@@ -42062,15 +42500,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
42062
42500
|
let reseedProject = null;
|
|
42063
42501
|
try {
|
|
42064
42502
|
for (const src of sources) {
|
|
42065
|
-
if (!
|
|
42066
|
-
const backupDest =
|
|
42503
|
+
if (!existsSync22(src.path)) continue;
|
|
42504
|
+
const backupDest = join27(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
|
|
42067
42505
|
const srcBytes = safeStatBytes(src.path);
|
|
42068
42506
|
const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
|
|
42069
42507
|
if (skipStagingCopy) {
|
|
42070
42508
|
onProgress?.(
|
|
42071
42509
|
`Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
|
|
42072
42510
|
);
|
|
42073
|
-
} else if (!
|
|
42511
|
+
} else if (!existsSync22(backupDest)) {
|
|
42074
42512
|
onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
|
|
42075
42513
|
copyFileSync5(src.path, backupDest);
|
|
42076
42514
|
backupPaths.push(backupDest);
|
|
@@ -42103,8 +42541,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
42103
42541
|
}
|
|
42104
42542
|
prepareExodusRecovery(projectNative, stagingDir);
|
|
42105
42543
|
if (globalNative !== null) prepareExodusRecovery(globalNative, stagingDir);
|
|
42106
|
-
const projectSources = sources.filter((s) => s.targetScope === "project" &&
|
|
42107
|
-
const globalSources = sources.filter((s) => s.targetScope === "global" &&
|
|
42544
|
+
const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
|
|
42545
|
+
const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync22(s.path));
|
|
42108
42546
|
if (globalNative === null && globalSources.length > 0)
|
|
42109
42547
|
throw new Error("A projectOnly exodus run was given global-scope sources");
|
|
42110
42548
|
await migrateScope(
|
|
@@ -42412,9 +42850,9 @@ __export(reconcile_exports, {
|
|
|
42412
42850
|
reconcileSupersededStores: () => reconcileSupersededStores,
|
|
42413
42851
|
unmigratedBareSources: () => unmigratedBareSources
|
|
42414
42852
|
});
|
|
42415
|
-
import { copyFileSync as copyFileSync6, existsSync as
|
|
42853
|
+
import { copyFileSync as copyFileSync6, existsSync as existsSync23, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
42416
42854
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
42417
|
-
import { basename as basename9, join as
|
|
42855
|
+
import { basename as basename9, join as join28 } from "node:path";
|
|
42418
42856
|
function ident2(name15) {
|
|
42419
42857
|
return `"${name15.replace(/"/g, '""')}"`;
|
|
42420
42858
|
}
|
|
@@ -42483,7 +42921,7 @@ function assessSupersededProjectStores(liveStorePath, sources, resolveTarget = r
|
|
|
42483
42921
|
}
|
|
42484
42922
|
function legacySourcesHoldRows(sources) {
|
|
42485
42923
|
for (const src of sources) {
|
|
42486
|
-
if (!
|
|
42924
|
+
if (!existsSync23(src.path)) continue;
|
|
42487
42925
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
42488
42926
|
try {
|
|
42489
42927
|
for (const table of orderTablesForCopy(snap.db)) {
|
|
@@ -42514,8 +42952,8 @@ async function bareTaskCoreSource(liveStorePath, resolveTarget, outDir) {
|
|
|
42514
42952
|
live.close();
|
|
42515
42953
|
}
|
|
42516
42954
|
if (tables.length === 0) return null;
|
|
42517
|
-
const seedPath = await buildFreshProjectStore(
|
|
42518
|
-
const path =
|
|
42955
|
+
const seedPath = await buildFreshProjectStore(join28(outDir, "fresh-project-seed.db"));
|
|
42956
|
+
const path = join28(outDir, "cleo-bare-task-core.db");
|
|
42519
42957
|
const snap = openCleoDbSnapshot(path, { readOnly: false });
|
|
42520
42958
|
let kept = 0;
|
|
42521
42959
|
try {
|
|
@@ -42563,7 +43001,7 @@ async function buildFreshProjectStore(path) {
|
|
|
42563
43001
|
}
|
|
42564
43002
|
function snapshotFresherBareRows(barePath, legacyTasksPath, stagingDir) {
|
|
42565
43003
|
if (legacyTasksPath === void 0) return null;
|
|
42566
|
-
const path =
|
|
43004
|
+
const path = join28(stagingDir, "cleo-bare-task-core-fresher.db");
|
|
42567
43005
|
const snap = openCleoDbSnapshot(barePath, { readOnly: true });
|
|
42568
43006
|
try {
|
|
42569
43007
|
snap.db.exec(`VACUUM INTO '${path.replace(/'/g, "''")}'`);
|
|
@@ -42714,7 +43152,7 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
|
|
|
42714
43152
|
const additive = options.additive === true;
|
|
42715
43153
|
const plan = buildExodusPlan(projectRoot);
|
|
42716
43154
|
const resolveTarget = await buildRuntimeTargetResolver();
|
|
42717
|
-
const scratch = mkdtempSync(
|
|
43155
|
+
const scratch = mkdtempSync(join28(tmpdir3(), "cleo-reconcile-"));
|
|
42718
43156
|
try {
|
|
42719
43157
|
return await reconcileWithScratch(
|
|
42720
43158
|
projectRoot,
|
|
@@ -42730,8 +43168,8 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
|
|
|
42730
43168
|
}
|
|
42731
43169
|
}
|
|
42732
43170
|
async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath, plan, resolveTarget, scratch) {
|
|
42733
|
-
const fileSources = plan.sources.filter((s) => s.targetScope === "project" &&
|
|
42734
|
-
const bare = !additive &&
|
|
43171
|
+
const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync23(s.path));
|
|
43172
|
+
const bare = !additive && existsSync23(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
|
|
42735
43173
|
const copyResolver = additive ? (sourceName, legacyTable) => {
|
|
42736
43174
|
const r = resolveTarget(sourceName, legacyTable);
|
|
42737
43175
|
return r.kind !== "skip" && isLiveAuthoritative(sourceName, legacyTable, r.targetName) ? { kind: "skip", reason: "additive: live-authoritative task graph" } : r;
|
|
@@ -42750,7 +43188,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42750
43188
|
stagingDir: null,
|
|
42751
43189
|
receiptPath: null
|
|
42752
43190
|
};
|
|
42753
|
-
if (sources.length === 0 || !
|
|
43191
|
+
if (sources.length === 0 || !existsSync23(liveStorePath)) {
|
|
42754
43192
|
return {
|
|
42755
43193
|
...base,
|
|
42756
43194
|
outcome: "nothing-to-reconcile",
|
|
@@ -42790,11 +43228,11 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42790
43228
|
};
|
|
42791
43229
|
}
|
|
42792
43230
|
const iso = (/* @__PURE__ */ new Date()).toISOString().replace(/[:]/g, "").replace(/\..+Z$/, "Z");
|
|
42793
|
-
const stagingDir =
|
|
43231
|
+
const stagingDir = join28(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
|
|
42794
43232
|
mkdirSync7(stagingDir, { recursive: true });
|
|
42795
43233
|
const copySources = sources.map((s) => {
|
|
42796
43234
|
if (s !== bare) return s;
|
|
42797
|
-
const kept =
|
|
43235
|
+
const kept = join28(stagingDir, basename9(s.path));
|
|
42798
43236
|
copyFileSync6(s.path, kept);
|
|
42799
43237
|
return { ...s, path: kept };
|
|
42800
43238
|
});
|
|
@@ -42814,7 +43252,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42814
43252
|
const result = await withLock(
|
|
42815
43253
|
`${liveStorePath}.exodus-on-open.lock`,
|
|
42816
43254
|
async () => {
|
|
42817
|
-
const liveBefore =
|
|
43255
|
+
const liveBefore = join28(scratch, "live-before.db");
|
|
42818
43256
|
snapshotLive(liveStorePath, liveBefore);
|
|
42819
43257
|
const migrated = await runExodusMigrate(reconcilePlan, false, (msg) => log11.debug(msg), {
|
|
42820
43258
|
projectOnly: true,
|
|
@@ -42864,7 +43302,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
42864
43302
|
},
|
|
42865
43303
|
{ stale: 6e5, retries: 30 }
|
|
42866
43304
|
);
|
|
42867
|
-
const receiptPath =
|
|
43305
|
+
const receiptPath = join28(stagingDir, RECEIPT_FILENAME);
|
|
42868
43306
|
const receipt2 = { ...result, receiptPath };
|
|
42869
43307
|
writeFileSync7(receiptPath, `${JSON.stringify(receipt2, null, 2)}
|
|
42870
43308
|
`, "utf8");
|
|
@@ -42941,20 +43379,20 @@ var init_seal = __esm({
|
|
|
42941
43379
|
});
|
|
42942
43380
|
|
|
42943
43381
|
// packages/core/src/store/exodus/status.ts
|
|
42944
|
-
import { existsSync as
|
|
42945
|
-
import { join as
|
|
43382
|
+
import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync8, statSync as statSync8 } from "node:fs";
|
|
43383
|
+
import { join as join29 } from "node:path";
|
|
42946
43384
|
function readJournal2(stagingDir) {
|
|
42947
|
-
const p =
|
|
42948
|
-
if (!
|
|
43385
|
+
const p = join29(stagingDir, JOURNAL_FILENAME2);
|
|
43386
|
+
if (!existsSync24(p)) return null;
|
|
42949
43387
|
try {
|
|
42950
|
-
return JSON.parse(
|
|
43388
|
+
return JSON.parse(readFileSync8(p, "utf8"));
|
|
42951
43389
|
} catch {
|
|
42952
43390
|
return null;
|
|
42953
43391
|
}
|
|
42954
43392
|
}
|
|
42955
43393
|
function findStagingDirs(cleoDir) {
|
|
42956
43394
|
try {
|
|
42957
|
-
return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) =>
|
|
43395
|
+
return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join29(cleoDir, e.name)).sort().reverse();
|
|
42958
43396
|
} catch {
|
|
42959
43397
|
return [];
|
|
42960
43398
|
}
|
|
@@ -42977,15 +43415,15 @@ function runExodusStatus(cwd) {
|
|
|
42977
43415
|
const sourcesInfo = plan.sources.map((s) => ({
|
|
42978
43416
|
name: s.name,
|
|
42979
43417
|
path: s.path,
|
|
42980
|
-
exists:
|
|
43418
|
+
exists: existsSync24(s.path),
|
|
42981
43419
|
bytes: safeBytes(s.path)
|
|
42982
43420
|
}));
|
|
42983
43421
|
return {
|
|
42984
43422
|
hasStaging: latestStaging !== null,
|
|
42985
43423
|
stagingDir: latestStaging,
|
|
42986
43424
|
journal,
|
|
42987
|
-
projectDbExists:
|
|
42988
|
-
globalDbExists:
|
|
43425
|
+
projectDbExists: existsSync24(projectDbPath),
|
|
43426
|
+
globalDbExists: existsSync24(globalDbPath),
|
|
42989
43427
|
sourcesPresent: sourcesInfo.some((s) => s.exists),
|
|
42990
43428
|
sources: sourcesInfo
|
|
42991
43429
|
};
|
|
@@ -43002,8 +43440,8 @@ var init_status = __esm({
|
|
|
43002
43440
|
});
|
|
43003
43441
|
|
|
43004
43442
|
// packages/core/src/store/exodus/verify-migration.ts
|
|
43005
|
-
import { existsSync as
|
|
43006
|
-
import { createRequire as
|
|
43443
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
43444
|
+
import { createRequire as createRequire9 } from "node:module";
|
|
43007
43445
|
function orderByClause(db, tableName) {
|
|
43008
43446
|
try {
|
|
43009
43447
|
const pragma = db.prepare(`PRAGMA table_info("${tableName}")`).all();
|
|
@@ -43267,7 +43705,7 @@ function orphanAlreadyInSource(targetDb, fk, sources, resolveTarget = resolveCon
|
|
|
43267
43705
|
const anyFeeder = (targetTable, probe) => {
|
|
43268
43706
|
for (const feeder of feedersOf(targetTable)) {
|
|
43269
43707
|
const src = sources.find((s) => s.name === feeder.sourceName);
|
|
43270
|
-
if (src === void 0 || !
|
|
43708
|
+
if (src === void 0 || !existsSync25(src.path)) continue;
|
|
43271
43709
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
43272
43710
|
try {
|
|
43273
43711
|
if (!tableExists3(snap.db, feeder.legacyTable)) continue;
|
|
@@ -43322,7 +43760,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43322
43760
|
const preExistingForeignKeyViolations = [];
|
|
43323
43761
|
const failureLines = [];
|
|
43324
43762
|
const sourceOrphanSigs = /* @__PURE__ */ new Set();
|
|
43325
|
-
if (!
|
|
43763
|
+
if (!existsSync25(projectDbPath)) {
|
|
43326
43764
|
return {
|
|
43327
43765
|
ok: false,
|
|
43328
43766
|
tables: [],
|
|
@@ -43333,7 +43771,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43333
43771
|
error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
|
|
43334
43772
|
};
|
|
43335
43773
|
}
|
|
43336
|
-
if (!
|
|
43774
|
+
if (!existsSync25(globalDbPath)) {
|
|
43337
43775
|
return {
|
|
43338
43776
|
ok: false,
|
|
43339
43777
|
tables: [],
|
|
@@ -43348,7 +43786,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
43348
43786
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
43349
43787
|
try {
|
|
43350
43788
|
for (const src of sources) {
|
|
43351
|
-
if (!
|
|
43789
|
+
if (!existsSync25(src.path)) {
|
|
43352
43790
|
onProgress?.(`Skipping ${src.name} (not present)`);
|
|
43353
43791
|
continue;
|
|
43354
43792
|
}
|
|
@@ -43543,7 +43981,7 @@ var init_verify_migration = __esm({
|
|
|
43543
43981
|
init_column_transforms();
|
|
43544
43982
|
init_table_name_map();
|
|
43545
43983
|
log13 = getLogger("verify-migration");
|
|
43546
|
-
_require5 =
|
|
43984
|
+
_require5 = createRequire9(import.meta.url);
|
|
43547
43985
|
CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
|
|
43548
43986
|
}
|
|
43549
43987
|
});
|
|
@@ -43639,11 +44077,11 @@ __export(on_open_exports, {
|
|
|
43639
44077
|
maybeRunExodusOnOpen: () => maybeRunExodusOnOpen,
|
|
43640
44078
|
withExodusOnOpenSuppressed: () => withExodusOnOpenSuppressed
|
|
43641
44079
|
});
|
|
43642
|
-
import { existsSync as
|
|
44080
|
+
import { existsSync as existsSync26, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
|
|
43643
44081
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
43644
|
-
import { join as
|
|
44082
|
+
import { join as join30, resolve as resolve13 } from "node:path";
|
|
43645
44083
|
async function withExodusOnOpenSuppressed(dbPath, fn) {
|
|
43646
|
-
const key =
|
|
44084
|
+
const key = resolve13(dbPath);
|
|
43647
44085
|
_reconcileInProgress.set(key, (_reconcileInProgress.get(key) ?? 0) + 1);
|
|
43648
44086
|
try {
|
|
43649
44087
|
return await fn();
|
|
@@ -43681,7 +44119,7 @@ function remedyFor(scope) {
|
|
|
43681
44119
|
}
|
|
43682
44120
|
async function strandedLegacySources(scope, cwd) {
|
|
43683
44121
|
const { buildExodusPlan: buildExodusPlan2, legacySourcesHoldRows: legacySourcesHoldRows2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
|
|
43684
|
-
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope &&
|
|
44122
|
+
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync26(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
|
|
43685
44123
|
}
|
|
43686
44124
|
async function rollbackBothScopes(plan) {
|
|
43687
44125
|
const { getDualScopeNativeDb: getDualScopeNativeDb2, openDualScopeDbAtPath: openDualScopeDbAtPath2 } = await Promise.resolve().then(() => (init_dual_scope_db(), dual_scope_db_exports));
|
|
@@ -43759,7 +44197,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43759
44197
|
if (_exodusInProgress) {
|
|
43760
44198
|
return { outcome: "skipped", reason: "re-entrant open during active migration" };
|
|
43761
44199
|
}
|
|
43762
|
-
if (_reconcileInProgress.has(
|
|
44200
|
+
if (_reconcileInProgress.has(resolve13(dbPath))) {
|
|
43763
44201
|
return {
|
|
43764
44202
|
outcome: "skipped",
|
|
43765
44203
|
reason: "an explicit superseded-store reconcile of this store is in progress"
|
|
@@ -43792,14 +44230,14 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43792
44230
|
const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
|
|
43793
44231
|
const plan = buildExodusPlan2(cwd);
|
|
43794
44232
|
const plannedTarget = scope === "project" ? plan.projectDbPath : plan.globalDbPath;
|
|
43795
|
-
if (
|
|
44233
|
+
if (resolve13(plannedTarget) !== resolve13(dbPath)) {
|
|
43796
44234
|
return {
|
|
43797
44235
|
outcome: "aborted",
|
|
43798
44236
|
reason: `migration plan target ${plannedTarget} does not match opened database ${dbPath}; no migration applied`
|
|
43799
44237
|
};
|
|
43800
44238
|
}
|
|
43801
44239
|
const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
|
|
43802
|
-
if (!scopeSources.some((s) =>
|
|
44240
|
+
if (!scopeSources.some((s) => existsSync26(s.path))) {
|
|
43803
44241
|
return {
|
|
43804
44242
|
outcome: "skipped",
|
|
43805
44243
|
reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
|
|
@@ -43816,12 +44254,12 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43816
44254
|
{
|
|
43817
44255
|
scope,
|
|
43818
44256
|
dbPath,
|
|
43819
|
-
sources: plan.sources.filter((s) =>
|
|
44257
|
+
sources: plan.sources.filter((s) => existsSync26(s.path)).map((s) => s.name)
|
|
43820
44258
|
},
|
|
43821
44259
|
"exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
|
|
43822
44260
|
);
|
|
43823
44261
|
_exodusInProgress = true;
|
|
43824
|
-
const bareScratch = mkdtempSync2(
|
|
44262
|
+
const bareScratch = mkdtempSync2(join30(tmpdir4(), "cleo-exodus-bare-"));
|
|
43825
44263
|
try {
|
|
43826
44264
|
const { buildRuntimeTargetResolver: buildRuntimeTargetResolver2 } = await Promise.resolve().then(() => (init_runtime_targets(), runtime_targets_exports));
|
|
43827
44265
|
const resolveTarget = await buildRuntimeTargetResolver2();
|
|
@@ -43829,7 +44267,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43829
44267
|
const bare = scope === "project" ? await unmigratedBareSources2(
|
|
43830
44268
|
dbPath,
|
|
43831
44269
|
resolveTarget,
|
|
43832
|
-
plan.sources.find((s) => s.name === "tasks" &&
|
|
44270
|
+
plan.sources.find((s) => s.name === "tasks" && existsSync26(s.path))?.path,
|
|
43833
44271
|
bareScratch
|
|
43834
44272
|
) : { first: [], last: [] };
|
|
43835
44273
|
const migratePlan = { ...plan, sources: [...bare.first, ...plan.sources, ...bare.last] };
|
|
@@ -43893,7 +44331,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
43893
44331
|
"exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
|
|
43894
44332
|
);
|
|
43895
44333
|
try {
|
|
43896
|
-
const consumed = plan.sources.filter((s) =>
|
|
44334
|
+
const consumed = plan.sources.filter((s) => existsSync26(s.path));
|
|
43897
44335
|
const identities = await sealTargets(plan, consumed);
|
|
43898
44336
|
const archiveResult = archiveMigratedSources(consumed, cwd, plan, identities);
|
|
43899
44337
|
log14.info(
|
|
@@ -43968,9 +44406,9 @@ __export(dual_scope_db_exports, {
|
|
|
43968
44406
|
upsertIdempotent: () => upsertIdempotent,
|
|
43969
44407
|
withStoreSchemaOwnership: () => withStoreSchemaOwnership
|
|
43970
44408
|
});
|
|
43971
|
-
import { existsSync as
|
|
43972
|
-
import { createRequire as
|
|
43973
|
-
import { dirname as
|
|
44409
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
|
|
44410
|
+
import { createRequire as createRequire10 } from "node:module";
|
|
44411
|
+
import { dirname as dirname17, join as join31, resolve as resolve14 } from "node:path";
|
|
43974
44412
|
function getDualScopeNativeDb(handle) {
|
|
43975
44413
|
const db = handle.db;
|
|
43976
44414
|
if ("$client" in db && db.$client instanceof getDatabaseSyncCtor()) return db.$client;
|
|
@@ -43992,9 +44430,9 @@ function cacheKey(scope, dbPath) {
|
|
|
43992
44430
|
}
|
|
43993
44431
|
function resolveDualScopeDbPath(scope, cwd, capturedGlobalHome) {
|
|
43994
44432
|
if (scope === "project") {
|
|
43995
|
-
return
|
|
44433
|
+
return join31(resolveCleoDir(cwd), "cleo.db");
|
|
43996
44434
|
}
|
|
43997
|
-
return
|
|
44435
|
+
return join31(capturedGlobalHome ?? getCleoHome(), "cleo.db");
|
|
43998
44436
|
}
|
|
43999
44437
|
function migrationsSetName(scope) {
|
|
44000
44438
|
return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
|
|
@@ -44044,8 +44482,8 @@ async function openDualScopeDb(scope, cwd, options) {
|
|
|
44044
44482
|
async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
44045
44483
|
execution?.assertActive();
|
|
44046
44484
|
log15.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
|
|
44047
|
-
const dir =
|
|
44048
|
-
if (!
|
|
44485
|
+
const dir = dirname17(dbPath);
|
|
44486
|
+
if (!existsSync27(dir)) {
|
|
44049
44487
|
mkdirSync8(dir, { recursive: true });
|
|
44050
44488
|
}
|
|
44051
44489
|
execution?.assertActive();
|
|
@@ -44053,6 +44491,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
|
44053
44491
|
const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
|
|
44054
44492
|
try {
|
|
44055
44493
|
applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
|
|
44494
|
+
installSchemaWriteGuard(nativeDb);
|
|
44056
44495
|
const drizzle2 = getDrizzle();
|
|
44057
44496
|
const db = drizzle2({ client: nativeDb });
|
|
44058
44497
|
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
@@ -44101,11 +44540,12 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
|
44101
44540
|
execution?.assertActive();
|
|
44102
44541
|
return handle;
|
|
44103
44542
|
} catch (err) {
|
|
44543
|
+
const explained = explainSchemaWriteDenial(nativeDb, err);
|
|
44104
44544
|
try {
|
|
44105
44545
|
nativeDb.close();
|
|
44106
44546
|
} catch {
|
|
44107
44547
|
}
|
|
44108
|
-
throw
|
|
44548
|
+
throw explained;
|
|
44109
44549
|
}
|
|
44110
44550
|
}
|
|
44111
44551
|
async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
@@ -44126,7 +44566,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44126
44566
|
);
|
|
44127
44567
|
}
|
|
44128
44568
|
const dedicated = options?.dedicated === true;
|
|
44129
|
-
const normalizedPath =
|
|
44569
|
+
const normalizedPath = resolve14(dbPath);
|
|
44130
44570
|
const key = cacheKey(scope, normalizedPath);
|
|
44131
44571
|
if (!dedicated) {
|
|
44132
44572
|
const existing = _cache.get(key);
|
|
@@ -44163,8 +44603,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44163
44603
|
}
|
|
44164
44604
|
let initResolve = null;
|
|
44165
44605
|
let initReject = null;
|
|
44166
|
-
const initPromise = new Promise((
|
|
44167
|
-
initResolve =
|
|
44606
|
+
const initPromise = new Promise((resolve17, reject) => {
|
|
44607
|
+
initResolve = resolve17;
|
|
44168
44608
|
initReject = reject;
|
|
44169
44609
|
});
|
|
44170
44610
|
_cache.set(key, {
|
|
@@ -44185,8 +44625,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44185
44625
|
try {
|
|
44186
44626
|
execution?.assertActive();
|
|
44187
44627
|
log15.debug({ scope, dbPath: normalizedPath }, "opening dual-scope cleo.db");
|
|
44188
|
-
const dir =
|
|
44189
|
-
if (!
|
|
44628
|
+
const dir = dirname17(normalizedPath);
|
|
44629
|
+
if (!existsSync27(dir)) {
|
|
44190
44630
|
mkdirSync8(dir, { recursive: true });
|
|
44191
44631
|
}
|
|
44192
44632
|
execution?.assertActive();
|
|
@@ -44194,6 +44634,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44194
44634
|
const nativeDb = new DatabaseSyncCtor(normalizedPath, { allowExtension: true });
|
|
44195
44635
|
openingNative = nativeDb;
|
|
44196
44636
|
applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
|
|
44637
|
+
installSchemaWriteGuard(nativeDb);
|
|
44197
44638
|
const drizzle2 = getDrizzle();
|
|
44198
44639
|
const db = drizzle2({ client: nativeDb });
|
|
44199
44640
|
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
@@ -44324,12 +44765,13 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
44324
44765
|
execution?.assertActive();
|
|
44325
44766
|
initResolve(finalHandle);
|
|
44326
44767
|
} catch (err) {
|
|
44768
|
+
const explained = openingNative ? explainSchemaWriteDenial(openingNative, err) : err;
|
|
44327
44769
|
try {
|
|
44328
44770
|
if (!published && openingNative?.isOpen) openingNative.close();
|
|
44329
44771
|
} catch (closeError) {
|
|
44330
44772
|
log15.warn({ closeError }, "failed to close unpublished database initializer");
|
|
44331
44773
|
}
|
|
44332
|
-
initReject(
|
|
44774
|
+
initReject(explained);
|
|
44333
44775
|
}
|
|
44334
44776
|
})();
|
|
44335
44777
|
return initPromise;
|
|
@@ -44402,6 +44844,7 @@ var init_dual_scope_db = __esm({
|
|
|
44402
44844
|
init_relocated_store_guard();
|
|
44403
44845
|
init_resolve_migrations_folder();
|
|
44404
44846
|
init_sqlite_pragmas();
|
|
44847
|
+
init_worktree_build_guard();
|
|
44405
44848
|
init_worktree_isolation_guard();
|
|
44406
44849
|
init_writer_lease();
|
|
44407
44850
|
ExodusAbortWriteUnsafeError = class extends Error {
|
|
@@ -44424,7 +44867,7 @@ var init_dual_scope_db = __esm({
|
|
|
44424
44867
|
}
|
|
44425
44868
|
};
|
|
44426
44869
|
_cache = /* @__PURE__ */ new Map();
|
|
44427
|
-
_require6 =
|
|
44870
|
+
_require6 = createRequire10(import.meta.url);
|
|
44428
44871
|
_drizzle4 = null;
|
|
44429
44872
|
_DatabaseSyncCtor = null;
|
|
44430
44873
|
EntryCancelledError = class extends Error {
|
|
@@ -44455,7 +44898,7 @@ var init_dual_scope_db = __esm({
|
|
|
44455
44898
|
}
|
|
44456
44899
|
/** @inheritdoc */
|
|
44457
44900
|
async openProject(dbPath, options) {
|
|
44458
|
-
const normalized =
|
|
44901
|
+
const normalized = resolve14(dbPath);
|
|
44459
44902
|
if (options?.dedicated) {
|
|
44460
44903
|
const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
|
|
44461
44904
|
dedicated: true
|
|
@@ -44467,7 +44910,7 @@ var init_dual_scope_db = __esm({
|
|
|
44467
44910
|
/** @inheritdoc */
|
|
44468
44911
|
async openGlobal(options) {
|
|
44469
44912
|
const dbPath = resolveDualScopeDbPath("global");
|
|
44470
|
-
const normalized =
|
|
44913
|
+
const normalized = resolve14(dbPath);
|
|
44471
44914
|
if (options?.dedicated) {
|
|
44472
44915
|
const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
|
|
44473
44916
|
dedicated: true
|
|
@@ -44478,7 +44921,7 @@ var init_dual_scope_db = __esm({
|
|
|
44478
44921
|
}
|
|
44479
44922
|
/** @inheritdoc */
|
|
44480
44923
|
async openGlobalAt(dbPath, options) {
|
|
44481
|
-
const normalized =
|
|
44924
|
+
const normalized = resolve14(dbPath);
|
|
44482
44925
|
if (options?.dedicated) {
|
|
44483
44926
|
const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
|
|
44484
44927
|
dedicated: true
|
|
@@ -44489,7 +44932,7 @@ var init_dual_scope_db = __esm({
|
|
|
44489
44932
|
}
|
|
44490
44933
|
/** @inheritdoc */
|
|
44491
44934
|
closeProject(dbPath) {
|
|
44492
|
-
const normalized =
|
|
44935
|
+
const normalized = resolve14(dbPath);
|
|
44493
44936
|
this.closeEntry("project", normalized);
|
|
44494
44937
|
}
|
|
44495
44938
|
/** @inheritdoc */
|
|
@@ -44526,8 +44969,8 @@ var init_dual_scope_db = __esm({
|
|
|
44526
44969
|
const entryId = ++this._nextId;
|
|
44527
44970
|
let initResolve;
|
|
44528
44971
|
let initReject;
|
|
44529
|
-
const initPromise = new Promise((
|
|
44530
|
-
initResolve =
|
|
44972
|
+
const initPromise = new Promise((resolve17, reject) => {
|
|
44973
|
+
initResolve = resolve17;
|
|
44531
44974
|
initReject = reject;
|
|
44532
44975
|
});
|
|
44533
44976
|
this._registry.set(key, { id: entryId, store: null, initPromise });
|
|
@@ -45320,8 +45763,8 @@ __export(nexus_sqlite_exports, {
|
|
|
45320
45763
|
resetNexusDbState: () => resetNexusDbState,
|
|
45321
45764
|
resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
|
|
45322
45765
|
});
|
|
45323
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
45324
|
-
import { join as
|
|
45766
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync28 } from "node:fs";
|
|
45767
|
+
import { join as join32 } from "node:path";
|
|
45325
45768
|
function getNexusDbPath(cwd) {
|
|
45326
45769
|
return resolveDualScopeDbPath("project", cwd);
|
|
45327
45770
|
}
|
|
@@ -45357,12 +45800,13 @@ function ensureGlobalRegistryAttached(nativeDb) {
|
|
|
45357
45800
|
}
|
|
45358
45801
|
}
|
|
45359
45802
|
nativeDb.exec(`ATTACH DATABASE '${escaped}' AS ${NEXUS_GLOBAL_ATTACH_ALIAS}`);
|
|
45803
|
+
refreshSchemaWriteGuard(nativeDb);
|
|
45360
45804
|
}
|
|
45361
45805
|
function resolveNexusMigrationsFolder() {
|
|
45362
45806
|
return resolveCorePackageMigrationsFolder("drizzle-nexus");
|
|
45363
45807
|
}
|
|
45364
45808
|
function getNestedNexusSentinelPath() {
|
|
45365
|
-
return
|
|
45809
|
+
return join32(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
|
|
45366
45810
|
}
|
|
45367
45811
|
function detectAndWarnOnNestedNexus() {
|
|
45368
45812
|
let nestedPath;
|
|
@@ -45371,7 +45815,7 @@ function detectAndWarnOnNestedNexus() {
|
|
|
45371
45815
|
} catch {
|
|
45372
45816
|
return false;
|
|
45373
45817
|
}
|
|
45374
|
-
if (!
|
|
45818
|
+
if (!existsSync28(nestedPath)) return false;
|
|
45375
45819
|
if (_warnedNestedPaths.has(nestedPath)) return false;
|
|
45376
45820
|
_warnedNestedPaths.add(nestedPath);
|
|
45377
45821
|
const canonicalPath = getNexusDbPath();
|
|
@@ -45530,7 +45974,7 @@ function runNexusMigrations(nativeDb, db, dbPath) {
|
|
|
45530
45974
|
const migrationsFolder = resolveNexusMigrationsFolder();
|
|
45531
45975
|
if (tableExists4(nativeDb, "nexus_nodes")) {
|
|
45532
45976
|
const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
|
|
45533
|
-
if (!
|
|
45977
|
+
if (!existsSync28(backupPath)) {
|
|
45534
45978
|
try {
|
|
45535
45979
|
copyFileSync7(dbPath, backupPath);
|
|
45536
45980
|
} catch {
|
|
@@ -45625,6 +46069,7 @@ var init_nexus_sqlite = __esm({
|
|
|
45625
46069
|
init_resolve_migrations_folder();
|
|
45626
46070
|
init_nexus_schema();
|
|
45627
46071
|
init_with_retry();
|
|
46072
|
+
init_worktree_build_guard();
|
|
45628
46073
|
NEXUS_SCHEMA_VERSION = "1.0.0";
|
|
45629
46074
|
NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
|
|
45630
46075
|
NESTED_NEXUS_SENTINEL = "nexus.db";
|
|
@@ -45659,15 +46104,15 @@ var init_legacy_alias = __esm({
|
|
|
45659
46104
|
|
|
45660
46105
|
// packages/core/src/llm/stable-device-id.ts
|
|
45661
46106
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
45662
|
-
import { existsSync as
|
|
45663
|
-
import { dirname as
|
|
46107
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
|
|
46108
|
+
import { dirname as dirname18 } from "node:path";
|
|
45664
46109
|
import { resolveStableDeviceIdPath } from "@cleocode/paths";
|
|
45665
46110
|
function getStableDeviceId() {
|
|
45666
46111
|
if (_cachedDeviceId !== null) return _cachedDeviceId;
|
|
45667
46112
|
const path = resolveStableDeviceIdPath();
|
|
45668
|
-
if (
|
|
46113
|
+
if (existsSync29(path)) {
|
|
45669
46114
|
try {
|
|
45670
|
-
const raw =
|
|
46115
|
+
const raw = readFileSync9(path, "utf-8").trim();
|
|
45671
46116
|
if (raw.length > 0) {
|
|
45672
46117
|
_cachedDeviceId = raw;
|
|
45673
46118
|
return raw;
|
|
@@ -45677,8 +46122,8 @@ function getStableDeviceId() {
|
|
|
45677
46122
|
}
|
|
45678
46123
|
const fresh = randomUUID3();
|
|
45679
46124
|
try {
|
|
45680
|
-
const dir =
|
|
45681
|
-
if (!
|
|
46125
|
+
const dir = dirname18(path);
|
|
46126
|
+
if (!existsSync29(dir)) {
|
|
45682
46127
|
mkdirSync9(dir, { recursive: true });
|
|
45683
46128
|
}
|
|
45684
46129
|
const tmpPath = `${path}.tmp.${process.pid}`;
|
|
@@ -45715,8 +46160,8 @@ var init_registry_roots = __esm({
|
|
|
45715
46160
|
// packages/core/src/nexus/projects-scan.ts
|
|
45716
46161
|
async function withinBudget(promise2, ms) {
|
|
45717
46162
|
let timer;
|
|
45718
|
-
const expiry = new Promise((
|
|
45719
|
-
timer = setTimeout(() =>
|
|
46163
|
+
const expiry = new Promise((resolve17) => {
|
|
46164
|
+
timer = setTimeout(() => resolve17("timeout"), ms);
|
|
45720
46165
|
timer.unref();
|
|
45721
46166
|
});
|
|
45722
46167
|
try {
|
|
@@ -45754,9 +46199,9 @@ __export(path_map_exports, {
|
|
|
45754
46199
|
supersededRegistryPath: () => supersededRegistryPath,
|
|
45755
46200
|
touchProjectLocation: () => touchProjectLocation
|
|
45756
46201
|
});
|
|
45757
|
-
import { existsSync as
|
|
46202
|
+
import { existsSync as existsSync30, lstatSync, readdirSync as readdirSync7 } from "node:fs";
|
|
45758
46203
|
import { lstat, readdir as readdir2 } from "node:fs/promises";
|
|
45759
|
-
import { isAbsolute as
|
|
46204
|
+
import { isAbsolute as isAbsolute5, join as join33, relative as relative3, sep as sep5 } from "node:path";
|
|
45760
46205
|
import { canonicalizePath as canonicalizePath3, readDeclaredProjectIdentity as readDeclaredProjectIdentity3 } from "@cleocode/paths";
|
|
45761
46206
|
import { and as and7, desc as desc3, eq as eq11, inArray as inArray5, ne as ne3 } from "drizzle-orm";
|
|
45762
46207
|
function holdingKey(projectId, path) {
|
|
@@ -45772,7 +46217,7 @@ function isSupersededRegistryPath(projectPath) {
|
|
|
45772
46217
|
return projectPath.startsWith(SUPERSEDED_PATH_PREFIX);
|
|
45773
46218
|
}
|
|
45774
46219
|
function projectHolding(path, projectId) {
|
|
45775
|
-
const cleoDir =
|
|
46220
|
+
const cleoDir = join33(path, ".cleo");
|
|
45776
46221
|
try {
|
|
45777
46222
|
lstatSync(cleoDir);
|
|
45778
46223
|
readdirSync7(cleoDir);
|
|
@@ -45784,7 +46229,7 @@ function projectHolding(path, projectId) {
|
|
|
45784
46229
|
return declared === null || declared.projectId === projectId ? "yes" : "no";
|
|
45785
46230
|
}
|
|
45786
46231
|
async function probeProjectHolding(path, projectId, timeoutMs) {
|
|
45787
|
-
const cleoDir =
|
|
46232
|
+
const cleoDir = join33(path, ".cleo");
|
|
45788
46233
|
const probe = async () => {
|
|
45789
46234
|
try {
|
|
45790
46235
|
await lstat(cleoDir);
|
|
@@ -45802,8 +46247,8 @@ async function probeProjectHolding(path, projectId, timeoutMs) {
|
|
|
45802
46247
|
return declared === null || declared.projectId === projectId ? "yes" : "no";
|
|
45803
46248
|
}
|
|
45804
46249
|
function isStrictlyInside(outer, inner) {
|
|
45805
|
-
const rel =
|
|
45806
|
-
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${
|
|
46250
|
+
const rel = relative3(canonicalizePath3(outer), canonicalizePath3(inner));
|
|
46251
|
+
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep5}`) && !isAbsolute5(rel);
|
|
45807
46252
|
}
|
|
45808
46253
|
function locationKey(projectId, deviceId, path) {
|
|
45809
46254
|
return and7(
|
|
@@ -45965,7 +46410,7 @@ function hasOtherLiveLocation(db, record2, deviceId) {
|
|
|
45965
46410
|
ne3(projectLocations.path, record2.projectPath)
|
|
45966
46411
|
)
|
|
45967
46412
|
).all().some(
|
|
45968
|
-
(location) => isStrictlyInside(record2.projectPath, location.path) &&
|
|
46413
|
+
(location) => isStrictlyInside(record2.projectPath, location.path) && existsSync30(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record2.projectId
|
|
45969
46414
|
);
|
|
45970
46415
|
}
|
|
45971
46416
|
function demoteProjectLocation(db, record2, state) {
|
|
@@ -46016,7 +46461,7 @@ function rehomeDisplacedRows(db, projectId, projectPath, deviceId, probed) {
|
|
|
46016
46461
|
).orderBy(desc3(projectLocations.lastSeen)).all();
|
|
46017
46462
|
const present = (path) => {
|
|
46018
46463
|
const holding = probed?.get(holdingKey(row.projectId, path));
|
|
46019
|
-
return holding === void 0 ?
|
|
46464
|
+
return holding === void 0 ? existsSync30(path) : holding === "yes";
|
|
46020
46465
|
};
|
|
46021
46466
|
const home = candidates.find(
|
|
46022
46467
|
(c) => present(c.path) && db.select({ projectId: projectRegistry.projectId }).from(projectRegistry).where(eq11(projectRegistry.projectPath, c.path)).all().length === 0
|
|
@@ -46045,7 +46490,7 @@ async function listProjectCheckouts(projectId, opts = {}) {
|
|
|
46045
46490
|
projectHash: generateProjectHash(row.path),
|
|
46046
46491
|
firstSeen: row.firstSeen,
|
|
46047
46492
|
lastSeen: row.lastSeen,
|
|
46048
|
-
exists: local &&
|
|
46493
|
+
exists: local && existsSync30(row.path),
|
|
46049
46494
|
deviceId: local ? deviceId : row.deviceId,
|
|
46050
46495
|
state: row.state
|
|
46051
46496
|
});
|
|
@@ -46074,13 +46519,13 @@ __export(checkout_nonce_exports, {
|
|
|
46074
46519
|
readCheckoutNonce: () => readCheckoutNonce
|
|
46075
46520
|
});
|
|
46076
46521
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
46077
|
-
import { existsSync as
|
|
46078
|
-
import { join as
|
|
46522
|
+
import { existsSync as existsSync31, readFileSync as readFileSync10, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
46523
|
+
import { join as join34 } from "node:path";
|
|
46079
46524
|
function readInfo(projectRoot) {
|
|
46080
|
-
const path =
|
|
46081
|
-
if (!
|
|
46525
|
+
const path = join34(projectRoot, ".cleo", "project-info.json");
|
|
46526
|
+
if (!existsSync31(path)) return null;
|
|
46082
46527
|
try {
|
|
46083
|
-
const parsed = JSON.parse(
|
|
46528
|
+
const parsed = JSON.parse(readFileSync10(path, "utf-8"));
|
|
46084
46529
|
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
46085
46530
|
} catch {
|
|
46086
46531
|
return null;
|
|
@@ -46096,7 +46541,7 @@ function ensureCheckoutNonce(projectRoot) {
|
|
|
46096
46541
|
const info = readInfo(projectRoot);
|
|
46097
46542
|
if (!info) return null;
|
|
46098
46543
|
const nonce = randomBytes2(16).toString("hex");
|
|
46099
|
-
const path =
|
|
46544
|
+
const path = join34(projectRoot, ".cleo", "project-info.json");
|
|
46100
46545
|
const temp = `${path}.${randomBytes2(6).toString("hex")}.tmp`;
|
|
46101
46546
|
writeFileSync9(temp, `${JSON.stringify({ ...info, [CHECKOUT_NONCE_FIELD]: nonce }, null, 2)}
|
|
46102
46547
|
`);
|
|
@@ -46171,10 +46616,10 @@ __export(paths_exports, {
|
|
|
46171
46616
|
validateProjectRoot: () => validateProjectRoot,
|
|
46172
46617
|
worktreeScope: () => worktreeScope
|
|
46173
46618
|
});
|
|
46174
|
-
import { existsSync as
|
|
46175
|
-
import { createRequire as
|
|
46619
|
+
import { existsSync as existsSync32, readFileSync as readFileSync11, statSync as statSync9 } from "node:fs";
|
|
46620
|
+
import { createRequire as createRequire11 } from "node:module";
|
|
46176
46621
|
import { homedir as homedir2 } from "node:os";
|
|
46177
|
-
import { basename as basename10, dirname as
|
|
46622
|
+
import { basename as basename10, dirname as dirname19, join as join35, resolve as resolve15 } from "node:path";
|
|
46178
46623
|
import {
|
|
46179
46624
|
getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
|
|
46180
46625
|
getCleoTemplatesTildePath as _getCleoTemplatesTildePath,
|
|
@@ -46184,7 +46629,7 @@ import {
|
|
|
46184
46629
|
resolveCanonicalCleoDir as _resolveCanonicalCleoDir
|
|
46185
46630
|
} from "@cleocode/paths";
|
|
46186
46631
|
function _getDatabaseSyncCtor() {
|
|
46187
|
-
const _require7 =
|
|
46632
|
+
const _require7 = createRequire11(import.meta.url);
|
|
46188
46633
|
const mod = _require7("node:sqlite");
|
|
46189
46634
|
return mod.DatabaseSync;
|
|
46190
46635
|
}
|
|
@@ -46196,20 +46641,20 @@ function runWithWorktreeScopeFromEnv(fn) {
|
|
|
46196
46641
|
}
|
|
46197
46642
|
function isProjectInitialized(projectRoot) {
|
|
46198
46643
|
const root = projectRoot ?? getProjectRoot();
|
|
46199
|
-
const cleoDir =
|
|
46200
|
-
return
|
|
46644
|
+
const cleoDir = join35(root, ".cleo");
|
|
46645
|
+
return existsSync32(cleoDir) && existsSync32(join35(cleoDir, "tasks.db"));
|
|
46201
46646
|
}
|
|
46202
46647
|
function getCleoHome() {
|
|
46203
46648
|
return getPlatformPaths().data;
|
|
46204
46649
|
}
|
|
46205
46650
|
function getCleoTemplatesDir() {
|
|
46206
|
-
return
|
|
46651
|
+
return join35(getCleoHome(), "templates");
|
|
46207
46652
|
}
|
|
46208
46653
|
function getCleoSchemasDir() {
|
|
46209
|
-
return
|
|
46654
|
+
return join35(getCleoHome(), "schemas");
|
|
46210
46655
|
}
|
|
46211
46656
|
function getCleoDocsDir() {
|
|
46212
|
-
return
|
|
46657
|
+
return join35(getCleoHome(), "docs");
|
|
46213
46658
|
}
|
|
46214
46659
|
function getCleoDir(cwd) {
|
|
46215
46660
|
if (cwd) {
|
|
@@ -46258,24 +46703,24 @@ function getCleoDirAbsolute(cwd, opts) {
|
|
|
46258
46703
|
try {
|
|
46259
46704
|
const projectRoot = getProjectRoot(cwd);
|
|
46260
46705
|
const canonical = _resolveCanonicalCleoDir(project.projectId);
|
|
46261
|
-
if (canonical !== null && canonical ===
|
|
46706
|
+
if (canonical !== null && canonical === resolve15(projectRoot, cleoDir)) {
|
|
46262
46707
|
return canonical;
|
|
46263
46708
|
}
|
|
46264
|
-
return
|
|
46709
|
+
return resolve15(projectRoot, cleoDir);
|
|
46265
46710
|
} catch {
|
|
46266
|
-
return
|
|
46711
|
+
return resolve15(project.projectRoot, cleoDir);
|
|
46267
46712
|
}
|
|
46268
46713
|
}
|
|
46269
46714
|
try {
|
|
46270
|
-
return
|
|
46715
|
+
return resolve15(getProjectRoot(cwd), cleoDir);
|
|
46271
46716
|
} catch (err) {
|
|
46272
46717
|
if (opts?.bootstrap) {
|
|
46273
|
-
return
|
|
46718
|
+
return resolve15(cwd ?? process.cwd(), cleoDir);
|
|
46274
46719
|
}
|
|
46275
46720
|
if (_cwdHasGitAncestor(cwd)) {
|
|
46276
46721
|
throw err;
|
|
46277
46722
|
}
|
|
46278
|
-
return
|
|
46723
|
+
return resolve15(cwd ?? process.cwd(), cleoDir);
|
|
46279
46724
|
}
|
|
46280
46725
|
}
|
|
46281
46726
|
function resolveCanonicalCleoDir(projectId) {
|
|
@@ -46302,9 +46747,9 @@ function resolveCanonicalCleoDir(projectId) {
|
|
|
46302
46747
|
function _resolveProjectByCwdFromNexus(cwd) {
|
|
46303
46748
|
try {
|
|
46304
46749
|
const cleoHome = getCleoHome();
|
|
46305
|
-
const globalDbPath =
|
|
46306
|
-
if (!
|
|
46307
|
-
const start =
|
|
46750
|
+
const globalDbPath = join35(cleoHome, "cleo.db");
|
|
46751
|
+
if (!existsSync32(globalDbPath)) return null;
|
|
46752
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46308
46753
|
let current = start;
|
|
46309
46754
|
const DatabaseSync3 = _getDatabaseSyncCtor();
|
|
46310
46755
|
const db = new DatabaseSync3(globalDbPath, { readOnly: true });
|
|
@@ -46317,7 +46762,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
|
|
|
46317
46762
|
if (row && typeof row.project_id === "string" && row.project_id.length > 0) {
|
|
46318
46763
|
return row.project_id;
|
|
46319
46764
|
}
|
|
46320
|
-
const parent =
|
|
46765
|
+
const parent = dirname19(current);
|
|
46321
46766
|
if (parent === current) break;
|
|
46322
46767
|
current = parent;
|
|
46323
46768
|
}
|
|
@@ -46337,18 +46782,18 @@ function _cleoDirEnvOverride() {
|
|
|
46337
46782
|
}
|
|
46338
46783
|
function _findCleoDirRoot(cwd) {
|
|
46339
46784
|
const homeRoot = homedir2();
|
|
46340
|
-
let current =
|
|
46785
|
+
let current = resolve15(cwd ?? process.cwd());
|
|
46341
46786
|
while (true) {
|
|
46342
46787
|
const isDangerousRoot = current === homeRoot || current === "/" || current === "";
|
|
46343
46788
|
if (!isDangerousRoot) {
|
|
46344
46789
|
try {
|
|
46345
|
-
if (statSync9(
|
|
46790
|
+
if (statSync9(join35(current, ".cleo")).isDirectory()) {
|
|
46346
46791
|
return current;
|
|
46347
46792
|
}
|
|
46348
46793
|
} catch {
|
|
46349
46794
|
}
|
|
46350
46795
|
}
|
|
46351
|
-
const parent =
|
|
46796
|
+
const parent = dirname19(current);
|
|
46352
46797
|
if (parent === current) break;
|
|
46353
46798
|
current = parent;
|
|
46354
46799
|
}
|
|
@@ -46367,7 +46812,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46367
46812
|
if (pathsResult !== null) {
|
|
46368
46813
|
return pathsResult.projectId;
|
|
46369
46814
|
}
|
|
46370
|
-
const start =
|
|
46815
|
+
const start = resolve15(from ?? process.cwd());
|
|
46371
46816
|
let current = start;
|
|
46372
46817
|
while (true) {
|
|
46373
46818
|
const mainRepo = _resolveMainRepoFromGitlink(current);
|
|
@@ -46378,7 +46823,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46378
46823
|
}
|
|
46379
46824
|
break;
|
|
46380
46825
|
}
|
|
46381
|
-
const parent =
|
|
46826
|
+
const parent = dirname19(current);
|
|
46382
46827
|
if (parent === current) break;
|
|
46383
46828
|
current = parent;
|
|
46384
46829
|
}
|
|
@@ -46397,7 +46842,7 @@ function resolveProjectByCwd(cwd) {
|
|
|
46397
46842
|
function resolveCleoDir(cwd) {
|
|
46398
46843
|
const scope = worktreeScope.getStore();
|
|
46399
46844
|
if (scope !== void 0) {
|
|
46400
|
-
return
|
|
46845
|
+
return join35(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
|
|
46401
46846
|
}
|
|
46402
46847
|
const override = _cleoDirEnvOverride();
|
|
46403
46848
|
if (override !== null) {
|
|
@@ -46405,16 +46850,16 @@ function resolveCleoDir(cwd) {
|
|
|
46405
46850
|
}
|
|
46406
46851
|
const root = _findCleoDirRoot(cwd);
|
|
46407
46852
|
if (root !== null) {
|
|
46408
|
-
return
|
|
46853
|
+
return join35(resolveStoreOwnerRoot(root), ".cleo");
|
|
46409
46854
|
}
|
|
46410
|
-
const start =
|
|
46855
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46411
46856
|
let current = start;
|
|
46412
46857
|
while (true) {
|
|
46413
46858
|
const mainRepo = _resolveMainRepoFromGitlink(current);
|
|
46414
46859
|
if (mainRepo !== null) {
|
|
46415
|
-
return
|
|
46860
|
+
return join35(mainRepo, ".cleo");
|
|
46416
46861
|
}
|
|
46417
|
-
const parent =
|
|
46862
|
+
const parent = dirname19(current);
|
|
46418
46863
|
if (parent === current) {
|
|
46419
46864
|
break;
|
|
46420
46865
|
}
|
|
@@ -46453,25 +46898,25 @@ function _resolveCleoDir(cwd) {
|
|
|
46453
46898
|
const project = _pathsResolveProjectByCwd(cwd);
|
|
46454
46899
|
if (project !== null) {
|
|
46455
46900
|
try {
|
|
46456
|
-
return
|
|
46901
|
+
return resolve15(getProjectRoot(cwd), cleoDir);
|
|
46457
46902
|
} catch {
|
|
46458
|
-
return
|
|
46903
|
+
return resolve15(project.projectRoot, cleoDir);
|
|
46459
46904
|
}
|
|
46460
46905
|
}
|
|
46461
46906
|
return getCleoDirAbsolute(cwd);
|
|
46462
46907
|
}
|
|
46463
46908
|
function _cwdHasGitAncestor(cwd) {
|
|
46464
|
-
const start =
|
|
46909
|
+
const start = resolve15(cwd ?? process.cwd());
|
|
46465
46910
|
let current = start;
|
|
46466
46911
|
while (true) {
|
|
46467
|
-
const gitMarker =
|
|
46912
|
+
const gitMarker = join35(current, ".git");
|
|
46468
46913
|
try {
|
|
46469
|
-
if (
|
|
46914
|
+
if (existsSync32(gitMarker)) {
|
|
46470
46915
|
return true;
|
|
46471
46916
|
}
|
|
46472
46917
|
} catch {
|
|
46473
46918
|
}
|
|
46474
|
-
const parent =
|
|
46919
|
+
const parent = dirname19(current);
|
|
46475
46920
|
if (parent === current) return false;
|
|
46476
46921
|
current = parent;
|
|
46477
46922
|
}
|
|
@@ -46498,55 +46943,55 @@ function resolveProjectPath(relativePath, cwd) {
|
|
|
46498
46943
|
return relativePath;
|
|
46499
46944
|
}
|
|
46500
46945
|
if (relativePath.startsWith("~/") || relativePath.startsWith("~\\") || relativePath === "~") {
|
|
46501
|
-
return
|
|
46946
|
+
return resolve15(homedir2(), relativePath.slice(2));
|
|
46502
46947
|
}
|
|
46503
|
-
return
|
|
46948
|
+
return resolve15(getProjectRoot(cwd), relativePath);
|
|
46504
46949
|
}
|
|
46505
46950
|
function getTaskPath(cwd) {
|
|
46506
|
-
return
|
|
46951
|
+
return join35(_resolveCleoDir(cwd), "tasks.db");
|
|
46507
46952
|
}
|
|
46508
46953
|
function getConfigPath(cwd) {
|
|
46509
|
-
return
|
|
46954
|
+
return join35(_resolveCleoDir(cwd), "config.json");
|
|
46510
46955
|
}
|
|
46511
46956
|
function getSessionsPath(cwd) {
|
|
46512
|
-
return
|
|
46957
|
+
return join35(_resolveCleoDir(cwd), "sessions.json");
|
|
46513
46958
|
}
|
|
46514
46959
|
function getArchivePath(cwd) {
|
|
46515
|
-
return
|
|
46960
|
+
return join35(_resolveCleoDir(cwd), "tasks-archive.json");
|
|
46516
46961
|
}
|
|
46517
46962
|
function getLogPath(cwd) {
|
|
46518
|
-
return
|
|
46963
|
+
return join35(_resolveCleoDir(cwd), "logs", "cleo.log");
|
|
46519
46964
|
}
|
|
46520
46965
|
function getBackupDir(cwd) {
|
|
46521
|
-
return
|
|
46966
|
+
return join35(_resolveCleoDir(cwd), "backups", "operational");
|
|
46522
46967
|
}
|
|
46523
46968
|
function getGlobalConfigPath() {
|
|
46524
|
-
return
|
|
46969
|
+
return join35(getCleoHome(), "config.json");
|
|
46525
46970
|
}
|
|
46526
46971
|
function getCleoGlobalRecipesDir() {
|
|
46527
|
-
return
|
|
46972
|
+
return join35(getCleoHome(), "global-recipes");
|
|
46528
46973
|
}
|
|
46529
46974
|
function getCleoGlobalJustfilePath() {
|
|
46530
|
-
return
|
|
46975
|
+
return join35(getCleoGlobalRecipesDir(), "justfile");
|
|
46531
46976
|
}
|
|
46532
46977
|
function getCleoPiExtensionsDir() {
|
|
46533
|
-
return
|
|
46978
|
+
return join35(getCleoHome(), "pi-extensions");
|
|
46534
46979
|
}
|
|
46535
46980
|
function getCleoCantWorkflowsDir() {
|
|
46536
|
-
return
|
|
46981
|
+
return join35(getCleoHome(), "cant-workflows");
|
|
46537
46982
|
}
|
|
46538
46983
|
function getCleoGlobalAgentsDir() {
|
|
46539
|
-
return
|
|
46984
|
+
return join35(getCleoHome(), "agents");
|
|
46540
46985
|
}
|
|
46541
46986
|
function getCleoGlobalCantAgentsDir() {
|
|
46542
|
-
return
|
|
46987
|
+
return join35(getCleoHome(), "cant", "agents");
|
|
46543
46988
|
}
|
|
46544
46989
|
function getAgentOutputsDir(cwd) {
|
|
46545
46990
|
const projectRoot = getProjectRoot(cwd);
|
|
46546
|
-
const configPath =
|
|
46547
|
-
if (
|
|
46991
|
+
const configPath = join35(projectRoot, ".cleo", "config.json");
|
|
46992
|
+
if (existsSync32(configPath)) {
|
|
46548
46993
|
try {
|
|
46549
|
-
const config2 = JSON.parse(
|
|
46994
|
+
const config2 = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
46550
46995
|
if (typeof config2.agentOutputs === "object" && config2.agentOutputs?.directory) {
|
|
46551
46996
|
return config2.agentOutputs.directory;
|
|
46552
46997
|
}
|
|
@@ -46569,17 +47014,17 @@ function getAgentOutputsAbsolute(cwd) {
|
|
|
46569
47014
|
if (isAbsolutePath2(dir)) {
|
|
46570
47015
|
return dir;
|
|
46571
47016
|
}
|
|
46572
|
-
return
|
|
47017
|
+
return resolve15(getProjectRoot(cwd), dir);
|
|
46573
47018
|
}
|
|
46574
47019
|
function getManifestPath(cwd) {
|
|
46575
47020
|
const outputDir = getAgentOutputsDir(cwd);
|
|
46576
47021
|
const projectRoot = getProjectRoot(cwd);
|
|
46577
|
-
const configPath =
|
|
47022
|
+
const configPath = join35(projectRoot, ".cleo", "config.json");
|
|
46578
47023
|
const legacyFileName = ["MANIFEST", "jsonl"].join(".");
|
|
46579
47024
|
let manifestFile = legacyFileName;
|
|
46580
|
-
if (
|
|
47025
|
+
if (existsSync32(configPath)) {
|
|
46581
47026
|
try {
|
|
46582
|
-
const config2 = JSON.parse(
|
|
47027
|
+
const config2 = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
46583
47028
|
const customFile = config2.agentOutputs?.manifestFile ?? config2.research?.manifestFile;
|
|
46584
47029
|
if (customFile) {
|
|
46585
47030
|
manifestFile = customFile;
|
|
@@ -46587,12 +47032,12 @@ function getManifestPath(cwd) {
|
|
|
46587
47032
|
} catch {
|
|
46588
47033
|
}
|
|
46589
47034
|
}
|
|
46590
|
-
return
|
|
47035
|
+
return resolve15(projectRoot, outputDir, manifestFile);
|
|
46591
47036
|
}
|
|
46592
47037
|
function getManifestArchivePath(cwd) {
|
|
46593
47038
|
const outputDir = getAgentOutputsDir(cwd);
|
|
46594
47039
|
const projectRoot = getProjectRoot(cwd);
|
|
46595
|
-
return
|
|
47040
|
+
return resolve15(projectRoot, outputDir, "MANIFEST.archive.jsonl");
|
|
46596
47041
|
}
|
|
46597
47042
|
function isAbsolutePath2(path) {
|
|
46598
47043
|
return _isAbsolutePath(path);
|
|
@@ -46616,24 +47061,24 @@ function getCanonicalTemplatesTildePath() {
|
|
|
46616
47061
|
return _getCanonicalTemplatesTildePath();
|
|
46617
47062
|
}
|
|
46618
47063
|
function getAgentsHome() {
|
|
46619
|
-
return process.env["AGENTS_HOME"] ??
|
|
47064
|
+
return process.env["AGENTS_HOME"] ?? join35(homedir2(), ".agents");
|
|
46620
47065
|
}
|
|
46621
47066
|
function getClaudeAgentsDir() {
|
|
46622
|
-
const claudeDir = process.env["CLAUDE_HOME"] ??
|
|
46623
|
-
return
|
|
47067
|
+
const claudeDir = process.env["CLAUDE_HOME"] ?? join35(homedir2(), ".claude");
|
|
47068
|
+
return join35(claudeDir, "agents");
|
|
46624
47069
|
}
|
|
46625
47070
|
function getClaudeMemDbPath() {
|
|
46626
|
-
return process.env["CLAUDE_MEM_DB"] ??
|
|
47071
|
+
return process.env["CLAUDE_MEM_DB"] ?? join35(homedir2(), ".claude-mem", "claude-mem.db");
|
|
46627
47072
|
}
|
|
46628
47073
|
function resolveWorktreeRouting(cwdOverride) {
|
|
46629
|
-
const cwd =
|
|
47074
|
+
const cwd = resolve15(cwdOverride ?? process.cwd());
|
|
46630
47075
|
const home = homedir2();
|
|
46631
47076
|
let worktreePath;
|
|
46632
47077
|
let current = cwd;
|
|
46633
47078
|
while (current !== home && current !== "/" && current !== "") {
|
|
46634
|
-
const gitPath =
|
|
47079
|
+
const gitPath = join35(current, ".git");
|
|
46635
47080
|
try {
|
|
46636
|
-
if (
|
|
47081
|
+
if (existsSync32(gitPath)) {
|
|
46637
47082
|
const stat3 = statSync9(gitPath);
|
|
46638
47083
|
if (stat3.isFile()) {
|
|
46639
47084
|
worktreePath = current;
|
|
@@ -46645,7 +47090,7 @@ function resolveWorktreeRouting(cwdOverride) {
|
|
|
46645
47090
|
}
|
|
46646
47091
|
} catch {
|
|
46647
47092
|
}
|
|
46648
|
-
const parent =
|
|
47093
|
+
const parent = dirname19(current);
|
|
46649
47094
|
if (parent === current) break;
|
|
46650
47095
|
current = parent;
|
|
46651
47096
|
}
|
|
@@ -46662,17 +47107,17 @@ function resolveWorktreeRouting(cwdOverride) {
|
|
|
46662
47107
|
}
|
|
46663
47108
|
function resolveWorktreeFilePath(filePath, routing) {
|
|
46664
47109
|
if (!routing.isWorktree || routing.worktreePath === void 0) {
|
|
46665
|
-
return
|
|
47110
|
+
return resolve15(filePath);
|
|
46666
47111
|
}
|
|
46667
|
-
return
|
|
47112
|
+
return resolve15(routing.cwd, filePath);
|
|
46668
47113
|
}
|
|
46669
47114
|
function detectStrayCleoDb(routing) {
|
|
46670
47115
|
if (!routing.isWorktree || routing.worktreePath === void 0) {
|
|
46671
47116
|
return void 0;
|
|
46672
47117
|
}
|
|
46673
|
-
const tasksDbPath =
|
|
47118
|
+
const tasksDbPath = join35(routing.worktreePath, ".cleo", "tasks.db");
|
|
46674
47119
|
try {
|
|
46675
|
-
if (
|
|
47120
|
+
if (existsSync32(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
|
|
46676
47121
|
return tasksDbPath;
|
|
46677
47122
|
}
|
|
46678
47123
|
} catch {
|
|
@@ -46682,7 +47127,7 @@ function detectStrayCleoDb(routing) {
|
|
|
46682
47127
|
async function resolveProjectById(projectId) {
|
|
46683
47128
|
try {
|
|
46684
47129
|
const { getNexusDb: getNexusDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
46685
|
-
if (!
|
|
47130
|
+
if (!existsSync32(getNexusRegistryDbPath2())) return null;
|
|
46686
47131
|
const { eq: eq12 } = await import("drizzle-orm");
|
|
46687
47132
|
const { projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
46688
47133
|
const db = await getNexusDb2();
|
|
@@ -46717,9 +47162,9 @@ function _rowToRegistryEntry(row) {
|
|
|
46717
47162
|
};
|
|
46718
47163
|
}
|
|
46719
47164
|
function _readProjectNameFromInfo(projectRoot) {
|
|
46720
|
-
const infoPath =
|
|
46721
|
-
if (!
|
|
46722
|
-
const raw =
|
|
47165
|
+
const infoPath = join35(projectRoot, ".cleo", "project-info.json");
|
|
47166
|
+
if (!existsSync32(infoPath)) return void 0;
|
|
47167
|
+
const raw = readFileSync11(infoPath, "utf-8");
|
|
46723
47168
|
const data = JSON.parse(raw);
|
|
46724
47169
|
return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
|
|
46725
47170
|
}
|
|
@@ -46770,7 +47215,7 @@ async function recordProjectEncounter(cwd) {
|
|
|
46770
47215
|
if (!shouldAutoRegisterProject(project.projectRoot, cleoHome)) return "ephemeral";
|
|
46771
47216
|
const checkout = captureProjectScope(project.projectRoot, worktreeScope.getStore()).worktreeRoot;
|
|
46772
47217
|
const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
46773
|
-
if (
|
|
47218
|
+
if (existsSync32(getNexusRegistryDbPath2(cleoHome))) {
|
|
46774
47219
|
const { and: and8, eq: eq12 } = await import("drizzle-orm");
|
|
46775
47220
|
const { projectLocations: projectLocations2, projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
46776
47221
|
const { currentDeviceId: currentDeviceId2 } = await Promise.resolve().then(() => (init_path_map(), path_map_exports));
|
|
@@ -46947,42 +47392,42 @@ var init_paths = __esm({
|
|
|
46947
47392
|
// packages/core/src/store/file-utils.ts
|
|
46948
47393
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
46949
47394
|
import {
|
|
46950
|
-
existsSync as
|
|
47395
|
+
existsSync as existsSync33,
|
|
46951
47396
|
mkdirSync as mkdirSync10,
|
|
46952
47397
|
readdirSync as readdirSync8,
|
|
46953
|
-
readFileSync as
|
|
47398
|
+
readFileSync as readFileSync12,
|
|
46954
47399
|
renameSync as renameSync11,
|
|
46955
47400
|
unlinkSync as unlinkSync6,
|
|
46956
47401
|
writeFileSync as writeFileSync10
|
|
46957
47402
|
} from "node:fs";
|
|
46958
|
-
import { basename as basename11, dirname as
|
|
47403
|
+
import { basename as basename11, dirname as dirname20, join as join36 } from "node:path";
|
|
46959
47404
|
import * as lockfile3 from "proper-lockfile";
|
|
46960
47405
|
function rotateBackup(filePath, mode) {
|
|
46961
|
-
const dir =
|
|
47406
|
+
const dir = dirname20(filePath);
|
|
46962
47407
|
const name15 = basename11(filePath);
|
|
46963
|
-
const backupDir =
|
|
47408
|
+
const backupDir = join36(dir, ".backups");
|
|
46964
47409
|
const dirMode = typeof mode === "number" ? modeToDirMode(mode) : void 0;
|
|
46965
|
-
if (!
|
|
47410
|
+
if (!existsSync33(backupDir)) {
|
|
46966
47411
|
mkdirSync10(backupDir, { recursive: true, mode: dirMode });
|
|
46967
47412
|
}
|
|
46968
47413
|
for (let i = MAX_BACKUPS; i >= 1; i--) {
|
|
46969
|
-
const current =
|
|
47414
|
+
const current = join36(backupDir, `${name15}.${i}`);
|
|
46970
47415
|
if (i === MAX_BACKUPS) {
|
|
46971
47416
|
try {
|
|
46972
47417
|
unlinkSync6(current);
|
|
46973
47418
|
} catch {
|
|
46974
47419
|
}
|
|
46975
47420
|
} else {
|
|
46976
|
-
const next =
|
|
47421
|
+
const next = join36(backupDir, `${name15}.${i + 1}`);
|
|
46977
47422
|
try {
|
|
46978
|
-
if (
|
|
47423
|
+
if (existsSync33(current)) renameSync11(current, next);
|
|
46979
47424
|
} catch {
|
|
46980
47425
|
}
|
|
46981
47426
|
}
|
|
46982
47427
|
}
|
|
46983
47428
|
try {
|
|
46984
|
-
const content =
|
|
46985
|
-
const backupPath =
|
|
47429
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
47430
|
+
const backupPath = join36(backupDir, `${name15}.1`);
|
|
46986
47431
|
if (typeof mode === "number") {
|
|
46987
47432
|
writeFileSync10(backupPath, content, { encoding: "utf-8", mode });
|
|
46988
47433
|
} else {
|
|
@@ -47002,8 +47447,8 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
|
|
|
47002
47447
|
const opts = typeof optsOrIndent === "number" ? { indent: optsOrIndent } : optsOrIndent;
|
|
47003
47448
|
const indent = opts.indent ?? 2;
|
|
47004
47449
|
const mode = opts.mode;
|
|
47005
|
-
const dir =
|
|
47006
|
-
const tempPath =
|
|
47450
|
+
const dir = dirname20(filePath);
|
|
47451
|
+
const tempPath = join36(dir, `.${basename11(filePath)}.${randomBytes3(6).toString("hex")}.tmp`);
|
|
47007
47452
|
const content = JSON.stringify(data, null, indent) + "\n";
|
|
47008
47453
|
if (typeof mode === "number") {
|
|
47009
47454
|
writeFileSync10(tempPath, content, { encoding: "utf-8", mode });
|
|
@@ -47011,7 +47456,7 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
|
|
|
47011
47456
|
writeFileSync10(tempPath, content, "utf-8");
|
|
47012
47457
|
}
|
|
47013
47458
|
try {
|
|
47014
|
-
if (
|
|
47459
|
+
if (existsSync33(filePath)) {
|
|
47015
47460
|
rotateBackup(filePath, mode);
|
|
47016
47461
|
}
|
|
47017
47462
|
renameSync11(tempPath, filePath);
|
|
@@ -47025,7 +47470,7 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
|
|
|
47025
47470
|
}
|
|
47026
47471
|
function readJsonFile(filePath) {
|
|
47027
47472
|
try {
|
|
47028
|
-
const content =
|
|
47473
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
47029
47474
|
return JSON.parse(content);
|
|
47030
47475
|
} catch (error48) {
|
|
47031
47476
|
if (error48.code === "ENOENT") {
|
|
@@ -47035,12 +47480,12 @@ function readJsonFile(filePath) {
|
|
|
47035
47480
|
}
|
|
47036
47481
|
}
|
|
47037
47482
|
async function withLock2(filePath, transform2, opts = {}) {
|
|
47038
|
-
const dir =
|
|
47483
|
+
const dir = dirname20(filePath);
|
|
47039
47484
|
const dirMode = typeof opts.mode === "number" ? modeToDirMode(opts.mode) : void 0;
|
|
47040
|
-
if (!
|
|
47485
|
+
if (!existsSync33(dir)) {
|
|
47041
47486
|
mkdirSync10(dir, { recursive: true, mode: dirMode });
|
|
47042
47487
|
}
|
|
47043
|
-
if (!
|
|
47488
|
+
if (!existsSync33(filePath)) {
|
|
47044
47489
|
if (typeof opts.mode === "number") {
|
|
47045
47490
|
writeFileSync10(filePath, "", { encoding: "utf-8", mode: opts.mode });
|
|
47046
47491
|
} else {
|
|
@@ -47061,11 +47506,11 @@ async function withLock2(filePath, transform2, opts = {}) {
|
|
|
47061
47506
|
}
|
|
47062
47507
|
}
|
|
47063
47508
|
async function withFileLock(filePath, operation) {
|
|
47064
|
-
const dir =
|
|
47065
|
-
if (!
|
|
47509
|
+
const dir = dirname20(filePath);
|
|
47510
|
+
if (!existsSync33(dir)) {
|
|
47066
47511
|
mkdirSync10(dir, { recursive: true });
|
|
47067
47512
|
}
|
|
47068
|
-
if (!
|
|
47513
|
+
if (!existsSync33(filePath)) {
|
|
47069
47514
|
writeFileSync10(filePath, "", "utf-8");
|
|
47070
47515
|
}
|
|
47071
47516
|
let release;
|
|
@@ -47099,10 +47544,10 @@ var init_file_utils = __esm({
|
|
|
47099
47544
|
|
|
47100
47545
|
// packages/core/src/llm/credential-removal.ts
|
|
47101
47546
|
import { unlinkSync as unlinkSync7 } from "node:fs";
|
|
47102
|
-
import { join as
|
|
47547
|
+
import { join as join37 } from "node:path";
|
|
47103
47548
|
import { getCleoHome as getCleoHome4 } from "@cleocode/paths";
|
|
47104
47549
|
function suppressionStatePath() {
|
|
47105
|
-
return
|
|
47550
|
+
return join37(getCleoHome4(), SUPPRESSION_FILENAME);
|
|
47106
47551
|
}
|
|
47107
47552
|
function readSuppressionFile() {
|
|
47108
47553
|
const data = readJsonFile(suppressionStatePath());
|
|
@@ -47206,7 +47651,7 @@ var init_credential_removal = __esm({
|
|
|
47206
47651
|
sourceId: "cleo-pkce",
|
|
47207
47652
|
description: "Delete CLEO-issued PKCE token at <CLEO_HOME>/anthropic-oauth.json",
|
|
47208
47653
|
async remove() {
|
|
47209
|
-
const path =
|
|
47654
|
+
const path = join37(getCleoHome4(), "anthropic-oauth.json");
|
|
47210
47655
|
const cleaned = [];
|
|
47211
47656
|
try {
|
|
47212
47657
|
unlinkSync7(path);
|
|
@@ -47264,12 +47709,12 @@ var init_credential_removal = __esm({
|
|
|
47264
47709
|
});
|
|
47265
47710
|
|
|
47266
47711
|
// packages/core/src/llm/credential-seeders/claude-code-seeder.ts
|
|
47267
|
-
import { readFileSync as
|
|
47712
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
47268
47713
|
import { homedir as homedir3 } from "node:os";
|
|
47269
|
-
import { join as
|
|
47714
|
+
import { join as join38 } from "node:path";
|
|
47270
47715
|
function defaultReadCredentialFile() {
|
|
47271
47716
|
try {
|
|
47272
|
-
return
|
|
47717
|
+
return readFileSync13(join38(homedir3(), ".claude", ".credentials.json"), "utf-8");
|
|
47273
47718
|
} catch {
|
|
47274
47719
|
return null;
|
|
47275
47720
|
}
|
|
@@ -47363,14 +47808,14 @@ var init_claude_code_seeder = __esm({
|
|
|
47363
47808
|
});
|
|
47364
47809
|
|
|
47365
47810
|
// packages/core/src/llm/credential-seeders/cleo-pkce-seeder.ts
|
|
47366
|
-
import { readFileSync as
|
|
47367
|
-
import { join as
|
|
47811
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
47812
|
+
import { join as join39 } from "node:path";
|
|
47368
47813
|
function defaultCleoPkcePath() {
|
|
47369
|
-
return
|
|
47814
|
+
return join39(getCleoHome(), "anthropic-oauth.json");
|
|
47370
47815
|
}
|
|
47371
47816
|
function defaultReadCredentialFile2() {
|
|
47372
47817
|
try {
|
|
47373
|
-
return
|
|
47818
|
+
return readFileSync14(defaultCleoPkcePath(), "utf-8");
|
|
47374
47819
|
} catch {
|
|
47375
47820
|
return null;
|
|
47376
47821
|
}
|
|
@@ -47437,13 +47882,13 @@ var init_cleo_pkce_seeder = __esm({
|
|
|
47437
47882
|
});
|
|
47438
47883
|
|
|
47439
47884
|
// packages/core/src/llm/credential-seeders/codex-cli-seeder.ts
|
|
47440
|
-
import { existsSync as
|
|
47885
|
+
import { existsSync as existsSync34, readFileSync as readFileSync15 } from "node:fs";
|
|
47441
47886
|
import { homedir as homedir4 } from "node:os";
|
|
47442
|
-
import { join as
|
|
47887
|
+
import { join as join40 } from "node:path";
|
|
47443
47888
|
function getCodexAuthPath() {
|
|
47444
47889
|
const codexHome = (process.env["CODEX_HOME"] ?? "").trim();
|
|
47445
|
-
const root = codexHome ||
|
|
47446
|
-
return
|
|
47890
|
+
const root = codexHome || join40(homedir4(), ".codex");
|
|
47891
|
+
return join40(root, "auth.json");
|
|
47447
47892
|
}
|
|
47448
47893
|
var CodexCliSeeder, codexCliSeeder;
|
|
47449
47894
|
var init_codex_cli_seeder = __esm({
|
|
@@ -47462,12 +47907,12 @@ var init_codex_cli_seeder = __esm({
|
|
|
47462
47907
|
*/
|
|
47463
47908
|
async seed() {
|
|
47464
47909
|
const authPath = getCodexAuthPath();
|
|
47465
|
-
if (!
|
|
47910
|
+
if (!existsSync34(authPath)) {
|
|
47466
47911
|
return { entries: [] };
|
|
47467
47912
|
}
|
|
47468
47913
|
let raw;
|
|
47469
47914
|
try {
|
|
47470
|
-
raw =
|
|
47915
|
+
raw = readFileSync15(authPath, "utf-8");
|
|
47471
47916
|
} catch (err) {
|
|
47472
47917
|
return {
|
|
47473
47918
|
entries: [],
|
|
@@ -47657,11 +48102,11 @@ var init_google_pkce = __esm({
|
|
|
47657
48102
|
});
|
|
47658
48103
|
|
|
47659
48104
|
// packages/core/src/llm/credential-seeders/gemini-cli-seeder.ts
|
|
47660
|
-
import { existsSync as
|
|
47661
|
-
import { join as
|
|
48105
|
+
import { existsSync as existsSync35, readFileSync as readFileSync16 } from "node:fs";
|
|
48106
|
+
import { join as join41 } from "node:path";
|
|
47662
48107
|
import { getCleoHome as getCleoHome5 } from "@cleocode/paths";
|
|
47663
48108
|
function getGoogleOauthPath() {
|
|
47664
|
-
return
|
|
48109
|
+
return join41(getCleoHome5(), "google_oauth.json");
|
|
47665
48110
|
}
|
|
47666
48111
|
function parseGoogleOauthFile(raw) {
|
|
47667
48112
|
let json2;
|
|
@@ -47706,12 +48151,12 @@ var init_gemini_cli_seeder = __esm({
|
|
|
47706
48151
|
*/
|
|
47707
48152
|
async seed() {
|
|
47708
48153
|
const path = getGoogleOauthPath();
|
|
47709
|
-
if (!
|
|
48154
|
+
if (!existsSync35(path)) {
|
|
47710
48155
|
return { entries: [] };
|
|
47711
48156
|
}
|
|
47712
48157
|
let raw;
|
|
47713
48158
|
try {
|
|
47714
|
-
raw =
|
|
48159
|
+
raw = readFileSync16(path, "utf-8");
|
|
47715
48160
|
} catch (err) {
|
|
47716
48161
|
return {
|
|
47717
48162
|
entries: [],
|
|
@@ -47931,23 +48376,23 @@ var init_credential_seeders = __esm({
|
|
|
47931
48376
|
|
|
47932
48377
|
// packages/core/src/llm/global-config-migration.ts
|
|
47933
48378
|
import {
|
|
47934
|
-
existsSync as
|
|
48379
|
+
existsSync as existsSync36,
|
|
47935
48380
|
mkdirSync as mkdirSync11,
|
|
47936
|
-
readFileSync as
|
|
48381
|
+
readFileSync as readFileSync17,
|
|
47937
48382
|
renameSync as renameSync12,
|
|
47938
48383
|
unlinkSync as unlinkSync8,
|
|
47939
48384
|
writeFileSync as writeFileSync11
|
|
47940
48385
|
} from "node:fs";
|
|
47941
|
-
import { join as
|
|
48386
|
+
import { join as join42 } from "node:path";
|
|
47942
48387
|
import { getCleoHome as getCleoHome6, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
|
|
47943
48388
|
function configDirGlobalConfigPath() {
|
|
47944
|
-
return
|
|
48389
|
+
return join42(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
|
|
47945
48390
|
}
|
|
47946
48391
|
function legacyGlobalConfigPath() {
|
|
47947
|
-
return
|
|
48392
|
+
return join42(getCleoHome6(), GLOBAL_CONFIG_FILENAME);
|
|
47948
48393
|
}
|
|
47949
48394
|
function migrationMarkerPath() {
|
|
47950
|
-
return
|
|
48395
|
+
return join42(getCleoHome6(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
|
|
47951
48396
|
}
|
|
47952
48397
|
function tempTargetPath() {
|
|
47953
48398
|
return `${configDirGlobalConfigPath()}.tmp`;
|
|
@@ -47957,17 +48402,17 @@ function migrateGlobalConfigToConfigDir() {
|
|
|
47957
48402
|
const source = legacyGlobalConfigPath();
|
|
47958
48403
|
const target = configDirGlobalConfigPath();
|
|
47959
48404
|
const marker16 = migrationMarkerPath();
|
|
47960
|
-
if (
|
|
47961
|
-
if (!
|
|
48405
|
+
if (existsSync36(marker16)) return false;
|
|
48406
|
+
if (!existsSync36(source)) {
|
|
47962
48407
|
stampMarker(marker16);
|
|
47963
48408
|
return false;
|
|
47964
48409
|
}
|
|
47965
|
-
if (
|
|
48410
|
+
if (existsSync36(target)) {
|
|
47966
48411
|
backupSourceQuiet(source);
|
|
47967
48412
|
stampMarker(marker16);
|
|
47968
48413
|
return false;
|
|
47969
48414
|
}
|
|
47970
|
-
const raw =
|
|
48415
|
+
const raw = readFileSync17(source, "utf-8");
|
|
47971
48416
|
try {
|
|
47972
48417
|
JSON.parse(raw);
|
|
47973
48418
|
} catch (err) {
|
|
@@ -47995,7 +48440,7 @@ function migrateGlobalConfigToConfigDir() {
|
|
|
47995
48440
|
} catch (err) {
|
|
47996
48441
|
try {
|
|
47997
48442
|
const temp = tempTargetPath();
|
|
47998
|
-
if (
|
|
48443
|
+
if (existsSync36(temp)) unlinkSync8(temp);
|
|
47999
48444
|
} catch {
|
|
48000
48445
|
}
|
|
48001
48446
|
console.error(
|
|
@@ -48006,7 +48451,7 @@ function migrateGlobalConfigToConfigDir() {
|
|
|
48006
48451
|
}
|
|
48007
48452
|
function stampMarker(markerPath) {
|
|
48008
48453
|
try {
|
|
48009
|
-
mkdirSync11(
|
|
48454
|
+
mkdirSync11(join42(getCleoHome6(), MIGRATIONS_SUBDIR), { recursive: true });
|
|
48010
48455
|
writeFileSync11(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
|
|
48011
48456
|
`, { mode: 420 });
|
|
48012
48457
|
} catch {
|
|
@@ -48015,7 +48460,7 @@ function stampMarker(markerPath) {
|
|
|
48015
48460
|
function backupSourceQuiet(source) {
|
|
48016
48461
|
try {
|
|
48017
48462
|
const backup = `${source}${BACKUP_SUFFIX}`;
|
|
48018
|
-
if (
|
|
48463
|
+
if (existsSync36(backup)) return;
|
|
48019
48464
|
renameSync12(source, backup);
|
|
48020
48465
|
} catch {
|
|
48021
48466
|
}
|
|
@@ -48038,15 +48483,15 @@ var init_global_config_migration = __esm({
|
|
|
48038
48483
|
});
|
|
48039
48484
|
|
|
48040
48485
|
// packages/core/src/llm/legacy-flat-key-import.ts
|
|
48041
|
-
import { existsSync as
|
|
48042
|
-
import { join as
|
|
48486
|
+
import { existsSync as existsSync37, readFileSync as readFileSync18, renameSync as renameSync13, writeFileSync as writeFileSync12 } from "node:fs";
|
|
48487
|
+
import { join as join43 } from "node:path";
|
|
48043
48488
|
import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
|
|
48044
48489
|
function migrationPaths() {
|
|
48045
48490
|
const home = getCleoHome7();
|
|
48046
48491
|
return {
|
|
48047
|
-
flatPath:
|
|
48048
|
-
bakPath:
|
|
48049
|
-
markerPath:
|
|
48492
|
+
flatPath: join43(home, "anthropic-key"),
|
|
48493
|
+
bakPath: join43(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
|
|
48494
|
+
markerPath: join43(home, LEGACY_FLAT_KEY_MARKER)
|
|
48050
48495
|
};
|
|
48051
48496
|
}
|
|
48052
48497
|
function writeMarker(markerPath) {
|
|
@@ -48067,8 +48512,8 @@ function writeMarker(markerPath) {
|
|
|
48067
48512
|
}
|
|
48068
48513
|
function readFlatKey(flatPath) {
|
|
48069
48514
|
try {
|
|
48070
|
-
if (!
|
|
48071
|
-
const raw =
|
|
48515
|
+
if (!existsSync37(flatPath)) return null;
|
|
48516
|
+
const raw = readFileSync18(flatPath, "utf-8").trim();
|
|
48072
48517
|
return raw || null;
|
|
48073
48518
|
} catch (err) {
|
|
48074
48519
|
logger.warn(
|
|
@@ -48080,7 +48525,7 @@ function readFlatKey(flatPath) {
|
|
|
48080
48525
|
}
|
|
48081
48526
|
async function importLegacyFlatAnthropicKey() {
|
|
48082
48527
|
const { flatPath, bakPath, markerPath } = migrationPaths();
|
|
48083
|
-
if (
|
|
48528
|
+
if (existsSync37(markerPath)) {
|
|
48084
48529
|
return { status: "marker-present", flatPath, bakPath: null, markerPath };
|
|
48085
48530
|
}
|
|
48086
48531
|
let existing = null;
|
|
@@ -48097,7 +48542,7 @@ async function importLegacyFlatAnthropicKey() {
|
|
|
48097
48542
|
writeMarker(markerPath);
|
|
48098
48543
|
return { status: "already-imported", flatPath, bakPath: null, markerPath };
|
|
48099
48544
|
}
|
|
48100
|
-
if (!
|
|
48545
|
+
if (!existsSync37(flatPath)) {
|
|
48101
48546
|
writeMarker(markerPath);
|
|
48102
48547
|
return { status: "no-flat-file", flatPath, bakPath: null, markerPath };
|
|
48103
48548
|
}
|
|
@@ -48174,15 +48619,15 @@ __export(credentials_exports, {
|
|
|
48174
48619
|
resolveProviderStatus: () => resolveProviderStatus,
|
|
48175
48620
|
storeAnthropicApiKey: () => storeAnthropicApiKey
|
|
48176
48621
|
});
|
|
48177
|
-
import { existsSync as
|
|
48178
|
-
import { join as
|
|
48622
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync13 } from "node:fs";
|
|
48623
|
+
import { join as join44 } from "node:path";
|
|
48179
48624
|
import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
|
|
48180
48625
|
function globalConfigPath() {
|
|
48181
48626
|
return configDirGlobalConfigPath();
|
|
48182
48627
|
}
|
|
48183
48628
|
function projectConfigPath(projectRoot) {
|
|
48184
48629
|
const cleoDir = process.env["CLEO_DIR"] ?? ".cleo";
|
|
48185
|
-
return
|
|
48630
|
+
return join44(projectRoot, cleoDir, "config.json");
|
|
48186
48631
|
}
|
|
48187
48632
|
function readGlobalProviderKey(provider) {
|
|
48188
48633
|
ensureGlobalConfigMigrated();
|
|
@@ -48192,9 +48637,9 @@ function readGlobalProviderKey(provider) {
|
|
|
48192
48637
|
}
|
|
48193
48638
|
function readFlatAnthropicKey() {
|
|
48194
48639
|
try {
|
|
48195
|
-
const keyFile =
|
|
48196
|
-
if (!
|
|
48197
|
-
const stored =
|
|
48640
|
+
const keyFile = join44(getCleoHome8(), "anthropic-key");
|
|
48641
|
+
if (!existsSync38(keyFile)) return null;
|
|
48642
|
+
const stored = readFileSync19(keyFile, "utf-8").trim();
|
|
48198
48643
|
return stored || null;
|
|
48199
48644
|
} catch {
|
|
48200
48645
|
return null;
|
|
@@ -48202,8 +48647,8 @@ function readFlatAnthropicKey() {
|
|
|
48202
48647
|
}
|
|
48203
48648
|
function readProviderKeyFromConfig(configFile, provider) {
|
|
48204
48649
|
try {
|
|
48205
|
-
if (!
|
|
48206
|
-
const raw =
|
|
48650
|
+
if (!existsSync38(configFile)) return null;
|
|
48651
|
+
const raw = readFileSync19(configFile, "utf-8");
|
|
48207
48652
|
const config2 = JSON.parse(raw);
|
|
48208
48653
|
const llm = config2["llm"];
|
|
48209
48654
|
if (!llm || typeof llm !== "object") return null;
|
|
@@ -48375,10 +48820,10 @@ function resolveProviderStatus(provider) {
|
|
|
48375
48820
|
}
|
|
48376
48821
|
function storeAnthropicApiKey(apiKey) {
|
|
48377
48822
|
const dir = getCleoHome8();
|
|
48378
|
-
if (!
|
|
48823
|
+
if (!existsSync38(dir)) {
|
|
48379
48824
|
mkdirSync12(dir, { recursive: true });
|
|
48380
48825
|
}
|
|
48381
|
-
const keyFile =
|
|
48826
|
+
const keyFile = join44(dir, "anthropic-key");
|
|
48382
48827
|
writeFileSync13(keyFile, apiKey.trim(), { mode: 384 });
|
|
48383
48828
|
}
|
|
48384
48829
|
function clearAnthropicKeyCache() {
|
|
@@ -48443,16 +48888,16 @@ __export(credentials_store_exports, {
|
|
|
48443
48888
|
pickCredentialForProviderSync: () => pickCredentialForProviderSync,
|
|
48444
48889
|
removeCredential: () => removeCredential
|
|
48445
48890
|
});
|
|
48446
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
48447
|
-
import { dirname as
|
|
48891
|
+
import { chmodSync as chmodSync2, existsSync as existsSync39, mkdirSync as mkdirSync13, readFileSync as readFileSync20, statSync as statSync10, writeFileSync as writeFileSync14 } from "node:fs";
|
|
48892
|
+
import { dirname as dirname21, join as join45 } from "node:path";
|
|
48448
48893
|
import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
|
|
48449
48894
|
function credentialsStorePath() {
|
|
48450
|
-
return
|
|
48895
|
+
return join45(getCleoHome9(), "llm-credentials.json");
|
|
48451
48896
|
}
|
|
48452
48897
|
function ensureFileInitialized(path) {
|
|
48453
|
-
if (
|
|
48454
|
-
const dir =
|
|
48455
|
-
if (!
|
|
48898
|
+
if (existsSync39(path)) return;
|
|
48899
|
+
const dir = dirname21(path);
|
|
48900
|
+
if (!existsSync39(dir)) {
|
|
48456
48901
|
mkdirSync13(dir, { recursive: true, mode: 448 });
|
|
48457
48902
|
} else {
|
|
48458
48903
|
try {
|
|
@@ -48496,7 +48941,7 @@ function readStoreSync() {
|
|
|
48496
48941
|
const path = credentialsStorePath();
|
|
48497
48942
|
let raw;
|
|
48498
48943
|
try {
|
|
48499
|
-
raw =
|
|
48944
|
+
raw = readFileSync20(path, "utf-8");
|
|
48500
48945
|
} catch {
|
|
48501
48946
|
return emptyStore();
|
|
48502
48947
|
}
|
|
@@ -49085,13 +49530,13 @@ var init_xai = __esm({
|
|
|
49085
49530
|
|
|
49086
49531
|
// packages/core/src/llm/provider-registry/loader.ts
|
|
49087
49532
|
import { readdirSync as readdirSync9, statSync as statSync11 } from "node:fs";
|
|
49088
|
-
import { join as
|
|
49533
|
+
import { join as join46 } from "node:path";
|
|
49089
49534
|
import { pathToFileURL } from "node:url";
|
|
49090
49535
|
function isPluginFile(filename) {
|
|
49091
49536
|
return PLUGIN_EXTENSIONS.some((ext) => filename.endsWith(ext));
|
|
49092
49537
|
}
|
|
49093
49538
|
function getPluginDir() {
|
|
49094
|
-
return
|
|
49539
|
+
return join46(getCleoHome(), "plugins", "model-providers");
|
|
49095
49540
|
}
|
|
49096
49541
|
async function loadOnePlugin(absPath, api) {
|
|
49097
49542
|
let mod;
|
|
@@ -49139,13 +49584,13 @@ async function scanAndLoadPlugins(pluginDir, api) {
|
|
|
49139
49584
|
}
|
|
49140
49585
|
const pluginFiles = entries.filter((name15) => !name15.startsWith(".") && isPluginFile(name15)).filter((name15) => {
|
|
49141
49586
|
try {
|
|
49142
|
-
return statSync11(
|
|
49587
|
+
return statSync11(join46(pluginDir, name15)).isFile();
|
|
49143
49588
|
} catch {
|
|
49144
49589
|
return false;
|
|
49145
49590
|
}
|
|
49146
49591
|
}).sort();
|
|
49147
49592
|
for (const filename of pluginFiles) {
|
|
49148
|
-
await loadOnePlugin(
|
|
49593
|
+
await loadOnePlugin(join46(pluginDir, filename), api);
|
|
49149
49594
|
}
|
|
49150
49595
|
}
|
|
49151
49596
|
async function runDiscovery(registerProvider2, builtins) {
|
|
@@ -49248,15 +49693,15 @@ var init_provider_registry = __esm({
|
|
|
49248
49693
|
});
|
|
49249
49694
|
|
|
49250
49695
|
// packages/core/src/llm/rate-limit-guard.ts
|
|
49251
|
-
import { existsSync as
|
|
49252
|
-
import { join as
|
|
49696
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync14, unlinkSync as unlinkSync9 } from "node:fs";
|
|
49697
|
+
import { join as join47 } from "node:path";
|
|
49253
49698
|
import { getCleoHome as getCleoHome10 } from "@cleocode/paths";
|
|
49254
49699
|
function sanitize(value) {
|
|
49255
49700
|
return value.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
49256
49701
|
}
|
|
49257
49702
|
function rateLimitStatePath(provider, label) {
|
|
49258
|
-
const dir =
|
|
49259
|
-
return
|
|
49703
|
+
const dir = join47(getCleoHome10(), "rate-limit-state");
|
|
49704
|
+
return join47(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
|
|
49260
49705
|
}
|
|
49261
49706
|
function parseResetFromHeaders(headers) {
|
|
49262
49707
|
const get = (k) => {
|
|
@@ -49303,8 +49748,8 @@ async function recordRateLimit(provider, label, opts) {
|
|
|
49303
49748
|
source = "default";
|
|
49304
49749
|
}
|
|
49305
49750
|
const filePath = rateLimitStatePath(provider, label);
|
|
49306
|
-
const dir =
|
|
49307
|
-
if (!
|
|
49751
|
+
const dir = join47(getCleoHome10(), "rate-limit-state");
|
|
49752
|
+
if (!existsSync40(dir)) {
|
|
49308
49753
|
mkdirSync14(dir, { recursive: true });
|
|
49309
49754
|
}
|
|
49310
49755
|
const state = { resetAt, recordedAt: now, source };
|
|
@@ -50205,31 +50650,31 @@ var init_error_classifier = __esm({
|
|
|
50205
50650
|
|
|
50206
50651
|
// packages/core/src/llm/catalog-cache.ts
|
|
50207
50652
|
import {
|
|
50208
|
-
existsSync as
|
|
50653
|
+
existsSync as existsSync41,
|
|
50209
50654
|
mkdirSync as mkdirSync15,
|
|
50210
50655
|
readdirSync as readdirSync10,
|
|
50211
|
-
readFileSync as
|
|
50656
|
+
readFileSync as readFileSync21,
|
|
50212
50657
|
statSync as statSync12,
|
|
50213
50658
|
symlinkSync,
|
|
50214
50659
|
unlinkSync as unlinkSync10,
|
|
50215
50660
|
writeFileSync as writeFileSync15
|
|
50216
50661
|
} from "node:fs";
|
|
50217
|
-
import { join as
|
|
50662
|
+
import { join as join48 } from "node:path";
|
|
50218
50663
|
import { getCleoHome as getCleoHome11 } from "@cleocode/paths";
|
|
50219
50664
|
function getCatalogDir() {
|
|
50220
50665
|
if (process.env["CLEO_DATA_DIR"]) {
|
|
50221
|
-
return
|
|
50666
|
+
return join48(process.env["CLEO_DATA_DIR"], "llm-catalog");
|
|
50222
50667
|
}
|
|
50223
|
-
return
|
|
50668
|
+
return join48(getCleoHome11(), "llm-catalog");
|
|
50224
50669
|
}
|
|
50225
50670
|
function findLatestCacheFile(dir) {
|
|
50226
|
-
if (!
|
|
50227
|
-
const files = readdirSync10(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync12(
|
|
50228
|
-
return files.length > 0 ?
|
|
50671
|
+
if (!existsSync41(dir)) return null;
|
|
50672
|
+
const files = readdirSync10(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync12(join48(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
50673
|
+
return files.length > 0 ? join48(dir, files[0].name) : null;
|
|
50229
50674
|
}
|
|
50230
50675
|
function readCacheFile(filePath) {
|
|
50231
50676
|
try {
|
|
50232
|
-
const raw =
|
|
50677
|
+
const raw = readFileSync21(filePath, "utf-8");
|
|
50233
50678
|
return JSON.parse(raw);
|
|
50234
50679
|
} catch {
|
|
50235
50680
|
return null;
|
|
@@ -50242,16 +50687,16 @@ var init_catalog_cache = __esm({
|
|
|
50242
50687
|
});
|
|
50243
50688
|
|
|
50244
50689
|
// packages/core/src/llm/model-metadata.ts
|
|
50245
|
-
import { readFileSync as
|
|
50246
|
-
import { dirname as
|
|
50247
|
-
import { fileURLToPath as
|
|
50690
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
50691
|
+
import { dirname as dirname22, join as join49 } from "node:path";
|
|
50692
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
50248
50693
|
function getCuratedTable() {
|
|
50249
50694
|
if (_curated !== void 0) {
|
|
50250
50695
|
return _curated;
|
|
50251
50696
|
}
|
|
50252
|
-
const thisDir =
|
|
50253
|
-
const jsonPath =
|
|
50254
|
-
const raw = JSON.parse(
|
|
50697
|
+
const thisDir = dirname22(fileURLToPath4(import.meta.url));
|
|
50698
|
+
const jsonPath = join49(thisDir, "curated-models.json");
|
|
50699
|
+
const raw = JSON.parse(readFileSync22(jsonPath, "utf-8"));
|
|
50255
50700
|
_curated = raw.models;
|
|
50256
50701
|
return _curated;
|
|
50257
50702
|
}
|
|
@@ -50336,7 +50781,7 @@ function storedToResolved(stored) {
|
|
|
50336
50781
|
};
|
|
50337
50782
|
}
|
|
50338
50783
|
function sleep3(ms) {
|
|
50339
|
-
return new Promise((
|
|
50784
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
50340
50785
|
}
|
|
50341
50786
|
function backoffMs(policy, attempt) {
|
|
50342
50787
|
const base = policy.baseDelayMs * 2 ** attempt;
|
|
@@ -54278,7 +54723,7 @@ function normalizeOllamaToolCall(tc) {
|
|
|
54278
54723
|
};
|
|
54279
54724
|
}
|
|
54280
54725
|
function sleep4(ms) {
|
|
54281
|
-
return new Promise((
|
|
54726
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
54282
54727
|
}
|
|
54283
54728
|
var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
|
|
54284
54729
|
var init_ollama2 = __esm({
|
|
@@ -74792,7 +75237,7 @@ function createProviderToolFactoryWithOutputSchema({
|
|
|
74792
75237
|
supportsDeferredResults
|
|
74793
75238
|
});
|
|
74794
75239
|
}
|
|
74795
|
-
async function
|
|
75240
|
+
async function resolve16(value) {
|
|
74796
75241
|
if (typeof value === "function") {
|
|
74797
75242
|
value = value();
|
|
74798
75243
|
}
|
|
@@ -78826,14 +79271,14 @@ var init_dist4 = __esm({
|
|
|
78826
79271
|
headers
|
|
78827
79272
|
}) {
|
|
78828
79273
|
return combineHeaders(
|
|
78829
|
-
await
|
|
79274
|
+
await resolve16(this.config.headers),
|
|
78830
79275
|
headers,
|
|
78831
79276
|
betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {}
|
|
78832
79277
|
);
|
|
78833
79278
|
}
|
|
78834
79279
|
async getBetasFromHeaders(requestHeaders) {
|
|
78835
79280
|
var _a17, _b16;
|
|
78836
|
-
const configHeaders = await
|
|
79281
|
+
const configHeaders = await resolve16(this.config.headers);
|
|
78837
79282
|
const configBetaHeader = (_a17 = configHeaders["anthropic-beta"]) != null ? _a17 : "";
|
|
78838
79283
|
const requestBetaHeader = (_b16 = requestHeaders == null ? void 0 : requestHeaders["anthropic-beta"]) != null ? _b16 : "";
|
|
78839
79284
|
return new Set(
|