@inerrata-corporation/errata 2.0.23-dev.4734 → 2.0.23-dev.4796

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.
@@ -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
- CREATE INDEX IF NOT EXISTS nodes_live_count ON nodes(valid_to);
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
- CREATE INDEX IF NOT EXISTS nodes_live_created ON nodes(label, valid_to, created_at) WHERE valid_to IS NULL;
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 && 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) && row.attrs_json === JSON.stringify(node.attrs ?? {})) return false;
18651
- this.mergeNode(node);
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. nodes_live_created
18732
- // serves this order without a sort.
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);