@cleocode/core 2026.9.24 → 2026.9.26
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/admin/import-tasks.d.ts.map +1 -1
- package/dist/admin/import-tasks.js +5 -2
- package/dist/admin/import-tasks.js.map +1 -1
- package/dist/admin/import.d.ts.map +1 -1
- package/dist/admin/import.js +7 -2
- package/dist/admin/import.js.map +1 -1
- package/dist/audit-prune.d.ts +32 -0
- package/dist/audit-prune.d.ts.map +1 -1
- package/dist/audit-prune.js +37 -3
- package/dist/audit-prune.js.map +1 -1
- package/dist/build-provenance.json +2 -2
- package/dist/cloud/crypto.d.ts +1 -2
- package/dist/cloud/crypto.d.ts.map +1 -1
- package/dist/cloud/crypto.js +1 -11
- package/dist/cloud/crypto.js.map +1 -1
- package/dist/cloud/index.d.ts +1 -0
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +1 -0
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/nexus-auth.d.ts +26 -1
- package/dist/cloud/nexus-auth.d.ts.map +1 -1
- package/dist/cloud/nexus-auth.js +61 -32
- package/dist/cloud/nexus-auth.js.map +1 -1
- package/dist/cloud/nexus-credentials.js +2 -2
- package/dist/cloud/nexus-credentials.js.map +1 -1
- package/dist/cloud/nexus-device.d.ts +809 -0
- package/dist/cloud/nexus-device.d.ts.map +1 -0
- package/dist/cloud/nexus-device.js +1680 -0
- package/dist/cloud/nexus-device.js.map +1 -0
- package/dist/cloud/nexus-enrol.d.ts +210 -0
- package/dist/cloud/nexus-enrol.d.ts.map +1 -0
- package/dist/cloud/nexus-enrol.js +1023 -0
- package/dist/cloud/nexus-enrol.js.map +1 -0
- package/dist/cloud/nexus-link.d.ts +3 -0
- package/dist/cloud/nexus-link.d.ts.map +1 -1
- package/dist/cloud/nexus-link.js +38 -4
- package/dist/cloud/nexus-link.js.map +1 -1
- package/dist/cloud/signing.d.ts +20 -0
- package/dist/cloud/signing.d.ts.map +1 -1
- package/dist/cloud/signing.js +14 -0
- package/dist/cloud/signing.js.map +1 -1
- package/dist/cloud/uuidv7.d.ts +9 -0
- package/dist/cloud/uuidv7.d.ts.map +1 -0
- package/dist/cloud/uuidv7.js +19 -0
- package/dist/cloud/uuidv7.js.map +1 -0
- package/dist/crypto/credentials.d.ts +61 -0
- package/dist/crypto/credentials.d.ts.map +1 -1
- package/dist/crypto/credentials.js +154 -58
- package/dist/crypto/credentials.js.map +1 -1
- package/dist/decide/bench/index.d.ts +1 -1
- package/dist/decide/bench/index.d.ts.map +1 -1
- package/dist/decide/bench/index.js +1 -1
- package/dist/decide/bench/index.js.map +1 -1
- package/dist/decide/bench/operation.d.ts +1 -1
- package/dist/decide/bench/operation.d.ts.map +1 -1
- package/dist/decide/bench/operation.js +1 -1
- package/dist/decide/bench/operation.js.map +1 -1
- package/dist/decide/bench/profiles.d.ts +50 -22
- package/dist/decide/bench/profiles.d.ts.map +1 -1
- package/dist/decide/bench/profiles.js +103 -59
- package/dist/decide/bench/profiles.js.map +1 -1
- package/dist/decide/bench/report.d.ts.map +1 -1
- package/dist/decide/bench/report.js +6 -1
- package/dist/decide/bench/report.js.map +1 -1
- package/dist/decide/bench/runner.d.ts +6 -1
- package/dist/decide/bench/runner.d.ts.map +1 -1
- package/dist/decide/bench/runner.js +1 -0
- package/dist/decide/bench/runner.js.map +1 -1
- package/dist/decide/client.d.ts.map +1 -1
- package/dist/decide/client.js +11 -5
- package/dist/decide/client.js.map +1 -1
- package/dist/decide/jev-wire.d.ts +31 -1
- package/dist/decide/jev-wire.d.ts.map +1 -1
- package/dist/decide/jev-wire.js +61 -7
- package/dist/decide/jev-wire.js.map +1 -1
- package/dist/docs/export-document.js +12907 -10622
- package/dist/docs/export-document.js.map +3 -3
- package/dist/doctor/dependency-cycles.d.ts +41 -0
- package/dist/doctor/dependency-cycles.d.ts.map +1 -0
- package/dist/doctor/dependency-cycles.js +39 -0
- package/dist/doctor/dependency-cycles.js.map +1 -0
- package/dist/doctor/index.d.ts +2 -0
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/orphan-ac-bindings.d.ts +64 -0
- package/dist/doctor/orphan-ac-bindings.d.ts.map +1 -0
- package/dist/doctor/orphan-ac-bindings.js +59 -0
- package/dist/doctor/orphan-ac-bindings.js.map +1 -0
- package/dist/doctor/projects.d.ts.map +1 -1
- package/dist/doctor/projects.js +43 -29
- package/dist/doctor/projects.js.map +1 -1
- package/dist/doctor/row-identity.d.ts +42 -0
- package/dist/doctor/row-identity.d.ts.map +1 -0
- package/dist/doctor/row-identity.js +151 -0
- package/dist/doctor/row-identity.js.map +1 -0
- package/dist/doctor/twin-collapse.d.ts +58 -2
- package/dist/doctor/twin-collapse.d.ts.map +1 -1
- package/dist/doctor/twin-collapse.js +212 -14
- package/dist/doctor/twin-collapse.js.map +1 -1
- package/dist/error-catalog.d.ts.map +1 -1
- package/dist/error-catalog.js +4 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +8 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.d.ts.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.js +10 -0
- package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
- package/dist/llm/plugin-facade.js +17767 -15482
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +19 -10
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/manifest-identity.d.ts +171 -0
- package/dist/memory/manifest-identity.d.ts.map +1 -0
- package/dist/memory/manifest-identity.js +345 -0
- package/dist/memory/manifest-identity.js.map +1 -0
- package/dist/memory/mental-model-queue.d.ts +14 -4
- package/dist/memory/mental-model-queue.d.ts.map +1 -1
- package/dist/memory/mental-model-queue.js +64 -35
- package/dist/memory/mental-model-queue.js.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.d.ts +47 -5
- package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.js +130 -14
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
- package/dist/memory/retrieval/observe.d.ts.map +1 -1
- package/dist/memory/retrieval/observe.js +2 -0
- package/dist/memory/retrieval/observe.js.map +1 -1
- package/dist/memory/transcript-scanner.js +1 -1
- package/dist/nexus/deps.d.ts.map +1 -1
- package/dist/nexus/deps.js +7 -14
- package/dist/nexus/deps.js.map +1 -1
- package/dist/nexus/discover.d.ts.map +1 -1
- package/dist/nexus/discover.js +6 -9
- package/dist/nexus/discover.js.map +1 -1
- package/dist/nexus/git-state.d.ts.map +1 -1
- package/dist/nexus/git-state.js +10 -1
- package/dist/nexus/git-state.js.map +1 -1
- package/dist/nexus/projects-clean.d.ts.map +1 -1
- package/dist/nexus/projects-clean.js +22 -11
- package/dist/nexus/projects-clean.js.map +1 -1
- package/dist/nexus/projects-scan.d.ts.map +1 -1
- package/dist/nexus/projects-scan.js +8 -13
- package/dist/nexus/projects-scan.js.map +1 -1
- package/dist/nexus/query.d.ts.map +1 -1
- package/dist/nexus/query.js +4 -12
- package/dist/nexus/query.js.map +1 -1
- package/dist/nexus/registry-roots.d.ts +5 -2
- package/dist/nexus/registry-roots.d.ts.map +1 -1
- package/dist/nexus/registry-roots.js +8 -10
- package/dist/nexus/registry-roots.js.map +1 -1
- package/dist/nexus/registry.d.ts +18 -0
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/nexus/registry.js +37 -16
- package/dist/nexus/registry.js.map +1 -1
- package/dist/nexus/workspace.d.ts.map +1 -1
- package/dist/nexus/workspace.js +54 -4
- package/dist/nexus/workspace.js.map +1 -1
- package/dist/orchestrate/lifecycle-ops.js +1 -1
- package/dist/orchestrate/lifecycle-ops.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +4 -2
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/orchestrate/query-ops.d.ts.map +1 -1
- package/dist/orchestrate/query-ops.js +3 -3
- package/dist/orchestrate/query-ops.js.map +1 -1
- package/dist/orchestrate/spawn-ops.js +1 -1
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestrate/worktree-complete.d.ts.map +1 -1
- package/dist/orchestrate/worktree-complete.js +40 -2
- package/dist/orchestrate/worktree-complete.js.map +1 -1
- package/dist/orchestration/index.js +1 -1
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lead-rollup.d.ts.map +1 -1
- package/dist/orchestration/lead-rollup.js +3 -3
- package/dist/orchestration/lead-rollup.js.map +1 -1
- package/dist/orchestration/parallel.js +1 -1
- package/dist/orchestration/parallel.js.map +1 -1
- package/dist/orchestration/spawn-prompt.d.ts +26 -0
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +62 -91
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/wave-topic.d.ts +4 -2
- package/dist/orchestration/wave-topic.d.ts.map +1 -1
- package/dist/orchestration/wave-topic.js +6 -4
- package/dist/orchestration/wave-topic.js.map +1 -1
- package/dist/orchestration/waves.d.ts +2 -1
- package/dist/orchestration/waves.d.ts.map +1 -1
- package/dist/orchestration/waves.js +4 -3
- package/dist/orchestration/waves.js.map +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +4 -2
- package/dist/phases/index.js.map +1 -1
- package/dist/release/ci-evidence.d.ts +190 -0
- package/dist/release/ci-evidence.d.ts.map +1 -1
- package/dist/release/ci-evidence.js +436 -4
- package/dist/release/ci-evidence.js.map +1 -1
- package/dist/sdk/validator-ac-pull.d.ts.map +1 -1
- package/dist/sdk/validator-ac-pull.js +2 -1
- package/dist/sdk/validator-ac-pull.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +12807 -10522
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sentient/cross-project-hygiene.d.ts +5 -0
- package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
- package/dist/sentient/cross-project-hygiene.js +7 -1
- package/dist/sentient/cross-project-hygiene.js.map +1 -1
- package/dist/sentient/propose-tick.d.ts.map +1 -1
- package/dist/sentient/propose-tick.js +2 -3
- package/dist/sentient/propose-tick.js.map +1 -1
- package/dist/sentient/stage-drift-tick.d.ts.map +1 -1
- package/dist/sentient/stage-drift-tick.js +2 -3
- package/dist/sentient/stage-drift-tick.js.map +1 -1
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +77 -49
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/focus-state-store.d.ts +69 -23
- package/dist/sessions/focus-state-store.d.ts.map +1 -1
- package/dist/sessions/focus-state-store.js +113 -27
- package/dist/sessions/focus-state-store.js.map +1 -1
- package/dist/sessions/handoff.js +1 -1
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +24 -13
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/terminal-identity.d.ts +165 -17
- package/dist/sessions/terminal-identity.d.ts.map +1 -1
- package/dist/sessions/terminal-identity.js +341 -32
- package/dist/sessions/terminal-identity.js.map +1 -1
- package/dist/skills/manifests/research.js +2 -0
- package/dist/skills/manifests/research.js.map +1 -1
- package/dist/skills/orchestrator/startup.js +2 -2
- package/dist/skills/orchestrator/startup.js.map +1 -1
- package/dist/skills/orchestrator/validator.d.ts.map +1 -1
- package/dist/skills/orchestrator/validator.js +9 -2
- package/dist/skills/orchestrator/validator.js.map +1 -1
- package/dist/skills/validation.d.ts +4 -1
- package/dist/skills/validation.d.ts.map +1 -1
- package/dist/skills/validation.js +11 -3
- package/dist/skills/validation.js.map +1 -1
- package/dist/snapshot/index.d.ts +4 -0
- package/dist/snapshot/index.d.ts.map +1 -1
- package/dist/snapshot/index.js +50 -3
- package/dist/snapshot/index.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts +111 -7
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +296 -8
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/store/ac-binding-prune.d.ts +144 -0
- package/dist/store/ac-binding-prune.d.ts.map +1 -0
- package/dist/store/ac-binding-prune.js +293 -0
- package/dist/store/ac-binding-prune.js.map +1 -0
- package/dist/store/agent-registry-store.d.ts.map +1 -1
- package/dist/store/agent-registry-store.js +3 -2
- package/dist/store/agent-registry-store.js.map +1 -1
- package/dist/store/backup-sidecar.d.ts +85 -2
- package/dist/store/backup-sidecar.d.ts.map +1 -1
- package/dist/store/backup-sidecar.js +173 -1
- package/dist/store/backup-sidecar.js.map +1 -1
- package/dist/store/conduit-sqlite.d.ts.map +1 -1
- package/dist/store/conduit-sqlite.js +3 -2
- 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 +3 -0
- package/dist/store/credential-transfer.js.map +1 -1
- package/dist/store/db-helpers.d.ts +32 -13
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +144 -40
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/dependency-cycles.d.ts +164 -0
- package/dist/store/dependency-cycles.d.ts.map +1 -0
- package/dist/store/dependency-cycles.js +360 -0
- package/dist/store/dependency-cycles.js.map +1 -0
- package/dist/store/display-id-alias.d.ts +585 -0
- package/dist/store/display-id-alias.d.ts.map +1 -0
- package/dist/store/display-id-alias.js +1538 -0
- package/dist/store/display-id-alias.js.map +1 -0
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +48 -0
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/migrate.d.ts.map +1 -1
- package/dist/store/exodus/migrate.js +8 -1
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/exodus/reconcile.d.ts.map +1 -1
- package/dist/store/exodus/reconcile.js +7 -2
- package/dist/store/exodus/reconcile.js.map +1 -1
- package/dist/store/exodus/recovery.d.ts.map +1 -1
- package/dist/store/exodus/recovery.js +20 -1
- package/dist/store/exodus/recovery.js.map +1 -1
- package/dist/store/global-salt.d.ts +35 -0
- package/dist/store/global-salt.d.ts.map +1 -1
- package/dist/store/global-salt.js +136 -16
- package/dist/store/global-salt.js.map +1 -1
- package/dist/store/legacy-tasks-lineage.d.ts.map +1 -1
- package/dist/store/legacy-tasks-lineage.js +19 -2
- package/dist/store/legacy-tasks-lineage.js.map +1 -1
- package/dist/store/migration-sqlite.d.ts.map +1 -1
- package/dist/store/migration-sqlite.js +19 -11
- package/dist/store/migration-sqlite.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +6 -0
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/row-identity-flag.d.ts +26 -0
- package/dist/store/row-identity-flag.d.ts.map +1 -0
- package/dist/store/row-identity-flag.js +31 -0
- package/dist/store/row-identity-flag.js.map +1 -0
- package/dist/store/row-identity-registry.d.ts +61 -0
- package/dist/store/row-identity-registry.d.ts.map +1 -0
- package/dist/store/row-identity-registry.js +206 -0
- package/dist/store/row-identity-registry.js.map +1 -0
- package/dist/store/row-identity.d.ts +480 -0
- package/dist/store/row-identity.d.ts.map +1 -0
- package/dist/store/row-identity.js +1509 -0
- package/dist/store/row-identity.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +5 -2
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +9 -2
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/schema/attachments.d.ts +1 -1
- package/dist/store/schema/audit.d.ts +4 -4
- package/dist/store/schema/background-jobs.d.ts +1 -1
- package/dist/store/schema/cleo-global/nexus.d.ts +1 -1
- package/dist/store/schema/cleo-global/skills.d.ts +2 -2
- package/dist/store/schema/cleo-project/audit.d.ts +4 -4
- package/dist/store/schema/cleo-project/docs.d.ts +1 -1
- package/dist/store/schema/cleo-project/lifecycle.d.ts +4 -4
- package/dist/store/schema/cleo-project/nexus-graph.d.ts +3 -3
- package/dist/store/schema/cleo-project/provenance-commits.d.ts +2 -2
- package/dist/store/schema/cleo-project/provenance-rest.d.ts +3 -3
- package/dist/store/schema/cleo-project/runtime.d.ts +3 -3
- package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts +87 -1
- package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core-batch2.js +35 -0
- package/dist/store/schema/cleo-project/tasks-core-batch2.js.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.d.ts +183 -7
- package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.js +52 -1
- package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +6 -6
- package/dist/store/schema/lifecycle.d.ts +4 -4
- package/dist/store/schema/manifest.d.ts +1 -1
- package/dist/store/schema/memory-schema.d.ts +5 -5
- package/dist/store/schema/nexus-schema.d.ts +3 -3
- package/dist/store/schema/provenance/releases.d.ts +1 -1
- package/dist/store/schema/skills-schema.d.ts +2 -2
- package/dist/store/schema/tasks.d.ts +6 -6
- package/dist/store/session-store.d.ts +63 -3
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +121 -8
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/split-brain-import.d.ts +2 -14
- package/dist/store/split-brain-import.d.ts.map +1 -1
- package/dist/store/split-brain-import.js +40 -19
- package/dist/store/split-brain-import.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +326 -2
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +782 -49
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sync/clock-store.d.ts +67 -0
- package/dist/store/sync/clock-store.d.ts.map +1 -0
- package/dist/store/sync/clock-store.js +117 -0
- package/dist/store/sync/clock-store.js.map +1 -0
- package/dist/store/sync/flags.d.ts +51 -0
- package/dist/store/sync/flags.d.ts.map +1 -0
- package/dist/store/sync/flags.js +81 -0
- package/dist/store/sync/flags.js.map +1 -0
- package/dist/store/sync/hlc.d.ts +115 -0
- package/dist/store/sync/hlc.d.ts.map +1 -0
- package/dist/store/sync/hlc.js +172 -0
- package/dist/store/sync/hlc.js.map +1 -0
- package/dist/store/sync/index.d.ts +20 -0
- package/dist/store/sync/index.d.ts.map +1 -0
- package/dist/store/sync/index.js +20 -0
- package/dist/store/sync/index.js.map +1 -0
- package/dist/store/sync/replica-registry.d.ts +85 -0
- package/dist/store/sync/replica-registry.d.ts.map +1 -0
- package/dist/store/sync/replica-registry.js +147 -0
- package/dist/store/sync/replica-registry.js.map +1 -0
- package/dist/store/sync/replica.d.ts +181 -0
- package/dist/store/sync/replica.d.ts.map +1 -0
- package/dist/store/sync/replica.js +305 -0
- package/dist/store/sync/replica.js.map +1 -0
- package/dist/store/sync/schema.d.ts +68 -0
- package/dist/store/sync/schema.d.ts.map +1 -0
- package/dist/store/sync/schema.js +130 -0
- package/dist/store/sync/schema.js.map +1 -0
- package/dist/store/sync/skew-hold.d.ts +71 -0
- package/dist/store/sync/skew-hold.d.ts.map +1 -0
- package/dist/store/sync/skew-hold.js +89 -0
- package/dist/store/sync/skew-hold.js.map +1 -0
- package/dist/store/table-classification.d.ts +10 -8
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +93 -25
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +23 -3
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +113 -2
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +247 -19
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +5 -2
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +9 -2
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +241 -49
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/health.d.ts +2 -0
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +57 -0
- package/dist/system/health.js.map +1 -1
- package/dist/system/project-health.d.ts +9 -2
- package/dist/system/project-health.d.ts.map +1 -1
- package/dist/system/project-health.js +8 -3
- package/dist/system/project-health.js.map +1 -1
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +9 -6
- package/dist/task-work/index.js.map +1 -1
- package/dist/tasks/ac-coverage-gate.d.ts.map +1 -1
- package/dist/tasks/ac-coverage-gate.js +3 -0
- package/dist/tasks/ac-coverage-gate.js.map +1 -1
- package/dist/tasks/ac-table.d.ts +35 -7
- package/dist/tasks/ac-table.d.ts.map +1 -1
- package/dist/tasks/ac-table.js +119 -14
- package/dist/tasks/ac-table.js.map +1 -1
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +48 -2
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/analyze.d.ts.map +1 -1
- package/dist/tasks/analyze.js +3 -2
- package/dist/tasks/analyze.js.map +1 -1
- package/dist/tasks/backfill-child-projections.js +47 -6
- package/dist/tasks/backfill-child-projections.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +6 -1
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/completion-evaluation.d.ts.map +1 -1
- package/dist/tasks/completion-evaluation.js +3 -0
- package/dist/tasks/completion-evaluation.js.map +1 -1
- package/dist/tasks/evidence.d.ts +19 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +93 -21
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/infer-add-params.js +1 -1
- package/dist/tasks/infer-add-params.js.map +1 -1
- package/dist/tasks/task-context.d.ts.map +1 -1
- package/dist/tasks/task-context.js +3 -1
- package/dist/tasks/task-context.js.map +1 -1
- package/dist/tasks/task-import.d.ts.map +1 -1
- package/dist/tasks/task-import.js +11 -3
- package/dist/tasks/task-import.js.map +1 -1
- package/dist/tasks/task-next.d.ts +5 -1
- package/dist/tasks/task-next.d.ts.map +1 -1
- package/dist/tasks/task-next.js +7 -2
- package/dist/tasks/task-next.js.map +1 -1
- package/dist/validation/compliance.d.ts +5 -1
- package/dist/validation/compliance.d.ts.map +1 -1
- package/dist/validation/compliance.js +24 -3
- package/dist/validation/compliance.js.map +1 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +3 -2
- package/dist/validation/engine-ops.js.map +1 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/protocol-common.d.ts +47 -2
- package/dist/validation/protocol-common.d.ts.map +1 -1
- package/dist/validation/protocol-common.js +86 -21
- package/dist/validation/protocol-common.js.map +1 -1
- package/dist/workgraph/scaffold-apply.d.ts.map +1 -1
- package/dist/workgraph/scaffold-apply.js +14 -5
- package/dist/workgraph/scaffold-apply.js.map +1 -1
- package/migrations/README.md +12 -0
- package/migrations/drizzle-cleo-project/20260928120000_t12341-row-uids/migration.sql +169 -0
- package/migrations/drizzle-cleo-project/20260930160000_t12886-dependency-cycle-guard/migration.sql +76 -0
- package/migrations/drizzle-cleo-project/20260930160000_t12886-dependency-cycle-guard/revert.sql +7 -0
- package/migrations/sync-journal/20260929140000_t12342-sync-clock/migration.sql +42 -0
- package/package.json +13 -13
- package/templates/CLEO-INJECTION.md +2 -2
- package/templates/CLEO-REFERENCE.md +5 -1
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
* @task T12535
|
|
180
180
|
*/
|
|
181
181
|
import { createHash } from 'node:crypto';
|
|
182
|
-
import { existsSync } from 'node:fs';
|
|
182
|
+
import { existsSync, statSync } from 'node:fs';
|
|
183
183
|
import { basename, dirname } from 'node:path';
|
|
184
184
|
import { fileURLToPath } from 'node:url';
|
|
185
185
|
import { ExitCode } from '@cleocode/contracts';
|
|
@@ -187,7 +187,7 @@ import { z } from 'zod';
|
|
|
187
187
|
import { CleoError } from '../errors.js';
|
|
188
188
|
import { getLogger } from '../logger.js';
|
|
189
189
|
import { getCleoVersion } from '../scaffold/ensure-config.js';
|
|
190
|
-
import { isPinnedBackup, pinBackup } from './backup-sidecar.js';
|
|
190
|
+
import { isPinnedBackup, pinBackup, readBackupSidecar, restoreBackupSidecar, unpinBackup, } from './backup-sidecar.js';
|
|
191
191
|
import { blobFileForRow, pinBlob, restoreBlob } from './blob-keep.js';
|
|
192
192
|
import { planMigrationSnapshot, writeMigrationSnapshot } from './pre-repair-snapshot.js';
|
|
193
193
|
const log = getLogger('twin-collapse');
|
|
@@ -1571,7 +1571,11 @@ function collapsePair(db, pair, snapshotPath, dbPath) {
|
|
|
1571
1571
|
task: 'T12535',
|
|
1572
1572
|
collapsedAt: state?.collapsedAt || now,
|
|
1573
1573
|
lastMergedAt: now,
|
|
1574
|
-
|
|
1574
|
+
// Only an initial collapse records the snapshot it took. A later one
|
|
1575
|
+
// keeps what the marker holds, including `null` after an owner
|
|
1576
|
+
// released it (T12767): the snapshot another pair's initial collapse
|
|
1577
|
+
// took is not this pair's pre-collapse store.
|
|
1578
|
+
snapshot: state === undefined ? snapshotPath : state.snapshot,
|
|
1575
1579
|
hashes: { bare: pair.bareHashes(db), twin: pair.twinHashes(db) },
|
|
1576
1580
|
dropped: state === undefined ? plan.dropped : state.dropped,
|
|
1577
1581
|
kept: state === undefined ? plan.kept.slice(0, MAX_CONFLICTS) : state.kept,
|
|
@@ -1924,9 +1928,10 @@ function stickySetsIfPresent(db, table) {
|
|
|
1924
1928
|
* @returns The plan.
|
|
1925
1929
|
* @task T12727
|
|
1926
1930
|
*/
|
|
1927
|
-
export function planTwinCollapseRecovery(live, snapshot) {
|
|
1931
|
+
export function planTwinCollapseRecovery(live, snapshot, options = {}) {
|
|
1928
1932
|
const state = readState(live, SCHEMA_META);
|
|
1929
|
-
const
|
|
1933
|
+
const recorded = state?.snapshot ?? null;
|
|
1934
|
+
const snapshotPath = recorded === null ? null : (options.snapshotPath ?? recorded);
|
|
1930
1935
|
const liveKv = kvRows(live, 'tasks_schema_meta');
|
|
1931
1936
|
const receipts = [...recoveryReceipts(live)]
|
|
1932
1937
|
.filter(([, r]) => r.rolledBackAt === null)
|
|
@@ -1935,12 +1940,14 @@ export function planTwinCollapseRecovery(live, snapshot) {
|
|
|
1935
1940
|
const empty = {
|
|
1936
1941
|
snapshot: snapshotPath,
|
|
1937
1942
|
snapshotExists: snapshot !== null,
|
|
1943
|
+
snapshotPinned: recoverySnapshotPinned(snapshotPath),
|
|
1938
1944
|
archive: [],
|
|
1939
1945
|
focusNotesAdded: 0,
|
|
1940
1946
|
stickyArchived: [],
|
|
1941
1947
|
stickyArchiveKey: STICKY_ARCHIVE_KEY,
|
|
1942
1948
|
receipts,
|
|
1943
1949
|
changes: false,
|
|
1950
|
+
movedFrom: recorded !== null && snapshotPath !== recorded ? recorded : null,
|
|
1944
1951
|
};
|
|
1945
1952
|
if (snapshot === null)
|
|
1946
1953
|
return empty;
|
|
@@ -1959,11 +1966,25 @@ export function planTwinCollapseRecovery(live, snapshot) {
|
|
|
1959
1966
|
continue; // not replaced
|
|
1960
1967
|
const reason = sBare.has(key) ? 'replaced' : 'dropped';
|
|
1961
1968
|
const done = liveKv.get(key) === twinValue || archivedValues.has(twinValue);
|
|
1962
|
-
if (key === 'focus_state' &&
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1969
|
+
if (key === 'focus_state' && !done && receipts.length === 0) {
|
|
1970
|
+
if (focusBefore !== null) {
|
|
1971
|
+
const merged = mergeFocusState(focusBefore, twinValue);
|
|
1972
|
+
if (merged !== focusBefore) {
|
|
1973
|
+
focusNotesAdded = sessionNotesOf(merged).length - sessionNotesOf(focusBefore).length;
|
|
1974
|
+
focusState = merged;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
else if (reason === 'dropped') {
|
|
1978
|
+
// Only the twin held it (the kodomeet shape) and nothing replaced the
|
|
1979
|
+
// legacy key since: its notes are live again. Its pointer is not:
|
|
1980
|
+
// bound sessions keep their focus under `focus_state:<sessionId>`
|
|
1981
|
+
// (T11345, T12501), and the next keyless one would adopt a live legacy
|
|
1982
|
+
// pointer months stale. The full value stays in the archive (T12771).
|
|
1983
|
+
const parsed = FocusNotesShape.safeParse(parseJson(twinValue));
|
|
1984
|
+
if (parsed.success) {
|
|
1985
|
+
focusState = JSON.stringify({ ...parsed.data, currentTask: null });
|
|
1986
|
+
focusNotesAdded = parsed.data.sessionNotes.length;
|
|
1987
|
+
}
|
|
1967
1988
|
}
|
|
1968
1989
|
}
|
|
1969
1990
|
if (done)
|
|
@@ -2017,6 +2038,7 @@ export function planTwinCollapseRecovery(live, snapshot) {
|
|
|
2017
2038
|
};
|
|
2018
2039
|
recoveryWrites.set(plan, {
|
|
2019
2040
|
snapshot,
|
|
2041
|
+
options,
|
|
2020
2042
|
kv,
|
|
2021
2043
|
focusBefore,
|
|
2022
2044
|
focusState,
|
|
@@ -2042,19 +2064,36 @@ export function planTwinCollapseRecovery(live, snapshot) {
|
|
|
2042
2064
|
* snapshot is missing (nothing is written).
|
|
2043
2065
|
* @task T12727
|
|
2044
2066
|
*/
|
|
2045
|
-
export function applyTwinCollapseRecovery(live, plan) {
|
|
2067
|
+
export function applyTwinCollapseRecovery(live, plan, onRepoint) {
|
|
2046
2068
|
if (plan.snapshot === null)
|
|
2047
|
-
return { plan, receipt: null };
|
|
2069
|
+
return { plan, receipt: null, repointed: null };
|
|
2048
2070
|
const preview = recoveryWrites.get(plan);
|
|
2049
2071
|
if (!plan.snapshotExists || preview === undefined)
|
|
2050
2072
|
throw missingSnapshot(plan.snapshot);
|
|
2051
2073
|
live.exec('BEGIN IMMEDIATE');
|
|
2052
2074
|
try {
|
|
2053
|
-
const fresh = planTwinCollapseRecovery(live, preview.snapshot);
|
|
2075
|
+
const fresh = planTwinCollapseRecovery(live, preview.snapshot, preview.options);
|
|
2054
2076
|
const writes = recoveryWrites.get(fresh);
|
|
2077
|
+
// Only when there is something to write (T12772): a re-run on a
|
|
2078
|
+
// recovered store is a no-op whatever the pin. Checked before anything
|
|
2079
|
+
// (the re-point, its audit row) is written.
|
|
2080
|
+
if (fresh.changes && writes !== undefined && !fresh.snapshotPinned)
|
|
2081
|
+
throw unpinnedSnapshot(fresh.snapshot);
|
|
2082
|
+
// A moved store (T12788): the markers name the file where it lives now,
|
|
2083
|
+
// whether or not anything is left to recover. `onRepoint` audits it just
|
|
2084
|
+
// before COMMIT, so a failure that rolls the re-point back leaves no
|
|
2085
|
+
// audit row claiming it.
|
|
2086
|
+
let repointed = null;
|
|
2087
|
+
if (fresh.movedFrom !== null && fresh.snapshot !== null)
|
|
2088
|
+
repointed = repointSnapshotMarkers(live, fresh.movedFrom, fresh.snapshot);
|
|
2055
2089
|
if (!fresh.changes || writes === undefined) {
|
|
2056
|
-
|
|
2057
|
-
|
|
2090
|
+
if (repointed === null)
|
|
2091
|
+
live.exec('ROLLBACK');
|
|
2092
|
+
else {
|
|
2093
|
+
onRepoint?.(repointed);
|
|
2094
|
+
live.exec('COMMIT');
|
|
2095
|
+
}
|
|
2096
|
+
return { plan: fresh, receipt: null, repointed };
|
|
2058
2097
|
}
|
|
2059
2098
|
const recoveredAt = new Date().toISOString();
|
|
2060
2099
|
let id = `${TWIN_COLLAPSE_RECOVERY_PREFIX}${recoveredAt}`;
|
|
@@ -2090,8 +2129,10 @@ export function applyTwinCollapseRecovery(live, plan) {
|
|
|
2090
2129
|
if (writes.stickyArchive !== null)
|
|
2091
2130
|
writeKv(live, 'brain_schema_meta', fresh.stickyArchiveKey, writes.stickyArchive);
|
|
2092
2131
|
writeKv(live, 'tasks_schema_meta', id, JSON.stringify(receipt));
|
|
2132
|
+
if (repointed !== null)
|
|
2133
|
+
onRepoint?.(repointed);
|
|
2093
2134
|
live.exec('COMMIT');
|
|
2094
|
-
return { plan: fresh, receipt };
|
|
2135
|
+
return { plan: fresh, receipt, repointed };
|
|
2095
2136
|
}
|
|
2096
2137
|
catch (error) {
|
|
2097
2138
|
if (live.isTransaction)
|
|
@@ -2099,6 +2140,24 @@ export function applyTwinCollapseRecovery(live, plan) {
|
|
|
2099
2140
|
throw error;
|
|
2100
2141
|
}
|
|
2101
2142
|
}
|
|
2143
|
+
/** Point every marker that records `from` at `to` (inside the caller's transaction). */
|
|
2144
|
+
function repointSnapshotMarkers(live, from, to) {
|
|
2145
|
+
const markers = [];
|
|
2146
|
+
for (const pair of PAIRS) {
|
|
2147
|
+
if (!hasMainTable(live, pair.kvTable))
|
|
2148
|
+
continue;
|
|
2149
|
+
const key = `${TWIN_COLLAPSE_MARKER_PREFIX}${pair.table}`;
|
|
2150
|
+
const raw = readKv(live, pair.kvTable, key);
|
|
2151
|
+
const parsed = raw === undefined ? undefined : parseJson(raw);
|
|
2152
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
2153
|
+
continue;
|
|
2154
|
+
if (parsed.snapshot !== from)
|
|
2155
|
+
continue;
|
|
2156
|
+
writeKv(live, pair.kvTable, key, JSON.stringify({ ...parsed, snapshot: to }));
|
|
2157
|
+
markers.push(`${pair.kvTable}:${key}`);
|
|
2158
|
+
}
|
|
2159
|
+
return { from, to, markers };
|
|
2160
|
+
}
|
|
2102
2161
|
/** The error for a recorded snapshot that is not on disk. */
|
|
2103
2162
|
export function missingSnapshot(path) {
|
|
2104
2163
|
return new CleoError(ExitCode.NOT_FOUND, `${E_TWIN_COLLAPSE_RECOVER}: the pre-collapse snapshot ${path ?? '(none recorded)'} is missing; nothing was recovered`, {
|
|
@@ -2106,6 +2165,28 @@ export function missingSnapshot(path) {
|
|
|
2106
2165
|
details: { field: 'snapshot', actual: path },
|
|
2107
2166
|
});
|
|
2108
2167
|
}
|
|
2168
|
+
/** The error for a recorded snapshot rotation could still delete. */
|
|
2169
|
+
export function unpinnedSnapshot(path) {
|
|
2170
|
+
return new CleoError(ExitCode.VALIDATION_ERROR, `${E_TWIN_COLLAPSE_RECOVER}: the pre-collapse snapshot ${path ?? '(none recorded)'} is not pinned, so backup rotation may delete it; nothing was recovered`, {
|
|
2171
|
+
fix: 'cleo doctor twin-collapse --recover --pin-snapshot # pins it (writes only its .meta.json sidecar), then recovers',
|
|
2172
|
+
details: { field: 'snapshotPinned', expected: true, actual: false },
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
/** Whether the recorded snapshot is on disk and pinned. */
|
|
2176
|
+
function recoverySnapshotPinned(path) {
|
|
2177
|
+
return (path !== null && existsSync(path) && isPinnedBackup(dirname(path), basename(path), 'migration'));
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* Pin the recorded pre-collapse snapshot before a recovery
|
|
2181
|
+
* (`--pin-snapshot`): writes its `.meta.json` sidecar only, never the snapshot.
|
|
2182
|
+
*
|
|
2183
|
+
* @param path - The snapshot the marker records.
|
|
2184
|
+
* @returns Whether it is pinned now.
|
|
2185
|
+
* @task T12727
|
|
2186
|
+
*/
|
|
2187
|
+
export function pinRecoverySnapshot(path) {
|
|
2188
|
+
return pinBackup(path, 'migration', SNAPSHOT_PIN_REASON);
|
|
2189
|
+
}
|
|
2109
2190
|
/**
|
|
2110
2191
|
* Undo one recovery apply (`cleo doctor twin-collapse --rollback <id>`), in
|
|
2111
2192
|
* one `BEGIN IMMEDIATE` transaction:
|
|
@@ -2152,12 +2233,16 @@ export function rollbackTwinCollapseRecovery(live, id) {
|
|
|
2152
2233
|
}
|
|
2153
2234
|
let focusState = 'none';
|
|
2154
2235
|
let notesRemoved = 0;
|
|
2155
|
-
if (receipt.after.focusState !== null
|
|
2236
|
+
if (receipt.after.focusState !== null) {
|
|
2156
2237
|
const current = readKv(live, 'tasks_schema_meta', 'focus_state');
|
|
2157
2238
|
if (current !== undefined && sha(current) === receipt.after.focusState) {
|
|
2158
2239
|
notesRemoved =
|
|
2159
|
-
sessionNotesOf(current).length -
|
|
2160
|
-
|
|
2240
|
+
sessionNotesOf(current).length -
|
|
2241
|
+
sessionNotesOf(receipt.before.focusState ?? undefined).length;
|
|
2242
|
+
if (receipt.before.focusState === null)
|
|
2243
|
+
live.prepare("DELETE FROM main.tasks_schema_meta WHERE key = 'focus_state'").run();
|
|
2244
|
+
else
|
|
2245
|
+
writeKv(live, 'tasks_schema_meta', 'focus_state', receipt.before.focusState);
|
|
2161
2246
|
focusState = 'restored';
|
|
2162
2247
|
}
|
|
2163
2248
|
else if (current !== undefined) {
|
|
@@ -2203,4 +2288,147 @@ export function rollbackTwinCollapseRecovery(live, id) {
|
|
|
2203
2288
|
throw error;
|
|
2204
2289
|
}
|
|
2205
2290
|
}
|
|
2291
|
+
// ── releasing a pre-collapse snapshot (T12767) ──────────────────────────────
|
|
2292
|
+
/** Error code of a snapshot release that cannot proceed; nothing was written. */
|
|
2293
|
+
export const E_TWIN_COLLAPSE_RELEASE = 'E_TWIN_COLLAPSE_RELEASE';
|
|
2294
|
+
/** Pairs whose loss the recovery (T12727) verifies; a release covers only these. */
|
|
2295
|
+
const RECOVERABLE_PAIRS = [SCHEMA_META, STICKY_TAGS];
|
|
2296
|
+
/** Whether a recorded snapshot path is the one `id` names (backup id, file name or path). */
|
|
2297
|
+
function namesSnapshot(path, id) {
|
|
2298
|
+
const want = basename(id);
|
|
2299
|
+
const have = basename(path);
|
|
2300
|
+
return have === want || have.endsWith(`.${want}`);
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* Plan releasing a pre-collapse snapshot (T12767): which markers reference
|
|
2304
|
+
* it, how many bytes it holds, and whether it may be released. It may only
|
|
2305
|
+
* after a verified recovery or a no-recovery-needed check: the recovery plan
|
|
2306
|
+
* against it ({@link planTwinCollapseRecovery}) must find nothing left to
|
|
2307
|
+
* recover, and only the `schema_meta` / `sticky_tags` markers (the pairs the
|
|
2308
|
+
* recovery covers) may reference it.
|
|
2309
|
+
*
|
|
2310
|
+
* @param live - The project `cleo.db` connection (read-only is enough).
|
|
2311
|
+
* @param id - The snapshot: its backup id (`migration-<timestamp>`), file name or path.
|
|
2312
|
+
* @param snapshot - The snapshot opened read-only, or `null` when it is not on disk.
|
|
2313
|
+
* @returns The plan.
|
|
2314
|
+
* @task T12767
|
|
2315
|
+
*/
|
|
2316
|
+
export function planSnapshotRelease(live, id, snapshot, options = {}) {
|
|
2317
|
+
let path = null;
|
|
2318
|
+
const markers = [];
|
|
2319
|
+
const blockers = [];
|
|
2320
|
+
for (const pair of PAIRS) {
|
|
2321
|
+
if (!hasMainTable(live, pair.kvTable))
|
|
2322
|
+
continue;
|
|
2323
|
+
const recorded = readState(live, pair)?.snapshot;
|
|
2324
|
+
if (typeof recorded !== 'string' || !namesSnapshot(recorded, id))
|
|
2325
|
+
continue;
|
|
2326
|
+
path ??= recorded;
|
|
2327
|
+
markers.push(`${pair.kvTable}:${TWIN_COLLAPSE_MARKER_PREFIX}${pair.table}`);
|
|
2328
|
+
if (!RECOVERABLE_PAIRS.includes(pair))
|
|
2329
|
+
blockers.push(`the ${pair.table} marker references it, and the recovery does not cover ${pair.table}`);
|
|
2330
|
+
}
|
|
2331
|
+
if (path === null)
|
|
2332
|
+
return {
|
|
2333
|
+
snapshot: null,
|
|
2334
|
+
markers,
|
|
2335
|
+
exists: false,
|
|
2336
|
+
bytes: 0,
|
|
2337
|
+
basis: null,
|
|
2338
|
+
receipts: [],
|
|
2339
|
+
blockers: [`no twin-collapse marker references ${id}`],
|
|
2340
|
+
movedFrom: null,
|
|
2341
|
+
};
|
|
2342
|
+
// A moved store (T12788): the markers name the old path; the file is local.
|
|
2343
|
+
const recorded = path;
|
|
2344
|
+
path = options.snapshotPath ?? recorded;
|
|
2345
|
+
const exists = existsSync(path);
|
|
2346
|
+
const bytes = [path, `${path}-wal`, `${path}-shm`].reduce((sum, f) => sum + (existsSync(f) ? statSync(f).size : 0), 0);
|
|
2347
|
+
const receipts = [...recoveryReceipts(live)]
|
|
2348
|
+
.filter(([, r]) => r.rolledBackAt === null && (r.snapshot === path || r.snapshot === recorded))
|
|
2349
|
+
.map(([k]) => k)
|
|
2350
|
+
.sort();
|
|
2351
|
+
if (!exists || snapshot === null)
|
|
2352
|
+
blockers.push('the snapshot is not on disk, so no recovery check can run against it');
|
|
2353
|
+
else {
|
|
2354
|
+
const recovery = planTwinCollapseRecovery(live, snapshot, { snapshotPath: path });
|
|
2355
|
+
if (recovery.changes)
|
|
2356
|
+
blockers.push(`it still holds ${recovery.archive.length} value(s), ${recovery.focusNotesAdded} session note(s) and ` +
|
|
2357
|
+
`${recovery.stickyArchived.length} sticky tag(s) the live store lacks: run --recover first`);
|
|
2358
|
+
}
|
|
2359
|
+
return {
|
|
2360
|
+
snapshot: path,
|
|
2361
|
+
markers,
|
|
2362
|
+
exists,
|
|
2363
|
+
bytes,
|
|
2364
|
+
basis: blockers.length > 0 ? null : receipts.length > 0 ? 'recovered' : 'no-recovery-needed',
|
|
2365
|
+
receipts,
|
|
2366
|
+
blockers,
|
|
2367
|
+
movedFrom: recorded !== path ? recorded : null,
|
|
2368
|
+
};
|
|
2369
|
+
}
|
|
2370
|
+
/** The release refusal for a plan with blockers. */
|
|
2371
|
+
export function releaseRefused(id, plan) {
|
|
2372
|
+
return new CleoError(ExitCode.VALIDATION_ERROR, `${E_TWIN_COLLAPSE_RELEASE}: ${id} cannot be released: ${plan.blockers.join('; ')}; nothing was changed`, {
|
|
2373
|
+
fix: `cleo doctor twin-collapse --recover --dry-run # then --recover, and --release-snapshot ${id} --dry-run`,
|
|
2374
|
+
details: { field: 'snapshot', actual: plan.snapshot, blockers: plan.blockers },
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* Release a pre-collapse snapshot, in one `BEGIN IMMEDIATE` transaction: the
|
|
2379
|
+
* plan is re-checked under the write lock, each referencing marker's
|
|
2380
|
+
* `snapshot` is cleared (so an open no longer pins it and rotation no longer
|
|
2381
|
+
* keeps it), its sidecar pin is released, and `audit` records the release
|
|
2382
|
+
* before the commit (a failed audit write refuses it). The snapshot file is
|
|
2383
|
+
* never touched; it rotates normally from then on.
|
|
2384
|
+
*
|
|
2385
|
+
* @param live - The project `cleo.db` connection, outside a transaction.
|
|
2386
|
+
* @param id - The snapshot: backup id, file name or path.
|
|
2387
|
+
* @param snapshot - The snapshot opened read-only, or `null`.
|
|
2388
|
+
* @param audit - Appends the audit row; throws to refuse.
|
|
2389
|
+
* @returns What was released.
|
|
2390
|
+
* @throws {CleoError} {@link E_TWIN_COLLAPSE_RELEASE} when it may not be released.
|
|
2391
|
+
* @task T12767
|
|
2392
|
+
*/
|
|
2393
|
+
export function releaseTwinCollapseSnapshot(live, id, snapshot, audit, options = {}) {
|
|
2394
|
+
live.exec('BEGIN IMMEDIATE');
|
|
2395
|
+
let sidecarBefore;
|
|
2396
|
+
let path = null;
|
|
2397
|
+
try {
|
|
2398
|
+
const plan = planSnapshotRelease(live, id, snapshot, options);
|
|
2399
|
+
if (plan.basis === null || plan.snapshot === null)
|
|
2400
|
+
throw releaseRefused(id, plan);
|
|
2401
|
+
path = plan.snapshot;
|
|
2402
|
+
for (const pair of PAIRS) {
|
|
2403
|
+
const key = `${TWIN_COLLAPSE_MARKER_PREFIX}${pair.table}`;
|
|
2404
|
+
if (!plan.markers.includes(`${pair.kvTable}:${key}`))
|
|
2405
|
+
continue;
|
|
2406
|
+
const raw = readKv(live, pair.kvTable, key);
|
|
2407
|
+
const parsed = raw === undefined ? undefined : parseJson(raw);
|
|
2408
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
2409
|
+
throw releaseRefused(id, { ...plan, blockers: [`the ${pair.table} marker is unreadable`] });
|
|
2410
|
+
writeKv(live, pair.kvTable, key, JSON.stringify({ ...parsed, snapshot: null }));
|
|
2411
|
+
}
|
|
2412
|
+
sidecarBefore = readBackupSidecar(path, 'migration');
|
|
2413
|
+
const sidecar = unpinBackup(path, 'migration', `T12767: released by an owner after a ${plan.basis} check`);
|
|
2414
|
+
const release = {
|
|
2415
|
+
snapshot: path,
|
|
2416
|
+
markers: plan.markers,
|
|
2417
|
+
basis: plan.basis,
|
|
2418
|
+
bytes: plan.bytes,
|
|
2419
|
+
releasedAt: sidecar.releasedAt ?? new Date().toISOString(),
|
|
2420
|
+
movedFrom: plan.movedFrom,
|
|
2421
|
+
};
|
|
2422
|
+
audit({ ...release, receipts: plan.receipts });
|
|
2423
|
+
live.exec('COMMIT');
|
|
2424
|
+
return release;
|
|
2425
|
+
}
|
|
2426
|
+
catch (error) {
|
|
2427
|
+
if (live.isTransaction)
|
|
2428
|
+
live.exec('ROLLBACK');
|
|
2429
|
+
if (sidecarBefore !== undefined && path !== null)
|
|
2430
|
+
restoreBackupSidecar(path, 'migration', sidecarBefore);
|
|
2431
|
+
throw error;
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2206
2434
|
//# sourceMappingURL=twin-collapse.js.map
|