@inerrata-corporation/errata 2.0.22-dev.4173 → 2.0.22-dev.4180
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/consolidate-worker.mjs +203 -26
- package/errata.mjs +258 -51
- package/generalize-worker.mjs +204 -27
- package/package.json +1 -1
- package/pass-worker.mjs +212 -33
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/consolidate-worker.mjs
CHANGED
|
@@ -16010,20 +16010,20 @@ function openDatabase(path2, opts) {
|
|
|
16010
16010
|
} catch {
|
|
16011
16011
|
}
|
|
16012
16012
|
}
|
|
16013
|
-
const wrapStmt = (
|
|
16013
|
+
const wrapStmt = (stmt2) => ({
|
|
16014
16014
|
run: (...params) => {
|
|
16015
|
-
const r =
|
|
16015
|
+
const r = stmt2.run(...coerceParams(params));
|
|
16016
16016
|
return {
|
|
16017
16017
|
changes: Number(r.changes),
|
|
16018
16018
|
lastInsertRowid: Number(r.lastInsertRowid)
|
|
16019
16019
|
};
|
|
16020
16020
|
},
|
|
16021
16021
|
get: (...params) => {
|
|
16022
|
-
const r =
|
|
16022
|
+
const r = stmt2.get(...coerceParams(params));
|
|
16023
16023
|
return r;
|
|
16024
16024
|
},
|
|
16025
16025
|
all: (...params) => {
|
|
16026
|
-
const r =
|
|
16026
|
+
const r = stmt2.all(...coerceParams(params));
|
|
16027
16027
|
return r;
|
|
16028
16028
|
}
|
|
16029
16029
|
});
|
|
@@ -17083,6 +17083,169 @@ function textIndexReady(db) {
|
|
|
17083
17083
|
return db.prepare("SELECT value FROM store_meta WHERE key = ?").get(TEXT_INDEX_KEY)?.["value"] === "installed";
|
|
17084
17084
|
}
|
|
17085
17085
|
|
|
17086
|
+
// ../../packages/local-graph/src/lineage-integrity.ts
|
|
17087
|
+
var statements = /* @__PURE__ */ new WeakMap();
|
|
17088
|
+
function stmt(db, sql) {
|
|
17089
|
+
let byDb = statements.get(db);
|
|
17090
|
+
if (!byDb) statements.set(db, byDb = /* @__PURE__ */ new Map());
|
|
17091
|
+
let s = byDb.get(sql);
|
|
17092
|
+
if (!s) byDb.set(sql, s = db.prepare(sql));
|
|
17093
|
+
return s;
|
|
17094
|
+
}
|
|
17095
|
+
var HISTORY_EDGE_TYPES = [
|
|
17096
|
+
"SUPERSEDED_BY",
|
|
17097
|
+
"CONTINUES",
|
|
17098
|
+
"FORKED_FROM",
|
|
17099
|
+
"REGRESSION_OF",
|
|
17100
|
+
"SPLIT_INTO",
|
|
17101
|
+
"REVEALED_BY"
|
|
17102
|
+
];
|
|
17103
|
+
var LINEAGE_INTEGRITY_KEY = "lineage-integrity-v1";
|
|
17104
|
+
var HISTORY_SQL = HISTORY_EDGE_TYPES.map((t) => `'${t}'`).join(",");
|
|
17105
|
+
var NOT_HISTORY = `type NOT IN (${HISTORY_SQL})`;
|
|
17106
|
+
var NOT_HISTORICAL_ROW = `json_type(attrs_json, '$.historical') IS NOT 'true'`;
|
|
17107
|
+
var RETAINS_EDGES = (n) => `(${n}.label = 'Problem'
|
|
17108
|
+
AND json_type(${n}.attrs_json, '$.resolvedAt') IS NOT NULL
|
|
17109
|
+
AND COALESCE(json_extract(${n}.attrs_json, '$.resolvedAs'), '') NOT IN ('duplicate', 'false_positive'))`;
|
|
17110
|
+
var PRESENT = (n) => `(${n}.valid_to IS NULL OR ${RETAINS_EDGES(n)})`;
|
|
17111
|
+
var STRANDED_EDGE_PREDICATE = `e.valid_to IS NULL AND e.${NOT_HISTORY}
|
|
17112
|
+
AND (NOT EXISTS (SELECT 1 FROM nodes f WHERE f.id = e.from_id AND ${PRESENT("f")})
|
|
17113
|
+
OR NOT EXISTS (SELECT 1 FROM nodes t WHERE t.id = e.to_id AND ${PRESENT("t")}))`;
|
|
17114
|
+
function countStrandedEdges(db) {
|
|
17115
|
+
const rows = db.prepare(`SELECT e.type AS type, count(*) AS n FROM edges e WHERE ${STRANDED_EDGE_PREDICATE} GROUP BY e.type ORDER BY n DESC`).all();
|
|
17116
|
+
const byType = {};
|
|
17117
|
+
let total = 0;
|
|
17118
|
+
for (const r of rows) {
|
|
17119
|
+
byType[r.type] = Number(r.n);
|
|
17120
|
+
total += Number(r.n);
|
|
17121
|
+
}
|
|
17122
|
+
return { total, byType };
|
|
17123
|
+
}
|
|
17124
|
+
function countLiveHeadConflicts(db) {
|
|
17125
|
+
const row = db.prepare(
|
|
17126
|
+
`SELECT count(*) AS n FROM (
|
|
17127
|
+
SELECT COALESCE(logical_id, id) AS lid FROM nodes
|
|
17128
|
+
WHERE valid_to IS NULL AND ${NOT_HISTORICAL_ROW}
|
|
17129
|
+
GROUP BY lid HAVING count(*) > 1)`
|
|
17130
|
+
).get();
|
|
17131
|
+
return Number(row?.n ?? 0);
|
|
17132
|
+
}
|
|
17133
|
+
function closeIncidentEdges(db, id, t) {
|
|
17134
|
+
let closed = 0;
|
|
17135
|
+
for (const side of ["from_id", "to_id"]) {
|
|
17136
|
+
const r = stmt(db, `UPDATE edges SET valid_to = MAX(valid_from, ?) WHERE ${side} = ? AND valid_to IS NULL AND ${NOT_HISTORY}`).run(t, id);
|
|
17137
|
+
closed += Number(r.changes);
|
|
17138
|
+
}
|
|
17139
|
+
return closed;
|
|
17140
|
+
}
|
|
17141
|
+
function reopenCascadeClosedEdges(db, id, closedAt) {
|
|
17142
|
+
let reopened = 0;
|
|
17143
|
+
for (const [side, other] of [["from_id", "to_id"], ["to_id", "from_id"]]) {
|
|
17144
|
+
const r = stmt(
|
|
17145
|
+
db,
|
|
17146
|
+
`UPDATE edges SET valid_to = NULL
|
|
17147
|
+
WHERE ${side} = ? AND valid_to = ? AND ${NOT_HISTORY}
|
|
17148
|
+
AND EXISTS (SELECT 1 FROM nodes o WHERE o.id = edges.${other} AND o.valid_to IS NULL)`
|
|
17149
|
+
).run(id, closedAt);
|
|
17150
|
+
reopened += Number(r.changes);
|
|
17151
|
+
}
|
|
17152
|
+
return reopened;
|
|
17153
|
+
}
|
|
17154
|
+
function collapseLiveHeads(db, logicalIds, t) {
|
|
17155
|
+
const headsOf = db.prepare(
|
|
17156
|
+
`SELECT id, version, valid_from FROM (
|
|
17157
|
+
SELECT id, version, valid_from, attrs_json FROM nodes WHERE logical_id = ?1 AND valid_to IS NULL
|
|
17158
|
+
UNION
|
|
17159
|
+
SELECT id, version, valid_from, attrs_json FROM nodes WHERE id = ?1 AND logical_id IS NULL AND valid_to IS NULL
|
|
17160
|
+
) WHERE ${NOT_HISTORICAL_ROW}`
|
|
17161
|
+
);
|
|
17162
|
+
const continuesInto = db.prepare(
|
|
17163
|
+
`SELECT to_id FROM edges WHERE from_id = ? AND type = 'CONTINUES' AND valid_to IS NULL`
|
|
17164
|
+
);
|
|
17165
|
+
const rekeyHead = db.prepare(`UPDATE nodes SET logical_id = ?1 WHERE id = ?1`);
|
|
17166
|
+
const rekeyCopies = db.prepare(
|
|
17167
|
+
`UPDATE nodes SET logical_id = ?1 WHERE logical_id = ?2 AND substr(id, 1, length(?1) + 2) = ?1 || '@v'`
|
|
17168
|
+
);
|
|
17169
|
+
const lineageMembers = db.prepare(
|
|
17170
|
+
`SELECT id FROM nodes WHERE logical_id = ?1 UNION SELECT id FROM nodes WHERE id = ?1`
|
|
17171
|
+
);
|
|
17172
|
+
const closeContinues = db.prepare(
|
|
17173
|
+
`UPDATE edges SET valid_to = MAX(valid_from, ?) WHERE from_id = ? AND to_id = ? AND type = 'CONTINUES' AND valid_to IS NULL`
|
|
17174
|
+
);
|
|
17175
|
+
let split = 0;
|
|
17176
|
+
const queue = [...new Set(logicalIds)];
|
|
17177
|
+
for (let i = 0; i < queue.length; i++) {
|
|
17178
|
+
const lid = queue[i];
|
|
17179
|
+
const heads = headsOf.all(lid);
|
|
17180
|
+
if (heads.length < 2) continue;
|
|
17181
|
+
const members = new Set(lineageMembers.all(lid).map((r) => r.id));
|
|
17182
|
+
const splitOff = (h) => {
|
|
17183
|
+
for (const { to_id } of continuesInto.all(h.id)) {
|
|
17184
|
+
if (members.has(to_id)) closeContinues.run(t, h.id, to_id);
|
|
17185
|
+
}
|
|
17186
|
+
rekeyHead.run(h.id);
|
|
17187
|
+
rekeyCopies.run(h.id, lid);
|
|
17188
|
+
queue.push(h.id);
|
|
17189
|
+
split++;
|
|
17190
|
+
};
|
|
17191
|
+
const kept = new Set(heads.map((h) => h.id));
|
|
17192
|
+
for (const h of heads) {
|
|
17193
|
+
if (h.id === lid) continue;
|
|
17194
|
+
const refuted = continuesInto.all(h.id).some(
|
|
17195
|
+
(e) => e.to_id !== h.id && kept.has(e.to_id)
|
|
17196
|
+
);
|
|
17197
|
+
if (refuted && kept.size > 1) {
|
|
17198
|
+
splitOff(h);
|
|
17199
|
+
kept.delete(h.id);
|
|
17200
|
+
}
|
|
17201
|
+
}
|
|
17202
|
+
let remaining = heads.filter((h) => kept.has(h.id));
|
|
17203
|
+
if (remaining.length < 2) continue;
|
|
17204
|
+
remaining = [...remaining].sort(
|
|
17205
|
+
(a, b) => Number(b.id === lid) - Number(a.id === lid) || Number(b.version) - Number(a.version) || Number(b.valid_from) - Number(a.valid_from) || (a.id < b.id ? -1 : 1)
|
|
17206
|
+
);
|
|
17207
|
+
for (const h of remaining.slice(1)) splitOff(h);
|
|
17208
|
+
}
|
|
17209
|
+
return split;
|
|
17210
|
+
}
|
|
17211
|
+
function repairLineageIntegrity(db, now) {
|
|
17212
|
+
const historicalRowsClosed = Number(
|
|
17213
|
+
db.prepare(
|
|
17214
|
+
`UPDATE nodes SET valid_to = MAX(valid_from, COALESCE(
|
|
17215
|
+
(SELECT s.valid_from FROM edges s WHERE s.id = 'edge_superseded_' || nodes.id), ?))
|
|
17216
|
+
WHERE valid_to IS NULL AND json_type(attrs_json, '$.historical') = 'true'`
|
|
17217
|
+
).run(now).changes
|
|
17218
|
+
);
|
|
17219
|
+
const conflicted = db.prepare(
|
|
17220
|
+
`SELECT COALESCE(logical_id, id) AS lid FROM nodes
|
|
17221
|
+
WHERE valid_to IS NULL AND ${NOT_HISTORICAL_ROW}
|
|
17222
|
+
GROUP BY lid HAVING count(*) > 1`
|
|
17223
|
+
).all().map((r) => r.lid);
|
|
17224
|
+
const headsSplit = collapseLiveHeads(db, conflicted, now);
|
|
17225
|
+
const strandedEdgesClosed = Number(
|
|
17226
|
+
db.prepare(
|
|
17227
|
+
`UPDATE edges SET valid_to = MAX(valid_from, COALESCE(
|
|
17228
|
+
(SELECT min(v) FROM (
|
|
17229
|
+
SELECT f.valid_to AS v FROM nodes f WHERE f.id = edges.from_id AND NOT ${PRESENT("f")}
|
|
17230
|
+
UNION ALL
|
|
17231
|
+
SELECT t.valid_to FROM nodes t WHERE t.id = edges.to_id AND NOT ${PRESENT("t")})), ?))
|
|
17232
|
+
WHERE id IN (SELECT e.id FROM edges e WHERE ${STRANDED_EDGE_PREDICATE})`
|
|
17233
|
+
).run(now).changes
|
|
17234
|
+
);
|
|
17235
|
+
return { historicalRowsClosed, headsSplit, strandedEdgesClosed };
|
|
17236
|
+
}
|
|
17237
|
+
function installLineageIntegrityRepair(db, now = Date.now()) {
|
|
17238
|
+
if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(LINEAGE_INTEGRITY_KEY)) return null;
|
|
17239
|
+
return db.transaction(() => {
|
|
17240
|
+
const report = repairLineageIntegrity(db, now);
|
|
17241
|
+
db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES (?, ?)").run(
|
|
17242
|
+
LINEAGE_INTEGRITY_KEY,
|
|
17243
|
+
JSON.stringify({ at: now, ...report })
|
|
17244
|
+
);
|
|
17245
|
+
return report;
|
|
17246
|
+
});
|
|
17247
|
+
}
|
|
17248
|
+
|
|
17086
17249
|
// ../../packages/math/src/constants.ts
|
|
17087
17250
|
var NEMORI_DEDUP_COSINE = 0.88;
|
|
17088
17251
|
|
|
@@ -17706,6 +17869,7 @@ var SqliteGraphStore = class {
|
|
|
17706
17869
|
this.db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES (?, 'done')").run(SESSION_REPAIR_KEY);
|
|
17707
17870
|
});
|
|
17708
17871
|
}
|
|
17872
|
+
installLineageIntegrityRepair(this.db);
|
|
17709
17873
|
this.stmts = {
|
|
17710
17874
|
insertNode: this.db.prepare(`
|
|
17711
17875
|
INSERT INTO nodes (
|
|
@@ -17916,6 +18080,12 @@ var SqliteGraphStore = class {
|
|
|
17916
18080
|
AND (t.id IS NULL OR t.valid_to IS NOT NULL)
|
|
17917
18081
|
`).all();
|
|
17918
18082
|
}
|
|
18083
|
+
strandedEdges() {
|
|
18084
|
+
return countStrandedEdges(this.db);
|
|
18085
|
+
}
|
|
18086
|
+
liveHeadConflicts() {
|
|
18087
|
+
return countLiveHeadConflicts(this.db);
|
|
18088
|
+
}
|
|
17919
18089
|
fileIndexStates(ids) {
|
|
17920
18090
|
if (ids.length === 0) return [];
|
|
17921
18091
|
if (ids.length > 500) throw new RangeError("fileIndexStates accepts at most 500 ids per read");
|
|
@@ -18084,15 +18254,15 @@ var SqliteGraphStore = class {
|
|
|
18084
18254
|
findNodeFieldsByLabel(label, attrKeys) {
|
|
18085
18255
|
for (const k of attrKeys) if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new Error(`findNodeFieldsByLabel: bad attr key ${k}`);
|
|
18086
18256
|
const cacheKey = attrKeys.join(",");
|
|
18087
|
-
let
|
|
18088
|
-
if (!
|
|
18257
|
+
let stmt2 = this.fieldStmts.get(cacheKey);
|
|
18258
|
+
if (!stmt2) {
|
|
18089
18259
|
const cols = attrKeys.map((k, i) => `, ${attrValueSql(`'$.${k}'`)} AS a${i}, json_type(attrs_json, '$.${k}') AS t${i}`).join("");
|
|
18090
|
-
|
|
18260
|
+
stmt2 = this.db.prepare(
|
|
18091
18261
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL`
|
|
18092
18262
|
);
|
|
18093
|
-
this.fieldStmts.set(cacheKey,
|
|
18263
|
+
this.fieldStmts.set(cacheKey, stmt2);
|
|
18094
18264
|
}
|
|
18095
|
-
return
|
|
18265
|
+
return stmt2.all(label).map((r) => {
|
|
18096
18266
|
const attrs = {};
|
|
18097
18267
|
attrKeys.forEach((k, i) => {
|
|
18098
18268
|
const v = decodeAttr(r[`a${i}`], r[`t${i}`]);
|
|
@@ -18212,14 +18382,14 @@ var SqliteGraphStore = class {
|
|
|
18212
18382
|
}
|
|
18213
18383
|
nodeLabels(ids) {
|
|
18214
18384
|
const width = NODE_LABELS_CHUNK;
|
|
18215
|
-
const
|
|
18385
|
+
const stmt2 = this.typedEdgeStmt(
|
|
18216
18386
|
`SELECT id, label FROM nodes WHERE id IN (${Array.from({ length: width }, () => "?").join(",")})`
|
|
18217
18387
|
);
|
|
18218
18388
|
const labels = /* @__PURE__ */ new Map();
|
|
18219
18389
|
for (let i = 0; i < ids.length; i += width) {
|
|
18220
18390
|
const chunk = ids.slice(i, i + width);
|
|
18221
18391
|
while (chunk.length < width) chunk.push(null);
|
|
18222
|
-
for (const row of
|
|
18392
|
+
for (const row of stmt2.all(...chunk)) labels.set(row.id, row.label);
|
|
18223
18393
|
}
|
|
18224
18394
|
return labels;
|
|
18225
18395
|
}
|
|
@@ -18418,12 +18588,12 @@ var SqliteGraphStore = class {
|
|
|
18418
18588
|
return scale;
|
|
18419
18589
|
}
|
|
18420
18590
|
typedEdgeStmt(sql) {
|
|
18421
|
-
let
|
|
18422
|
-
if (!
|
|
18423
|
-
|
|
18424
|
-
this.typedEdgeStmts.set(sql,
|
|
18591
|
+
let stmt2 = this.typedEdgeStmts.get(sql);
|
|
18592
|
+
if (!stmt2) {
|
|
18593
|
+
stmt2 = this.db.prepare(sql);
|
|
18594
|
+
this.typedEdgeStmts.set(sql, stmt2);
|
|
18425
18595
|
}
|
|
18426
|
-
return
|
|
18596
|
+
return stmt2;
|
|
18427
18597
|
}
|
|
18428
18598
|
outEdges(nodeId, types) {
|
|
18429
18599
|
if (!types || types.length === 0) {
|
|
@@ -18624,22 +18794,28 @@ var SqliteGraphStore = class {
|
|
|
18624
18794
|
}
|
|
18625
18795
|
}
|
|
18626
18796
|
reviveReobserved(relPaths, workspaceId, since) {
|
|
18627
|
-
|
|
18797
|
+
const revived = [];
|
|
18628
18798
|
const CHUNK = 400;
|
|
18629
18799
|
for (let i = 0; i < relPaths.length; i += CHUNK) {
|
|
18630
18800
|
const slice = relPaths.slice(i, i + CHUNK);
|
|
18631
18801
|
if (slice.length === 0) continue;
|
|
18632
|
-
const
|
|
18633
|
-
`
|
|
18802
|
+
const rows = this.db.prepare(
|
|
18803
|
+
`SELECT id, valid_to AS closedAt, COALESCE(logical_id, id) AS lid FROM nodes
|
|
18634
18804
|
WHERE valid_to IS NOT NULL
|
|
18635
18805
|
AND last_updated_at >= ?
|
|
18636
18806
|
AND json_extract(attrs_json, '$.workspaceId') = ?
|
|
18637
|
-
AND json_extract(attrs_json, '$.relPath') IN (${slice.map(() => "?").join(",")})
|
|
18638
|
-
|
|
18639
|
-
|
|
18807
|
+
AND json_extract(attrs_json, '$.relPath') IN (${slice.map(() => "?").join(",")})
|
|
18808
|
+
AND json_type(attrs_json, '$.historical') IS NOT 'true'`
|
|
18809
|
+
).all(since, workspaceId, ...slice);
|
|
18810
|
+
revived.push(...rows);
|
|
18640
18811
|
}
|
|
18641
|
-
if (revived
|
|
18642
|
-
|
|
18812
|
+
if (revived.length === 0) return 0;
|
|
18813
|
+
const reopen = this.db.prepare("UPDATE nodes SET valid_to = NULL WHERE id = ? AND valid_to IS NOT NULL");
|
|
18814
|
+
for (const r of revived) reopen.run(r.id);
|
|
18815
|
+
for (const r of revived) reopenCascadeClosedEdges(this.db, r.id, Number(r.closedAt));
|
|
18816
|
+
collapseLiveHeads(this.db, revived.map((r) => r.lid), since);
|
|
18817
|
+
this.mutations++;
|
|
18818
|
+
return revived.length;
|
|
18643
18819
|
}
|
|
18644
18820
|
incomingEdgeCoverage(label, edgeTypes, cloudOnly) {
|
|
18645
18821
|
if (edgeTypes.length === 0) return { count: 0, total: 0 };
|
|
@@ -18785,8 +18961,9 @@ var SqliteGraphStore = class {
|
|
|
18785
18961
|
this.stmts.advanceLive.run({ live_id: liveId, t });
|
|
18786
18962
|
return frozenId;
|
|
18787
18963
|
}
|
|
18788
|
-
closeNode(id, t) {
|
|
18789
|
-
this.stmts.closeNode.run({ id, t });
|
|
18964
|
+
closeNode(id, t, opts = {}) {
|
|
18965
|
+
const r = this.stmts.closeNode.run({ id, t });
|
|
18966
|
+
if (Number(r.changes) > 0 && !opts.retainEdges) closeIncidentEdges(this.db, id, t);
|
|
18790
18967
|
}
|
|
18791
18968
|
closeEdge(id, t) {
|
|
18792
18969
|
this.stmts.closeEdge.run({ id, t });
|