@cleocode/core 2026.5.133 → 2026.5.134
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/store/exodus/index.d.ts +16 -0
- package/dist/store/exodus/index.d.ts.map +1 -0
- package/dist/store/exodus/index.js +16 -0
- package/dist/store/exodus/index.js.map +1 -0
- package/dist/store/exodus/migrate.d.ts +41 -0
- package/dist/store/exodus/migrate.d.ts.map +1 -0
- package/dist/store/exodus/migrate.js +416 -0
- package/dist/store/exodus/migrate.js.map +1 -0
- package/dist/store/exodus/plan.d.ts +44 -0
- package/dist/store/exodus/plan.d.ts.map +1 -0
- package/dist/store/exodus/plan.js +178 -0
- package/dist/store/exodus/plan.js.map +1 -0
- package/dist/store/exodus/status.d.ts +22 -0
- package/dist/store/exodus/status.d.ts.map +1 -0
- package/dist/store/exodus/status.js +88 -0
- package/dist/store/exodus/status.js.map +1 -0
- package/dist/store/exodus/types.d.ts +169 -0
- package/dist/store/exodus/types.d.ts.map +1 -0
- package/dist/store/exodus/types.js +21 -0
- package/dist/store/exodus/types.js.map +1 -0
- package/dist/store/exodus/verify.d.ts +34 -0
- package/dist/store/exodus/verify.d.ts.map +1 -0
- package/dist/store/exodus/verify.js +168 -0
- package/dist/store/exodus/verify.js.map +1 -0
- package/package.json +12 -12
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exodus verification engine.
|
|
3
|
+
*
|
|
4
|
+
* `runExodusVerify()` checks equivalence between source legacy DBs and the
|
|
5
|
+
* consolidated dual-scope `cleo.db` after a migration.
|
|
6
|
+
*
|
|
7
|
+
* ## Equivalence checks (AC7)
|
|
8
|
+
*
|
|
9
|
+
* Per-table:
|
|
10
|
+
* 1. `COUNT(*)` parity — source and target row counts must match.
|
|
11
|
+
* 2. Ordered canonical-JSON digest — SELECT all rows ORDER BY rowid, JSON-
|
|
12
|
+
* stringify each row, SHA-256 the concatenation (truncated to 32 hex).
|
|
13
|
+
*
|
|
14
|
+
* @task T11248 (E5 · AC7 · SG-DB-SUBSTRATE-V2)
|
|
15
|
+
* @saga T11242
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync } from 'node:fs';
|
|
18
|
+
import { createRequire } from 'node:module';
|
|
19
|
+
import { getLogger } from '../../logger.js';
|
|
20
|
+
import { openCleoDbSnapshot } from '../open-cleo-db.js';
|
|
21
|
+
const log = getLogger('exodus-verify');
|
|
22
|
+
const _require = createRequire(import.meta.url);
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Digest helper (AC7)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Compute an ordered canonical-JSON SHA-256 digest (32 hex chars) for all rows
|
|
28
|
+
* in a table.
|
|
29
|
+
*
|
|
30
|
+
* Rows are fetched `ORDER BY rowid` so the ordering is deterministic. Each row
|
|
31
|
+
* is canonicalized as `JSON.stringify(row)` and appended to the hash.
|
|
32
|
+
*/
|
|
33
|
+
function computeTableDigest(db, tableName) {
|
|
34
|
+
const { createHash } = _require('node:crypto');
|
|
35
|
+
const hasher = createHash('sha256');
|
|
36
|
+
const rows = db.prepare(`SELECT * FROM "${tableName}" ORDER BY rowid`).all();
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
hasher.update(JSON.stringify(row));
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
count: rows.length,
|
|
42
|
+
hash: hasher.digest('hex').slice(0, 32),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Table listing
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
function listTables(db) {
|
|
49
|
+
const rows = db
|
|
50
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name")
|
|
51
|
+
.all();
|
|
52
|
+
return rows.map((r) => r.name);
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Main verify runner
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Run equivalence verification after an exodus migration.
|
|
59
|
+
*
|
|
60
|
+
* Opens source DBs read-only and the consolidated target DBs read-only, then
|
|
61
|
+
* compares row counts and canonical-JSON digests per table.
|
|
62
|
+
*
|
|
63
|
+
* @param sources - Legacy source descriptors (from `buildExodusPlan()`).
|
|
64
|
+
* @param projectDbPath - Absolute path to the consolidated project `cleo.db`.
|
|
65
|
+
* @param globalDbPath - Absolute path to the consolidated global `cleo.db`.
|
|
66
|
+
* @param onProgress - Optional progress callback.
|
|
67
|
+
*
|
|
68
|
+
* @returns {@link ExodusVerifyResult}
|
|
69
|
+
*
|
|
70
|
+
* @task T11248 (AC7)
|
|
71
|
+
*/
|
|
72
|
+
export function runExodusVerify(sources, projectDbPath, globalDbPath, onProgress) {
|
|
73
|
+
const tableResults = [];
|
|
74
|
+
let overallOk = true;
|
|
75
|
+
// Check target DBs exist
|
|
76
|
+
if (!existsSync(projectDbPath)) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
tables: [],
|
|
80
|
+
error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (!existsSync(globalDbPath)) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
tables: [],
|
|
87
|
+
error: `Consolidated global cleo.db not found at ${globalDbPath}. Run 'cleo exodus migrate' first.`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
|
|
91
|
+
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
92
|
+
try {
|
|
93
|
+
for (const src of sources) {
|
|
94
|
+
if (!existsSync(src.path)) {
|
|
95
|
+
onProgress?.(`Skipping ${src.name} (not present)`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
99
|
+
const targetSnap = src.targetScope === 'project' ? projectSnap : globalSnap;
|
|
100
|
+
const scope = src.targetScope;
|
|
101
|
+
try {
|
|
102
|
+
const sourceTables = listTables(srcSnap.db);
|
|
103
|
+
const targetTables = new Set(listTables(targetSnap.db));
|
|
104
|
+
for (const tableName of sourceTables) {
|
|
105
|
+
onProgress?.(`Verifying ${src.name}.${tableName}…`);
|
|
106
|
+
if (!targetTables.has(tableName)) {
|
|
107
|
+
// Table missing in target (E6 will populate it — treat as skipped rows = 0)
|
|
108
|
+
const srcResult = computeTableDigest(srcSnap.db, tableName);
|
|
109
|
+
const result = {
|
|
110
|
+
tableName,
|
|
111
|
+
scope,
|
|
112
|
+
sourceCount: srcResult.count,
|
|
113
|
+
targetCount: 0,
|
|
114
|
+
sourceHash: srcResult.hash,
|
|
115
|
+
targetHash: '',
|
|
116
|
+
hashMatch: srcResult.count === 0, // only ok if source was empty
|
|
117
|
+
countMatch: srcResult.count === 0,
|
|
118
|
+
};
|
|
119
|
+
if (!result.countMatch) {
|
|
120
|
+
overallOk = false;
|
|
121
|
+
log.warn({ tableName, sourceDb: src.name }, 'Table missing in consolidated DB');
|
|
122
|
+
}
|
|
123
|
+
tableResults.push(result);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const srcDigest = computeTableDigest(srcSnap.db, tableName);
|
|
127
|
+
const tgtDigest = computeTableDigest(targetSnap.db, tableName);
|
|
128
|
+
const countMatch = srcDigest.count === tgtDigest.count;
|
|
129
|
+
const hashMatch = srcDigest.hash === tgtDigest.hash;
|
|
130
|
+
if (!countMatch || !hashMatch) {
|
|
131
|
+
overallOk = false;
|
|
132
|
+
log.warn({
|
|
133
|
+
tableName,
|
|
134
|
+
srcCount: srcDigest.count,
|
|
135
|
+
tgtCount: tgtDigest.count,
|
|
136
|
+
countMatch,
|
|
137
|
+
hashMatch,
|
|
138
|
+
}, 'Equivalence check failed');
|
|
139
|
+
}
|
|
140
|
+
tableResults.push({
|
|
141
|
+
tableName,
|
|
142
|
+
scope,
|
|
143
|
+
sourceCount: srcDigest.count,
|
|
144
|
+
targetCount: tgtDigest.count,
|
|
145
|
+
sourceHash: srcDigest.hash,
|
|
146
|
+
targetHash: tgtDigest.hash,
|
|
147
|
+
hashMatch,
|
|
148
|
+
countMatch,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
srcSnap.close();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
159
|
+
log.error({ err }, 'Exodus verify failed');
|
|
160
|
+
return { ok: false, tables: tableResults, error };
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
projectSnap.close();
|
|
164
|
+
globalSnap.close();
|
|
165
|
+
}
|
|
166
|
+
return { ok: overallOk, tables: tableResults };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/store/exodus/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAQxD,MAAM,GAAG,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEhD,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,EAAgB,EAAE,SAAiB;IAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAiC,CAAC;IAC/E,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEpC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,kBAAkB,SAAS,kBAAkB,CAAC,CAAC,GAAG,EAAe,CAAC;IAE1F,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,SAAS,UAAU,CAAC,EAAgB;IAClC,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CACN,8HAA8H,CAC/H;SACA,GAAG,EAA6B,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,OAA6B,EAC7B,aAAqB,EACrB,YAAoB,EACpB,UAAkC;IAElC,MAAM,YAAY,GAAwB,EAAE,CAAC;IAC7C,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,yBAAyB;IACzB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,6CAA6C,aAAa,oCAAoC;SACtG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,4CAA4C,YAAY,oCAAoC;SACpG,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,kBAAkB,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAExE,IAAI,CAAC;QACH,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,UAAU,EAAE,CAAC,YAAY,GAAG,CAAC,IAAI,gBAAgB,CAAC,CAAC;gBACnD,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,MAAM,UAAU,GACd,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;YAC3D,MAAM,KAAK,GAAgB,GAAG,CAAC,WAAW,CAAC;YAE3C,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;gBAExD,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;oBACrC,UAAU,EAAE,CAAC,aAAa,GAAG,CAAC,IAAI,IAAI,SAAS,GAAG,CAAC,CAAC;oBAEpD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;wBACjC,4EAA4E;wBAC5E,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;wBAC5D,MAAM,MAAM,GAAsB;4BAChC,SAAS;4BACT,KAAK;4BACL,WAAW,EAAE,SAAS,CAAC,KAAK;4BAC5B,WAAW,EAAE,CAAC;4BACd,UAAU,EAAE,SAAS,CAAC,IAAI;4BAC1B,UAAU,EAAE,EAAE;4BACd,SAAS,EAAE,SAAS,CAAC,KAAK,KAAK,CAAC,EAAE,8BAA8B;4BAChE,UAAU,EAAE,SAAS,CAAC,KAAK,KAAK,CAAC;yBAClC,CAAC;wBACF,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;4BACvB,SAAS,GAAG,KAAK,CAAC;4BAClB,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,kCAAkC,CAAC,CAAC;wBAClF,CAAC;wBACD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAC1B,SAAS;oBACX,CAAC;oBAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;oBAC5D,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;oBAE/D,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK,CAAC;oBACvD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC;oBAEpD,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;wBAC9B,SAAS,GAAG,KAAK,CAAC;wBAClB,GAAG,CAAC,IAAI,CACN;4BACE,SAAS;4BACT,QAAQ,EAAE,SAAS,CAAC,KAAK;4BACzB,QAAQ,EAAE,SAAS,CAAC,KAAK;4BACzB,UAAU;4BACV,SAAS;yBACV,EACD,0BAA0B,CAC3B,CAAC;oBACJ,CAAC;oBAED,YAAY,CAAC,IAAI,CAAC;wBAChB,SAAS;wBACT,KAAK;wBACL,WAAW,EAAE,SAAS,CAAC,KAAK;wBAC5B,WAAW,EAAE,SAAS,CAAC,KAAK;wBAC5B,UAAU,EAAE,SAAS,CAAC,IAAI;wBAC1B,UAAU,EAAE,SAAS,CAAC,IAAI;wBAC1B,SAAS;wBACT,UAAU;qBACX,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/D,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,sBAAsB,CAAC,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACjD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/core",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.134",
|
|
4
4
|
"description": "CLEO core business logic kernel — tasks, sessions, memory, orchestration, lifecycle, with bundled SQLite store",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -399,16 +399,16 @@
|
|
|
399
399
|
"write-file-atomic": "^7.0.1",
|
|
400
400
|
"yaml": "^2.8.3",
|
|
401
401
|
"zod": "^4.3.6",
|
|
402
|
-
"@cleocode/adapters": "2026.5.
|
|
403
|
-
"@cleocode/
|
|
404
|
-
"@cleocode/
|
|
405
|
-
"@cleocode/
|
|
406
|
-
"@cleocode/
|
|
407
|
-
"@cleocode/nexus": "2026.5.
|
|
408
|
-
"@cleocode/paths": "2026.5.
|
|
409
|
-
"@cleocode/skills": "2026.5.
|
|
410
|
-
"@cleocode/
|
|
411
|
-
"@cleocode/
|
|
402
|
+
"@cleocode/adapters": "2026.5.134",
|
|
403
|
+
"@cleocode/agents": "2026.5.134",
|
|
404
|
+
"@cleocode/lafs": "2026.5.134",
|
|
405
|
+
"@cleocode/caamp": "2026.5.134",
|
|
406
|
+
"@cleocode/contracts": "2026.5.134",
|
|
407
|
+
"@cleocode/nexus": "2026.5.134",
|
|
408
|
+
"@cleocode/paths": "2026.5.134",
|
|
409
|
+
"@cleocode/skills": "2026.5.134",
|
|
410
|
+
"@cleocode/worktree": "2026.5.134",
|
|
411
|
+
"@cleocode/utils": "2026.5.122"
|
|
412
412
|
},
|
|
413
413
|
"engines": {
|
|
414
414
|
"node": ">=24.16.0"
|
|
@@ -440,7 +440,7 @@
|
|
|
440
440
|
},
|
|
441
441
|
"optionalDependencies": {
|
|
442
442
|
"llmtxt": "^2026.5.15",
|
|
443
|
-
"@cleocode/studio": "^2026.5.
|
|
443
|
+
"@cleocode/studio": "^2026.5.134"
|
|
444
444
|
},
|
|
445
445
|
"scripts": {
|
|
446
446
|
"build": "tsc",
|