@cleocode/core 2026.9.24 → 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/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/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/decide/bench/index.d.ts +1 -1
- package/dist/decide/bench/index.d.ts.map +1 -1
- package/dist/decide/bench/index.js +1 -1
- package/dist/decide/bench/index.js.map +1 -1
- package/dist/decide/bench/operation.d.ts +1 -1
- package/dist/decide/bench/operation.d.ts.map +1 -1
- package/dist/decide/bench/operation.js +1 -1
- package/dist/decide/bench/operation.js.map +1 -1
- package/dist/decide/bench/profiles.d.ts +50 -22
- package/dist/decide/bench/profiles.d.ts.map +1 -1
- package/dist/decide/bench/profiles.js +103 -59
- package/dist/decide/bench/profiles.js.map +1 -1
- package/dist/decide/bench/report.d.ts.map +1 -1
- package/dist/decide/bench/report.js +6 -1
- package/dist/decide/bench/report.js.map +1 -1
- package/dist/decide/bench/runner.d.ts +6 -1
- package/dist/decide/bench/runner.d.ts.map +1 -1
- package/dist/decide/bench/runner.js +1 -0
- package/dist/decide/bench/runner.js.map +1 -1
- package/dist/decide/client.d.ts.map +1 -1
- package/dist/decide/client.js +11 -5
- package/dist/decide/client.js.map +1 -1
- package/dist/decide/jev-wire.d.ts +31 -1
- package/dist/decide/jev-wire.d.ts.map +1 -1
- package/dist/decide/jev-wire.js +61 -7
- package/dist/decide/jev-wire.js.map +1 -1
- package/dist/docs/export-document.js +17181 -15536
- package/dist/docs/export-document.js.map +3 -3
- package/dist/doctor/orphan-ac-bindings.d.ts +64 -0
- package/dist/doctor/orphan-ac-bindings.d.ts.map +1 -0
- package/dist/doctor/orphan-ac-bindings.js +59 -0
- package/dist/doctor/orphan-ac-bindings.js.map +1 -0
- package/dist/doctor/projects.d.ts.map +1 -1
- package/dist/doctor/projects.js +43 -29
- package/dist/doctor/projects.js.map +1 -1
- package/dist/doctor/row-identity.d.ts +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 +58 -2
- package/dist/doctor/twin-collapse.d.ts.map +1 -1
- package/dist/doctor/twin-collapse.js +212 -14
- package/dist/doctor/twin-collapse.js.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.d.ts.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.js +10 -0
- package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
- package/dist/llm/plugin-facade.js +17045 -15400
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +19 -10
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/manifest-identity.d.ts +171 -0
- package/dist/memory/manifest-identity.d.ts.map +1 -0
- package/dist/memory/manifest-identity.js +345 -0
- package/dist/memory/manifest-identity.js.map +1 -0
- package/dist/memory/mental-model-queue.d.ts +14 -4
- package/dist/memory/mental-model-queue.d.ts.map +1 -1
- package/dist/memory/mental-model-queue.js +64 -35
- package/dist/memory/mental-model-queue.js.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.d.ts +47 -5
- package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.js +130 -14
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
- package/dist/memory/retrieval/observe.d.ts.map +1 -1
- package/dist/memory/retrieval/observe.js +2 -0
- package/dist/memory/retrieval/observe.js.map +1 -1
- package/dist/memory/transcript-scanner.js +1 -1
- package/dist/nexus/deps.d.ts.map +1 -1
- package/dist/nexus/deps.js +7 -14
- package/dist/nexus/deps.js.map +1 -1
- package/dist/nexus/discover.d.ts.map +1 -1
- package/dist/nexus/discover.js +6 -9
- package/dist/nexus/discover.js.map +1 -1
- package/dist/nexus/git-state.d.ts.map +1 -1
- package/dist/nexus/git-state.js +10 -1
- package/dist/nexus/git-state.js.map +1 -1
- package/dist/nexus/projects-clean.d.ts.map +1 -1
- package/dist/nexus/projects-clean.js +22 -11
- package/dist/nexus/projects-clean.js.map +1 -1
- package/dist/nexus/projects-scan.d.ts.map +1 -1
- package/dist/nexus/projects-scan.js +8 -13
- package/dist/nexus/projects-scan.js.map +1 -1
- package/dist/nexus/query.d.ts.map +1 -1
- package/dist/nexus/query.js +4 -12
- package/dist/nexus/query.js.map +1 -1
- package/dist/nexus/registry-roots.d.ts +5 -2
- package/dist/nexus/registry-roots.d.ts.map +1 -1
- package/dist/nexus/registry-roots.js +8 -10
- package/dist/nexus/registry-roots.js.map +1 -1
- package/dist/nexus/registry.d.ts +18 -0
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/nexus/registry.js +37 -16
- package/dist/nexus/registry.js.map +1 -1
- package/dist/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/spawn-prompt.d.ts +26 -0
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +62 -91
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/release/ci-evidence.d.ts +190 -0
- package/dist/release/ci-evidence.d.ts.map +1 -1
- package/dist/release/ci-evidence.js +436 -4
- package/dist/release/ci-evidence.js.map +1 -1
- package/dist/sdk/validator-ac-pull.d.ts.map +1 -1
- package/dist/sdk/validator-ac-pull.js +2 -1
- package/dist/sdk/validator-ac-pull.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +17049 -15404
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sentient/cross-project-hygiene.d.ts +5 -0
- package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
- package/dist/sentient/cross-project-hygiene.js +7 -1
- package/dist/sentient/cross-project-hygiene.js.map +1 -1
- package/dist/sentient/propose-tick.d.ts.map +1 -1
- package/dist/sentient/propose-tick.js +2 -3
- package/dist/sentient/propose-tick.js.map +1 -1
- package/dist/sentient/stage-drift-tick.d.ts.map +1 -1
- package/dist/sentient/stage-drift-tick.js +2 -3
- package/dist/sentient/stage-drift-tick.js.map +1 -1
- package/dist/skills/manifests/research.js +2 -0
- package/dist/skills/manifests/research.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/spawn/branch-lock.d.ts +111 -7
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +296 -8
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/store/ac-binding-prune.d.ts +144 -0
- package/dist/store/ac-binding-prune.d.ts.map +1 -0
- package/dist/store/ac-binding-prune.js +293 -0
- package/dist/store/ac-binding-prune.js.map +1 -0
- package/dist/store/agent-registry-store.d.ts.map +1 -1
- package/dist/store/agent-registry-store.js +3 -2
- package/dist/store/agent-registry-store.js.map +1 -1
- package/dist/store/backup-sidecar.d.ts +85 -2
- package/dist/store/backup-sidecar.d.ts.map +1 -1
- package/dist/store/backup-sidecar.js +173 -1
- package/dist/store/backup-sidecar.js.map +1 -1
- package/dist/store/conduit-sqlite.d.ts.map +1 -1
- package/dist/store/conduit-sqlite.js +3 -2
- package/dist/store/conduit-sqlite.js.map +1 -1
- package/dist/store/credential-transfer.d.ts.map +1 -1
- package/dist/store/credential-transfer.js +3 -0
- package/dist/store/credential-transfer.js.map +1 -1
- package/dist/store/db-helpers.d.ts +17 -11
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +61 -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/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/legacy-tasks-lineage.d.ts.map +1 -1
- package/dist/store/legacy-tasks-lineage.js +19 -2
- package/dist/store/legacy-tasks-lineage.js.map +1 -1
- package/dist/store/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 +2 -0
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +4 -0
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/schema/attachments.d.ts +1 -1
- package/dist/store/schema/audit.d.ts +4 -4
- package/dist/store/schema/background-jobs.d.ts +1 -1
- package/dist/store/schema/cleo-global/nexus.d.ts +1 -1
- package/dist/store/schema/cleo-global/skills.d.ts +2 -2
- package/dist/store/schema/cleo-project/audit.d.ts +4 -4
- package/dist/store/schema/cleo-project/docs.d.ts +1 -1
- package/dist/store/schema/cleo-project/lifecycle.d.ts +4 -4
- package/dist/store/schema/cleo-project/nexus-graph.d.ts +3 -3
- package/dist/store/schema/cleo-project/provenance-commits.d.ts +2 -2
- package/dist/store/schema/cleo-project/provenance-rest.d.ts +3 -3
- package/dist/store/schema/cleo-project/runtime.d.ts +3 -3
- package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts +87 -1
- package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core-batch2.js +35 -0
- package/dist/store/schema/cleo-project/tasks-core-batch2.js.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.d.ts +183 -7
- package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.js +52 -1
- package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +6 -6
- package/dist/store/schema/lifecycle.d.ts +4 -4
- package/dist/store/schema/manifest.d.ts +1 -1
- package/dist/store/schema/memory-schema.d.ts +5 -5
- package/dist/store/schema/nexus-schema.d.ts +3 -3
- package/dist/store/schema/provenance/releases.d.ts +1 -1
- package/dist/store/schema/skills-schema.d.ts +2 -2
- package/dist/store/schema/tasks.d.ts +6 -6
- package/dist/store/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 +544 -44
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sync/clock-store.d.ts +67 -0
- package/dist/store/sync/clock-store.d.ts.map +1 -0
- package/dist/store/sync/clock-store.js +117 -0
- package/dist/store/sync/clock-store.js.map +1 -0
- package/dist/store/sync/flags.d.ts +51 -0
- package/dist/store/sync/flags.d.ts.map +1 -0
- package/dist/store/sync/flags.js +81 -0
- package/dist/store/sync/flags.js.map +1 -0
- package/dist/store/sync/hlc.d.ts +115 -0
- package/dist/store/sync/hlc.d.ts.map +1 -0
- package/dist/store/sync/hlc.js +172 -0
- package/dist/store/sync/hlc.js.map +1 -0
- package/dist/store/sync/index.d.ts +20 -0
- package/dist/store/sync/index.d.ts.map +1 -0
- package/dist/store/sync/index.js +20 -0
- package/dist/store/sync/index.js.map +1 -0
- package/dist/store/sync/replica-registry.d.ts +85 -0
- package/dist/store/sync/replica-registry.d.ts.map +1 -0
- package/dist/store/sync/replica-registry.js +147 -0
- package/dist/store/sync/replica-registry.js.map +1 -0
- package/dist/store/sync/replica.d.ts +181 -0
- package/dist/store/sync/replica.d.ts.map +1 -0
- package/dist/store/sync/replica.js +305 -0
- package/dist/store/sync/replica.js.map +1 -0
- package/dist/store/sync/schema.d.ts +68 -0
- package/dist/store/sync/schema.d.ts.map +1 -0
- package/dist/store/sync/schema.js +130 -0
- package/dist/store/sync/schema.js.map +1 -0
- package/dist/store/sync/skew-hold.d.ts +71 -0
- package/dist/store/sync/skew-hold.d.ts.map +1 -0
- package/dist/store/sync/skew-hold.js +89 -0
- package/dist/store/sync/skew-hold.js.map +1 -0
- package/dist/store/table-classification.d.ts +10 -8
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +93 -25
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +9 -1
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +113 -2
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +247 -19
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +2 -0
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +4 -0
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +241 -49
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +3 -0
- package/dist/system/health.js.map +1 -1
- package/dist/system/project-health.d.ts +9 -2
- package/dist/system/project-health.d.ts.map +1 -1
- package/dist/system/project-health.js +8 -3
- package/dist/system/project-health.js.map +1 -1
- package/dist/tasks/ac-coverage-gate.d.ts.map +1 -1
- package/dist/tasks/ac-coverage-gate.js +3 -0
- package/dist/tasks/ac-coverage-gate.js.map +1 -1
- package/dist/tasks/ac-table.d.ts +35 -7
- package/dist/tasks/ac-table.d.ts.map +1 -1
- package/dist/tasks/ac-table.js +119 -14
- package/dist/tasks/ac-table.js.map +1 -1
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +48 -2
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/backfill-child-projections.js +47 -6
- package/dist/tasks/backfill-child-projections.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +6 -1
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/completion-evaluation.d.ts.map +1 -1
- package/dist/tasks/completion-evaluation.js +3 -0
- package/dist/tasks/completion-evaluation.js.map +1 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +14 -3
- package/dist/tasks/evidence.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/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/migrations/README.md +12 -0
- package/migrations/drizzle-cleo-project/20260928120000_t12341-row-uids/migration.sql +169 -0
- package/migrations/sync-journal/20260929140000_t12342-sync-clock/migration.sql +42 -0
- package/package.json +13 -13
- package/templates/CLEO-REFERENCE.md +4 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The change journal's own schema, applied lazily.
|
|
3
|
+
*
|
|
4
|
+
* The DDL lives in `packages/core/migrations/sync-journal/<folder>/migration.sql`,
|
|
5
|
+
* one folder per migration, like the drizzle lineages. It is NOT a drizzle
|
|
6
|
+
* lineage: it runs only when a `sync.*` flag is first enabled on a store
|
|
7
|
+
* ({@link ensureSyncSchema}), so a store with every flag off (the default)
|
|
8
|
+
* never gains a table or a journal row. Applied folders are recorded in
|
|
9
|
+
* `_sync_meta` under `schema:<folder>` with the sha256 of the folder's SQL,
|
|
10
|
+
* never in `__drizzle_migrations`. A folder whose SQL changed after it was
|
|
11
|
+
* applied is refused with {@link SyncSchemaHashDriftError}, never skipped.
|
|
12
|
+
*
|
|
13
|
+
* @task T12342
|
|
14
|
+
* @module store/sync/schema
|
|
15
|
+
*/
|
|
16
|
+
import { createHash } from 'node:crypto';
|
|
17
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { resolveCorePackageMigrationsFolder } from '../resolve-migrations-folder.js';
|
|
20
|
+
/** The migrations sub-directory that holds the sync schema. */
|
|
21
|
+
export const SYNC_SCHEMA_SET = 'sync-journal';
|
|
22
|
+
/** Key prefix under which `_sync_meta` records an applied schema folder. */
|
|
23
|
+
const APPLIED_PREFIX = 'schema:';
|
|
24
|
+
/**
|
|
25
|
+
* An applied sync schema folder whose SQL no longer matches what was applied
|
|
26
|
+
* (in the spirit of `E_MIGRATION_HASH_DRIFT`). Editing an applied folder is
|
|
27
|
+
* never correct: add a new folder instead.
|
|
28
|
+
*/
|
|
29
|
+
export class SyncSchemaHashDriftError extends Error {
|
|
30
|
+
folder;
|
|
31
|
+
applied;
|
|
32
|
+
current;
|
|
33
|
+
code = 'E_SYNC_SCHEMA_HASH_DRIFT';
|
|
34
|
+
constructor(folder, applied, current) {
|
|
35
|
+
super(`sync schema folder ${folder} was applied with sha256 ${applied}, but its SQL now hashes ` +
|
|
36
|
+
`to ${current}. An applied folder must never change; add a new folder instead.`);
|
|
37
|
+
this.folder = folder;
|
|
38
|
+
this.applied = applied;
|
|
39
|
+
this.current = current;
|
|
40
|
+
this.name = 'SyncSchemaHashDriftError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const sha256 = (text) => createHash('sha256').update(text).digest('hex');
|
|
44
|
+
/** Whether a table exists in the `main` schema. Read-only. */
|
|
45
|
+
export function hasTable(db, table) {
|
|
46
|
+
return (db.prepare("SELECT 1 FROM main.sqlite_master WHERE type = 'table' AND name = ?").get(table) !==
|
|
47
|
+
undefined);
|
|
48
|
+
}
|
|
49
|
+
/** The sync schema folders, oldest first. */
|
|
50
|
+
export function syncSchemaFolders(root = resolveCorePackageMigrationsFolder(SYNC_SCHEMA_SET)) {
|
|
51
|
+
if (!existsSync(root)) {
|
|
52
|
+
throw new Error(`sync schema folder not found: ${root}`);
|
|
53
|
+
}
|
|
54
|
+
return readdirSync(root, { withFileTypes: true })
|
|
55
|
+
.filter((d) => d.isDirectory() && existsSync(join(root, d.name, 'migration.sql')))
|
|
56
|
+
.map((d) => d.name)
|
|
57
|
+
.sort()
|
|
58
|
+
.map((name) => {
|
|
59
|
+
const sql = readFileSync(join(root, name, 'migration.sql'), 'utf8');
|
|
60
|
+
return { name, sql, hash: sha256(sql) };
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The schema folders already applied to this store, with the sha256 each was
|
|
65
|
+
* applied with. Read-only: a store with no `_sync_meta` has none.
|
|
66
|
+
*/
|
|
67
|
+
export function appliedSyncSchemaHashes(db) {
|
|
68
|
+
if (!hasTable(db, '_sync_meta'))
|
|
69
|
+
return new Map();
|
|
70
|
+
const rows = db
|
|
71
|
+
.prepare('SELECT key, value FROM _sync_meta WHERE key LIKE ? ORDER BY key')
|
|
72
|
+
.all(`${APPLIED_PREFIX}%`);
|
|
73
|
+
return new Map(rows.map((r) => [r.key.slice(APPLIED_PREFIX.length), r.value]));
|
|
74
|
+
}
|
|
75
|
+
/** The names of the schema folders already applied to this store. Read-only. */
|
|
76
|
+
export function appliedSyncSchema(db) {
|
|
77
|
+
return [...appliedSyncSchemaHashes(db).keys()];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The folders still to apply, after checking every applied one for drift.
|
|
81
|
+
*
|
|
82
|
+
* @throws {SyncSchemaHashDriftError} When an applied folder's SQL changed.
|
|
83
|
+
*/
|
|
84
|
+
function pending(folders, applied) {
|
|
85
|
+
for (const f of folders) {
|
|
86
|
+
const was = applied.get(f.name);
|
|
87
|
+
if (was !== undefined && was !== f.hash)
|
|
88
|
+
throw new SyncSchemaHashDriftError(f.name, was, f.hash);
|
|
89
|
+
}
|
|
90
|
+
return folders.filter((f) => !applied.has(f.name));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Apply every sync schema folder this store has not applied yet, in one
|
|
94
|
+
* transaction (a savepoint when the caller already holds one).
|
|
95
|
+
*
|
|
96
|
+
* The applied set is read again INSIDE the transaction, under the write
|
|
97
|
+
* lock, so two processes enabling a flag at once apply each folder once.
|
|
98
|
+
*
|
|
99
|
+
* @param db - The store handle.
|
|
100
|
+
* @param options - `root` overrides the schema folder (tests); `now` stamps
|
|
101
|
+
* the journal rows; `beforeLock` runs between the unlocked pre-check and
|
|
102
|
+
* taking the lock (a test seam for the two-process race).
|
|
103
|
+
* @returns The folders applied by this call.
|
|
104
|
+
* @throws {SyncSchemaHashDriftError} When an applied folder's SQL changed.
|
|
105
|
+
*/
|
|
106
|
+
export function ensureSyncSchema(db, options = {}) {
|
|
107
|
+
const folders = syncSchemaFolders(options.root);
|
|
108
|
+
// Unlocked pre-check: the common case (all applied) takes no write lock.
|
|
109
|
+
if (pending(folders, appliedSyncSchemaHashes(db)).length === 0)
|
|
110
|
+
return [];
|
|
111
|
+
options.beforeLock?.();
|
|
112
|
+
const stamp = (options.now ?? new Date()).toISOString();
|
|
113
|
+
const nested = db.isTransaction;
|
|
114
|
+
db.exec(nested ? 'SAVEPOINT sync_schema' : 'BEGIN IMMEDIATE');
|
|
115
|
+
try {
|
|
116
|
+
const todo = pending(folders, appliedSyncSchemaHashes(db));
|
|
117
|
+
for (const f of todo) {
|
|
118
|
+
db.exec(f.sql);
|
|
119
|
+
db.prepare('INSERT INTO _sync_meta (key, value, updated_at) VALUES (?, ?, ?) ' +
|
|
120
|
+
'ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at').run(`${APPLIED_PREFIX}${f.name}`, f.hash, stamp);
|
|
121
|
+
}
|
|
122
|
+
db.exec(nested ? 'RELEASE sync_schema' : 'COMMIT');
|
|
123
|
+
return todo.map((f) => f.name);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
db.exec(nested ? 'ROLLBACK TO sync_schema; RELEASE sync_schema' : 'ROLLBACK');
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/store/sync/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-replica FIFO skew hold (journal spec §1.3, M2).
|
|
3
|
+
*
|
|
4
|
+
* A received transaction whose HLC is more than the skew bound ahead of the
|
|
5
|
+
* local wall clock is held: not applied, and it does not advance the clock.
|
|
6
|
+
* Every later transaction from the SAME origin replica is held behind it, in
|
|
7
|
+
* `(replicaSeq, index)` order, even when its own HLC is in bounds, so that
|
|
8
|
+
* replica's causal order is preserved. Other replicas keep flowing. The held
|
|
9
|
+
* head is re-evaluated on every drain, and the queue releases in order once
|
|
10
|
+
* the head is within bounds. Nothing is ever dropped.
|
|
11
|
+
*
|
|
12
|
+
* This is the in-memory ordering core. Staging the held transactions durably
|
|
13
|
+
* (`held-skew`) and reporting them through `cleo doctor sync` belong to the
|
|
14
|
+
* pull slice (S5).
|
|
15
|
+
*
|
|
16
|
+
* @task T12342
|
|
17
|
+
* @module store/sync/skew-hold
|
|
18
|
+
*/
|
|
19
|
+
/** One received transaction, as far as ordering is concerned. */
|
|
20
|
+
export interface InboundTxn {
|
|
21
|
+
/** Origin replica id. */
|
|
22
|
+
readonly replica: string;
|
|
23
|
+
/** The origin's gap-free segment sequence number. */
|
|
24
|
+
readonly replicaSeq: number;
|
|
25
|
+
/** Position of the transaction inside its segment. */
|
|
26
|
+
readonly index: number;
|
|
27
|
+
/** The transaction's HLC (its largest op HLC), encoded. */
|
|
28
|
+
readonly hlc: string;
|
|
29
|
+
}
|
|
30
|
+
/** A replica whose queue is blocked by an out-of-bound head. */
|
|
31
|
+
export interface HeldReplica {
|
|
32
|
+
readonly replica: string;
|
|
33
|
+
/** The transaction that is too far ahead. */
|
|
34
|
+
readonly head: InboundTxn;
|
|
35
|
+
/** How many transactions wait, the head included. */
|
|
36
|
+
readonly waiting: number;
|
|
37
|
+
/** How far the head is ahead of the local wall clock, in ms. */
|
|
38
|
+
readonly aheadMs: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Per-replica FIFO queues that release transactions in origin order and hold
|
|
42
|
+
* a replica's whole queue behind an out-of-bound head.
|
|
43
|
+
*/
|
|
44
|
+
export declare class SkewHold {
|
|
45
|
+
private readonly maxDriftMs;
|
|
46
|
+
private readonly queues;
|
|
47
|
+
/**
|
|
48
|
+
* @param maxDriftMs - The skew bound; defaults to {@link MAX_DRIFT_MS}.
|
|
49
|
+
*/
|
|
50
|
+
constructor(maxDriftMs?: number);
|
|
51
|
+
/**
|
|
52
|
+
* Queue a received transaction behind earlier ones from the same replica.
|
|
53
|
+
* A transaction the queue already holds (same replica, seq and index) is
|
|
54
|
+
* ignored, so a re-pull is idempotent.
|
|
55
|
+
*/
|
|
56
|
+
offer(txn: InboundTxn): void;
|
|
57
|
+
/**
|
|
58
|
+
* Release every transaction that may apply now, in per-replica order, and
|
|
59
|
+
* report the replicas that stay held.
|
|
60
|
+
*
|
|
61
|
+
* @param nowMs - The local wall clock.
|
|
62
|
+
* @returns `ready` (to apply, grouped by replica in origin order) and `held`.
|
|
63
|
+
*/
|
|
64
|
+
drain(nowMs: number): {
|
|
65
|
+
ready: InboundTxn[];
|
|
66
|
+
held: HeldReplica[];
|
|
67
|
+
};
|
|
68
|
+
/** How many transactions are queued, over all replicas. */
|
|
69
|
+
get size(): number;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=skew-hold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skew-hold.d.ts","sourceRoot":"","sources":["../../../src/store/sync/skew-hold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,iEAAiE;AACjE,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAOD;;;GAGG;AACH,qBAAa,QAAQ;IAMP,OAAO,CAAC,QAAQ,CAAC,UAAU;IALvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAE1D;;OAEG;gBAC0B,UAAU,GAAE,MAAqB;IAE9D;;;;OAIG;IACH,KAAK,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAY5B;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,IAAI,EAAE,WAAW,EAAE,CAAA;KAAE;IAmBlE,2DAA2D;IAC3D,IAAI,IAAI,IAAI,MAAM,CAIjB;CACF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-replica FIFO skew hold (journal spec §1.3, M2).
|
|
3
|
+
*
|
|
4
|
+
* A received transaction whose HLC is more than the skew bound ahead of the
|
|
5
|
+
* local wall clock is held: not applied, and it does not advance the clock.
|
|
6
|
+
* Every later transaction from the SAME origin replica is held behind it, in
|
|
7
|
+
* `(replicaSeq, index)` order, even when its own HLC is in bounds, so that
|
|
8
|
+
* replica's causal order is preserved. Other replicas keep flowing. The held
|
|
9
|
+
* head is re-evaluated on every drain, and the queue releases in order once
|
|
10
|
+
* the head is within bounds. Nothing is ever dropped.
|
|
11
|
+
*
|
|
12
|
+
* This is the in-memory ordering core. Staging the held transactions durably
|
|
13
|
+
* (`held-skew`) and reporting them through `cleo doctor sync` belong to the
|
|
14
|
+
* pull slice (S5).
|
|
15
|
+
*
|
|
16
|
+
* @task T12342
|
|
17
|
+
* @module store/sync/skew-hold
|
|
18
|
+
*/
|
|
19
|
+
import { isWithinSkew, MAX_DRIFT_MS, parseHlc } from './hlc.js';
|
|
20
|
+
function order(a, b) {
|
|
21
|
+
if (a.replicaSeq !== b.replicaSeq)
|
|
22
|
+
return a.replicaSeq - b.replicaSeq;
|
|
23
|
+
return a.index - b.index;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Per-replica FIFO queues that release transactions in origin order and hold
|
|
27
|
+
* a replica's whole queue behind an out-of-bound head.
|
|
28
|
+
*/
|
|
29
|
+
export class SkewHold {
|
|
30
|
+
maxDriftMs;
|
|
31
|
+
queues = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* @param maxDriftMs - The skew bound; defaults to {@link MAX_DRIFT_MS}.
|
|
34
|
+
*/
|
|
35
|
+
constructor(maxDriftMs = MAX_DRIFT_MS) {
|
|
36
|
+
this.maxDriftMs = maxDriftMs;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Queue a received transaction behind earlier ones from the same replica.
|
|
40
|
+
* A transaction the queue already holds (same replica, seq and index) is
|
|
41
|
+
* ignored, so a re-pull is idempotent.
|
|
42
|
+
*/
|
|
43
|
+
offer(txn) {
|
|
44
|
+
const hlc = parseHlc(txn.hlc);
|
|
45
|
+
if (hlc.replica !== txn.replica) {
|
|
46
|
+
throw new Error(`transaction HLC ${txn.hlc} was not issued by replica ${txn.replica}`);
|
|
47
|
+
}
|
|
48
|
+
const q = this.queues.get(txn.replica) ?? [];
|
|
49
|
+
if (q.some((t) => t.replicaSeq === txn.replicaSeq && t.index === txn.index))
|
|
50
|
+
return;
|
|
51
|
+
q.push(txn);
|
|
52
|
+
q.sort(order);
|
|
53
|
+
this.queues.set(txn.replica, q);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Release every transaction that may apply now, in per-replica order, and
|
|
57
|
+
* report the replicas that stay held.
|
|
58
|
+
*
|
|
59
|
+
* @param nowMs - The local wall clock.
|
|
60
|
+
* @returns `ready` (to apply, grouped by replica in origin order) and `held`.
|
|
61
|
+
*/
|
|
62
|
+
drain(nowMs) {
|
|
63
|
+
const ready = [];
|
|
64
|
+
const held = [];
|
|
65
|
+
for (const [replica, q] of [...this.queues].sort(([a], [b]) => (a < b ? -1 : 1))) {
|
|
66
|
+
while (q.length > 0) {
|
|
67
|
+
const head = q[0];
|
|
68
|
+
const h = parseHlc(head.hlc);
|
|
69
|
+
if (!isWithinSkew(h, nowMs, this.maxDriftMs)) {
|
|
70
|
+
held.push({ replica, head, waiting: q.length, aheadMs: h.phys - Math.floor(nowMs) });
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
ready.push(head);
|
|
74
|
+
q.shift();
|
|
75
|
+
}
|
|
76
|
+
if (q.length === 0)
|
|
77
|
+
this.queues.delete(replica);
|
|
78
|
+
}
|
|
79
|
+
return { ready, held };
|
|
80
|
+
}
|
|
81
|
+
/** How many transactions are queued, over all replicas. */
|
|
82
|
+
get size() {
|
|
83
|
+
let n = 0;
|
|
84
|
+
for (const q of this.queues.values())
|
|
85
|
+
n += q.length;
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=skew-hold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skew-hold.js","sourceRoot":"","sources":["../../../src/store/sync/skew-hold.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,21 +44,23 @@
|
|
|
44
44
|
* that is meaningless off-device: leases, queues, pids, paths, locations and
|
|
45
45
|
* fs-keyed caches.
|
|
46
46
|
*
|
|
47
|
-
* ##
|
|
47
|
+
* ## STDP event history syncs (cleo-dev ruling 2026-09-29)
|
|
48
48
|
*
|
|
49
|
-
* `brain_plasticity_events` and `brain_weight_history` are
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
49
|
+
* `brain_plasticity_events` and `brain_weight_history` are `portable-personal`
|
|
50
|
+
* (journal spec review, Q11, under the owner's direction that the cloud backs
|
|
51
|
+
* up everything). The 2026-09-28 ruling had them local-only, with the current
|
|
52
|
+
* learned weights to follow as a projection or snapshot blob. They are
|
|
53
|
+
* append-only with 14M+ lifetime inserts, so they set the change journal's
|
|
54
|
+
* op-rate ceiling; how much event history replicates is the journal spec's
|
|
55
|
+
* open retention question (Q15).
|
|
55
56
|
*
|
|
56
57
|
* ## Sources
|
|
57
58
|
*
|
|
58
59
|
* The classes come from the classification draft
|
|
59
60
|
* (`docs/research/table-classification-draft.md` in the cleo-nexus repo), the
|
|
60
61
|
* core owner's rulings in its §F, and the core owner's two-tier ruling of
|
|
61
|
-
* 2026-09-28
|
|
62
|
+
* 2026-09-28, its follow-up rulings on the STDP tables, and its journal spec
|
|
63
|
+
* review rulings of 2026-09-29 (STDP and `token_usage`). Table
|
|
62
64
|
* classification was delegated to agents by the owner, so these are cleo-dev
|
|
63
65
|
* rulings; the ruling supersedes earlier ones where they conflict (each such
|
|
64
66
|
* entry carries the old reasoning in its `note`). Rows marked
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-classification.d.ts","sourceRoot":"","sources":["../../src/store/table-classification.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"table-classification.d.ts","sourceRoot":"","sources":["../../src/store/table-classification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AAEH,OAAO,KAAK,EAEV,UAAU,EACV,mBAAmB,EAGnB,UAAU,EACV,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAgwD7B;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAKpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,kBAKnC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,UAAU,EAM9C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAM5F,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAEtE;AAcD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAYlF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAEpE"}
|
|
@@ -44,21 +44,23 @@
|
|
|
44
44
|
* that is meaningless off-device: leases, queues, pids, paths, locations and
|
|
45
45
|
* fs-keyed caches.
|
|
46
46
|
*
|
|
47
|
-
* ##
|
|
47
|
+
* ## STDP event history syncs (cleo-dev ruling 2026-09-29)
|
|
48
48
|
*
|
|
49
|
-
* `brain_plasticity_events` and `brain_weight_history` are
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
49
|
+
* `brain_plasticity_events` and `brain_weight_history` are `portable-personal`
|
|
50
|
+
* (journal spec review, Q11, under the owner's direction that the cloud backs
|
|
51
|
+
* up everything). The 2026-09-28 ruling had them local-only, with the current
|
|
52
|
+
* learned weights to follow as a projection or snapshot blob. They are
|
|
53
|
+
* append-only with 14M+ lifetime inserts, so they set the change journal's
|
|
54
|
+
* op-rate ceiling; how much event history replicates is the journal spec's
|
|
55
|
+
* open retention question (Q15).
|
|
55
56
|
*
|
|
56
57
|
* ## Sources
|
|
57
58
|
*
|
|
58
59
|
* The classes come from the classification draft
|
|
59
60
|
* (`docs/research/table-classification-draft.md` in the cleo-nexus repo), the
|
|
60
61
|
* core owner's rulings in its §F, and the core owner's two-tier ruling of
|
|
61
|
-
* 2026-09-28
|
|
62
|
+
* 2026-09-28, its follow-up rulings on the STDP tables, and its journal spec
|
|
63
|
+
* review rulings of 2026-09-29 (STDP and `token_usage`). Table
|
|
62
64
|
* classification was delegated to agents by the owner, so these are cleo-dev
|
|
63
65
|
* rulings; the ruling supersedes earlier ones where they conflict (each such
|
|
64
66
|
* entry carries the old reasoning in its `note`). Rows marked
|
|
@@ -99,6 +101,24 @@ const PROJECT_TABLES = {
|
|
|
99
101
|
status: 'draft',
|
|
100
102
|
source: 'table-classification-draft.md',
|
|
101
103
|
},
|
|
104
|
+
_sync_clock: {
|
|
105
|
+
class: 'local-only',
|
|
106
|
+
status: 'optional-transient',
|
|
107
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
108
|
+
note: "the HLC clock of this store's replica; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled",
|
|
109
|
+
},
|
|
110
|
+
_sync_meta: {
|
|
111
|
+
class: 'local-only',
|
|
112
|
+
status: 'optional-transient',
|
|
113
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
114
|
+
note: 'store-level sync.* flags and journal bookkeeping; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled',
|
|
115
|
+
},
|
|
116
|
+
_sync_replica: {
|
|
117
|
+
class: 'local-only',
|
|
118
|
+
status: 'optional-transient',
|
|
119
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
120
|
+
note: 'the replica binding (inode, birthtime, nonce, device) of this store file; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled',
|
|
121
|
+
},
|
|
102
122
|
_writer_leases: { class: 'local-only', status: 'draft', source: 'table-classification-draft.md' },
|
|
103
123
|
_writer_queue: { class: 'local-only', status: 'draft', source: 'table-classification-draft.md' },
|
|
104
124
|
acceptance_projection_dirty: {
|
|
@@ -310,10 +330,10 @@ const PROJECT_TABLES = {
|
|
|
310
330
|
source: 'table-classification-draft.md',
|
|
311
331
|
},
|
|
312
332
|
brain_plasticity_events: {
|
|
313
|
-
class: '
|
|
333
|
+
class: 'portable-personal',
|
|
314
334
|
status: 'resolved',
|
|
315
|
-
source: 'cleo-dev ruling 2026-09-
|
|
316
|
-
note:
|
|
335
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q11)',
|
|
336
|
+
note: "supersedes the 2026-09-28 local-only ruling under the owner's direction that the cloud backs up everything: STDP event history is learned state a new device would otherwise lose. Append-only with 14M+ lifetime inserts, so it sets the journal's op-rate ceiling; retention is journal spec Q15",
|
|
317
337
|
},
|
|
318
338
|
brain_promotion_log: {
|
|
319
339
|
class: 'portable-personal',
|
|
@@ -379,10 +399,10 @@ const PROJECT_TABLES = {
|
|
|
379
399
|
note: 'named in the ruling; pre-T1402 name of brain_observations_staging, dropped by T12535',
|
|
380
400
|
},
|
|
381
401
|
brain_weight_history: {
|
|
382
|
-
class: '
|
|
402
|
+
class: 'portable-personal',
|
|
383
403
|
status: 'resolved',
|
|
384
|
-
source: 'cleo-dev ruling 2026-09-
|
|
385
|
-
note:
|
|
404
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q11)',
|
|
405
|
+
note: "supersedes the 2026-09-28 local-only ruling under the owner's direction that the cloud backs up everything: STDP event history is learned state a new device would otherwise lose. Append-only with 14M+ lifetime inserts, so it sets the journal's op-rate ceiling; retention is journal spec Q15",
|
|
386
406
|
},
|
|
387
407
|
commit_files: {
|
|
388
408
|
class: 'local-only',
|
|
@@ -919,6 +939,18 @@ const PROJECT_TABLES = {
|
|
|
919
939
|
},
|
|
920
940
|
],
|
|
921
941
|
},
|
|
942
|
+
tasks_display_id_aliases: {
|
|
943
|
+
class: 'portable-project',
|
|
944
|
+
status: 'resolved',
|
|
945
|
+
source: 'T12341 (row uids; spec t12341-uid-scheme §9)',
|
|
946
|
+
note: 'displaced display ids (a T#### re-minted on a merge collision) must resolve on every device and for every collaborator; ADR-094 alias pattern',
|
|
947
|
+
},
|
|
948
|
+
tasks_ac_uid_graveyard: {
|
|
949
|
+
class: 'local-only',
|
|
950
|
+
status: 'resolved',
|
|
951
|
+
source: 'T12341 (row uids; spec t12341-uid-scheme §6.5)',
|
|
952
|
+
note: 'repair scratch: uids of deleted acceptance criteria, so the next open re-links a criterion an older build recreated; pruned at every open',
|
|
953
|
+
},
|
|
922
954
|
tasks_evidence_ac_bindings: {
|
|
923
955
|
class: 'portable-project',
|
|
924
956
|
status: 'draft',
|
|
@@ -941,6 +973,12 @@ const PROJECT_TABLES = {
|
|
|
941
973
|
source: 'cleo-dev ruling 2026-09-28 (round 2)',
|
|
942
974
|
note: 'per-agent goal state (turn budget, verdict); an agent resuming on another device needs it. No bare `goal` twin exists',
|
|
943
975
|
},
|
|
976
|
+
tasks_identity_quarantine: {
|
|
977
|
+
class: 'local-only',
|
|
978
|
+
status: 'resolved',
|
|
979
|
+
source: 'T12341 (row uids; spec t12341-uid-scheme §6.4)',
|
|
980
|
+
note: 'staging for incoming rows a merge cannot place yet (uid or display-id collision awaiting its authority, or a reference awaiting one); re-pulled from sync if lost',
|
|
981
|
+
},
|
|
944
982
|
tasks_lifecycle_evidence: {
|
|
945
983
|
class: 'portable-project',
|
|
946
984
|
status: 'draft',
|
|
@@ -1047,6 +1085,12 @@ const PROJECT_TABLES = {
|
|
|
1047
1085
|
status: 'draft',
|
|
1048
1086
|
source: 'table-classification-draft.md',
|
|
1049
1087
|
},
|
|
1088
|
+
tasks_row_identity_meta: {
|
|
1089
|
+
class: 'local-only',
|
|
1090
|
+
status: 'resolved',
|
|
1091
|
+
source: 'T12341 (row uids; spec t12341-uid-scheme §12.1)',
|
|
1092
|
+
note: 'the identity recipe version this store derived its uids with, and the sync layer marker; per-store state',
|
|
1093
|
+
},
|
|
1050
1094
|
tasks_session_handoff_entries: {
|
|
1051
1095
|
class: 'portable-personal',
|
|
1052
1096
|
status: 'draft',
|
|
@@ -1127,9 +1171,15 @@ const PROJECT_TABLES = {
|
|
|
1127
1171
|
},
|
|
1128
1172
|
tasks_token_usage: {
|
|
1129
1173
|
class: 'portable-personal',
|
|
1130
|
-
status: '
|
|
1131
|
-
source: 'cleo-dev ruling 2026-09-
|
|
1132
|
-
note: 'ruling: token_usage is portable (cost history)
|
|
1174
|
+
status: 'resolved',
|
|
1175
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q9)',
|
|
1176
|
+
note: 'ruling: token_usage is portable (cost history), merged per person (keyed by session, and sessions are personal)',
|
|
1177
|
+
},
|
|
1178
|
+
tasks_uid_aliases: {
|
|
1179
|
+
class: 'portable-project',
|
|
1180
|
+
status: 'resolved',
|
|
1181
|
+
source: 'T12341 (row uids; spec t12341-uid-scheme §6.4)',
|
|
1182
|
+
note: 'uid re-keys after a detected uid collision; every device must resolve the old uid',
|
|
1133
1183
|
},
|
|
1134
1184
|
tasks_warp_chain_instances: {
|
|
1135
1185
|
class: 'portable-project',
|
|
@@ -1143,8 +1193,8 @@ const PROJECT_TABLES = {
|
|
|
1143
1193
|
},
|
|
1144
1194
|
token_usage: {
|
|
1145
1195
|
class: 'portable-personal',
|
|
1146
|
-
status: '
|
|
1147
|
-
source: 'cleo-dev ruling 2026-09-
|
|
1196
|
+
status: 'resolved',
|
|
1197
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q9)',
|
|
1148
1198
|
note: 'live bare twin of tasks_token_usage; same ruling',
|
|
1149
1199
|
},
|
|
1150
1200
|
warp_chain_instances: {
|
|
@@ -1169,6 +1219,24 @@ const GLOBAL_TABLES = {
|
|
|
1169
1219
|
__drizzle_migrations: { class: 'local-only', status: 'draft', source: 'draft §3' },
|
|
1170
1220
|
_agent_registry_meta: { class: 'local-only', status: 'draft', source: 'draft §3' },
|
|
1171
1221
|
_agent_registry_migrations: { class: 'local-only', status: 'draft', source: 'draft §3' },
|
|
1222
|
+
_sync_clock: {
|
|
1223
|
+
class: 'local-only',
|
|
1224
|
+
status: 'optional-transient',
|
|
1225
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
1226
|
+
note: "the HLC clock of this store's replica; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled",
|
|
1227
|
+
},
|
|
1228
|
+
_sync_meta: {
|
|
1229
|
+
class: 'local-only',
|
|
1230
|
+
status: 'optional-transient',
|
|
1231
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
1232
|
+
note: 'store-level sync.* flags and journal bookkeeping; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled',
|
|
1233
|
+
},
|
|
1234
|
+
_sync_replica: {
|
|
1235
|
+
class: 'local-only',
|
|
1236
|
+
status: 'optional-transient',
|
|
1237
|
+
source: 'journal spec t12342-t12343-journal-design §1.4-§1.5 (T12342)',
|
|
1238
|
+
note: 'the replica binding (inode, birthtime, nonce, device) of this store file; describes this physical file, so meaningless on another device. Created lazily by store/sync/schema.ts when a sync.* flag is first enabled',
|
|
1239
|
+
},
|
|
1172
1240
|
_writer_leases: { class: 'local-only', status: 'draft', source: 'draft §3' },
|
|
1173
1241
|
_writer_queue: { class: 'local-only', status: 'draft', source: 'draft §3' },
|
|
1174
1242
|
accounts: {
|
|
@@ -1436,10 +1504,10 @@ const GLOBAL_TABLES = {
|
|
|
1436
1504
|
note: 'writer verified: memory/specialists.ts (LLM Induction/CodePattern specialists) and sleep-consolidation.ts',
|
|
1437
1505
|
},
|
|
1438
1506
|
brain_plasticity_events: {
|
|
1439
|
-
class: '
|
|
1507
|
+
class: 'portable-personal',
|
|
1440
1508
|
status: 'resolved',
|
|
1441
|
-
source: 'cleo-dev ruling 2026-09-
|
|
1442
|
-
note:
|
|
1509
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q11)',
|
|
1510
|
+
note: "supersedes the 2026-09-28 local-only ruling under the owner's direction that the cloud backs up everything: STDP event history is learned state a new device would otherwise lose. Append-only with 14M+ lifetime inserts, so it sets the journal's op-rate ceiling; retention is journal spec Q15",
|
|
1443
1511
|
},
|
|
1444
1512
|
brain_promotion_log: {
|
|
1445
1513
|
class: 'portable-personal',
|
|
@@ -1486,10 +1554,10 @@ const GLOBAL_TABLES = {
|
|
|
1486
1554
|
note: '"all brain_*" per the ruling, but it is feedback telemetry (10,152 rows) that drives quality scores; confirm',
|
|
1487
1555
|
},
|
|
1488
1556
|
brain_weight_history: {
|
|
1489
|
-
class: '
|
|
1557
|
+
class: 'portable-personal',
|
|
1490
1558
|
status: 'resolved',
|
|
1491
|
-
source: 'cleo-dev ruling 2026-09-
|
|
1492
|
-
note:
|
|
1559
|
+
source: 'cleo-dev ruling 2026-09-29 (journal spec review, Q11)',
|
|
1560
|
+
note: "supersedes the 2026-09-28 local-only ruling under the owner's direction that the cloud backs up everything: STDP event history is learned state a new device would otherwise lose. Append-only with 14M+ lifetime inserts, so it sets the journal's op-rate ceiling; retention is journal spec Q15",
|
|
1493
1561
|
},
|
|
1494
1562
|
models_catalog: {
|
|
1495
1563
|
class: 'local-only',
|