@cleocode/core 2026.9.23 → 2026.9.25
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 +35 -6
- package/dist/admin/import-tasks.js.map +1 -1
- package/dist/admin/import.d.ts.map +1 -1
- package/dist/admin/import.js +25 -6
- 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/http.d.ts +8 -0
- package/dist/cloud/http.d.ts.map +1 -1
- package/dist/cloud/http.js +8 -1
- package/dist/cloud/http.js.map +1 -1
- package/dist/cloud/index.d.ts +6 -1
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +6 -1
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/nexus-auth.d.ts +169 -0
- package/dist/cloud/nexus-auth.d.ts.map +1 -0
- package/dist/cloud/nexus-auth.js +372 -0
- package/dist/cloud/nexus-auth.js.map +1 -0
- package/dist/cloud/nexus-credentials.d.ts +188 -0
- package/dist/cloud/nexus-credentials.d.ts.map +1 -0
- package/dist/cloud/nexus-credentials.js +323 -0
- package/dist/cloud/nexus-credentials.js.map +1 -0
- package/dist/cloud/nexus-link.d.ts +85 -0
- package/dist/cloud/nexus-link.d.ts.map +1 -0
- package/dist/cloud/nexus-link.js +226 -0
- package/dist/cloud/nexus-link.js.map +1 -0
- package/dist/cloud/presence.d.ts +88 -0
- package/dist/cloud/presence.d.ts.map +1 -0
- package/dist/cloud/presence.js +137 -0
- package/dist/cloud/presence.js.map +1 -0
- package/dist/cloud/projects.d.ts +3 -1
- package/dist/cloud/projects.d.ts.map +1 -1
- package/dist/cloud/projects.js +4 -2
- package/dist/cloud/projects.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 +14 -4
- package/dist/crypto/credentials.d.ts.map +1 -1
- package/dist/crypto/credentials.js +15 -1
- package/dist/crypto/credentials.js.map +1 -1
- package/dist/decide/bench/dataset.d.ts +125 -0
- package/dist/decide/bench/dataset.d.ts.map +1 -0
- package/dist/decide/bench/dataset.js +457 -0
- package/dist/decide/bench/dataset.js.map +1 -0
- package/dist/decide/bench/index.d.ts +23 -0
- package/dist/decide/bench/index.d.ts.map +1 -0
- package/dist/decide/bench/index.js +23 -0
- package/dist/decide/bench/index.js.map +1 -0
- package/dist/decide/bench/metrics.d.ts +55 -0
- package/dist/decide/bench/metrics.d.ts.map +1 -0
- package/dist/decide/bench/metrics.js +100 -0
- package/dist/decide/bench/metrics.js.map +1 -0
- package/dist/decide/bench/operation.d.ts +119 -0
- package/dist/decide/bench/operation.d.ts.map +1 -0
- package/dist/decide/bench/operation.js +171 -0
- package/dist/decide/bench/operation.js.map +1 -0
- package/dist/decide/bench/profiles.d.ts +102 -0
- package/dist/decide/bench/profiles.d.ts.map +1 -0
- package/dist/decide/bench/profiles.js +175 -0
- package/dist/decide/bench/profiles.js.map +1 -0
- package/dist/decide/bench/questions.d.ts +40 -0
- package/dist/decide/bench/questions.d.ts.map +1 -0
- package/dist/decide/bench/questions.js +107 -0
- package/dist/decide/bench/questions.js.map +1 -0
- package/dist/decide/bench/report.d.ts +21 -0
- package/dist/decide/bench/report.d.ts.map +1 -0
- package/dist/decide/bench/report.js +125 -0
- package/dist/decide/bench/report.js.map +1 -0
- package/dist/decide/bench/runner.d.ts +208 -0
- package/dist/decide/bench/runner.d.ts.map +1 -0
- package/dist/decide/bench/runner.js +336 -0
- package/dist/decide/bench/runner.js.map +1 -0
- package/dist/decide/bench/source.d.ts +21 -0
- package/dist/decide/bench/source.d.ts.map +1 -0
- package/dist/decide/bench/source.js +67 -0
- package/dist/decide/bench/source.js.map +1 -0
- package/dist/decide/bench/spot-check.d.ts +117 -0
- package/dist/decide/bench/spot-check.d.ts.map +1 -0
- package/dist/decide/bench/spot-check.js +221 -0
- package/dist/decide/bench/spot-check.js.map +1 -0
- package/dist/decide/bench/stats.d.ts +57 -0
- package/dist/decide/bench/stats.d.ts.map +1 -0
- package/dist/decide/bench/stats.js +82 -0
- package/dist/decide/bench/stats.js.map +1 -0
- package/dist/decide/bench/types.d.ts +216 -0
- package/dist/decide/bench/types.d.ts.map +1 -0
- package/dist/decide/bench/types.js +104 -0
- package/dist/decide/bench/types.js.map +1 -0
- package/dist/decide/client.d.ts +35 -1
- package/dist/decide/client.d.ts.map +1 -1
- package/dist/decide/client.js +135 -35
- package/dist/decide/client.js.map +1 -1
- package/dist/decide/credentials.d.ts +177 -17
- package/dist/decide/credentials.d.ts.map +1 -1
- package/dist/decide/credentials.js +505 -41
- package/dist/decide/credentials.js.map +1 -1
- package/dist/decide/index.d.ts +8 -8
- package/dist/decide/index.d.ts.map +1 -1
- package/dist/decide/index.js +8 -8
- package/dist/decide/index.js.map +1 -1
- package/dist/decide/jev-wire.d.ts +55 -19
- package/dist/decide/jev-wire.d.ts.map +1 -1
- package/dist/decide/jev-wire.js +116 -37
- package/dist/decide/jev-wire.js.map +1 -1
- package/dist/decide/operations.d.ts +63 -12
- package/dist/decide/operations.d.ts.map +1 -1
- package/dist/decide/operations.js +116 -58
- package/dist/decide/operations.js.map +1 -1
- package/dist/decide/provider-state.d.ts +85 -12
- package/dist/decide/provider-state.d.ts.map +1 -1
- package/dist/decide/provider-state.js +154 -21
- package/dist/decide/provider-state.js.map +1 -1
- package/dist/decide/provider.d.ts +5 -0
- package/dist/decide/provider.d.ts.map +1 -1
- package/dist/decide/provider.js.map +1 -1
- package/dist/decide/providers.d.ts +15 -2
- package/dist/decide/providers.d.ts.map +1 -1
- package/dist/decide/providers.js +22 -6
- package/dist/decide/providers.js.map +1 -1
- package/dist/decide/sites/registry.d.ts +22 -0
- package/dist/decide/sites/registry.d.ts.map +1 -1
- package/dist/decide/sites/registry.js +23 -0
- package/dist/decide/sites/registry.js.map +1 -1
- package/dist/decide/wizard.d.ts +12 -4
- package/dist/decide/wizard.d.ts.map +1 -1
- package/dist/decide/wizard.js +79 -26
- package/dist/decide/wizard.js.map +1 -1
- package/dist/dispatch/mvi-projection.d.ts +15 -2
- package/dist/dispatch/mvi-projection.d.ts.map +1 -1
- package/dist/dispatch/mvi-projection.js +73 -12
- package/dist/dispatch/mvi-projection.js.map +1 -1
- package/dist/docs/adr-allocator.d.ts +2 -2
- package/dist/docs/adr-allocator.d.ts.map +1 -1
- package/dist/docs/adr-allocator.js +17 -4
- package/dist/docs/adr-allocator.js.map +1 -1
- package/dist/docs/blob-consolidation.js +1 -1
- package/dist/docs/blob-consolidation.js.map +1 -1
- package/dist/docs/display-alias.d.ts +1 -1
- package/dist/docs/display-alias.d.ts.map +1 -1
- package/dist/docs/display-alias.js +7 -4
- package/dist/docs/display-alias.js.map +1 -1
- package/dist/docs/docs-inconsistency-detector.js +1 -1
- package/dist/docs/docs-inconsistency-detector.js.map +1 -1
- package/dist/docs/docs-update.d.ts.map +1 -1
- package/dist/docs/docs-update.js +6 -1
- package/dist/docs/docs-update.js.map +1 -1
- package/dist/docs/export-document.js +18058 -14538
- package/dist/docs/export-document.js.map +3 -3
- package/dist/docs/numbering.js +1 -1
- package/dist/docs/numbering.js.map +1 -1
- package/dist/docs/supersede.d.ts.map +1 -1
- package/dist/docs/supersede.js +6 -3
- package/dist/docs/supersede.js.map +1 -1
- package/dist/docs/version-ssot.js +1 -1
- package/dist/docs/version-ssot.js.map +1 -1
- package/dist/doctor/db-substrate.d.ts.map +1 -1
- package/dist/doctor/db-substrate.js +39 -24
- package/dist/doctor/db-substrate.js.map +1 -1
- package/dist/doctor/knowledge-summary.d.ts +10 -3
- package/dist/doctor/knowledge-summary.d.ts.map +1 -1
- package/dist/doctor/knowledge-summary.js +10 -3
- package/dist/doctor/knowledge-summary.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/project-identity.d.ts +128 -37
- package/dist/doctor/project-identity.d.ts.map +1 -1
- package/dist/doctor/project-identity.js +476 -63
- package/dist/doctor/project-identity.js.map +1 -1
- 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 +31 -0
- package/dist/doctor/row-identity.d.ts.map +1 -0
- package/dist/doctor/row-identity.js +93 -0
- package/dist/doctor/row-identity.js.map +1 -0
- package/dist/doctor/twin-collapse.d.ts +108 -2
- package/dist/doctor/twin-collapse.d.ts.map +1 -1
- package/dist/doctor/twin-collapse.js +309 -7
- package/dist/doctor/twin-collapse.js.map +1 -1
- package/dist/error-catalog.js +2 -2
- package/dist/error-catalog.js.map +1 -1
- package/dist/error-registry.js +1 -1
- package/dist/error-registry.js.map +1 -1
- package/dist/gateway-client/generated/types.gen.d.ts +22 -2
- package/dist/gateway-client/generated/types.gen.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +20 -11
- package/dist/init.js.map +1 -1
- package/dist/inject/index.d.ts.map +1 -1
- package/dist/inject/index.js +2 -3
- package/dist/inject/index.js.map +1 -1
- package/dist/internal.d.ts +5 -4
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +6 -4
- package/dist/internal.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/credential-remove-entry.d.ts +59 -0
- package/dist/llm/credential-remove-entry.d.ts.map +1 -0
- package/dist/llm/credential-remove-entry.js +101 -0
- package/dist/llm/credential-remove-entry.js.map +1 -0
- package/dist/llm/oauth/device-code.d.ts +26 -6
- package/dist/llm/oauth/device-code.d.ts.map +1 -1
- package/dist/llm/oauth/device-code.js +44 -12
- package/dist/llm/oauth/device-code.js.map +1 -1
- package/dist/llm/plugin-facade.js +18202 -14682
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/attention.d.ts.map +1 -1
- package/dist/memory/attention.js +5 -3
- package/dist/memory/attention.js.map +1 -1
- package/dist/memory/decisions.d.ts +48 -3
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/decisions.js +98 -14
- package/dist/memory/decisions.js.map +1 -1
- 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/learnings.d.ts +6 -6
- 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/patterns.d.ts +4 -4
- 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/migration/manual/T10165-backfill-adr-index.d.ts.map +1 -1
- package/dist/migration/manual/T10165-backfill-adr-index.js +5 -1
- package/dist/migration/manual/T10165-backfill-adr-index.js.map +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/fleet-status.d.ts +83 -0
- package/dist/nexus/fleet-status.d.ts.map +1 -0
- package/dist/nexus/fleet-status.js +414 -0
- package/dist/nexus/fleet-status.js.map +1 -0
- package/dist/nexus/git-state.d.ts +15 -0
- package/dist/nexus/git-state.d.ts.map +1 -1
- package/dist/nexus/git-state.js +77 -3
- package/dist/nexus/git-state.js.map +1 -1
- package/dist/nexus/identity.d.ts.map +1 -1
- package/dist/nexus/identity.js +4 -0
- package/dist/nexus/identity.js.map +1 -1
- package/dist/nexus/index.d.ts +4 -1
- package/dist/nexus/index.d.ts.map +1 -1
- package/dist/nexus/index.js +7 -1
- package/dist/nexus/index.js.map +1 -1
- package/dist/nexus/migrate-json-to-sqlite.d.ts +3 -2
- package/dist/nexus/migrate-json-to-sqlite.d.ts.map +1 -1
- package/dist/nexus/migrate-json-to-sqlite.js +9 -17
- package/dist/nexus/migrate-json-to-sqlite.js.map +1 -1
- package/dist/nexus/ops.d.ts +1 -0
- package/dist/nexus/ops.d.ts.map +1 -1
- package/dist/nexus/project-activity.d.ts +104 -0
- package/dist/nexus/project-activity.d.ts.map +1 -0
- package/dist/nexus/project-activity.js +150 -0
- package/dist/nexus/project-activity.js.map +1 -0
- 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 +2 -2
- package/dist/nexus/query.d.ts.map +1 -1
- package/dist/nexus/query.js +8 -31
- package/dist/nexus/query.js.map +1 -1
- package/dist/nexus/registry-errors.d.ts +61 -0
- package/dist/nexus/registry-errors.d.ts.map +1 -0
- package/dist/nexus/registry-errors.js +85 -0
- package/dist/nexus/registry-errors.js.map +1 -0
- 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 +48 -5
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/nexus/registry.js +151 -85
- package/dist/nexus/registry.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts +4 -0
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +75 -12
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/orchestrate/query-ops.d.ts.map +1 -1
- package/dist/orchestrate/query-ops.js +29 -27
- 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 +29 -3
- 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/bootstrap.d.ts.map +1 -1
- package/dist/orchestration/bootstrap.js +20 -14
- package/dist/orchestration/bootstrap.js.map +1 -1
- package/dist/orchestration/index.d.ts +15 -1
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +25 -6
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lead-rollup.d.ts +7 -1
- package/dist/orchestration/lead-rollup.d.ts.map +1 -1
- package/dist/orchestration/lead-rollup.js +6 -3
- package/dist/orchestration/lead-rollup.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 +63 -92
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/waves.d.ts +21 -10
- package/dist/orchestration/waves.d.ts.map +1 -1
- package/dist/orchestration/waves.js +38 -35
- package/dist/orchestration/waves.js.map +1 -1
- package/dist/paths.d.ts +9 -2
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +30 -13
- package/dist/paths.js.map +1 -1
- package/dist/phases/index.d.ts +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +3 -4
- package/dist/phases/index.js.map +1 -1
- package/dist/project-info.d.ts +40 -3
- package/dist/project-info.d.ts.map +1 -1
- package/dist/project-info.js +74 -6
- package/dist/project-info.js.map +1 -1
- package/dist/project-lifecycle.d.ts +28 -7
- package/dist/project-lifecycle.d.ts.map +1 -1
- package/dist/project-lifecycle.js +114 -47
- package/dist/project-lifecycle.js.map +1 -1
- package/dist/project-scope.d.ts +70 -3
- package/dist/project-scope.d.ts.map +1 -1
- package/dist/project-scope.js +154 -15
- package/dist/project-scope.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/release/open.d.ts +12 -2
- package/dist/release/open.d.ts.map +1 -1
- package/dist/release/open.js +32 -3
- package/dist/release/open.js.map +1 -1
- package/dist/release/preflight-skip.d.ts +73 -0
- package/dist/release/preflight-skip.d.ts.map +1 -0
- package/dist/release/preflight-skip.js +254 -0
- package/dist/release/preflight-skip.js.map +1 -0
- package/dist/render/decide/index.d.ts +51 -0
- package/dist/render/decide/index.d.ts.map +1 -0
- package/dist/render/decide/index.js +289 -0
- package/dist/render/decide/index.js.map +1 -0
- package/dist/render/index.d.ts +1 -0
- package/dist/render/index.d.ts.map +1 -1
- package/dist/render/index.js +1 -0
- package/dist/render/index.js.map +1 -1
- package/dist/render/nexus/graph/index.d.ts +5 -0
- package/dist/render/nexus/graph/index.d.ts.map +1 -1
- package/dist/render/nexus/graph/index.js +53 -0
- package/dist/render/nexus/graph/index.js.map +1 -1
- package/dist/scaffold/ensure-config.d.ts +14 -6
- package/dist/scaffold/ensure-config.d.ts.map +1 -1
- package/dist/scaffold/ensure-config.js +39 -17
- package/dist/scaffold/ensure-config.js.map +1 -1
- package/dist/scaffold/project-identity.d.ts +115 -23
- package/dist/scaffold/project-identity.d.ts.map +1 -1
- package/dist/scaffold/project-identity.js +196 -44
- package/dist/scaffold/project-identity.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 +18221 -14701
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sentient/cross-project-hygiene.d.ts +17 -6
- package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
- package/dist/sentient/cross-project-hygiene.js +22 -11
- 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 +13 -4
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +38 -45
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/briefing.d.ts +7 -3
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +10 -10
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/drift-watchdog.d.ts.map +1 -1
- package/dist/sessions/drift-watchdog.js +11 -19
- package/dist/sessions/drift-watchdog.js.map +1 -1
- package/dist/sessions/focus-state-store.d.ts +103 -26
- package/dist/sessions/focus-state-store.d.ts.map +1 -1
- package/dist/sessions/focus-state-store.js +166 -37
- package/dist/sessions/focus-state-store.js.map +1 -1
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +9 -18
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts +4 -2
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +35 -6
- 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 -2
- package/dist/sessions/session-drift.js.map +1 -1
- package/dist/sessions/session-view.d.ts +8 -1
- package/dist/sessions/session-view.d.ts.map +1 -1
- package/dist/sessions/session-view.js +9 -2
- package/dist/sessions/session-view.js.map +1 -1
- package/dist/setup/config-json-merge.d.ts.map +1 -1
- package/dist/setup/config-json-merge.js +1 -0
- package/dist/setup/config-json-merge.js.map +1 -1
- package/dist/setup/index.d.ts +4 -2
- package/dist/setup/index.d.ts.map +1 -1
- package/dist/setup/index.js +6 -2
- package/dist/setup/index.js.map +1 -1
- package/dist/setup/sections/nexus-account.d.ts +32 -0
- package/dist/setup/sections/nexus-account.d.ts.map +1 -0
- package/dist/setup/sections/nexus-account.js +64 -0
- package/dist/setup/sections/nexus-account.js.map +1 -0
- package/dist/setup/wizard.d.ts +1 -1
- package/dist/setup/wizard.d.ts.map +1 -1
- package/dist/setup/wizard.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.d.ts.map +1 -1
- package/dist/skills/orchestrator/startup.js +18 -31
- 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.map +1 -1
- package/dist/snapshot/index.js +60 -53
- package/dist/snapshot/index.js.map +1 -1
- package/dist/spawn/agent-identity.d.ts +33 -1
- package/dist/spawn/agent-identity.d.ts.map +1 -1
- package/dist/spawn/agent-identity.js +53 -1
- package/dist/spawn/agent-identity.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/spawn/index.d.ts +1 -1
- package/dist/spawn/index.d.ts.map +1 -1
- package/dist/spawn/index.js +1 -1
- package/dist/spawn/index.js.map +1 -1
- package/dist/stats/index.d.ts.map +1 -1
- package/dist/stats/index.js +3 -4
- package/dist/stats/index.js.map +1 -1
- package/dist/status/index.d.ts +12 -3
- package/dist/status/index.d.ts.map +1 -1
- package/dist/status/index.js +47 -5
- package/dist/status/index.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/attachment-repair.d.ts.map +1 -1
- package/dist/store/attachment-repair.js +42 -3
- package/dist/store/attachment-repair.js.map +1 -1
- package/dist/store/attachment-store.d.ts.map +1 -1
- package/dist/store/attachment-store.js +30 -46
- package/dist/store/attachment-store.js.map +1 -1
- package/dist/store/backup-recover-brain.d.ts +4 -0
- package/dist/store/backup-recover-brain.d.ts.map +1 -1
- package/dist/store/backup-recover-brain.js +2 -0
- package/dist/store/backup-recover-brain.js.map +1 -1
- package/dist/store/backup-recover.d.ts +9 -0
- package/dist/store/backup-recover.d.ts.map +1 -1
- package/dist/store/backup-recover.js +28 -1
- package/dist/store/backup-recover.js.map +1 -1
- package/dist/store/backup-sidecar.d.ts +115 -2
- package/dist/store/backup-sidecar.d.ts.map +1 -1
- package/dist/store/backup-sidecar.js +263 -3
- package/dist/store/backup-sidecar.js.map +1 -1
- package/dist/store/blob-keep.d.ts +135 -0
- package/dist/store/blob-keep.d.ts.map +1 -0
- package/dist/store/blob-keep.js +283 -0
- package/dist/store/blob-keep.js.map +1 -0
- 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/converters.d.ts.map +1 -1
- package/dist/store/converters.js +11 -0
- package/dist/store/converters.js.map +1 -1
- package/dist/store/credential-transfer.d.ts +37 -5
- package/dist/store/credential-transfer.d.ts.map +1 -1
- package/dist/store/credential-transfer.js +76 -18
- package/dist/store/credential-transfer.js.map +1 -1
- package/dist/store/data-accessor.d.ts +1 -1
- package/dist/store/data-accessor.d.ts.map +1 -1
- package/dist/store/data-accessor.js.map +1 -1
- package/dist/store/db-helpers.d.ts +35 -11
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +107 -38
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/display-id-alias.d.ts +529 -0
- package/dist/store/display-id-alias.d.ts.map +1 -0
- package/dist/store/display-id-alias.js +1063 -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 +21 -0
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/on-open.d.ts.map +1 -1
- package/dist/store/exodus/on-open.js +35 -0
- package/dist/store/exodus/on-open.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/exodus/runtime-targets.d.ts +3 -3
- package/dist/store/exodus/runtime-targets.js +3 -3
- package/dist/store/import-remap.d.ts +12 -1
- package/dist/store/import-remap.d.ts.map +1 -1
- package/dist/store/import-remap.js +14 -0
- package/dist/store/import-remap.js.map +1 -1
- package/dist/store/legacy-tasks-lineage.d.ts +3 -1
- package/dist/store/legacy-tasks-lineage.d.ts.map +1 -1
- package/dist/store/legacy-tasks-lineage.js +22 -3
- package/dist/store/legacy-tasks-lineage.js.map +1 -1
- package/dist/store/memory-accessor.js +1 -1
- package/dist/store/memory-accessor.js.map +1 -1
- package/dist/store/migration-manager.d.ts +61 -0
- package/dist/store/migration-manager.d.ts.map +1 -1
- package/dist/store/migration-manager.js +102 -4
- package/dist/store/migration-manager.js.map +1 -1
- package/dist/store/nexus-validation-schemas.d.ts +64 -0
- package/dist/store/nexus-validation-schemas.d.ts.map +1 -1
- package/dist/store/portable-bundle-import.d.ts +8 -0
- package/dist/store/portable-bundle-import.d.ts.map +1 -1
- package/dist/store/portable-bundle-import.js +10 -0
- package/dist/store/portable-bundle-import.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +1 -0
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/portable-bundle.d.ts.map +1 -1
- package/dist/store/portable-bundle.js +15 -14
- package/dist/store/portable-bundle.js.map +1 -1
- package/dist/store/pre-repair-snapshot.d.ts +4 -1
- package/dist/store/pre-repair-snapshot.d.ts.map +1 -1
- package/dist/store/pre-repair-snapshot.js +5 -1
- package/dist/store/pre-repair-snapshot.js.map +1 -1
- package/dist/store/regenerators.d.ts +4 -2
- package/dist/store/regenerators.d.ts.map +1 -1
- package/dist/store/regenerators.js +7 -3
- package/dist/store/regenerators.js.map +1 -1
- package/dist/store/repair-malformed-dbs.d.ts +4 -0
- package/dist/store/repair-malformed-dbs.d.ts.map +1 -1
- package/dist/store/repair-malformed-dbs.js +3 -0
- package/dist/store/repair-malformed-dbs.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 +198 -0
- package/dist/store/row-identity-registry.js.map +1 -0
- package/dist/store/row-identity.d.ts +390 -0
- package/dist/store/row-identity.d.ts.map +1 -0
- package/dist/store/row-identity.js +1240 -0
- package/dist/store/row-identity.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +10 -3
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +15 -4
- 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 +49 -1
- package/dist/store/schema/cleo-global/nexus.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/nexus.js +17 -0
- package/dist/store/schema/cleo-global/nexus.js.map +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 +17 -1
- package/dist/store/schema/cleo-project/docs.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/docs.js +10 -0
- package/dist/store/schema/cleo-project/docs.js.map +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 +263 -7
- package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.js +77 -2
- package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +7 -7
- 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 +6 -6
- package/dist/store/schema/nexus-schema.d.ts +51 -3
- package/dist/store/schema/nexus-schema.d.ts.map +1 -1
- package/dist/store/schema/nexus-schema.js +28 -7
- package/dist/store/schema/nexus-schema.js.map +1 -1
- 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 +65 -0
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +108 -7
- 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 +4 -19
- package/dist/store/split-brain-import.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +279 -2
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +789 -91
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sqlite.d.ts +15 -3
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +52 -20
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/store-write-guard.d.ts +9 -3
- package/dist/store/store-write-guard.d.ts.map +1 -1
- package/dist/store/store-write-guard.js +25 -4
- package/dist/store/store-write-guard.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 +11 -9
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +127 -33
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/task-claim.d.ts +144 -0
- package/dist/store/task-claim.d.ts.map +1 -0
- package/dist/store/task-claim.js +195 -0
- package/dist/store/task-claim.js.map +1 -0
- package/dist/store/task-version.d.ts +43 -5
- package/dist/store/task-version.d.ts.map +1 -1
- package/dist/store/task-version.js +113 -17
- package/dist/store/task-version.js.map +1 -1
- package/dist/store/tasks-schema.d.ts +2 -0
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/tasks-schema.js +1 -0
- package/dist/store/tasks-schema.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +10 -2
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +450 -22
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +1552 -49
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +10 -3
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +14 -4
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +402 -50
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/store/with-retry.d.ts +36 -0
- package/dist/store/with-retry.d.ts.map +1 -1
- package/dist/store/with-retry.js +51 -0
- package/dist/store/with-retry.js.map +1 -1
- package/dist/store/worktree-build-guard.d.ts +13 -4
- package/dist/store/worktree-build-guard.d.ts.map +1 -1
- package/dist/store/worktree-build-guard.js +21 -10
- package/dist/store/worktree-build-guard.js.map +1 -1
- package/dist/store/worktree-isolation-guard.d.ts +121 -10
- package/dist/store/worktree-isolation-guard.d.ts.map +1 -1
- package/dist/store/worktree-isolation-guard.js +155 -34
- package/dist/store/worktree-isolation-guard.js.map +1 -1
- package/dist/system/backup.d.ts +7 -0
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/backup.js +5 -0
- package/dist/system/backup.js.map +1 -1
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +6 -1
- package/dist/system/health.js.map +1 -1
- package/dist/system/inject-generate.d.ts.map +1 -1
- package/dist/system/inject-generate.js +23 -10
- package/dist/system/inject-generate.js.map +1 -1
- package/dist/system/project-health.d.ts +17 -2
- package/dist/system/project-health.d.ts.map +1 -1
- package/dist/system/project-health.js +19 -6
- package/dist/system/project-health.js.map +1 -1
- package/dist/task-tools/index.d.ts +1 -1
- package/dist/task-tools/index.d.ts.map +1 -1
- package/dist/task-tools/index.js +1 -1
- package/dist/task-tools/index.js.map +1 -1
- package/dist/task-tools/score-task-priority.d.ts +38 -0
- package/dist/task-tools/score-task-priority.d.ts.map +1 -1
- package/dist/task-tools/score-task-priority.js +51 -0
- package/dist/task-tools/score-task-priority.js.map +1 -1
- package/dist/task-work/claims.d.ts +215 -0
- package/dist/task-work/claims.d.ts.map +1 -0
- package/dist/task-work/claims.js +272 -0
- package/dist/task-work/claims.js.map +1 -0
- package/dist/task-work/index.d.ts +47 -3
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +74 -41
- 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 +51 -4
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/analyze.d.ts.map +1 -1
- package/dist/tasks/analyze.js +3 -4
- 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/change-set.d.ts +5 -0
- package/dist/tasks/change-set.d.ts.map +1 -1
- package/dist/tasks/change-set.js +59 -3
- package/dist/tasks/change-set.js.map +1 -1
- package/dist/tasks/complete.d.ts +16 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +33 -8
- 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/component-pr.d.ts +162 -1
- package/dist/tasks/component-pr.d.ts.map +1 -1
- package/dist/tasks/component-pr.js +560 -59
- package/dist/tasks/component-pr.js.map +1 -1
- package/dist/tasks/done-record.d.ts +14 -1
- package/dist/tasks/done-record.d.ts.map +1 -1
- package/dist/tasks/done-record.js +37 -0
- package/dist/tasks/done-record.js.map +1 -1
- package/dist/tasks/duplicate-detector.d.ts +20 -1
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +10 -2
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/tasks/engine-wrap-ops.d.ts +19 -10
- package/dist/tasks/engine-wrap-ops.d.ts.map +1 -1
- package/dist/tasks/engine-wrap-ops.js +38 -10
- package/dist/tasks/engine-wrap-ops.js.map +1 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +14 -3
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/graph-ops.d.ts +9 -2
- package/dist/tasks/graph-ops.d.ts.map +1 -1
- package/dist/tasks/graph-ops.js +24 -32
- package/dist/tasks/graph-ops.js.map +1 -1
- package/dist/tasks/plan.d.ts.map +1 -1
- package/dist/tasks/plan.js +16 -60
- package/dist/tasks/plan.js.map +1 -1
- package/dist/tasks/task-context.d.ts.map +1 -1
- package/dist/tasks/task-context.js +13 -0
- 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 +21 -12
- package/dist/tasks/task-import.js.map +1 -1
- package/dist/tasks/task-next.d.ts +25 -2
- package/dist/tasks/task-next.d.ts.map +1 -1
- package/dist/tasks/task-next.js +32 -13
- package/dist/tasks/task-next.js.map +1 -1
- package/dist/tasks/update.d.ts.map +1 -1
- package/dist/tasks/update.js +7 -5
- package/dist/tasks/update.js.map +1 -1
- package/dist/upgrade.d.ts +1 -1
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +48 -9
- package/dist/upgrade.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/doctor/checks.d.ts +20 -6
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/doctor/checks.js +51 -8
- package/dist/validation/doctor/checks.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/validation/validate-ops.d.ts.map +1 -1
- package/dist/validation/validate-ops.js +2 -3
- package/dist/validation/validate-ops.js.map +1 -1
- package/migrations/README.md +12 -0
- package/migrations/drizzle-cleo-global/20260929010000_t12512-registry-probed-opened/migration.sql +35 -0
- package/migrations/drizzle-cleo-global/20260929020000_t12721-git-state-head-committed-at/migration.sql +25 -0
- package/migrations/drizzle-cleo-project/20260928120000_t12341-row-uids/migration.sql +169 -0
- package/migrations/drizzle-cleo-project/20260929000000_t12535-docs-attachments-union-shape/migration.sql +21 -0
- package/migrations/drizzle-cleo-project/20260929120000_t12502-task-claim-leases/migration.sql +77 -0
- package/migrations/drizzle-cleo-project/20260929130000_t12736-claim-lease-iso-repair/migration.sql +37 -0
- package/migrations/sync-journal/20260929140000_t12342-sync-clock/migration.sql +42 -0
- package/package.json +23 -13
- package/schemas/project-info.schema.json +10 -4
- package/templates/CLEO-INJECTION.md +1 -1
- package/templates/CLEO-REFERENCE.md +7 -3
- package/templates/cleo-gitignore +11 -0
- package/templates/workflows/release-prepare.yml.tmpl +156 -10
|
@@ -12,21 +12,26 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
14
14
|
import { resolve } from 'node:path';
|
|
15
|
-
import { ARCHIVE_REASON_TOMBSTONE, } from '@cleocode/contracts';
|
|
16
|
-
import { and, eq, getTableColumns, inArray, isNull, like, ne, notInArray, or, sql, } from 'drizzle-orm';
|
|
15
|
+
import { ARCHIVE_REASON_TOMBSTONE, ExitCode, } from '@cleocode/contracts';
|
|
16
|
+
import { and, eq, getTableColumns, inArray, isNull, like, lte, ne, notInArray, or, sql, } from 'drizzle-orm';
|
|
17
|
+
import { CleoError } from '../errors.js';
|
|
17
18
|
import { captureProjectScope as captureTaskAccessorScope, getProjectRoot, worktreeScope, } from '../project-scope.js';
|
|
19
|
+
import { acTextHash, buildAcRowId } from '../tasks/ac-table.js';
|
|
20
|
+
import { generateAuditLogId, pruneAcBindingsForAcIds, pruneAcBindingsForTask, pruneOrphanAcBindings, selectOrphanAcBindings, } from './ac-binding-prune.js';
|
|
18
21
|
import { withBackgroundOpCommitBoundary } from './background-ops.js';
|
|
19
22
|
import { archivedTaskToRow, rowToSession, rowToTask, taskToRow } from './converters.js';
|
|
20
23
|
import { cleanupBrainRefsOnSessionDelete } from './cross-db-cleanup.js';
|
|
21
|
-
import { batchUpdateDependencies, loadDependenciesForTasks, loadRelationsForTasks, parseLabels, updateDependencies, updateTaskLabels, upsertSession, upsertTask, } from './db-helpers.js';
|
|
24
|
+
import { batchUpdateDependencies, insertNewTask, loadDependenciesForTasks, loadRelationsForTasks, parseLabels, updateDependencies, updateTaskLabels, upsertSession, upsertTask, } from './db-helpers.js';
|
|
25
|
+
import { registerRowIdentityWriters } from './row-identity.js';
|
|
22
26
|
import { tasksAuditLog } from './schema/cleo-project/audit.js';
|
|
23
27
|
import { resolveCurrentSession } from './session-store.js';
|
|
24
28
|
import { closeDb, getDb, getNativeTasksDb } from './sqlite.js';
|
|
25
29
|
import { TERMINAL_TASK_STATUSES } from './status-registry.js';
|
|
26
|
-
import {
|
|
30
|
+
import { claimAllows, claimColumnsOf, claimFromColumns, isClaimExpired, leaseExpiresAtFrom, taskClaimedError, taskClaimLeaseMs, } from './task-claim.js';
|
|
31
|
+
import { nextTaskVersion, taskConflictError, taskVersion } from './task-version.js';
|
|
27
32
|
import * as schema from './tasks-schema.js';
|
|
28
33
|
import { assertTwinCollapseWritable, bareCounterOf, mirrorCounterToBare } from './twin-collapse.js';
|
|
29
|
-
import { withWriteRetry } from './with-retry.js';
|
|
34
|
+
import { runHeartbeatWrite, withWriteRetry } from './with-retry.js';
|
|
30
35
|
/**
|
|
31
36
|
* Per-process monotonic counter for unique nested SAVEPOINT names (T9814).
|
|
32
37
|
* Only used when DataAccessor.transaction() is called from within an
|
|
@@ -35,13 +40,67 @@ import { withWriteRetry } from './with-retry.js';
|
|
|
35
40
|
*/
|
|
36
41
|
let _txSavepointCounter = 0;
|
|
37
42
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
43
|
+
* Evidence bindings for a set of CURRENT AC ids (T12341).
|
|
44
|
+
*
|
|
45
|
+
* A binding is matched through the criterion's uid (`ac_uid`), which survives
|
|
46
|
+
* an AC edit, and falls back to `ac_id` for a binding whose uid is not filled.
|
|
47
|
+
* A binding recorded against an older text of a criterion is reported under
|
|
48
|
+
* the criterion's current id, so callers keyed by AC id keep working, and is
|
|
49
|
+
* marked `stale` when the text hash it recorded (`ac_text_hash`) differs from
|
|
50
|
+
* the criterion's current text: evidence for different text never satisfies a
|
|
51
|
+
* gate (spec §8.2).
|
|
40
52
|
*/
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
async function selectAcBindings(db, acIds) {
|
|
54
|
+
if (acIds.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
const b = schema.evidenceAcBindings;
|
|
57
|
+
const ac = schema.taskAcceptanceCriteria;
|
|
58
|
+
const ids = acIds;
|
|
59
|
+
const columns = {
|
|
60
|
+
id: b.id,
|
|
61
|
+
evidenceAtomId: b.evidenceAtomId,
|
|
62
|
+
acId: b.acId,
|
|
63
|
+
currentAcId: ac.id,
|
|
64
|
+
currentAcText: ac.text,
|
|
65
|
+
recordedTextHash: b.acTextHash,
|
|
66
|
+
bindingType: b.bindingType,
|
|
67
|
+
createdAt: b.createdAt,
|
|
68
|
+
};
|
|
69
|
+
// Two indexed lookups rather than one OR across the join: by the current
|
|
70
|
+
// criterion's uid, then by the recorded ac_id.
|
|
71
|
+
const byUid = await db
|
|
72
|
+
.select(columns)
|
|
73
|
+
.from(b)
|
|
74
|
+
.innerJoin(ac, eq(ac.uid, b.acUid))
|
|
75
|
+
.where(inArray(ac.id, ids))
|
|
76
|
+
.all();
|
|
77
|
+
const byId = await db
|
|
78
|
+
.select(columns)
|
|
79
|
+
.from(b)
|
|
80
|
+
.leftJoin(ac, eq(ac.uid, b.acUid))
|
|
81
|
+
.where(inArray(b.acId, ids))
|
|
82
|
+
.all();
|
|
83
|
+
const rows = [...byUid, ...byId];
|
|
84
|
+
const wanted = new Set(ids);
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const r of rows) {
|
|
88
|
+
if (seen.has(r.id))
|
|
89
|
+
continue;
|
|
90
|
+
seen.add(r.id);
|
|
91
|
+
const stale = r.recordedTextHash !== null &&
|
|
92
|
+
r.currentAcText !== null &&
|
|
93
|
+
acTextHash(r.currentAcText) !== r.recordedTextHash;
|
|
94
|
+
out.push({
|
|
95
|
+
id: r.id,
|
|
96
|
+
evidenceAtomId: r.evidenceAtomId,
|
|
97
|
+
acId: r.currentAcId && wanted.has(r.currentAcId) ? r.currentAcId : r.acId,
|
|
98
|
+
bindingType: r.bindingType,
|
|
99
|
+
createdAt: r.createdAt,
|
|
100
|
+
...(stale ? { stale: true } : {}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
45
104
|
}
|
|
46
105
|
// ---- Schema meta helpers ----
|
|
47
106
|
/** Read a JSON blob from the schema_meta table by key. */
|
|
@@ -70,7 +129,7 @@ export async function setMetaValue(cwd, key, value) {
|
|
|
70
129
|
async function writeMetaValue(cwd, key, value) {
|
|
71
130
|
const db = await getDb(cwd);
|
|
72
131
|
// T12535: fail fast on a store degraded by a failed twin collapse.
|
|
73
|
-
assertTwinCollapseWritable(getNativeTasksDb(cwd));
|
|
132
|
+
assertTwinCollapseWritable(getNativeTasksDb(cwd), 'schema_meta');
|
|
74
133
|
const json = JSON.stringify(value);
|
|
75
134
|
await db
|
|
76
135
|
.insert(schema.schemaMeta)
|
|
@@ -105,7 +164,7 @@ async function writeMetaValue(cwd, key, value) {
|
|
|
105
164
|
* @task T12535
|
|
106
165
|
*/
|
|
107
166
|
export function advanceTaskIdSequence(nativeDb, floor) {
|
|
108
|
-
assertTwinCollapseWritable(nativeDb);
|
|
167
|
+
assertTwinCollapseWritable(nativeDb, 'schema_meta');
|
|
109
168
|
// T12535: an id the older build reserved in the bare counter is taken too.
|
|
110
169
|
const lowest = Math.max(floor, bareCounterOf(nativeDb, 'task_id_sequence'));
|
|
111
170
|
nativeDb
|
|
@@ -130,6 +189,398 @@ export function advanceTaskIdSequence(nativeDb, floor) {
|
|
|
130
189
|
.get();
|
|
131
190
|
return row?.counter;
|
|
132
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Give the task with `uid` the display id `toId`: a compare-and-set on the
|
|
194
|
+
* stored version AND claim lease that advances the version (so a stale
|
|
195
|
+
* `--if-match` writer fails, #1698), with the claim columns carried unchanged
|
|
196
|
+
* (#1701), then every local reference rewritten. Runs in the caller's
|
|
197
|
+
* transaction with foreign keys deferred to its commit.
|
|
198
|
+
*
|
|
199
|
+
* A collision re-mint is a system write: it passes no claim guard and never
|
|
200
|
+
* takes or drops a lease, but the version bump makes the lease holder's next
|
|
201
|
+
* guarded write re-read. A caller acting for a session (a manual rename)
|
|
202
|
+
* passes `guard`: `expectedUpdatedAt` fails with `E_CONFLICT` when the task
|
|
203
|
+
* moved on, `claim` fails with `E_TASK_CLAIMED` when another session holds it.
|
|
204
|
+
*
|
|
205
|
+
* @param nativeDb - The project `cleo.db` handle holding the transaction.
|
|
206
|
+
* @param uid - Uid of the task to rename.
|
|
207
|
+
* @param toId - Its new display id.
|
|
208
|
+
* @param refs - Columns that hold task display ids.
|
|
209
|
+
* @param guard - Optional version / claim guard.
|
|
210
|
+
* @returns The id it had and the rows rewritten per `table.column`.
|
|
211
|
+
* @task T12341
|
|
212
|
+
* @task T12748
|
|
213
|
+
*/
|
|
214
|
+
export function renameTaskDisplayIdNative(nativeDb, uid, toId, refs, guard = {}) {
|
|
215
|
+
const current = nativeDb
|
|
216
|
+
.prepare(`SELECT id, updated_at AS updatedAt, created_at AS createdAt,
|
|
217
|
+
claimed_by_session AS claimedBySession, claimed_by_agent AS claimedByAgent,
|
|
218
|
+
claimed_at AS claimedAt, lease_expires_at AS leaseExpiresAt
|
|
219
|
+
FROM tasks_tasks WHERE uid = ?`)
|
|
220
|
+
.get(uid);
|
|
221
|
+
if (!current)
|
|
222
|
+
throw new Error(`No task with uid ${uid}`);
|
|
223
|
+
if (guard.expectedUpdatedAt !== undefined && guard.expectedUpdatedAt !== taskVersion(current)) {
|
|
224
|
+
throw taskConflictError(current.id, guard.expectedUpdatedAt, current);
|
|
225
|
+
}
|
|
226
|
+
if (guard.claim)
|
|
227
|
+
assertClaimAllowed(current.id, current, guard.claim, []);
|
|
228
|
+
nativeDb.exec('PRAGMA defer_foreign_keys = ON');
|
|
229
|
+
const changed = nativeDb
|
|
230
|
+
.prepare(`UPDATE tasks_tasks SET id = ?, updated_at = ?
|
|
231
|
+
WHERE uid = ? AND id = ? AND updated_at IS ? AND claimed_by_session IS ?
|
|
232
|
+
AND lease_expires_at IS ?`)
|
|
233
|
+
.run(toId, nextTaskVersion(current), uid, current.id, current.updatedAt, current.claimedBySession, current.leaseExpiresAt).changes;
|
|
234
|
+
if (Number(changed) !== 1) {
|
|
235
|
+
throw taskConflictError(current.id, taskVersion(current), null);
|
|
236
|
+
}
|
|
237
|
+
const rewritten = {};
|
|
238
|
+
const q = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
239
|
+
for (const ref of refs) {
|
|
240
|
+
const table = `main.${q(ref.table)}`;
|
|
241
|
+
const col = q(ref.column);
|
|
242
|
+
const n = ref.jsonArray
|
|
243
|
+
? nativeDb
|
|
244
|
+
.prepare(`UPDATE ${table} SET ${col} = (
|
|
245
|
+
SELECT json_group_array(CASE WHEN j.value = ? THEN ? ELSE j.value END)
|
|
246
|
+
FROM json_each(${table}.${col}) j)
|
|
247
|
+
WHERE json_valid(${col}) AND EXISTS (
|
|
248
|
+
SELECT 1 FROM json_each(${table}.${col}) j WHERE j.value = ?)`)
|
|
249
|
+
.run(current.id, toId, current.id).changes
|
|
250
|
+
: nativeDb.prepare(`UPDATE ${table} SET ${col} = ? WHERE ${col} = ?`).run(toId, current.id)
|
|
251
|
+
.changes;
|
|
252
|
+
if (Number(n) > 0)
|
|
253
|
+
rewritten[`${ref.table}.${ref.column}`] = Number(n);
|
|
254
|
+
}
|
|
255
|
+
for (const [key, n] of Object.entries(rederiveAcIdsNative(nativeDb, current.id, toId))) {
|
|
256
|
+
if (n > 0)
|
|
257
|
+
rewritten[key] = n;
|
|
258
|
+
}
|
|
259
|
+
return { fromId: current.id, rewritten };
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* After a task's display id changed from `fromId` to `toId`, re-derive the
|
|
263
|
+
* ids of the acceptance criteria derived from it (`buildAcRowId(taskId,
|
|
264
|
+
* identity)`): the task's own criteria, and a parent's child-projection
|
|
265
|
+
* criteria (`child:<id>`, whose source key is rewritten too). The binding and
|
|
266
|
+
* history rows that point at a re-derived id follow. A criterion whose id was
|
|
267
|
+
* not derived from the old id (an explicit id) keeps it. Without this, two
|
|
268
|
+
* tasks that once shared a display id keep identical ids for same-text
|
|
269
|
+
* criteria ("tests pass") and collide on every merge (T12799).
|
|
270
|
+
*
|
|
271
|
+
* @param nativeDb - The project `cleo.db` handle, inside the rename's transaction.
|
|
272
|
+
* @param fromId - The task's old display id.
|
|
273
|
+
* @param toId - Its new display id (the task row already carries it).
|
|
274
|
+
* @returns Rows rewritten per `table.column`.
|
|
275
|
+
* @task T12799
|
|
276
|
+
*/
|
|
277
|
+
export function rederiveAcIdsNative(nativeDb, fromId, toId) {
|
|
278
|
+
const count = {};
|
|
279
|
+
const bump = (key, n) => {
|
|
280
|
+
count[key] = (count[key] ?? 0) + Number(n);
|
|
281
|
+
};
|
|
282
|
+
const has = (table) => nativeDb
|
|
283
|
+
.prepare("SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
284
|
+
.get(table) !== undefined;
|
|
285
|
+
if (!has('tasks_task_acceptance_criteria'))
|
|
286
|
+
return count;
|
|
287
|
+
const oldChild = `child:${fromId}`;
|
|
288
|
+
const rows = nativeDb
|
|
289
|
+
.prepare(`SELECT id, task_id AS taskId, kind, text, source_key AS sourceKey
|
|
290
|
+
FROM tasks_task_acceptance_criteria WHERE task_id = ? OR source_key = ?`)
|
|
291
|
+
.all(toId, oldChild);
|
|
292
|
+
const followers = ['tasks_evidence_ac_bindings', 'tasks_task_acceptance_criteria_history'].filter(has);
|
|
293
|
+
for (const row of rows) {
|
|
294
|
+
const ownerBefore = row.taskId === toId ? fromId : row.taskId;
|
|
295
|
+
const sourceAfter = row.sourceKey === oldChild ? `child:${toId}` : row.sourceKey;
|
|
296
|
+
const identity = (source) => (row.kind === 'text' ? row.text : (source ?? ''));
|
|
297
|
+
const derived = row.id === buildAcRowId(ownerBefore, identity(row.sourceKey));
|
|
298
|
+
const newId = derived ? buildAcRowId(row.taskId, identity(sourceAfter)) : row.id;
|
|
299
|
+
if (newId === row.id && sourceAfter === row.sourceKey)
|
|
300
|
+
continue;
|
|
301
|
+
bump('tasks_task_acceptance_criteria.id', nativeDb
|
|
302
|
+
.prepare('UPDATE tasks_task_acceptance_criteria SET id = ?, source_key = ? WHERE id = ?')
|
|
303
|
+
.run(newId, sourceAfter, row.id).changes);
|
|
304
|
+
if (newId === row.id)
|
|
305
|
+
continue;
|
|
306
|
+
for (const table of followers) {
|
|
307
|
+
bump(`${table}.ac_id`, nativeDb.prepare(`UPDATE ${table} SET ac_id = ? WHERE ac_id = ?`).run(newId, row.id)
|
|
308
|
+
.changes);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return count;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Insert a display-id alias row (idempotent on its uid).
|
|
315
|
+
*
|
|
316
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
317
|
+
* @param row - The alias.
|
|
318
|
+
* @task T12341
|
|
319
|
+
*/
|
|
320
|
+
export function insertDisplayIdAliasNative(nativeDb, row) {
|
|
321
|
+
nativeDb
|
|
322
|
+
.prepare(`INSERT OR IGNORE INTO tasks_display_id_aliases
|
|
323
|
+
(uid, entity_table, display_id, entity_uid, reason, origin, displaced_hlc, created_at,
|
|
324
|
+
entity_birth_fp)
|
|
325
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
326
|
+
.run(row.uid, row.entityTable, row.displayId, row.entityUid, row.reason, row.origin, row.displacedHlc, row.createdAt, row.entityBirthFp);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Delete one display-id alias row (a local alias whose entity was re-keyed is
|
|
330
|
+
* re-inserted under its new entity uid by the caller).
|
|
331
|
+
*
|
|
332
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
333
|
+
* @param uid - The alias row's uid.
|
|
334
|
+
* @task T12341
|
|
335
|
+
*/
|
|
336
|
+
export function deleteDisplayIdAliasNative(nativeDb, uid) {
|
|
337
|
+
nativeDb.prepare('DELETE FROM tasks_display_id_aliases WHERE uid = ?').run(uid);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Insert a uid re-key alias row (idempotent on its uid).
|
|
341
|
+
*
|
|
342
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
343
|
+
* @param row - The alias.
|
|
344
|
+
* @task T12341
|
|
345
|
+
*/
|
|
346
|
+
export function insertUidAliasNative(nativeDb, row) {
|
|
347
|
+
nativeDb
|
|
348
|
+
.prepare(`INSERT OR IGNORE INTO tasks_uid_aliases
|
|
349
|
+
(uid, entity_table, old_uid, old_birth_fp, new_uid, origin, displaced_hlc, created_at)
|
|
350
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
351
|
+
.run(row.uid, row.entityTable, row.oldUid, row.oldBirthFp, row.newUid, row.origin, row.displacedHlc, row.createdAt);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Hold an incoming row the merge cannot place yet (replacing an older hold of
|
|
355
|
+
* the same row).
|
|
356
|
+
*
|
|
357
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
358
|
+
* @param row - The held row.
|
|
359
|
+
* @task T12341
|
|
360
|
+
*/
|
|
361
|
+
export function insertQuarantineNative(nativeDb, row) {
|
|
362
|
+
nativeDb
|
|
363
|
+
.prepare(`INSERT INTO tasks_identity_quarantine
|
|
364
|
+
(entity_table, uid, birth_fp, reason, contested_id, row_json, received_hlc, created_at)
|
|
365
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
366
|
+
ON CONFLICT(entity_table, uid, birth_fp) DO UPDATE SET
|
|
367
|
+
reason = excluded.reason, contested_id = excluded.contested_id,
|
|
368
|
+
row_json = excluded.row_json, received_hlc = excluded.received_hlc,
|
|
369
|
+
created_at = excluded.created_at`)
|
|
370
|
+
.run(row.entityTable, row.uid, row.birthFp, row.reason, row.contestedId, row.rowJson, row.receivedHlc, row.createdAt);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Drop a held row (released or superseded).
|
|
374
|
+
*
|
|
375
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
376
|
+
* @param key - The held row's table, uid and birth fingerprint.
|
|
377
|
+
* @task T12341
|
|
378
|
+
*/
|
|
379
|
+
export function deleteQuarantineNative(nativeDb, key) {
|
|
380
|
+
nativeDb
|
|
381
|
+
.prepare('DELETE FROM tasks_identity_quarantine WHERE entity_table = ? AND uid = ? AND birth_fp = ?')
|
|
382
|
+
.run(key.entityTable, key.uid, key.birthFp);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Write a row-identity meta value (the recipe marker, a re-mint record).
|
|
386
|
+
*
|
|
387
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
388
|
+
* @param key - Meta key.
|
|
389
|
+
* @param value - Meta value.
|
|
390
|
+
* @task T12341
|
|
391
|
+
*/
|
|
392
|
+
export function writeRowIdentityMetaNative(nativeDb, key, value) {
|
|
393
|
+
nativeDb
|
|
394
|
+
.prepare(`INSERT INTO tasks_row_identity_meta (key, value) VALUES (?, ?)
|
|
395
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`)
|
|
396
|
+
.run(key, value);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Hand a criterion back the uid its deleted predecessor carried (AC uid
|
|
400
|
+
* graveyard re-link, spec §6.5), with that predecessor's birth fingerprint.
|
|
401
|
+
*
|
|
402
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
403
|
+
* @param acId - The criterion to re-link (its uid is NULL).
|
|
404
|
+
* @param uid - The uid to hand back.
|
|
405
|
+
* @param birthFp - The fingerprint that goes with it, when recorded.
|
|
406
|
+
* @returns Rows changed (0 or 1).
|
|
407
|
+
* @task T12341
|
|
408
|
+
*/
|
|
409
|
+
export function relinkAcUidNative(nativeDb, acId, uid, birthFp) {
|
|
410
|
+
return Number(nativeDb
|
|
411
|
+
.prepare('UPDATE tasks_task_acceptance_criteria SET uid = ?, birth_fp = COALESCE(?, birth_fp) WHERE id = ? AND uid IS NULL')
|
|
412
|
+
.run(uid, birthFp, acId).changes);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Empty the AC uid graveyard (after the open pass consumed it).
|
|
416
|
+
*
|
|
417
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
418
|
+
* @task T12341
|
|
419
|
+
*/
|
|
420
|
+
export function clearAcUidGraveyardNative(nativeDb) {
|
|
421
|
+
nativeDb.exec('DELETE FROM tasks_ac_uid_graveyard');
|
|
422
|
+
}
|
|
423
|
+
/** Quote an identifier for the dynamic row-identity writes below. */
|
|
424
|
+
function quoteIdent(name) {
|
|
425
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Fill a NULL identity column (`uid`, `birth_fp`, a stored reference uid) of a
|
|
429
|
+
* declared table from its recipe SQL (the row-uid open pass, spec §6.1).
|
|
430
|
+
*
|
|
431
|
+
* @param nativeDb - The `cleo.db` handle holding the cold-open lease.
|
|
432
|
+
* @param table - Declared table.
|
|
433
|
+
* @param column - Identity column.
|
|
434
|
+
* @param valueSql - Recipe expression over `main."<table>"` columns.
|
|
435
|
+
* @param rowid - One row only (the clash fallback); all NULL rows otherwise.
|
|
436
|
+
* @returns Rows written.
|
|
437
|
+
* @task T12341
|
|
438
|
+
*/
|
|
439
|
+
export function fillIdentityColumnNative(nativeDb, table, column, valueSql, rowid) {
|
|
440
|
+
const col = quoteIdent(column);
|
|
441
|
+
const sql = `UPDATE main.${quoteIdent(table)} SET ${col} = ${valueSql} WHERE ${col} IS NULL`;
|
|
442
|
+
const changes = rowid === undefined
|
|
443
|
+
? nativeDb.prepare(sql).run().changes
|
|
444
|
+
: nativeDb.prepare(`${sql} AND rowid = ?`).run(rowid).changes;
|
|
445
|
+
return Number(changes);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Clear one pre-release birth fingerprint so the fill re-derives it (spec §12.1).
|
|
449
|
+
*
|
|
450
|
+
* @param nativeDb - The `cleo.db` handle holding the cold-open lease.
|
|
451
|
+
* @param table - Declared minted table.
|
|
452
|
+
* @param rowid - The row.
|
|
453
|
+
* @task T12341
|
|
454
|
+
*/
|
|
455
|
+
export function clearBirthFpNative(nativeDb, table, rowid) {
|
|
456
|
+
nativeDb
|
|
457
|
+
.prepare(`UPDATE main.${quoteIdent(table)} SET birth_fp = NULL WHERE rowid = ?`)
|
|
458
|
+
.run(rowid);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Insert one row into a declared identity table, with the columns the row
|
|
462
|
+
* carries that the table has (a row released from the identity quarantine).
|
|
463
|
+
*
|
|
464
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
465
|
+
* @param table - Declared table.
|
|
466
|
+
* @param row - Column → value.
|
|
467
|
+
* @task T12341
|
|
468
|
+
*/
|
|
469
|
+
export function insertIdentityRowNative(nativeDb, table, row) {
|
|
470
|
+
const have = new Set(nativeDb.prepare('SELECT name FROM pragma_table_info(?)').all(table).map((c) => c.name));
|
|
471
|
+
const cols = Object.keys(row).filter((c) => have.has(c));
|
|
472
|
+
nativeDb
|
|
473
|
+
.prepare(`INSERT INTO main.${quoteIdent(table)} (${cols.map(quoteIdent).join(', ')}) VALUES (${cols
|
|
474
|
+
.map(() => '?')
|
|
475
|
+
.join(', ')})`)
|
|
476
|
+
.run(...cols.map((c) => row[c] ?? null));
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Give the row of `table` identified by (`oldUid`, `birthFp`) the uid
|
|
480
|
+
* `newUid` (a uid re-key; the birth fingerprint never changes).
|
|
481
|
+
*
|
|
482
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
483
|
+
* @param table - Declared minted table.
|
|
484
|
+
* @param oldUid - The colliding uid.
|
|
485
|
+
* @param birthFp - The row's birth fingerprint.
|
|
486
|
+
* @param newUid - Its new uid.
|
|
487
|
+
* @returns Rows changed (0 or 1).
|
|
488
|
+
* @task T12341
|
|
489
|
+
*/
|
|
490
|
+
export function setRowUidNative(nativeDb, table, oldUid, birthFp, newUid) {
|
|
491
|
+
return Number(nativeDb
|
|
492
|
+
.prepare(`UPDATE main.${quoteIdent(table)} SET uid = ? WHERE uid = ? AND birth_fp = ?`)
|
|
493
|
+
.run(newUid, oldUid, birthFp).changes);
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Point a stored reference uid column (`ac_uid`) of the rows that reference
|
|
497
|
+
* the re-keyed row by key at its new uid. Scoped by the key column, so a row
|
|
498
|
+
* referencing the OTHER holder of a colliding uid is never touched.
|
|
499
|
+
*
|
|
500
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
501
|
+
* @param table - Table holding the column.
|
|
502
|
+
* @param column - The stored reference uid column.
|
|
503
|
+
* @param fromColumn - The column that references the row by key (`ac_id`).
|
|
504
|
+
* @param key - The re-keyed row's local key.
|
|
505
|
+
* @param oldUid - Old referenced uid.
|
|
506
|
+
* @param newUid - New referenced uid.
|
|
507
|
+
* @returns Rows changed.
|
|
508
|
+
* @task T12341
|
|
509
|
+
*/
|
|
510
|
+
export function rewriteStoredRefUidNative(nativeDb, table, column, fromColumn, key, oldUid, newUid) {
|
|
511
|
+
const col = quoteIdent(column);
|
|
512
|
+
return Number(nativeDb
|
|
513
|
+
.prepare(`UPDATE main.${quoteIdent(table)} SET ${col} = ? WHERE ${col} = ? AND ${quoteIdent(fromColumn)} = ?`)
|
|
514
|
+
.run(newUid, oldUid, key).changes);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Clear one row's uid so the natural recipe re-derives it (a uid re-key
|
|
518
|
+
* changed an endpoint's uid).
|
|
519
|
+
*
|
|
520
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
521
|
+
* @param table - Declared natural table.
|
|
522
|
+
* @param rowid - The row.
|
|
523
|
+
* @task T12341
|
|
524
|
+
*/
|
|
525
|
+
export function clearRowUidNative(nativeDb, table, rowid) {
|
|
526
|
+
nativeDb.prepare(`UPDATE main.${quoteIdent(table)} SET uid = NULL WHERE rowid = ?`).run(rowid);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Delete a row-identity meta value (a re-mint record that moved with a re-key).
|
|
530
|
+
*
|
|
531
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
532
|
+
* @param key - Meta key.
|
|
533
|
+
* @task T12341
|
|
534
|
+
*/
|
|
535
|
+
export function deleteRowIdentityMetaNative(nativeDb, key) {
|
|
536
|
+
nativeDb.prepare('DELETE FROM tasks_row_identity_meta WHERE key = ?').run(key);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Set a natural row's uid by its current uid (a re-key re-derives the natural
|
|
540
|
+
* uids keyed by the re-keyed row; a receiver applies the published values).
|
|
541
|
+
*
|
|
542
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
543
|
+
* @param table - Declared natural table.
|
|
544
|
+
* @param oldUid - Current uid.
|
|
545
|
+
* @param newUid - New uid.
|
|
546
|
+
* @returns Rows changed.
|
|
547
|
+
* @task T12341
|
|
548
|
+
*/
|
|
549
|
+
export function setNaturalUidNative(nativeDb, table, oldUid, newUid) {
|
|
550
|
+
return Number(nativeDb
|
|
551
|
+
.prepare(`UPDATE main.${quoteIdent(table)} SET uid = ? WHERE uid = ?`)
|
|
552
|
+
.run(newUid, oldUid).changes);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Rewrite a held row (identity quarantine) under a new uid: a uid re-key of a
|
|
556
|
+
* row this replica holds but has not placed.
|
|
557
|
+
*
|
|
558
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
559
|
+
* @param key - The held row's table, uid and birth fingerprint.
|
|
560
|
+
* @param newUid - Its new uid.
|
|
561
|
+
* @param rowJson - Its wire form with the new uid.
|
|
562
|
+
* @task T12341
|
|
563
|
+
*/
|
|
564
|
+
export function rekeyQuarantineNative(nativeDb, key, newUid, rowJson) {
|
|
565
|
+
nativeDb
|
|
566
|
+
.prepare(`UPDATE tasks_identity_quarantine SET uid = ?, row_json = ?
|
|
567
|
+
WHERE entity_table = ? AND uid = ? AND birth_fp = ?`)
|
|
568
|
+
.run(newUid, rowJson, key.entityTable, key.uid, key.birthFp);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Add labels to a task's label junction (idempotent), for writers that
|
|
572
|
+
* insert a task with raw SQL (the sentient proposal ticks).
|
|
573
|
+
*
|
|
574
|
+
* @param nativeDb - The project `cleo.db` handle.
|
|
575
|
+
* @param taskId - The task.
|
|
576
|
+
* @param labels - Labels to add.
|
|
577
|
+
* @task T12341
|
|
578
|
+
*/
|
|
579
|
+
export function addTaskLabelsNative(nativeDb, taskId, labels) {
|
|
580
|
+
const stmt = nativeDb.prepare('INSERT OR IGNORE INTO tasks_task_labels (task_id, label) VALUES (?, ?)');
|
|
581
|
+
for (const label of labels)
|
|
582
|
+
stmt.run(taskId, label);
|
|
583
|
+
}
|
|
133
584
|
// One queue per shared native handle, independent of accessor identity. These
|
|
134
585
|
// hold coordination state only; the ProjectStore remains the owner of handles.
|
|
135
586
|
const taskTransactionQueue = new WeakMap();
|
|
@@ -189,6 +640,87 @@ async function scheduleTaskBackground(native, work) {
|
|
|
189
640
|
* ```
|
|
190
641
|
*/
|
|
191
642
|
export { captureProjectScope as captureTaskAccessorScope } from '../project-scope.js';
|
|
643
|
+
/** The claim lease columns, selected alongside a row's version (T12502). */
|
|
644
|
+
const CLAIM_COLUMNS = {
|
|
645
|
+
claimedBySession: schema.tasks.claimedBySession,
|
|
646
|
+
claimedByAgent: schema.tasks.claimedByAgent,
|
|
647
|
+
claimedAt: schema.tasks.claimedAt,
|
|
648
|
+
leaseExpiresAt: schema.tasks.leaseExpiresAt,
|
|
649
|
+
};
|
|
650
|
+
/**
|
|
651
|
+
* The claim compare-and-set predicate for an UPDATE's WHERE clause (T12502).
|
|
652
|
+
* The SQL mirror of `claimAllows`; `force` adds no predicate.
|
|
653
|
+
*
|
|
654
|
+
* @param guard - The claim guard.
|
|
655
|
+
* @param allowedHolders - Holders `acquire` / `take-over` may replace even
|
|
656
|
+
* while live (hand-off source, spawn-edge parent and children).
|
|
657
|
+
*/
|
|
658
|
+
function claimPredicate(guard, allowedHolders) {
|
|
659
|
+
const holder = schema.tasks.claimedBySession;
|
|
660
|
+
if (guard.mode === 'force')
|
|
661
|
+
return undefined;
|
|
662
|
+
const mine = guard.sessionId === null ? undefined : eq(holder, guard.sessionId);
|
|
663
|
+
if (guard.mode === 'renew' || guard.mode === 'release')
|
|
664
|
+
return mine ?? sql `0`;
|
|
665
|
+
const related = allowedHolders.length > 0 ? inArray(holder, [...allowedHolders]) : undefined;
|
|
666
|
+
const expired = guard.mode === 'take-over'
|
|
667
|
+
? or(isNull(schema.tasks.leaseExpiresAt), lte(schema.tasks.leaseExpiresAt, guard.now))
|
|
668
|
+
: undefined;
|
|
669
|
+
return or(isNull(holder), mine, related, expired);
|
|
670
|
+
}
|
|
671
|
+
/** Throw `E_TASK_CLAIMED` when the stored holder refuses this claim write. */
|
|
672
|
+
function assertClaimAllowed(taskId, row, guard, allowedHolders) {
|
|
673
|
+
const stored = claimFromColumns(row);
|
|
674
|
+
if (claimAllows(stored, guard.mode, guard.sessionId, guard.now, allowedHolders))
|
|
675
|
+
return;
|
|
676
|
+
if (!stored) {
|
|
677
|
+
throw new CleoError(ExitCode.NOT_FOUND, `Task ${taskId} has no claim held by session ${guard.sessionId ?? '(unbound)'} to ${guard.mode}`, { fix: `Take the claim first: cleo claim ${taskId}` });
|
|
678
|
+
}
|
|
679
|
+
throw taskClaimedError(taskId, stored, { sessionId: guard.sessionId, agentId: null }, guard.now);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* The holders an `acquire` / `take-over` claim write may replace even while
|
|
683
|
+
* their lease is live (T12502): the explicit hand-off source, plus the
|
|
684
|
+
* caller's claim family — the session that spawned it and the sessions it
|
|
685
|
+
* spawned (`tasks_sessions.spawned_by_session_id`, written only by the spawn
|
|
686
|
+
* itself). The self-declared `parent_session_id` (from
|
|
687
|
+
* `CLEO_PARENT_SESSION_ID` at `session start`) is NOT trusted here: any
|
|
688
|
+
* process can name any parent, so honouring it would let a forged child take
|
|
689
|
+
* a live lease silently. A spawned worker whose calls
|
|
690
|
+
* resolve to its orchestrator's session, or an orchestrator taking a task
|
|
691
|
+
* back from its own worker, is a hand-off, not a conflict.
|
|
692
|
+
*
|
|
693
|
+
* @param db - The project DB handle (inside the write transaction).
|
|
694
|
+
* @param guard - The claim guard.
|
|
695
|
+
* @returns Distinct session ids other than the caller's.
|
|
696
|
+
*/
|
|
697
|
+
async function claimAllowedHolders(db, guard) {
|
|
698
|
+
if (guard.mode !== 'acquire' && guard.mode !== 'take-over')
|
|
699
|
+
return [];
|
|
700
|
+
const holders = new Set();
|
|
701
|
+
if (guard.handoffFrom)
|
|
702
|
+
holders.add(guard.handoffFrom);
|
|
703
|
+
const sessionId = guard.sessionId;
|
|
704
|
+
if (sessionId) {
|
|
705
|
+
const [self] = await db
|
|
706
|
+
.select({ parent: schema.sessions.spawnedBySessionId })
|
|
707
|
+
.from(schema.sessions)
|
|
708
|
+
.where(eq(schema.sessions.id, sessionId))
|
|
709
|
+
.limit(1)
|
|
710
|
+
.all();
|
|
711
|
+
if (self?.parent)
|
|
712
|
+
holders.add(self.parent);
|
|
713
|
+
const children = await db
|
|
714
|
+
.select({ id: schema.sessions.id })
|
|
715
|
+
.from(schema.sessions)
|
|
716
|
+
.where(eq(schema.sessions.spawnedBySessionId, sessionId))
|
|
717
|
+
.all();
|
|
718
|
+
for (const child of children)
|
|
719
|
+
holders.add(child.id);
|
|
720
|
+
holders.delete(sessionId);
|
|
721
|
+
}
|
|
722
|
+
return [...holders];
|
|
723
|
+
}
|
|
192
724
|
/**
|
|
193
725
|
* Bind all asynchronous accessor methods, including transaction ports, to one project.
|
|
194
726
|
* @typeParam T - Concrete accessor contract retained by the scoped wrapper.
|
|
@@ -445,6 +977,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
445
977
|
async upsertSingleTask(task) {
|
|
446
978
|
await accessor.transaction((tx) => tx.upsertSingleTask(task));
|
|
447
979
|
},
|
|
980
|
+
async insertNewTask(task) {
|
|
981
|
+
await accessor.transaction((tx) => tx.insertNewTask(task));
|
|
982
|
+
},
|
|
448
983
|
async addRelation(taskId, relatedTo, relationType, reason) {
|
|
449
984
|
return accessor.transaction(async () => {
|
|
450
985
|
const db = await getDb(cwd);
|
|
@@ -521,6 +1056,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
521
1056
|
createdAt: schema.taskAcceptanceCriteria.createdAt,
|
|
522
1057
|
updatedAt: schema.taskAcceptanceCriteria.updatedAt,
|
|
523
1058
|
contentHash: schema.taskAcceptanceCriteria.contentHash,
|
|
1059
|
+
uid: schema.taskAcceptanceCriteria.uid,
|
|
1060
|
+
birthFp: schema.taskAcceptanceCriteria.birthFp,
|
|
524
1061
|
})
|
|
525
1062
|
.from(schema.taskAcceptanceCriteria)
|
|
526
1063
|
.where(eq(schema.taskAcceptanceCriteria.taskId, taskId))
|
|
@@ -538,31 +1075,20 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
538
1075
|
createdAt: r.createdAt,
|
|
539
1076
|
updatedAt: r.updatedAt ?? null,
|
|
540
1077
|
contentHash: r.contentHash ?? null,
|
|
1078
|
+
uid: r.uid ?? null,
|
|
1079
|
+
birthFp: r.birthFp ?? null,
|
|
541
1080
|
}));
|
|
542
1081
|
},
|
|
543
1082
|
// ---- AC bindings (T10509 — AC-coverage gate) ----
|
|
544
1083
|
async getAcBindings(acIds) {
|
|
545
1084
|
if (acIds.length === 0)
|
|
546
1085
|
return [];
|
|
1086
|
+
return selectAcBindings(await getDb(cwd), acIds);
|
|
1087
|
+
},
|
|
1088
|
+
// ---- AC bindings — orphan scan (T12790) ----
|
|
1089
|
+
async findOrphanAcBindings() {
|
|
547
1090
|
const db = await getDb(cwd);
|
|
548
|
-
|
|
549
|
-
.select({
|
|
550
|
-
id: schema.evidenceAcBindings.id,
|
|
551
|
-
evidenceAtomId: schema.evidenceAcBindings.evidenceAtomId,
|
|
552
|
-
acId: schema.evidenceAcBindings.acId,
|
|
553
|
-
bindingType: schema.evidenceAcBindings.bindingType,
|
|
554
|
-
createdAt: schema.evidenceAcBindings.createdAt,
|
|
555
|
-
})
|
|
556
|
-
.from(schema.evidenceAcBindings)
|
|
557
|
-
.where(inArray(schema.evidenceAcBindings.acId, acIds))
|
|
558
|
-
.all();
|
|
559
|
-
return rows.map((r) => ({
|
|
560
|
-
id: r.id,
|
|
561
|
-
evidenceAtomId: r.evidenceAtomId,
|
|
562
|
-
acId: r.acId,
|
|
563
|
-
bindingType: r.bindingType,
|
|
564
|
-
createdAt: r.createdAt,
|
|
565
|
-
}));
|
|
1091
|
+
return selectOrphanAcBindings(db);
|
|
566
1092
|
},
|
|
567
1093
|
async archiveSingleTask(taskId, fields) {
|
|
568
1094
|
return accessor.transaction(async () => {
|
|
@@ -606,6 +1132,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
606
1132
|
.delete(schema.taskDependencies)
|
|
607
1133
|
.where(eq(schema.taskDependencies.dependsOn, taskId))
|
|
608
1134
|
.run();
|
|
1135
|
+
// T12790: the bindings table has no FK to the AC rows that cascade
|
|
1136
|
+
// from tasks_tasks — remove (and audit) them explicitly.
|
|
1137
|
+
await pruneAcBindingsForTask(db, taskId);
|
|
609
1138
|
// Delete the task itself
|
|
610
1139
|
await db.delete(schema.tasks).where(eq(schema.tasks.id, taskId)).run();
|
|
611
1140
|
});
|
|
@@ -1018,24 +1547,54 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1018
1547
|
// E_CONFLICT, and advance the version strictly so a same-millisecond
|
|
1019
1548
|
// write can never reproduce a version a stale reader already holds.
|
|
1020
1549
|
const [current] = await db
|
|
1021
|
-
.select({
|
|
1550
|
+
.select({
|
|
1551
|
+
updatedAt: schema.tasks.updatedAt,
|
|
1552
|
+
createdAt: schema.tasks.createdAt,
|
|
1553
|
+
...CLAIM_COLUMNS,
|
|
1554
|
+
})
|
|
1022
1555
|
.from(schema.tasks)
|
|
1023
1556
|
.where(eq(schema.tasks.id, taskId))
|
|
1024
1557
|
.limit(1)
|
|
1025
1558
|
.all();
|
|
1026
1559
|
if (!current)
|
|
1027
1560
|
throw new Error(`Task not found: ${taskId}`);
|
|
1028
|
-
|
|
1561
|
+
// T12502: refuse a claim write the stored holder does not allow before
|
|
1562
|
+
// touching anything, with the holder named. The WHERE clause below
|
|
1563
|
+
// repeats the predicate, so the write itself is the compare-and-set.
|
|
1564
|
+
const claimGuard = guard?.claim;
|
|
1565
|
+
const allowedHolders = claimGuard ? await claimAllowedHolders(db, claimGuard) : [];
|
|
1566
|
+
if (claimGuard)
|
|
1567
|
+
assertClaimAllowed(taskId, current, claimGuard, allowedHolders);
|
|
1568
|
+
const expected = guard?.expectedUpdatedAt;
|
|
1569
|
+
if (expected !== undefined && taskVersion(current) !== expected) {
|
|
1570
|
+
throw taskConflictError(taskId, expected, (await accessor.loadSingleTask(taskId)) ?? current, guard?.baseline);
|
|
1571
|
+
}
|
|
1029
1572
|
const updateRow = {
|
|
1030
1573
|
...fields,
|
|
1031
|
-
updatedAt: fields.updatedAt ?? nextTaskVersion(current),
|
|
1574
|
+
updatedAt: fields.updatedAt ?? (guard?.keepVersion ? current.updatedAt : nextTaskVersion(current)),
|
|
1032
1575
|
};
|
|
1576
|
+
// T12503: a guarded write is a compare-and-set in SQL — the UPDATE
|
|
1577
|
+
// matches only while the stored version is still the expected one, so
|
|
1578
|
+
// the check and the write are one statement, not a read-then-write.
|
|
1579
|
+
const versionMatch = expected === undefined
|
|
1580
|
+
? undefined
|
|
1581
|
+
: current.updatedAt === null
|
|
1582
|
+
? isNull(schema.tasks.updatedAt)
|
|
1583
|
+
: eq(schema.tasks.updatedAt, current.updatedAt);
|
|
1584
|
+
const where = and(eq(schema.tasks.id, taskId), versionMatch, claimGuard ? claimPredicate(claimGuard, allowedHolders) : undefined);
|
|
1033
1585
|
// gh#391: this is the chokepoint for `cleo update <id> --add-labels`.
|
|
1034
1586
|
// Parallel invocations from a single shell used to lose ~50% of writes
|
|
1035
1587
|
// to SQLITE_BUSY; withWriteRetry recovers them.
|
|
1036
|
-
const result = await withWriteRetry(() => db.update(schema.tasks).set(updateRow).where(
|
|
1037
|
-
if (Number(result.changes) !== 1)
|
|
1038
|
-
|
|
1588
|
+
const result = await withWriteRetry(() => db.update(schema.tasks).set(updateRow).where(where).run());
|
|
1589
|
+
if (Number(result.changes) !== 1) {
|
|
1590
|
+
const stored = await accessor.loadSingleTask(taskId);
|
|
1591
|
+
if (!stored)
|
|
1592
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
1593
|
+
if (claimGuard) {
|
|
1594
|
+
assertClaimAllowed(taskId, claimColumnsOf(stored.claim), claimGuard, allowedHolders);
|
|
1595
|
+
}
|
|
1596
|
+
throw taskConflictError(taskId, expected ?? taskVersion(current), stored, guard?.baseline);
|
|
1597
|
+
}
|
|
1039
1598
|
if (fields.labelsJson !== undefined) {
|
|
1040
1599
|
await updateTaskLabels(db, taskId, parseLabels(fields.labelsJson));
|
|
1041
1600
|
}
|
|
@@ -1089,6 +1648,14 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1089
1648
|
await updateDependencies(db, task.id, task.depends ?? []);
|
|
1090
1649
|
});
|
|
1091
1650
|
},
|
|
1651
|
+
async insertNewTask(task) {
|
|
1652
|
+
scope.assertActive();
|
|
1653
|
+
return accessor.transaction(async () => {
|
|
1654
|
+
scope.assertActive();
|
|
1655
|
+
await insertNewTask(db, taskToRow(task));
|
|
1656
|
+
await updateDependencies(db, task.id, task.depends ?? []);
|
|
1657
|
+
});
|
|
1658
|
+
},
|
|
1092
1659
|
async archiveSingleTask(taskId, fields) {
|
|
1093
1660
|
scope.assertActive();
|
|
1094
1661
|
return accessor.transaction(async () => {
|
|
@@ -1118,6 +1685,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1118
1685
|
.delete(schema.taskDependencies)
|
|
1119
1686
|
.where(eq(schema.taskDependencies.dependsOn, taskId))
|
|
1120
1687
|
.run();
|
|
1688
|
+
// T12790: bindings of the cascading AC rows (no FK).
|
|
1689
|
+
await pruneAcBindingsForTask(db, taskId);
|
|
1121
1690
|
await db.delete(schema.tasks).where(eq(schema.tasks.id, taskId)).run();
|
|
1122
1691
|
});
|
|
1123
1692
|
},
|
|
@@ -1197,6 +1766,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1197
1766
|
projection: r.projection ?? 'legacy',
|
|
1198
1767
|
text: r.text,
|
|
1199
1768
|
contentHash: r.contentHash ?? null,
|
|
1769
|
+
// A kept criterion keeps its uid (T12341); else one is minted.
|
|
1770
|
+
...(r.uid ? { uid: r.uid } : {}),
|
|
1771
|
+
...(r.uid && r.birthFp ? { birthFp: r.birthFp } : {}),
|
|
1200
1772
|
})))
|
|
1201
1773
|
.run();
|
|
1202
1774
|
});
|
|
@@ -1216,6 +1788,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1216
1788
|
createdAt: schema.taskAcceptanceCriteria.createdAt,
|
|
1217
1789
|
updatedAt: schema.taskAcceptanceCriteria.updatedAt,
|
|
1218
1790
|
contentHash: schema.taskAcceptanceCriteria.contentHash,
|
|
1791
|
+
uid: schema.taskAcceptanceCriteria.uid,
|
|
1792
|
+
birthFp: schema.taskAcceptanceCriteria.birthFp,
|
|
1219
1793
|
})
|
|
1220
1794
|
.from(schema.taskAcceptanceCriteria)
|
|
1221
1795
|
.where(eq(schema.taskAcceptanceCriteria.taskId, taskId))
|
|
@@ -1233,18 +1807,70 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1233
1807
|
createdAt: r.createdAt,
|
|
1234
1808
|
updatedAt: r.updatedAt ?? null,
|
|
1235
1809
|
contentHash: r.contentHash ?? null,
|
|
1810
|
+
uid: r.uid ?? null,
|
|
1811
|
+
birthFp: r.birthFp ?? null,
|
|
1236
1812
|
}));
|
|
1237
1813
|
},
|
|
1238
1814
|
async deleteAcRowsForTask(taskId) {
|
|
1239
1815
|
scope.assertActive();
|
|
1240
1816
|
return accessor.transaction(async () => {
|
|
1241
1817
|
scope.assertActive();
|
|
1818
|
+
// T12790: remove (and audit) the departing rows' bindings.
|
|
1819
|
+
await pruneAcBindingsForTask(db, taskId, 'ac-removed');
|
|
1242
1820
|
await db
|
|
1243
1821
|
.delete(schema.taskAcceptanceCriteria)
|
|
1244
1822
|
.where(eq(schema.taskAcceptanceCriteria.taskId, taskId))
|
|
1245
1823
|
.run();
|
|
1246
1824
|
});
|
|
1247
1825
|
},
|
|
1826
|
+
async deleteAcRowsByIds(taskId, ids, keepBindingsForUids = []) {
|
|
1827
|
+
scope.assertActive();
|
|
1828
|
+
if (ids.length === 0)
|
|
1829
|
+
return;
|
|
1830
|
+
return accessor.transaction(async () => {
|
|
1831
|
+
scope.assertActive();
|
|
1832
|
+
// T12790: only ids this task actually owns leave the set —
|
|
1833
|
+
// prune (and audit) exactly their bindings.
|
|
1834
|
+
const owned = await db
|
|
1835
|
+
.select({ id: schema.taskAcceptanceCriteria.id })
|
|
1836
|
+
.from(schema.taskAcceptanceCriteria)
|
|
1837
|
+
.where(and(eq(schema.taskAcceptanceCriteria.taskId, taskId), inArray(schema.taskAcceptanceCriteria.id, ids)))
|
|
1838
|
+
.all();
|
|
1839
|
+
await pruneAcBindingsForAcIds(db, taskId, owned.map((r) => r.id), 'ac-removed', keepBindingsForUids);
|
|
1840
|
+
await db
|
|
1841
|
+
.delete(schema.taskAcceptanceCriteria)
|
|
1842
|
+
.where(and(eq(schema.taskAcceptanceCriteria.taskId, taskId), inArray(schema.taskAcceptanceCriteria.id, ids)))
|
|
1843
|
+
.run();
|
|
1844
|
+
});
|
|
1845
|
+
},
|
|
1846
|
+
async updateAcRows(rows) {
|
|
1847
|
+
scope.assertActive();
|
|
1848
|
+
if (rows.length === 0)
|
|
1849
|
+
return;
|
|
1850
|
+
return accessor.transaction(async () => {
|
|
1851
|
+
scope.assertActive();
|
|
1852
|
+
const updatedAt = new Date().toISOString();
|
|
1853
|
+
for (const r of rows) {
|
|
1854
|
+
const result = await db
|
|
1855
|
+
.update(schema.taskAcceptanceCriteria)
|
|
1856
|
+
.set({
|
|
1857
|
+
ordinal: r.ordinal,
|
|
1858
|
+
kind: r.kind ?? 'text',
|
|
1859
|
+
sourceKey: r.sourceKey ?? `text:${r.ordinal}`,
|
|
1860
|
+
targetTaskId: r.targetTaskId ?? null,
|
|
1861
|
+
projection: r.projection ?? 'legacy',
|
|
1862
|
+
text: r.text,
|
|
1863
|
+
contentHash: r.contentHash ?? null,
|
|
1864
|
+
updatedAt,
|
|
1865
|
+
})
|
|
1866
|
+
.where(and(eq(schema.taskAcceptanceCriteria.id, r.id), eq(schema.taskAcceptanceCriteria.taskId, r.taskId)))
|
|
1867
|
+
.run();
|
|
1868
|
+
if (Number(result.changes) === 0) {
|
|
1869
|
+
throw new CleoError(ExitCode.VALIDATION_ERROR, `Acceptance criterion ${r.id} does not exist on task ${r.taskId}; refusing to update it`);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
});
|
|
1873
|
+
},
|
|
1248
1874
|
async appendAcHistory(rows) {
|
|
1249
1875
|
scope.assertActive();
|
|
1250
1876
|
return accessor.transaction(async () => {
|
|
@@ -1257,6 +1883,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1257
1883
|
acId: r.acId,
|
|
1258
1884
|
previousText: r.previousText,
|
|
1259
1885
|
reason: r.reason,
|
|
1886
|
+
...(r.acUid ? { acUid: r.acUid } : {}),
|
|
1260
1887
|
})))
|
|
1261
1888
|
.run();
|
|
1262
1889
|
});
|
|
@@ -1264,26 +1891,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1264
1891
|
// ---- AC bindings (T10509 — AC-coverage gate) ----
|
|
1265
1892
|
async getAcBindings(acIds) {
|
|
1266
1893
|
scope.assertActive();
|
|
1267
|
-
|
|
1268
|
-
return [];
|
|
1269
|
-
const out = await db
|
|
1270
|
-
.select({
|
|
1271
|
-
id: schema.evidenceAcBindings.id,
|
|
1272
|
-
evidenceAtomId: schema.evidenceAcBindings.evidenceAtomId,
|
|
1273
|
-
acId: schema.evidenceAcBindings.acId,
|
|
1274
|
-
bindingType: schema.evidenceAcBindings.bindingType,
|
|
1275
|
-
createdAt: schema.evidenceAcBindings.createdAt,
|
|
1276
|
-
})
|
|
1277
|
-
.from(schema.evidenceAcBindings)
|
|
1278
|
-
.where(inArray(schema.evidenceAcBindings.acId, acIds))
|
|
1279
|
-
.all();
|
|
1280
|
-
return out.map((r) => ({
|
|
1281
|
-
id: r.id,
|
|
1282
|
-
evidenceAtomId: r.evidenceAtomId,
|
|
1283
|
-
acId: r.acId,
|
|
1284
|
-
bindingType: r.bindingType,
|
|
1285
|
-
createdAt: r.createdAt,
|
|
1286
|
-
}));
|
|
1894
|
+
return selectAcBindings(db, acIds);
|
|
1287
1895
|
},
|
|
1288
1896
|
// ---- AC bindings — writer (T10511, Validator SDK tools) ----
|
|
1289
1897
|
async insertAcBindings(rows) {
|
|
@@ -1312,6 +1920,14 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1312
1920
|
.run();
|
|
1313
1921
|
});
|
|
1314
1922
|
},
|
|
1923
|
+
// ---- AC bindings — orphan repair (T12790) ----
|
|
1924
|
+
async pruneOrphanAcBindings() {
|
|
1925
|
+
scope.assertActive();
|
|
1926
|
+
return accessor.transaction(async () => {
|
|
1927
|
+
scope.assertActive();
|
|
1928
|
+
return pruneOrphanAcBindings(db);
|
|
1929
|
+
});
|
|
1930
|
+
},
|
|
1315
1931
|
};
|
|
1316
1932
|
const result = await fn(bindTaskAccessorScope(tx, accessorScope));
|
|
1317
1933
|
await scope.pending;
|
|
@@ -1378,52 +1994,134 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
1378
1994
|
const { getAgentInstance: getAgent } = await import('../agents/registry.js');
|
|
1379
1995
|
return getAgent(agentId, cwd);
|
|
1380
1996
|
},
|
|
1381
|
-
// ---- Agent task claiming ----
|
|
1382
|
-
async claimTask(taskId,
|
|
1997
|
+
// ---- Agent task claiming (leased, T12502) ----
|
|
1998
|
+
async claimTask(taskId, request) {
|
|
1999
|
+
const now = request.now ?? new Date().toISOString();
|
|
2000
|
+
const guard = {
|
|
2001
|
+
sessionId: request.sessionId,
|
|
2002
|
+
mode: request.mode,
|
|
2003
|
+
now,
|
|
2004
|
+
handoffFrom: request.handoffFrom ?? null,
|
|
2005
|
+
};
|
|
1383
2006
|
return accessor.transaction(async () => {
|
|
1384
|
-
const
|
|
1385
|
-
if (!
|
|
1386
|
-
throw new Error('Native database not initialized');
|
|
1387
|
-
}
|
|
1388
|
-
// Verify the task exists first
|
|
1389
|
-
const existsRow = nativeDb
|
|
1390
|
-
.prepare('SELECT assignee FROM tasks_tasks WHERE id = ?')
|
|
1391
|
-
.get(taskId);
|
|
1392
|
-
if (!existsRow) {
|
|
2007
|
+
const task = await accessor.loadSingleTask(taskId);
|
|
2008
|
+
if (!task)
|
|
1393
2009
|
throw new Error(`Task not found: ${taskId}`);
|
|
2010
|
+
const before = task.claim;
|
|
2011
|
+
if (request.sessionId === null) {
|
|
2012
|
+
// An override names who takes the task; an unbound caller has no
|
|
2013
|
+
// session to record, so it is refused rather than silently ignored.
|
|
2014
|
+
if (request.mode === 'take-over' || request.mode === 'force') {
|
|
2015
|
+
const flag = request.mode === 'force' ? '--force-claim' : '--take-over';
|
|
2016
|
+
throw new CleoError(ExitCode.SESSION_UNBOUND, `Cannot ${flag} task ${taskId}: this caller is not bound to a session, so there is no session to hand the claim to.`, {
|
|
2017
|
+
fix: `Bind a session first (cleo session start --scope global --name "<work>", cleo session resume <id>, or export CLEO_SESSION_ID=<id>), then retry with ${flag}.`,
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
2020
|
+
// An unbound caller holds no lease; the guarded no-op write still
|
|
2021
|
+
// proves, under the write lock, that no other session holds it.
|
|
2022
|
+
await accessor.updateTaskFields(taskId, {}, { claim: guard, keepVersion: true });
|
|
2023
|
+
return null;
|
|
1394
2024
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
.
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
2025
|
+
const renewing = before?.sessionId === request.sessionId;
|
|
2026
|
+
const lease = {
|
|
2027
|
+
sessionId: request.sessionId,
|
|
2028
|
+
agentId: request.agentId ?? (renewing ? (before?.agentId ?? null) : null),
|
|
2029
|
+
claimedAt: renewing && before ? before.claimedAt : now,
|
|
2030
|
+
leaseExpiresAt: leaseExpiresAtFrom(now, request.leaseMs ?? taskClaimLeaseMs()),
|
|
2031
|
+
};
|
|
2032
|
+
await accessor.updateTaskFields(taskId, {
|
|
2033
|
+
claimedBySession: lease.sessionId,
|
|
2034
|
+
claimedByAgent: lease.agentId,
|
|
2035
|
+
claimedAt: lease.claimedAt,
|
|
2036
|
+
leaseExpiresAt: lease.leaseExpiresAt,
|
|
2037
|
+
},
|
|
2038
|
+
// Renewing one's own lease is bookkeeping, not an edit: it must not
|
|
2039
|
+
// move the version another writer holds for --if-match.
|
|
2040
|
+
{ claim: guard, keepVersion: renewing });
|
|
2041
|
+
const replaced = before && before.sessionId !== request.sessionId ? before : undefined;
|
|
2042
|
+
if (replaced) {
|
|
2043
|
+
// A write the predicate allowed over a LIVE lease without `force` is
|
|
2044
|
+
// a claim-family hand-off (spawn source, spawn-edge parent or child).
|
|
2045
|
+
const handoff = request.mode !== 'force' && !isClaimExpired(replaced, now);
|
|
2046
|
+
await accessor.appendLog({
|
|
2047
|
+
action: handoff
|
|
2048
|
+
? 'task_claim_handoff'
|
|
2049
|
+
: request.mode === 'force'
|
|
2050
|
+
? 'task_claim_force'
|
|
2051
|
+
: 'task_claim_takeover',
|
|
2052
|
+
taskId,
|
|
2053
|
+
actor: request.agentId ?? request.sessionId,
|
|
2054
|
+
sessionId: request.sessionId,
|
|
2055
|
+
timestamp: now,
|
|
2056
|
+
details: {
|
|
2057
|
+
mode: request.mode,
|
|
2058
|
+
leaseExpired: replaced.leaseExpiresAt <= now,
|
|
2059
|
+
},
|
|
2060
|
+
before: replaced,
|
|
2061
|
+
after: lease,
|
|
2062
|
+
});
|
|
1406
2063
|
}
|
|
2064
|
+
return lease;
|
|
1407
2065
|
});
|
|
1408
2066
|
},
|
|
1409
|
-
async unclaimTask(taskId) {
|
|
2067
|
+
async unclaimTask(taskId, release) {
|
|
2068
|
+
const now = new Date().toISOString();
|
|
1410
2069
|
return accessor.transaction(async () => {
|
|
1411
|
-
const
|
|
1412
|
-
if (!
|
|
1413
|
-
throw new Error('Native database not initialized');
|
|
1414
|
-
}
|
|
1415
|
-
// Verify the task exists
|
|
1416
|
-
const existsRow = nativeDb.prepare('SELECT id FROM tasks_tasks WHERE id = ?').get(taskId);
|
|
1417
|
-
if (!existsRow) {
|
|
2070
|
+
const task = await accessor.loadSingleTask(taskId);
|
|
2071
|
+
if (!task)
|
|
1418
2072
|
throw new Error(`Task not found: ${taskId}`);
|
|
2073
|
+
const held = task.claim;
|
|
2074
|
+
if (!held)
|
|
2075
|
+
return false;
|
|
2076
|
+
await accessor.updateTaskFields(taskId, { claimedBySession: null, claimedByAgent: null, claimedAt: null, leaseExpiresAt: null }, {
|
|
2077
|
+
claim: { sessionId: release.sessionId, mode: release.force ? 'force' : 'release', now },
|
|
2078
|
+
keepVersion: true,
|
|
2079
|
+
});
|
|
2080
|
+
if (held.sessionId !== release.sessionId) {
|
|
2081
|
+
await accessor.appendLog({
|
|
2082
|
+
action: 'task_claim_force_release',
|
|
2083
|
+
taskId,
|
|
2084
|
+
actor: release.sessionId ?? 'unbound',
|
|
2085
|
+
sessionId: release.sessionId,
|
|
2086
|
+
timestamp: now,
|
|
2087
|
+
details: { mode: 'force', leaseExpired: held.leaseExpiresAt <= now },
|
|
2088
|
+
before: held,
|
|
2089
|
+
});
|
|
1419
2090
|
}
|
|
1420
|
-
|
|
1421
|
-
nativeDb
|
|
1422
|
-
.prepare('UPDATE tasks_tasks SET assignee = NULL, updated_at = ? WHERE id = ?')
|
|
1423
|
-
.run(new Date().toISOString(), taskId);
|
|
2091
|
+
return true;
|
|
1424
2092
|
});
|
|
1425
2093
|
},
|
|
2094
|
+
async renewSessionClaims(sessionId, leaseExpiresAt) {
|
|
2095
|
+
// The heartbeat follows EVERY mutation of a bound session, and almost no
|
|
2096
|
+
// session holds a lease. Probe the claimed_by_session index first and
|
|
2097
|
+
// write only when there is a lease to extend, so the common case costs
|
|
2098
|
+
// one indexed read and no lock.
|
|
2099
|
+
const db = await getDb(cwd);
|
|
2100
|
+
const [held] = await db
|
|
2101
|
+
.select({ id: schema.tasks.id })
|
|
2102
|
+
.from(schema.tasks)
|
|
2103
|
+
.where(eq(schema.tasks.claimedBySession, sessionId))
|
|
2104
|
+
.limit(1)
|
|
2105
|
+
.all();
|
|
2106
|
+
if (!held)
|
|
2107
|
+
return 0;
|
|
2108
|
+
// Bounded lock wait, skipped on SQLITE_BUSY or inside another caller's
|
|
2109
|
+
// transaction — see runHeartbeatWrite. The next mutation renews.
|
|
2110
|
+
return (runHeartbeatWrite(db, getNativeTasksDb(cwd), () => Number(db
|
|
2111
|
+
.update(schema.tasks)
|
|
2112
|
+
.set({ leaseExpiresAt })
|
|
2113
|
+
.where(eq(schema.tasks.claimedBySession, sessionId))
|
|
2114
|
+
.run().changes)) ?? 0);
|
|
2115
|
+
},
|
|
1426
2116
|
};
|
|
1427
2117
|
return accessor;
|
|
1428
2118
|
}
|
|
2119
|
+
// T12341: the row-identity open pass writes through these chokepoint helpers.
|
|
2120
|
+
registerRowIdentityWriters({
|
|
2121
|
+
relinkAcUidNative,
|
|
2122
|
+
clearAcUidGraveyardNative,
|
|
2123
|
+
writeRowIdentityMetaNative,
|
|
2124
|
+
fillIdentityColumnNative,
|
|
2125
|
+
clearBirthFpNative,
|
|
2126
|
+
});
|
|
1429
2127
|
//# sourceMappingURL=sqlite-data-accessor.js.map
|