@inerrata-corporation/errata 2.0.23-dev.4689 → 2.0.23-dev.4779
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
CHANGED
|
@@ -17613,7 +17613,8 @@ var SELECT_INDEXES = [
|
|
|
17613
17613
|
"nodes_live_fold_candidate",
|
|
17614
17614
|
"nodes_live_resolved",
|
|
17615
17615
|
"nodes_live_fix_candidate",
|
|
17616
|
-
"nodes_live_anchor_hint"
|
|
17616
|
+
"nodes_live_anchor_hint",
|
|
17617
|
+
"nodes_live_created_v2"
|
|
17617
17618
|
];
|
|
17618
17619
|
var EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
|
|
17619
17620
|
var KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
@@ -17934,7 +17935,10 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
|
|
|
17934
17935
|
`;
|
|
17935
17936
|
var TEMPORAL_INDEX_SQL = `
|
|
17936
17937
|
CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
17937
|
-
|
|
17938
|
+
-- Dropped: a prefix of nodes_live_page_rank (valid_to, page_rank), which serves
|
|
17939
|
+
-- the live count and the "any live node?" check as a covering index too. It was
|
|
17940
|
+
-- re-keyed on every close and revive: ~11 KB of a symbol flip's ~80 KB.
|
|
17941
|
+
DROP INDEX IF EXISTS nodes_live_count;
|
|
17938
17942
|
-- Problems by recency (the only label read newest-first). Over every live row,
|
|
17939
17943
|
-- each write that stamps last_updated_at moved a code symbol's entry from a
|
|
17940
17944
|
-- scattered leaf: ~19 KB per position-only symbol rewrite on a 1.1 GB store.
|
|
@@ -17946,7 +17950,13 @@ CREATE INDEX IF NOT EXISTS nodes_live_problem_recent ON nodes(label, last_update
|
|
|
17946
17950
|
-- walks nodes_live and reads every live row of the label to test created_at:
|
|
17947
17951
|
-- 56 MB per guard on a 1.1 GB store, to learn there was nothing to do. valid_to
|
|
17948
17952
|
-- is a key column so the planner prefers this over nodes_live (one more term).
|
|
17949
|
-
|
|
17953
|
+
-- last_updated_at rides along for errata.recent on code labels, which names this
|
|
17954
|
+
-- index: the filter runs on index entries, not on every row of the label (79 ms
|
|
17955
|
+
-- \u2192 3 ms for Function on a 1.1 GB store). It costs no extra writes: a close or
|
|
17956
|
+
-- revive already re-keys this index, and mergeNodeIfChanged leaves a symbol's
|
|
17957
|
+
-- last_updated_at alone when only its position moved.
|
|
17958
|
+
DROP INDEX IF EXISTS nodes_live_created;
|
|
17959
|
+
CREATE INDEX IF NOT EXISTS nodes_live_created_v2 ON nodes(label, valid_to, created_at, last_updated_at) WHERE valid_to IS NULL;
|
|
17950
17960
|
-- Community members (the skills pull reads them twice per session boundary):
|
|
17951
17961
|
-- ~15% of semantic nodes carry a localCommunity, and without this every live
|
|
17952
17962
|
-- semantic row was read to find them (168 MB \u2192 18 MB per read).
|
|
@@ -18131,6 +18141,12 @@ function sameSqlValue(a, b) {
|
|
|
18131
18141
|
if (a instanceof Uint8Array && b instanceof Uint8Array) return Buffer.compare(a, b) === 0;
|
|
18132
18142
|
return false;
|
|
18133
18143
|
}
|
|
18144
|
+
var POSITION_ATTRS = ["startByte", "endByte", "startRow"];
|
|
18145
|
+
function attrsJsonWithoutPositions(attrs) {
|
|
18146
|
+
const rest = { ...attrs };
|
|
18147
|
+
for (const k of POSITION_ATTRS) delete rest[k];
|
|
18148
|
+
return JSON.stringify(rest);
|
|
18149
|
+
}
|
|
18134
18150
|
var PRIOR_TAG_MARKER = '"priorTag":true';
|
|
18135
18151
|
var SqliteGraphStore = class {
|
|
18136
18152
|
db;
|
|
@@ -18231,7 +18247,7 @@ var SqliteGraphStore = class {
|
|
|
18231
18247
|
lastUpdatedOf: this.db.prepare("SELECT last_updated_at AS t, attrs_json FROM nodes WHERE id = ?"),
|
|
18232
18248
|
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
18233
18249
|
nodeContent: this.db.prepare(
|
|
18234
|
-
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, attrs_json FROM nodes WHERE id = ?"
|
|
18250
|
+
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, last_updated_at, attrs_json FROM nodes WHERE id = ?"
|
|
18235
18251
|
),
|
|
18236
18252
|
edgeContent: this.db.prepare(
|
|
18237
18253
|
"SELECT confidence, valid_to, attrs_json FROM edges WHERE from_id = ? AND type = ? AND to_id = ?"
|
|
@@ -18644,11 +18660,23 @@ var SqliteGraphStore = class {
|
|
|
18644
18660
|
* rank, community, landmark, surprise, hits, tier and the vector belong to
|
|
18645
18661
|
* the passes that compute them, and a skipped write leaves them as they are
|
|
18646
18662
|
* where a merge would have reset them to the producer's defaults. Returns
|
|
18647
|
-
* whether it wrote.
|
|
18663
|
+
* whether it wrote.
|
|
18664
|
+
*
|
|
18665
|
+
* A live row whose only change is its position keeps its lastUpdatedAt, so
|
|
18666
|
+
* that stamp means "this symbol's content changed": what errata.recent lists
|
|
18667
|
+
* and the fix-candidate ask reads, and what lets nodes_live_created_v2 carry
|
|
18668
|
+
* it without being re-keyed by every edit above a symbol. A closed row is
|
|
18669
|
+
* always stamped: reviveReobserved reopens what this pass stamped. */
|
|
18648
18670
|
mergeNodeIfChanged(node) {
|
|
18649
18671
|
const row = this.stmts.nodeContent.get(node.id);
|
|
18650
|
-
if (row
|
|
18651
|
-
|
|
18672
|
+
if (!row || row.valid_to !== null || row.label !== node.label || row.description !== node.description || row.extraction_confidence !== node.extractionConfidence || row.stability !== node.stability || EXPOSURE_ATTRS.some((k) => node.attrs?.[k] !== void 0)) {
|
|
18673
|
+
this.mergeNode(node);
|
|
18674
|
+
return true;
|
|
18675
|
+
}
|
|
18676
|
+
const attrs = node.attrs ?? {};
|
|
18677
|
+
if (row.attrs_json === JSON.stringify(attrs)) return false;
|
|
18678
|
+
const moved = attrsJsonWithoutPositions(JSON.parse(row.attrs_json)) === attrsJsonWithoutPositions(attrs);
|
|
18679
|
+
this.mergeNode(moved ? { ...node, lastUpdatedAt: row.last_updated_at } : node);
|
|
18652
18680
|
return true;
|
|
18653
18681
|
}
|
|
18654
18682
|
updateNode(id, patch) {
|
|
@@ -18728,8 +18756,8 @@ var SqliteGraphStore = class {
|
|
|
18728
18756
|
stmt2 = this.db.prepare(
|
|
18729
18757
|
// Ordered, not left to the planner: readers take "first row wins" (the
|
|
18730
18758
|
// symbol lexicon's name winner and doc pick), and the order otherwise
|
|
18731
|
-
// followed whichever partial index the planner chose.
|
|
18732
|
-
// serves
|
|
18759
|
+
// followed whichever partial index the planner chose. nodes_live_created_v2
|
|
18760
|
+
// serves it, sorting rowids only within an equal created_at.
|
|
18733
18761
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY created_at, rowid`
|
|
18734
18762
|
);
|
|
18735
18763
|
this.fieldStmts.set(cacheKey, stmt2);
|
package/errata.mjs
CHANGED
|
@@ -20645,7 +20645,8 @@ var init_node_select = __esm({
|
|
|
20645
20645
|
"nodes_live_fold_candidate",
|
|
20646
20646
|
"nodes_live_resolved",
|
|
20647
20647
|
"nodes_live_fix_candidate",
|
|
20648
|
-
"nodes_live_anchor_hint"
|
|
20648
|
+
"nodes_live_anchor_hint",
|
|
20649
|
+
"nodes_live_created_v2"
|
|
20649
20650
|
];
|
|
20650
20651
|
EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
|
|
20651
20652
|
KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
@@ -20761,10 +20762,15 @@ function sameSqlValue(a, b) {
|
|
|
20761
20762
|
if (a instanceof Uint8Array && b instanceof Uint8Array) return Buffer.compare(a, b) === 0;
|
|
20762
20763
|
return false;
|
|
20763
20764
|
}
|
|
20765
|
+
function attrsJsonWithoutPositions(attrs) {
|
|
20766
|
+
const rest2 = { ...attrs };
|
|
20767
|
+
for (const k of POSITION_ATTRS) delete rest2[k];
|
|
20768
|
+
return JSON.stringify(rest2);
|
|
20769
|
+
}
|
|
20764
20770
|
function openGraphStore(opts) {
|
|
20765
20771
|
return new SqliteGraphStore(opts);
|
|
20766
20772
|
}
|
|
20767
|
-
var PAGE_RANK_SCALE_KEY, TEXT_SEARCH_COLUMNS, LOCAL_RULE_OVERRIDES, SCHEMA_VERSION, SESSION_REPAIR_KEY, EXPOSURE_SIDE_KEY, SESSION_EVIDENCE_PREDICATE, SCHEMA_SQL, TEMPORAL_INDEX_SQL, FINGERPRINT_INDEXED_LABELS, NODE_LABELS_CHUNK, NODE_UPSERT_COLUMNS, EDGE_UPSERT_COLUMNS, PRIOR_TAG_MARKER, SqliteGraphStore;
|
|
20773
|
+
var PAGE_RANK_SCALE_KEY, TEXT_SEARCH_COLUMNS, LOCAL_RULE_OVERRIDES, SCHEMA_VERSION, SESSION_REPAIR_KEY, EXPOSURE_SIDE_KEY, SESSION_EVIDENCE_PREDICATE, SCHEMA_SQL, TEMPORAL_INDEX_SQL, FINGERPRINT_INDEXED_LABELS, NODE_LABELS_CHUNK, NODE_UPSERT_COLUMNS, EDGE_UPSERT_COLUMNS, POSITION_ATTRS, PRIOR_TAG_MARKER, SqliteGraphStore;
|
|
20768
20774
|
var init_store = __esm({
|
|
20769
20775
|
"../../packages/local-graph/src/store.ts"() {
|
|
20770
20776
|
"use strict";
|
|
@@ -20918,7 +20924,10 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
|
|
|
20918
20924
|
`;
|
|
20919
20925
|
TEMPORAL_INDEX_SQL = `
|
|
20920
20926
|
CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
20921
|
-
|
|
20927
|
+
-- Dropped: a prefix of nodes_live_page_rank (valid_to, page_rank), which serves
|
|
20928
|
+
-- the live count and the "any live node?" check as a covering index too. It was
|
|
20929
|
+
-- re-keyed on every close and revive: ~11 KB of a symbol flip's ~80 KB.
|
|
20930
|
+
DROP INDEX IF EXISTS nodes_live_count;
|
|
20922
20931
|
-- Problems by recency (the only label read newest-first). Over every live row,
|
|
20923
20932
|
-- each write that stamps last_updated_at moved a code symbol's entry from a
|
|
20924
20933
|
-- scattered leaf: ~19 KB per position-only symbol rewrite on a 1.1 GB store.
|
|
@@ -20930,7 +20939,13 @@ CREATE INDEX IF NOT EXISTS nodes_live_problem_recent ON nodes(label, last_update
|
|
|
20930
20939
|
-- walks nodes_live and reads every live row of the label to test created_at:
|
|
20931
20940
|
-- 56 MB per guard on a 1.1 GB store, to learn there was nothing to do. valid_to
|
|
20932
20941
|
-- is a key column so the planner prefers this over nodes_live (one more term).
|
|
20933
|
-
|
|
20942
|
+
-- last_updated_at rides along for errata.recent on code labels, which names this
|
|
20943
|
+
-- index: the filter runs on index entries, not on every row of the label (79 ms
|
|
20944
|
+
-- \u2192 3 ms for Function on a 1.1 GB store). It costs no extra writes: a close or
|
|
20945
|
+
-- revive already re-keys this index, and mergeNodeIfChanged leaves a symbol's
|
|
20946
|
+
-- last_updated_at alone when only its position moved.
|
|
20947
|
+
DROP INDEX IF EXISTS nodes_live_created;
|
|
20948
|
+
CREATE INDEX IF NOT EXISTS nodes_live_created_v2 ON nodes(label, valid_to, created_at, last_updated_at) WHERE valid_to IS NULL;
|
|
20934
20949
|
-- Community members (the skills pull reads them twice per session boundary):
|
|
20935
20950
|
-- ~15% of semantic nodes carry a localCommunity, and without this every live
|
|
20936
20951
|
-- semantic row was read to find them (168 MB \u2192 18 MB per read).
|
|
@@ -21053,6 +21068,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21053
21068
|
"attrs_json"
|
|
21054
21069
|
];
|
|
21055
21070
|
EDGE_UPSERT_COLUMNS = ["confidence", "last_seen_at", "nav_successes", "nav_failures", "valid_to", "attrs_json"];
|
|
21071
|
+
POSITION_ATTRS = ["startByte", "endByte", "startRow"];
|
|
21056
21072
|
PRIOR_TAG_MARKER = '"priorTag":true';
|
|
21057
21073
|
SqliteGraphStore = class {
|
|
21058
21074
|
db;
|
|
@@ -21153,7 +21169,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21153
21169
|
lastUpdatedOf: this.db.prepare("SELECT last_updated_at AS t, attrs_json FROM nodes WHERE id = ?"),
|
|
21154
21170
|
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
21155
21171
|
nodeContent: this.db.prepare(
|
|
21156
|
-
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, attrs_json FROM nodes WHERE id = ?"
|
|
21172
|
+
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, last_updated_at, attrs_json FROM nodes WHERE id = ?"
|
|
21157
21173
|
),
|
|
21158
21174
|
edgeContent: this.db.prepare(
|
|
21159
21175
|
"SELECT confidence, valid_to, attrs_json FROM edges WHERE from_id = ? AND type = ? AND to_id = ?"
|
|
@@ -21566,11 +21582,23 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21566
21582
|
* rank, community, landmark, surprise, hits, tier and the vector belong to
|
|
21567
21583
|
* the passes that compute them, and a skipped write leaves them as they are
|
|
21568
21584
|
* where a merge would have reset them to the producer's defaults. Returns
|
|
21569
|
-
* whether it wrote.
|
|
21585
|
+
* whether it wrote.
|
|
21586
|
+
*
|
|
21587
|
+
* A live row whose only change is its position keeps its lastUpdatedAt, so
|
|
21588
|
+
* that stamp means "this symbol's content changed": what errata.recent lists
|
|
21589
|
+
* and the fix-candidate ask reads, and what lets nodes_live_created_v2 carry
|
|
21590
|
+
* it without being re-keyed by every edit above a symbol. A closed row is
|
|
21591
|
+
* always stamped: reviveReobserved reopens what this pass stamped. */
|
|
21570
21592
|
mergeNodeIfChanged(node2) {
|
|
21571
21593
|
const row = this.stmts.nodeContent.get(node2.id);
|
|
21572
|
-
if (row
|
|
21573
|
-
|
|
21594
|
+
if (!row || row.valid_to !== null || row.label !== node2.label || row.description !== node2.description || row.extraction_confidence !== node2.extractionConfidence || row.stability !== node2.stability || EXPOSURE_ATTRS.some((k) => node2.attrs?.[k] !== void 0)) {
|
|
21595
|
+
this.mergeNode(node2);
|
|
21596
|
+
return true;
|
|
21597
|
+
}
|
|
21598
|
+
const attrs = node2.attrs ?? {};
|
|
21599
|
+
if (row.attrs_json === JSON.stringify(attrs)) return false;
|
|
21600
|
+
const moved = attrsJsonWithoutPositions(JSON.parse(row.attrs_json)) === attrsJsonWithoutPositions(attrs);
|
|
21601
|
+
this.mergeNode(moved ? { ...node2, lastUpdatedAt: row.last_updated_at } : node2);
|
|
21574
21602
|
return true;
|
|
21575
21603
|
}
|
|
21576
21604
|
updateNode(id, patch) {
|
|
@@ -21650,8 +21678,8 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21650
21678
|
stmt2 = this.db.prepare(
|
|
21651
21679
|
// Ordered, not left to the planner: readers take "first row wins" (the
|
|
21652
21680
|
// symbol lexicon's name winner and doc pick), and the order otherwise
|
|
21653
|
-
// followed whichever partial index the planner chose.
|
|
21654
|
-
// serves
|
|
21681
|
+
// followed whichever partial index the planner chose. nodes_live_created_v2
|
|
21682
|
+
// serves it, sorting rowids only within an equal created_at.
|
|
21655
21683
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY created_at, rowid`
|
|
21656
21684
|
);
|
|
21657
21685
|
this.fieldStmts.set(cacheKey2, stmt2);
|
|
@@ -23199,10 +23227,12 @@ function crystallize(store, opts = { ts: 0 }) {
|
|
|
23199
23227
|
const s = support(c) + Math.max(0, sourcesCount(c) - 1);
|
|
23200
23228
|
const f = contradictions;
|
|
23201
23229
|
const confidence = (1 + s) / (2 + s + f);
|
|
23202
|
-
|
|
23203
|
-
|
|
23204
|
-
|
|
23205
|
-
|
|
23230
|
+
if (c.attrs["confidence"] !== confidence) {
|
|
23231
|
+
store.updateNode(c.id, {
|
|
23232
|
+
attrs: { ...c.attrs, confidence },
|
|
23233
|
+
lastUpdatedAt: opts.ts
|
|
23234
|
+
});
|
|
23235
|
+
}
|
|
23206
23236
|
const sup = support(c);
|
|
23207
23237
|
let tier = c.memoryTier;
|
|
23208
23238
|
if (sup >= PERSISTENT_SUPPORT && confidence >= PERSISTENT_CONFIDENCE) tier = "persistent";
|
|
@@ -23270,7 +23300,10 @@ function mergeTruthKind(a, b) {
|
|
|
23270
23300
|
function markBoth(store, a, b, patch, ts) {
|
|
23271
23301
|
for (const n of [a, b]) {
|
|
23272
23302
|
const fresh = store.getNode(n.id);
|
|
23273
|
-
|
|
23303
|
+
const next = { ...patch };
|
|
23304
|
+
if (fresh.attrs["revisit"] === true && fresh.attrs["revisitReason"] === next["revisitReason"]) delete next["revisitSinceTs"];
|
|
23305
|
+
if (Object.entries(next).every(([k, v]) => fresh.attrs[k] === v)) continue;
|
|
23306
|
+
store.updateNode(n.id, { attrs: { ...fresh.attrs, ...next }, lastUpdatedAt: ts });
|
|
23274
23307
|
}
|
|
23275
23308
|
}
|
|
23276
23309
|
var LONG_TERM_SUPPORT, PERSISTENT_SUPPORT, PERSISTENT_CONFIDENCE, SCOPE_AXES;
|
|
@@ -49322,7 +49355,14 @@ var init_mcp = __esm({
|
|
|
49322
49355
|
total += count;
|
|
49323
49356
|
groups[label] = {
|
|
49324
49357
|
count,
|
|
49325
|
-
items: store.selectNodes({
|
|
49358
|
+
items: store.selectNodes({
|
|
49359
|
+
...q,
|
|
49360
|
+
orderBy: { column: col, desc: true },
|
|
49361
|
+
limit: sliceEnd(limit),
|
|
49362
|
+
// Unnamed, the planner reads every row of a code label through
|
|
49363
|
+
// nodes_live to test last_updated_at; this index carries it.
|
|
49364
|
+
...col === "last_updated_at" ? { indexedBy: "nodes_live_created_v2" } : {}
|
|
49365
|
+
}).map((n) => ({ id: n.id, description: n.description.slice(0, 160), at: col === "last_updated_at" ? n.lastUpdatedAt : n.createdAt }))
|
|
49326
49366
|
};
|
|
49327
49367
|
}
|
|
49328
49368
|
}
|
|
@@ -85606,7 +85646,7 @@ var OntologyValidationError = class extends Error {
|
|
|
85606
85646
|
}
|
|
85607
85647
|
};
|
|
85608
85648
|
function phrase(text, article) {
|
|
85609
|
-
const capitalized =
|
|
85649
|
+
const capitalized = firstAlphaCharUpper(text);
|
|
85610
85650
|
return { text, article, textCapitalized: capitalized };
|
|
85611
85651
|
}
|
|
85612
85652
|
var DEFAULT_ONTOLOGY2 = {
|
|
@@ -85729,7 +85769,7 @@ function expectedArticleKind(text) {
|
|
|
85729
85769
|
return "bare";
|
|
85730
85770
|
}
|
|
85731
85771
|
function firstAlphaCharUpper(s) {
|
|
85732
|
-
return s.
|
|
85772
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
85733
85773
|
}
|
|
85734
85774
|
function phraseTriggersLayer1(text) {
|
|
85735
85775
|
for (const pat of ALL_PATTERNS) {
|
|
@@ -87480,7 +87520,7 @@ function createWatchBreaker(deps) {
|
|
|
87480
87520
|
}
|
|
87481
87521
|
|
|
87482
87522
|
// src/engine.ts
|
|
87483
|
-
var DAEMON_VERSION = true ? "2.0.23-dev.
|
|
87523
|
+
var DAEMON_VERSION = true ? "2.0.23-dev.4779" : "2.0.0-alpha.0";
|
|
87484
87524
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
87485
87525
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
87486
87526
|
var GIT_OP_MUTE_MS = 4e3;
|
package/generalize-worker.mjs
CHANGED
|
@@ -16010,7 +16010,8 @@ var SELECT_INDEXES = [
|
|
|
16010
16010
|
"nodes_live_fold_candidate",
|
|
16011
16011
|
"nodes_live_resolved",
|
|
16012
16012
|
"nodes_live_fix_candidate",
|
|
16013
|
-
"nodes_live_anchor_hint"
|
|
16013
|
+
"nodes_live_anchor_hint",
|
|
16014
|
+
"nodes_live_created_v2"
|
|
16014
16015
|
];
|
|
16015
16016
|
var EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
|
|
16016
16017
|
var KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
@@ -16331,7 +16332,10 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
|
|
|
16331
16332
|
`;
|
|
16332
16333
|
var TEMPORAL_INDEX_SQL = `
|
|
16333
16334
|
CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
16334
|
-
|
|
16335
|
+
-- Dropped: a prefix of nodes_live_page_rank (valid_to, page_rank), which serves
|
|
16336
|
+
-- the live count and the "any live node?" check as a covering index too. It was
|
|
16337
|
+
-- re-keyed on every close and revive: ~11 KB of a symbol flip's ~80 KB.
|
|
16338
|
+
DROP INDEX IF EXISTS nodes_live_count;
|
|
16335
16339
|
-- Problems by recency (the only label read newest-first). Over every live row,
|
|
16336
16340
|
-- each write that stamps last_updated_at moved a code symbol's entry from a
|
|
16337
16341
|
-- scattered leaf: ~19 KB per position-only symbol rewrite on a 1.1 GB store.
|
|
@@ -16343,7 +16347,13 @@ CREATE INDEX IF NOT EXISTS nodes_live_problem_recent ON nodes(label, last_update
|
|
|
16343
16347
|
-- walks nodes_live and reads every live row of the label to test created_at:
|
|
16344
16348
|
-- 56 MB per guard on a 1.1 GB store, to learn there was nothing to do. valid_to
|
|
16345
16349
|
-- is a key column so the planner prefers this over nodes_live (one more term).
|
|
16346
|
-
|
|
16350
|
+
-- last_updated_at rides along for errata.recent on code labels, which names this
|
|
16351
|
+
-- index: the filter runs on index entries, not on every row of the label (79 ms
|
|
16352
|
+
-- \u2192 3 ms for Function on a 1.1 GB store). It costs no extra writes: a close or
|
|
16353
|
+
-- revive already re-keys this index, and mergeNodeIfChanged leaves a symbol's
|
|
16354
|
+
-- last_updated_at alone when only its position moved.
|
|
16355
|
+
DROP INDEX IF EXISTS nodes_live_created;
|
|
16356
|
+
CREATE INDEX IF NOT EXISTS nodes_live_created_v2 ON nodes(label, valid_to, created_at, last_updated_at) WHERE valid_to IS NULL;
|
|
16347
16357
|
-- Community members (the skills pull reads them twice per session boundary):
|
|
16348
16358
|
-- ~15% of semantic nodes carry a localCommunity, and without this every live
|
|
16349
16359
|
-- semantic row was read to find them (168 MB \u2192 18 MB per read).
|
|
@@ -16528,6 +16538,12 @@ function sameSqlValue(a, b) {
|
|
|
16528
16538
|
if (a instanceof Uint8Array && b instanceof Uint8Array) return Buffer.compare(a, b) === 0;
|
|
16529
16539
|
return false;
|
|
16530
16540
|
}
|
|
16541
|
+
var POSITION_ATTRS = ["startByte", "endByte", "startRow"];
|
|
16542
|
+
function attrsJsonWithoutPositions(attrs) {
|
|
16543
|
+
const rest = { ...attrs };
|
|
16544
|
+
for (const k of POSITION_ATTRS) delete rest[k];
|
|
16545
|
+
return JSON.stringify(rest);
|
|
16546
|
+
}
|
|
16531
16547
|
var PRIOR_TAG_MARKER = '"priorTag":true';
|
|
16532
16548
|
var SqliteGraphStore = class {
|
|
16533
16549
|
db;
|
|
@@ -16628,7 +16644,7 @@ var SqliteGraphStore = class {
|
|
|
16628
16644
|
lastUpdatedOf: this.db.prepare("SELECT last_updated_at AS t, attrs_json FROM nodes WHERE id = ?"),
|
|
16629
16645
|
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
16630
16646
|
nodeContent: this.db.prepare(
|
|
16631
|
-
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, attrs_json FROM nodes WHERE id = ?"
|
|
16647
|
+
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, last_updated_at, attrs_json FROM nodes WHERE id = ?"
|
|
16632
16648
|
),
|
|
16633
16649
|
edgeContent: this.db.prepare(
|
|
16634
16650
|
"SELECT confidence, valid_to, attrs_json FROM edges WHERE from_id = ? AND type = ? AND to_id = ?"
|
|
@@ -17041,11 +17057,23 @@ var SqliteGraphStore = class {
|
|
|
17041
17057
|
* rank, community, landmark, surprise, hits, tier and the vector belong to
|
|
17042
17058
|
* the passes that compute them, and a skipped write leaves them as they are
|
|
17043
17059
|
* where a merge would have reset them to the producer's defaults. Returns
|
|
17044
|
-
* whether it wrote.
|
|
17060
|
+
* whether it wrote.
|
|
17061
|
+
*
|
|
17062
|
+
* A live row whose only change is its position keeps its lastUpdatedAt, so
|
|
17063
|
+
* that stamp means "this symbol's content changed": what errata.recent lists
|
|
17064
|
+
* and the fix-candidate ask reads, and what lets nodes_live_created_v2 carry
|
|
17065
|
+
* it without being re-keyed by every edit above a symbol. A closed row is
|
|
17066
|
+
* always stamped: reviveReobserved reopens what this pass stamped. */
|
|
17045
17067
|
mergeNodeIfChanged(node) {
|
|
17046
17068
|
const row = this.stmts.nodeContent.get(node.id);
|
|
17047
|
-
if (row
|
|
17048
|
-
|
|
17069
|
+
if (!row || row.valid_to !== null || row.label !== node.label || row.description !== node.description || row.extraction_confidence !== node.extractionConfidence || row.stability !== node.stability || EXPOSURE_ATTRS.some((k) => node.attrs?.[k] !== void 0)) {
|
|
17070
|
+
this.mergeNode(node);
|
|
17071
|
+
return true;
|
|
17072
|
+
}
|
|
17073
|
+
const attrs = node.attrs ?? {};
|
|
17074
|
+
if (row.attrs_json === JSON.stringify(attrs)) return false;
|
|
17075
|
+
const moved = attrsJsonWithoutPositions(JSON.parse(row.attrs_json)) === attrsJsonWithoutPositions(attrs);
|
|
17076
|
+
this.mergeNode(moved ? { ...node, lastUpdatedAt: row.last_updated_at } : node);
|
|
17049
17077
|
return true;
|
|
17050
17078
|
}
|
|
17051
17079
|
updateNode(id, patch) {
|
|
@@ -17125,8 +17153,8 @@ var SqliteGraphStore = class {
|
|
|
17125
17153
|
stmt2 = this.db.prepare(
|
|
17126
17154
|
// Ordered, not left to the planner: readers take "first row wins" (the
|
|
17127
17155
|
// symbol lexicon's name winner and doc pick), and the order otherwise
|
|
17128
|
-
// followed whichever partial index the planner chose.
|
|
17129
|
-
// serves
|
|
17156
|
+
// followed whichever partial index the planner chose. nodes_live_created_v2
|
|
17157
|
+
// serves it, sorting rowids only within an equal created_at.
|
|
17130
17158
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY created_at, rowid`
|
|
17131
17159
|
);
|
|
17132
17160
|
this.fieldStmts.set(cacheKey, stmt2);
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -26982,7 +26982,8 @@ var SELECT_INDEXES = [
|
|
|
26982
26982
|
"nodes_live_fold_candidate",
|
|
26983
26983
|
"nodes_live_resolved",
|
|
26984
26984
|
"nodes_live_fix_candidate",
|
|
26985
|
-
"nodes_live_anchor_hint"
|
|
26985
|
+
"nodes_live_anchor_hint",
|
|
26986
|
+
"nodes_live_created_v2"
|
|
26986
26987
|
];
|
|
26987
26988
|
var EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
|
|
26988
26989
|
var KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
@@ -27303,7 +27304,10 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
|
|
|
27303
27304
|
`;
|
|
27304
27305
|
var TEMPORAL_INDEX_SQL = `
|
|
27305
27306
|
CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
27306
|
-
|
|
27307
|
+
-- Dropped: a prefix of nodes_live_page_rank (valid_to, page_rank), which serves
|
|
27308
|
+
-- the live count and the "any live node?" check as a covering index too. It was
|
|
27309
|
+
-- re-keyed on every close and revive: ~11 KB of a symbol flip's ~80 KB.
|
|
27310
|
+
DROP INDEX IF EXISTS nodes_live_count;
|
|
27307
27311
|
-- Problems by recency (the only label read newest-first). Over every live row,
|
|
27308
27312
|
-- each write that stamps last_updated_at moved a code symbol's entry from a
|
|
27309
27313
|
-- scattered leaf: ~19 KB per position-only symbol rewrite on a 1.1 GB store.
|
|
@@ -27315,7 +27319,13 @@ CREATE INDEX IF NOT EXISTS nodes_live_problem_recent ON nodes(label, last_update
|
|
|
27315
27319
|
-- walks nodes_live and reads every live row of the label to test created_at:
|
|
27316
27320
|
-- 56 MB per guard on a 1.1 GB store, to learn there was nothing to do. valid_to
|
|
27317
27321
|
-- is a key column so the planner prefers this over nodes_live (one more term).
|
|
27318
|
-
|
|
27322
|
+
-- last_updated_at rides along for errata.recent on code labels, which names this
|
|
27323
|
+
-- index: the filter runs on index entries, not on every row of the label (79 ms
|
|
27324
|
+
-- \u2192 3 ms for Function on a 1.1 GB store). It costs no extra writes: a close or
|
|
27325
|
+
-- revive already re-keys this index, and mergeNodeIfChanged leaves a symbol's
|
|
27326
|
+
-- last_updated_at alone when only its position moved.
|
|
27327
|
+
DROP INDEX IF EXISTS nodes_live_created;
|
|
27328
|
+
CREATE INDEX IF NOT EXISTS nodes_live_created_v2 ON nodes(label, valid_to, created_at, last_updated_at) WHERE valid_to IS NULL;
|
|
27319
27329
|
-- Community members (the skills pull reads them twice per session boundary):
|
|
27320
27330
|
-- ~15% of semantic nodes carry a localCommunity, and without this every live
|
|
27321
27331
|
-- semantic row was read to find them (168 MB \u2192 18 MB per read).
|
|
@@ -27500,6 +27510,12 @@ function sameSqlValue(a, b) {
|
|
|
27500
27510
|
if (a instanceof Uint8Array && b instanceof Uint8Array) return Buffer.compare(a, b) === 0;
|
|
27501
27511
|
return false;
|
|
27502
27512
|
}
|
|
27513
|
+
var POSITION_ATTRS = ["startByte", "endByte", "startRow"];
|
|
27514
|
+
function attrsJsonWithoutPositions(attrs) {
|
|
27515
|
+
const rest = { ...attrs };
|
|
27516
|
+
for (const k of POSITION_ATTRS) delete rest[k];
|
|
27517
|
+
return JSON.stringify(rest);
|
|
27518
|
+
}
|
|
27503
27519
|
var PRIOR_TAG_MARKER = '"priorTag":true';
|
|
27504
27520
|
var SqliteGraphStore = class {
|
|
27505
27521
|
db;
|
|
@@ -27600,7 +27616,7 @@ var SqliteGraphStore = class {
|
|
|
27600
27616
|
lastUpdatedOf: this.db.prepare("SELECT last_updated_at AS t, attrs_json FROM nodes WHERE id = ?"),
|
|
27601
27617
|
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
27602
27618
|
nodeContent: this.db.prepare(
|
|
27603
|
-
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, attrs_json FROM nodes WHERE id = ?"
|
|
27619
|
+
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, last_updated_at, attrs_json FROM nodes WHERE id = ?"
|
|
27604
27620
|
),
|
|
27605
27621
|
edgeContent: this.db.prepare(
|
|
27606
27622
|
"SELECT confidence, valid_to, attrs_json FROM edges WHERE from_id = ? AND type = ? AND to_id = ?"
|
|
@@ -28013,11 +28029,23 @@ var SqliteGraphStore = class {
|
|
|
28013
28029
|
* rank, community, landmark, surprise, hits, tier and the vector belong to
|
|
28014
28030
|
* the passes that compute them, and a skipped write leaves them as they are
|
|
28015
28031
|
* where a merge would have reset them to the producer's defaults. Returns
|
|
28016
|
-
* whether it wrote.
|
|
28032
|
+
* whether it wrote.
|
|
28033
|
+
*
|
|
28034
|
+
* A live row whose only change is its position keeps its lastUpdatedAt, so
|
|
28035
|
+
* that stamp means "this symbol's content changed": what errata.recent lists
|
|
28036
|
+
* and the fix-candidate ask reads, and what lets nodes_live_created_v2 carry
|
|
28037
|
+
* it without being re-keyed by every edit above a symbol. A closed row is
|
|
28038
|
+
* always stamped: reviveReobserved reopens what this pass stamped. */
|
|
28017
28039
|
mergeNodeIfChanged(node) {
|
|
28018
28040
|
const row = this.stmts.nodeContent.get(node.id);
|
|
28019
|
-
if (row
|
|
28020
|
-
|
|
28041
|
+
if (!row || row.valid_to !== null || row.label !== node.label || row.description !== node.description || row.extraction_confidence !== node.extractionConfidence || row.stability !== node.stability || EXPOSURE_ATTRS.some((k) => node.attrs?.[k] !== void 0)) {
|
|
28042
|
+
this.mergeNode(node);
|
|
28043
|
+
return true;
|
|
28044
|
+
}
|
|
28045
|
+
const attrs = node.attrs ?? {};
|
|
28046
|
+
if (row.attrs_json === JSON.stringify(attrs)) return false;
|
|
28047
|
+
const moved = attrsJsonWithoutPositions(JSON.parse(row.attrs_json)) === attrsJsonWithoutPositions(attrs);
|
|
28048
|
+
this.mergeNode(moved ? { ...node, lastUpdatedAt: row.last_updated_at } : node);
|
|
28021
28049
|
return true;
|
|
28022
28050
|
}
|
|
28023
28051
|
updateNode(id, patch) {
|
|
@@ -28097,8 +28125,8 @@ var SqliteGraphStore = class {
|
|
|
28097
28125
|
stmt2 = this.db.prepare(
|
|
28098
28126
|
// Ordered, not left to the planner: readers take "first row wins" (the
|
|
28099
28127
|
// symbol lexicon's name winner and doc pick), and the order otherwise
|
|
28100
|
-
// followed whichever partial index the planner chose.
|
|
28101
|
-
// serves
|
|
28128
|
+
// followed whichever partial index the planner chose. nodes_live_created_v2
|
|
28129
|
+
// serves it, sorting rowids only within an equal created_at.
|
|
28102
28130
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY created_at, rowid`
|
|
28103
28131
|
);
|
|
28104
28132
|
this.fieldStmts.set(cacheKey, stmt2);
|
|
@@ -29130,10 +29158,12 @@ function crystallize(store2, opts = { ts: 0 }) {
|
|
|
29130
29158
|
const s = support(c) + Math.max(0, sourcesCount(c) - 1);
|
|
29131
29159
|
const f = contradictions;
|
|
29132
29160
|
const confidence = (1 + s) / (2 + s + f);
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29161
|
+
if (c.attrs["confidence"] !== confidence) {
|
|
29162
|
+
store2.updateNode(c.id, {
|
|
29163
|
+
attrs: { ...c.attrs, confidence },
|
|
29164
|
+
lastUpdatedAt: opts.ts
|
|
29165
|
+
});
|
|
29166
|
+
}
|
|
29137
29167
|
const sup = support(c);
|
|
29138
29168
|
let tier = c.memoryTier;
|
|
29139
29169
|
if (sup >= PERSISTENT_SUPPORT && confidence >= PERSISTENT_CONFIDENCE) tier = "persistent";
|
|
@@ -29201,7 +29231,10 @@ function mergeTruthKind(a, b) {
|
|
|
29201
29231
|
function markBoth(store2, a, b, patch, ts) {
|
|
29202
29232
|
for (const n of [a, b]) {
|
|
29203
29233
|
const fresh = store2.getNode(n.id);
|
|
29204
|
-
|
|
29234
|
+
const next = { ...patch };
|
|
29235
|
+
if (fresh.attrs["revisit"] === true && fresh.attrs["revisitReason"] === next["revisitReason"]) delete next["revisitSinceTs"];
|
|
29236
|
+
if (Object.entries(next).every(([k, v]) => fresh.attrs[k] === v)) continue;
|
|
29237
|
+
store2.updateNode(n.id, { attrs: { ...fresh.attrs, ...next }, lastUpdatedAt: ts });
|
|
29205
29238
|
}
|
|
29206
29239
|
}
|
|
29207
29240
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
8c2ed59e34694f0fbec381b67731aae53d87a289c92222a279d038f65e3bcad0 .codex-plugin/plugin.json
|
|
2
2
|
a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
|
|
3
3
|
fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
|
|
4
4
|
73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js
|