@inerrata-corporation/errata 2.0.22-dev.4652 → 2.0.22-dev.4660
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 +37 -13
- package/errata.mjs +40 -16
- package/generalize-worker.mjs +37 -13
- package/package.json +1 -1
- package/pass-worker.mjs +39 -14
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/consolidate-worker.mjs
CHANGED
|
@@ -15778,7 +15778,7 @@ var init_history_read = __esm({
|
|
|
15778
15778
|
"../../packages/shared/src/history-read.ts"() {
|
|
15779
15779
|
"use strict";
|
|
15780
15780
|
init_history_dependencies();
|
|
15781
|
-
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding"];
|
|
15781
|
+
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding", "structEmbedding", "structEmbeddedAt"];
|
|
15782
15782
|
}
|
|
15783
15783
|
});
|
|
15784
15784
|
|
|
@@ -17001,7 +17001,9 @@ function installEditPlaceholderRetirement(db) {
|
|
|
17001
17001
|
|
|
17002
17002
|
// ../../packages/local-graph/src/cloud-attr-compaction.ts
|
|
17003
17003
|
init_src2();
|
|
17004
|
-
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-
|
|
17004
|
+
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-2";
|
|
17005
|
+
var V1_KEY = "cloud-attr-compaction-1";
|
|
17006
|
+
var STRUCT_LABELS = "('Problem', 'Solution', 'RootCause')";
|
|
17005
17007
|
var DUPES = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `'${k}'`).join(",");
|
|
17006
17008
|
function compacted(row) {
|
|
17007
17009
|
const packed = `json_extract(${row}.attrs_json, '$.attrsJson')`;
|
|
@@ -17020,14 +17022,17 @@ function dirty(row) {
|
|
|
17020
17022
|
return `json_extract(${row}.attrs_json, '$.source') = 'cloud' AND (${has})`;
|
|
17021
17023
|
}
|
|
17022
17024
|
function installCloudAttrCompaction(db) {
|
|
17023
|
-
|
|
17025
|
+
const marked = (key) => Boolean(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
17026
|
+
if (marked(CLOUD_ATTR_COMPACTION_KEY)) return;
|
|
17027
|
+
const scope = marked(V1_KEY) ? ` AND label IN ${STRUCT_LABELS}` : "";
|
|
17024
17028
|
db.transaction(() => {
|
|
17025
17029
|
for (const operation of ["INSERT", "UPDATE"]) {
|
|
17026
|
-
db.exec(`
|
|
17030
|
+
db.exec(`DROP TRIGGER IF EXISTS cloud_attr_compact_${operation.toLowerCase()}`);
|
|
17031
|
+
db.exec(`CREATE TRIGGER cloud_attr_compact_${operation.toLowerCase()}
|
|
17027
17032
|
AFTER ${operation} ON nodes WHEN ${dirty("NEW")}
|
|
17028
17033
|
BEGIN UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE id = NEW.id; END;`);
|
|
17029
17034
|
}
|
|
17030
|
-
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}`);
|
|
17035
|
+
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}${scope}`);
|
|
17031
17036
|
db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(CLOUD_ATTR_COMPACTION_KEY, "installed");
|
|
17032
17037
|
});
|
|
17033
17038
|
}
|
|
@@ -17126,6 +17131,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
17126
17131
|
// ../../packages/local-graph/src/change-feed.ts
|
|
17127
17132
|
var CHANGE_FEED_KEY = "change-feed";
|
|
17128
17133
|
var ANY_CHANGE = "*";
|
|
17134
|
+
var nodeScope = (label) => `node:${label}`;
|
|
17129
17135
|
var CHANGE_LOG_KEEP = 25e4;
|
|
17130
17136
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
17131
17137
|
function installChangeFeed(db) {
|
|
@@ -18040,6 +18046,7 @@ var SqliteGraphStore = class {
|
|
|
18040
18046
|
initialPageRankScale;
|
|
18041
18047
|
constructor(opts) {
|
|
18042
18048
|
this.db = openDatabase(opts.path);
|
|
18049
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
18043
18050
|
this.db.exec(SCHEMA_SQL);
|
|
18044
18051
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
18045
18052
|
if (!versionRow) {
|
|
@@ -18104,6 +18111,7 @@ var SqliteGraphStore = class {
|
|
|
18104
18111
|
attrs_json = excluded.attrs_json
|
|
18105
18112
|
`),
|
|
18106
18113
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
18114
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
18107
18115
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
18108
18116
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
18109
18117
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -18603,11 +18611,13 @@ var SqliteGraphStore = class {
|
|
|
18603
18611
|
}
|
|
18604
18612
|
}
|
|
18605
18613
|
edgeRuleViolation(edge) {
|
|
18606
|
-
return localEdgeViolation(
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18614
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
18615
|
+
}
|
|
18616
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
18617
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
18618
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
18619
|
+
labelOf(id) {
|
|
18620
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
18611
18621
|
}
|
|
18612
18622
|
updateEdge(id, patch) {
|
|
18613
18623
|
this.stmts.updateEdge.run({
|
|
@@ -18651,7 +18661,21 @@ var SqliteGraphStore = class {
|
|
|
18651
18661
|
* per project per request; the materializing form held the daemon's event
|
|
18652
18662
|
* loop for seconds at scale. */
|
|
18653
18663
|
countNodesByLabel(label) {
|
|
18654
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
18664
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
18665
|
+
}
|
|
18666
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
18667
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
18668
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
18669
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
18670
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
18671
|
+
counts = /* @__PURE__ */ new Map();
|
|
18672
|
+
countAt(key, scopes, count) {
|
|
18673
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
18674
|
+
const hit = this.counts.get(key);
|
|
18675
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
18676
|
+
const n = count();
|
|
18677
|
+
this.counts.set(key, { seq, n });
|
|
18678
|
+
return n;
|
|
18655
18679
|
}
|
|
18656
18680
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
18657
18681
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -18918,7 +18942,7 @@ var SqliteGraphStore = class {
|
|
|
18918
18942
|
return out;
|
|
18919
18943
|
}
|
|
18920
18944
|
nodeCount() {
|
|
18921
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
18945
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
18922
18946
|
}
|
|
18923
18947
|
mutationCount() {
|
|
18924
18948
|
return this.mutations;
|
|
@@ -18962,7 +18986,7 @@ var SqliteGraphStore = class {
|
|
|
18962
18986
|
return this.ingestSeq;
|
|
18963
18987
|
}
|
|
18964
18988
|
edgeCount() {
|
|
18965
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
18989
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
18966
18990
|
}
|
|
18967
18991
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
18968
18992
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
package/errata.mjs
CHANGED
|
@@ -17382,7 +17382,7 @@ var init_history_read = __esm({
|
|
|
17382
17382
|
"../../packages/shared/src/history-read.ts"() {
|
|
17383
17383
|
"use strict";
|
|
17384
17384
|
init_history_dependencies();
|
|
17385
|
-
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding"];
|
|
17385
|
+
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding", "structEmbedding", "structEmbeddedAt"];
|
|
17386
17386
|
}
|
|
17387
17387
|
});
|
|
17388
17388
|
|
|
@@ -19061,23 +19061,28 @@ function dirty(row) {
|
|
|
19061
19061
|
return `json_extract(${row}.attrs_json, '$.source') = 'cloud' AND (${has})`;
|
|
19062
19062
|
}
|
|
19063
19063
|
function installCloudAttrCompaction(db) {
|
|
19064
|
-
|
|
19064
|
+
const marked = (key) => Boolean(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
19065
|
+
if (marked(CLOUD_ATTR_COMPACTION_KEY)) return;
|
|
19066
|
+
const scope = marked(V1_KEY) ? ` AND label IN ${STRUCT_LABELS}` : "";
|
|
19065
19067
|
db.transaction(() => {
|
|
19066
19068
|
for (const operation of ["INSERT", "UPDATE"]) {
|
|
19067
|
-
db.exec(`
|
|
19069
|
+
db.exec(`DROP TRIGGER IF EXISTS cloud_attr_compact_${operation.toLowerCase()}`);
|
|
19070
|
+
db.exec(`CREATE TRIGGER cloud_attr_compact_${operation.toLowerCase()}
|
|
19068
19071
|
AFTER ${operation} ON nodes WHEN ${dirty("NEW")}
|
|
19069
19072
|
BEGIN UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE id = NEW.id; END;`);
|
|
19070
19073
|
}
|
|
19071
|
-
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}`);
|
|
19074
|
+
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}${scope}`);
|
|
19072
19075
|
db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(CLOUD_ATTR_COMPACTION_KEY, "installed");
|
|
19073
19076
|
});
|
|
19074
19077
|
}
|
|
19075
|
-
var CLOUD_ATTR_COMPACTION_KEY, DUPES;
|
|
19078
|
+
var CLOUD_ATTR_COMPACTION_KEY, V1_KEY, STRUCT_LABELS, DUPES;
|
|
19076
19079
|
var init_cloud_attr_compaction = __esm({
|
|
19077
19080
|
"../../packages/local-graph/src/cloud-attr-compaction.ts"() {
|
|
19078
19081
|
"use strict";
|
|
19079
19082
|
init_src2();
|
|
19080
|
-
CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-
|
|
19083
|
+
CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-2";
|
|
19084
|
+
V1_KEY = "cloud-attr-compaction-1";
|
|
19085
|
+
STRUCT_LABELS = "('Problem', 'Solution', 'RootCause')";
|
|
19081
19086
|
DUPES = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `'${k}'`).join(",");
|
|
19082
19087
|
}
|
|
19083
19088
|
});
|
|
@@ -20892,6 +20897,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20892
20897
|
initialPageRankScale;
|
|
20893
20898
|
constructor(opts) {
|
|
20894
20899
|
this.db = openDatabase(opts.path);
|
|
20900
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
20895
20901
|
this.db.exec(SCHEMA_SQL);
|
|
20896
20902
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
20897
20903
|
if (!versionRow) {
|
|
@@ -20956,6 +20962,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20956
20962
|
attrs_json = excluded.attrs_json
|
|
20957
20963
|
`),
|
|
20958
20964
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
20965
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
20959
20966
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
20960
20967
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
20961
20968
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -21455,11 +21462,13 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21455
21462
|
}
|
|
21456
21463
|
}
|
|
21457
21464
|
edgeRuleViolation(edge2) {
|
|
21458
|
-
return localEdgeViolation(
|
|
21459
|
-
|
|
21460
|
-
|
|
21461
|
-
|
|
21462
|
-
|
|
21465
|
+
return localEdgeViolation(this.labelOf(edge2.from), edge2.type, this.labelOf(edge2.to));
|
|
21466
|
+
}
|
|
21467
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
21468
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
21469
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
21470
|
+
labelOf(id) {
|
|
21471
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
21463
21472
|
}
|
|
21464
21473
|
updateEdge(id, patch) {
|
|
21465
21474
|
this.stmts.updateEdge.run({
|
|
@@ -21503,7 +21512,21 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21503
21512
|
* per project per request; the materializing form held the daemon's event
|
|
21504
21513
|
* loop for seconds at scale. */
|
|
21505
21514
|
countNodesByLabel(label) {
|
|
21506
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
21515
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
21516
|
+
}
|
|
21517
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
21518
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
21519
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
21520
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
21521
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
21522
|
+
counts = /* @__PURE__ */ new Map();
|
|
21523
|
+
countAt(key, scopes, count) {
|
|
21524
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
21525
|
+
const hit = this.counts.get(key);
|
|
21526
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
21527
|
+
const n = count();
|
|
21528
|
+
this.counts.set(key, { seq, n });
|
|
21529
|
+
return n;
|
|
21507
21530
|
}
|
|
21508
21531
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
21509
21532
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -21770,7 +21793,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21770
21793
|
return out2;
|
|
21771
21794
|
}
|
|
21772
21795
|
nodeCount() {
|
|
21773
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
21796
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
21774
21797
|
}
|
|
21775
21798
|
mutationCount() {
|
|
21776
21799
|
return this.mutations;
|
|
@@ -21814,7 +21837,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21814
21837
|
return this.ingestSeq;
|
|
21815
21838
|
}
|
|
21816
21839
|
edgeCount() {
|
|
21817
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
21840
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
21818
21841
|
}
|
|
21819
21842
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
21820
21843
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
|
@@ -39603,9 +39626,10 @@ async function runIndexer(store, opts) {
|
|
|
39603
39626
|
if (ei > 0) await new Promise((r) => setImmediate(r));
|
|
39604
39627
|
const slice = pendingEdges.slice(ei, ei + EDGE_BATCH);
|
|
39605
39628
|
store.transaction(() => {
|
|
39629
|
+
const present = store.nodeLabels([...new Set(slice.flatMap((e) => [e.from, e.to]))]);
|
|
39606
39630
|
for (const e of slice) {
|
|
39607
39631
|
if (e.from === e.to) continue;
|
|
39608
|
-
if (!
|
|
39632
|
+
if (!present.has(e.from) || !present.has(e.to)) continue;
|
|
39609
39633
|
upsertEdge(
|
|
39610
39634
|
store,
|
|
39611
39635
|
e.from,
|
|
@@ -87006,7 +87030,7 @@ function createWatchBreaker(deps) {
|
|
|
87006
87030
|
}
|
|
87007
87031
|
|
|
87008
87032
|
// src/engine.ts
|
|
87009
|
-
var DAEMON_VERSION = true ? "2.0.22-dev.
|
|
87033
|
+
var DAEMON_VERSION = true ? "2.0.22-dev.4660" : "2.0.0-alpha.0";
|
|
87010
87034
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
87011
87035
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
87012
87036
|
var GIT_OP_MUTE_MS = 4e3;
|
package/generalize-worker.mjs
CHANGED
|
@@ -14697,7 +14697,7 @@ var CastaliaIngestPayloadSchema = external_exports.object({
|
|
|
14697
14697
|
});
|
|
14698
14698
|
|
|
14699
14699
|
// ../../packages/shared/src/history-read.ts
|
|
14700
|
-
var CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding"];
|
|
14700
|
+
var CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding", "structEmbedding", "structEmbeddedAt"];
|
|
14701
14701
|
|
|
14702
14702
|
// ../../packages/shared/src/history-revision.ts
|
|
14703
14703
|
var Sha = external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
|
|
@@ -15576,7 +15576,9 @@ function installEditPlaceholderRetirement(db) {
|
|
|
15576
15576
|
}
|
|
15577
15577
|
|
|
15578
15578
|
// ../../packages/local-graph/src/cloud-attr-compaction.ts
|
|
15579
|
-
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-
|
|
15579
|
+
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-2";
|
|
15580
|
+
var V1_KEY = "cloud-attr-compaction-1";
|
|
15581
|
+
var STRUCT_LABELS = "('Problem', 'Solution', 'RootCause')";
|
|
15580
15582
|
var DUPES = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `'${k}'`).join(",");
|
|
15581
15583
|
function compacted(row) {
|
|
15582
15584
|
const packed = `json_extract(${row}.attrs_json, '$.attrsJson')`;
|
|
@@ -15595,14 +15597,17 @@ function dirty(row) {
|
|
|
15595
15597
|
return `json_extract(${row}.attrs_json, '$.source') = 'cloud' AND (${has})`;
|
|
15596
15598
|
}
|
|
15597
15599
|
function installCloudAttrCompaction(db) {
|
|
15598
|
-
|
|
15600
|
+
const marked = (key) => Boolean(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
15601
|
+
if (marked(CLOUD_ATTR_COMPACTION_KEY)) return;
|
|
15602
|
+
const scope = marked(V1_KEY) ? ` AND label IN ${STRUCT_LABELS}` : "";
|
|
15599
15603
|
db.transaction(() => {
|
|
15600
15604
|
for (const operation of ["INSERT", "UPDATE"]) {
|
|
15601
|
-
db.exec(`
|
|
15605
|
+
db.exec(`DROP TRIGGER IF EXISTS cloud_attr_compact_${operation.toLowerCase()}`);
|
|
15606
|
+
db.exec(`CREATE TRIGGER cloud_attr_compact_${operation.toLowerCase()}
|
|
15602
15607
|
AFTER ${operation} ON nodes WHEN ${dirty("NEW")}
|
|
15603
15608
|
BEGIN UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE id = NEW.id; END;`);
|
|
15604
15609
|
}
|
|
15605
|
-
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}`);
|
|
15610
|
+
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}${scope}`);
|
|
15606
15611
|
db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(CLOUD_ATTR_COMPACTION_KEY, "installed");
|
|
15607
15612
|
});
|
|
15608
15613
|
}
|
|
@@ -15700,6 +15705,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
15700
15705
|
// ../../packages/local-graph/src/change-feed.ts
|
|
15701
15706
|
var CHANGE_FEED_KEY = "change-feed";
|
|
15702
15707
|
var ANY_CHANGE = "*";
|
|
15708
|
+
var nodeScope = (label) => `node:${label}`;
|
|
15703
15709
|
var CHANGE_LOG_KEEP = 25e4;
|
|
15704
15710
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
15705
15711
|
function installChangeFeed(db) {
|
|
@@ -16437,6 +16443,7 @@ var SqliteGraphStore = class {
|
|
|
16437
16443
|
initialPageRankScale;
|
|
16438
16444
|
constructor(opts) {
|
|
16439
16445
|
this.db = openDatabase(opts.path);
|
|
16446
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
16440
16447
|
this.db.exec(SCHEMA_SQL);
|
|
16441
16448
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
16442
16449
|
if (!versionRow) {
|
|
@@ -16501,6 +16508,7 @@ var SqliteGraphStore = class {
|
|
|
16501
16508
|
attrs_json = excluded.attrs_json
|
|
16502
16509
|
`),
|
|
16503
16510
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
16511
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
16504
16512
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
16505
16513
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
16506
16514
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -17000,11 +17008,13 @@ var SqliteGraphStore = class {
|
|
|
17000
17008
|
}
|
|
17001
17009
|
}
|
|
17002
17010
|
edgeRuleViolation(edge) {
|
|
17003
|
-
return localEdgeViolation(
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17011
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
17012
|
+
}
|
|
17013
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
17014
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
17015
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
17016
|
+
labelOf(id) {
|
|
17017
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
17008
17018
|
}
|
|
17009
17019
|
updateEdge(id, patch) {
|
|
17010
17020
|
this.stmts.updateEdge.run({
|
|
@@ -17048,7 +17058,21 @@ var SqliteGraphStore = class {
|
|
|
17048
17058
|
* per project per request; the materializing form held the daemon's event
|
|
17049
17059
|
* loop for seconds at scale. */
|
|
17050
17060
|
countNodesByLabel(label) {
|
|
17051
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
17061
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
17062
|
+
}
|
|
17063
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
17064
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
17065
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
17066
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
17067
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
17068
|
+
counts = /* @__PURE__ */ new Map();
|
|
17069
|
+
countAt(key, scopes, count) {
|
|
17070
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
17071
|
+
const hit = this.counts.get(key);
|
|
17072
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
17073
|
+
const n = count();
|
|
17074
|
+
this.counts.set(key, { seq, n });
|
|
17075
|
+
return n;
|
|
17052
17076
|
}
|
|
17053
17077
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
17054
17078
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -17315,7 +17339,7 @@ var SqliteGraphStore = class {
|
|
|
17315
17339
|
return out;
|
|
17316
17340
|
}
|
|
17317
17341
|
nodeCount() {
|
|
17318
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
17342
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
17319
17343
|
}
|
|
17320
17344
|
mutationCount() {
|
|
17321
17345
|
return this.mutations;
|
|
@@ -17359,7 +17383,7 @@ var SqliteGraphStore = class {
|
|
|
17359
17383
|
return this.ingestSeq;
|
|
17360
17384
|
}
|
|
17361
17385
|
edgeCount() {
|
|
17362
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
17386
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
17363
17387
|
}
|
|
17364
17388
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
17365
17389
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -16172,7 +16172,7 @@ var init_history_read = __esm({
|
|
|
16172
16172
|
"../../packages/shared/src/history-read.ts"() {
|
|
16173
16173
|
"use strict";
|
|
16174
16174
|
init_history_dependencies();
|
|
16175
|
-
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding"];
|
|
16175
|
+
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding", "structEmbedding", "structEmbeddedAt"];
|
|
16176
16176
|
}
|
|
16177
16177
|
});
|
|
16178
16178
|
|
|
@@ -18280,9 +18280,10 @@ async function runIndexer(store2, opts) {
|
|
|
18280
18280
|
if (ei > 0) await new Promise((r) => setImmediate(r));
|
|
18281
18281
|
const slice = pendingEdges.slice(ei, ei + EDGE_BATCH);
|
|
18282
18282
|
store2.transaction(() => {
|
|
18283
|
+
const present = store2.nodeLabels([...new Set(slice.flatMap((e) => [e.from, e.to]))]);
|
|
18283
18284
|
for (const e of slice) {
|
|
18284
18285
|
if (e.from === e.to) continue;
|
|
18285
|
-
if (!
|
|
18286
|
+
if (!present.has(e.from) || !present.has(e.to)) continue;
|
|
18286
18287
|
upsertEdge(
|
|
18287
18288
|
store2,
|
|
18288
18289
|
e.from,
|
|
@@ -26017,7 +26018,9 @@ function installEditPlaceholderRetirement(db) {
|
|
|
26017
26018
|
|
|
26018
26019
|
// ../../packages/local-graph/src/cloud-attr-compaction.ts
|
|
26019
26020
|
init_src2();
|
|
26020
|
-
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-
|
|
26021
|
+
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-2";
|
|
26022
|
+
var V1_KEY = "cloud-attr-compaction-1";
|
|
26023
|
+
var STRUCT_LABELS = "('Problem', 'Solution', 'RootCause')";
|
|
26021
26024
|
var DUPES = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `'${k}'`).join(",");
|
|
26022
26025
|
function compacted(row) {
|
|
26023
26026
|
const packed = `json_extract(${row}.attrs_json, '$.attrsJson')`;
|
|
@@ -26036,14 +26039,17 @@ function dirty(row) {
|
|
|
26036
26039
|
return `json_extract(${row}.attrs_json, '$.source') = 'cloud' AND (${has})`;
|
|
26037
26040
|
}
|
|
26038
26041
|
function installCloudAttrCompaction(db) {
|
|
26039
|
-
|
|
26042
|
+
const marked = (key) => Boolean(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
26043
|
+
if (marked(CLOUD_ATTR_COMPACTION_KEY)) return;
|
|
26044
|
+
const scope = marked(V1_KEY) ? ` AND label IN ${STRUCT_LABELS}` : "";
|
|
26040
26045
|
db.transaction(() => {
|
|
26041
26046
|
for (const operation of ["INSERT", "UPDATE"]) {
|
|
26042
|
-
db.exec(`
|
|
26047
|
+
db.exec(`DROP TRIGGER IF EXISTS cloud_attr_compact_${operation.toLowerCase()}`);
|
|
26048
|
+
db.exec(`CREATE TRIGGER cloud_attr_compact_${operation.toLowerCase()}
|
|
26043
26049
|
AFTER ${operation} ON nodes WHEN ${dirty("NEW")}
|
|
26044
26050
|
BEGIN UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE id = NEW.id; END;`);
|
|
26045
26051
|
}
|
|
26046
|
-
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}`);
|
|
26052
|
+
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}${scope}`);
|
|
26047
26053
|
db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(CLOUD_ATTR_COMPACTION_KEY, "installed");
|
|
26048
26054
|
});
|
|
26049
26055
|
}
|
|
@@ -26142,6 +26148,7 @@ var EXPOSURE_SCOPE = "exposure";
|
|
|
26142
26148
|
// ../../packages/local-graph/src/change-feed.ts
|
|
26143
26149
|
var CHANGE_FEED_KEY = "change-feed";
|
|
26144
26150
|
var ANY_CHANGE = "*";
|
|
26151
|
+
var nodeScope = (label) => `node:${label}`;
|
|
26145
26152
|
var CHANGE_LOG_KEEP = 25e4;
|
|
26146
26153
|
var PRUNED_TO_KEY = "change-log-pruned-to";
|
|
26147
26154
|
function installChangeFeed(db) {
|
|
@@ -27315,6 +27322,7 @@ var SqliteGraphStore = class {
|
|
|
27315
27322
|
initialPageRankScale;
|
|
27316
27323
|
constructor(opts) {
|
|
27317
27324
|
this.db = openDatabase(opts.path);
|
|
27325
|
+
this.db.exec("PRAGMA cache_size = -32768");
|
|
27318
27326
|
this.db.exec(SCHEMA_SQL);
|
|
27319
27327
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
27320
27328
|
if (!versionRow) {
|
|
@@ -27379,6 +27387,7 @@ var SqliteGraphStore = class {
|
|
|
27379
27387
|
attrs_json = excluded.attrs_json
|
|
27380
27388
|
`),
|
|
27381
27389
|
getNode: this.db.prepare("SELECT * FROM nodes WHERE id = ?"),
|
|
27390
|
+
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
27382
27391
|
// Single-column fast paths for the nightly pass — writing 100k pageRank
|
|
27383
27392
|
// values through the 18-column COALESCE updateNode took ~30s; these are ~10x
|
|
27384
27393
|
// cheaper (one bound column, no COALESCE evaluation per row).
|
|
@@ -27878,11 +27887,13 @@ var SqliteGraphStore = class {
|
|
|
27878
27887
|
}
|
|
27879
27888
|
}
|
|
27880
27889
|
edgeRuleViolation(edge) {
|
|
27881
|
-
return localEdgeViolation(
|
|
27882
|
-
|
|
27883
|
-
|
|
27884
|
-
|
|
27885
|
-
|
|
27890
|
+
return localEdgeViolation(this.labelOf(edge.from), edge.type, this.labelOf(edge.to));
|
|
27891
|
+
}
|
|
27892
|
+
/** An endpoint's label, any version, as `getNode(id)?.label` reads it. Every
|
|
27893
|
+
* edge write checks both endpoints, and hydrating them (attrs + vector) to
|
|
27894
|
+
* read one leading column was most of an incremental reindex's reads. */
|
|
27895
|
+
labelOf(id) {
|
|
27896
|
+
return this.stmts.labelOf.get(id)?.label;
|
|
27886
27897
|
}
|
|
27887
27898
|
updateEdge(id, patch) {
|
|
27888
27899
|
this.stmts.updateEdge.run({
|
|
@@ -27926,7 +27937,21 @@ var SqliteGraphStore = class {
|
|
|
27926
27937
|
* per project per request; the materializing form held the daemon's event
|
|
27927
27938
|
* loop for seconds at scale. */
|
|
27928
27939
|
countNodesByLabel(label) {
|
|
27929
|
-
return Number(this.stmts.countByLabel.get(label).n);
|
|
27940
|
+
return this.countAt(`label:${label}`, [nodeScope(label)], () => Number(this.stmts.countByLabel.get(label).n));
|
|
27941
|
+
}
|
|
27942
|
+
/** Counts asked for on every status poll (/health, `errata status`, the
|
|
27943
|
+
* dashboards): a live-node COUNT(*) reads the whole liveness index, ~3 MB per
|
|
27944
|
+
* call on a 1.1 GB store, to recount a set that moves only on a write. Each is
|
|
27945
|
+
* kept with the change-feed reading of the rows it counts — triggers bump it on
|
|
27946
|
+
* every write from any connection, so a hit is exact, not a TTL guess. */
|
|
27947
|
+
counts = /* @__PURE__ */ new Map();
|
|
27948
|
+
countAt(key, scopes, count) {
|
|
27949
|
+
const seq = readChangeSeq(this.db, scopes);
|
|
27950
|
+
const hit = this.counts.get(key);
|
|
27951
|
+
if (hit && hit.seq === seq) return hit.n;
|
|
27952
|
+
const n = count();
|
|
27953
|
+
this.counts.set(key, { seq, n });
|
|
27954
|
+
return n;
|
|
27930
27955
|
}
|
|
27931
27956
|
/** Live rows for a label with attrs and creation stamps only — for scans that
|
|
27932
27957
|
* read attrs and never the vector. `findNodesByLabel` decodes every embedding
|
|
@@ -28193,7 +28218,7 @@ var SqliteGraphStore = class {
|
|
|
28193
28218
|
return out2;
|
|
28194
28219
|
}
|
|
28195
28220
|
nodeCount() {
|
|
28196
|
-
return Number(this.stmts.nodeCount.get().n);
|
|
28221
|
+
return this.countAt("nodes", [ANY_CHANGE], () => Number(this.stmts.nodeCount.get().n));
|
|
28197
28222
|
}
|
|
28198
28223
|
mutationCount() {
|
|
28199
28224
|
return this.mutations;
|
|
@@ -28237,7 +28262,7 @@ var SqliteGraphStore = class {
|
|
|
28237
28262
|
return this.ingestSeq;
|
|
28238
28263
|
}
|
|
28239
28264
|
edgeCount() {
|
|
28240
|
-
return Number(this.stmts.edgeCount.get().n);
|
|
28265
|
+
return this.countAt("edges", [ANY_CHANGE], () => Number(this.stmts.edgeCount.get().n));
|
|
28241
28266
|
}
|
|
28242
28267
|
// Lightweight whole-graph scans — select only the columns the caller needs so a
|
|
28243
28268
|
// 100k-node pass skips the per-row attrs JSON.parse + embedding decode rowToNode
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
3bcb422706463f9d29ee3751dd1036046ce56211386ec8d38b1cbe53b26ac809 .codex-plugin/plugin.json
|
|
2
2
|
a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
|
|
3
3
|
fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
|
|
4
4
|
73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js
|