@inerrata-corporation/errata 2.0.22-dev.4020 → 2.0.22-dev.4054

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.
@@ -1235,10 +1235,10 @@ function mergeDefs(...defs) {
1235
1235
  function cloneDef(schema) {
1236
1236
  return mergeDefs(schema._zod.def);
1237
1237
  }
1238
- function getElementAtPath(obj, path) {
1239
- if (!path)
1238
+ function getElementAtPath(obj, path2) {
1239
+ if (!path2)
1240
1240
  return obj;
1241
- return path.reduce((acc, key) => acc?.[key], obj);
1241
+ return path2.reduce((acc, key) => acc?.[key], obj);
1242
1242
  }
1243
1243
  function promiseAllObject(promisesObj) {
1244
1244
  const keys = Object.keys(promisesObj);
@@ -1621,11 +1621,11 @@ function aborted(x, startIndex = 0) {
1621
1621
  }
1622
1622
  return false;
1623
1623
  }
1624
- function prefixIssues(path, issues) {
1624
+ function prefixIssues(path2, issues) {
1625
1625
  return issues.map((iss) => {
1626
1626
  var _a2;
1627
1627
  (_a2 = iss).path ?? (_a2.path = []);
1628
- iss.path.unshift(path);
1628
+ iss.path.unshift(path2);
1629
1629
  return iss;
1630
1630
  });
1631
1631
  }
@@ -1808,7 +1808,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
1808
1808
  }
1809
1809
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
1810
1810
  const result = { errors: [] };
1811
- const processError = (error49, path = []) => {
1811
+ const processError = (error49, path2 = []) => {
1812
1812
  var _a2, _b;
1813
1813
  for (const issue2 of error49.issues) {
1814
1814
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -1818,7 +1818,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1818
1818
  } else if (issue2.code === "invalid_element") {
1819
1819
  processError({ issues: issue2.issues }, issue2.path);
1820
1820
  } else {
1821
- const fullpath = [...path, ...issue2.path];
1821
+ const fullpath = [...path2, ...issue2.path];
1822
1822
  if (fullpath.length === 0) {
1823
1823
  result.errors.push(mapper(issue2));
1824
1824
  continue;
@@ -1850,8 +1850,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1850
1850
  }
1851
1851
  function toDotPath(_path) {
1852
1852
  const segs = [];
1853
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1854
- for (const seg of path) {
1853
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1854
+ for (const seg of path2) {
1855
1855
  if (typeof seg === "number")
1856
1856
  segs.push(`[${seg}]`);
1857
1857
  else if (typeof seg === "symbol")
@@ -13828,13 +13828,13 @@ function resolveRef(ref, ctx) {
13828
13828
  if (!ref.startsWith("#")) {
13829
13829
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
13830
13830
  }
13831
- const path = ref.slice(1).split("/").filter(Boolean);
13832
- if (path.length === 0) {
13831
+ const path2 = ref.slice(1).split("/").filter(Boolean);
13832
+ if (path2.length === 0) {
13833
13833
  return ctx.rootSchema;
13834
13834
  }
13835
13835
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
13836
- if (path[0] === defsKey) {
13837
- const key = path[1];
13836
+ if (path2[0] === defsKey) {
13837
+ const key = path2[1];
13838
13838
  if (!key || !ctx.defs[key]) {
13839
13839
  throw new Error(`Reference not found: ${ref}`);
13840
13840
  }
@@ -14773,13 +14773,13 @@ function loadNodeSqlite() {
14773
14773
  }
14774
14774
  }
14775
14775
  var DatabaseSync = loadNodeSqlite().DatabaseSync;
14776
- function openDatabase(path, opts) {
14777
- const db = opts ? new DatabaseSync(path, opts) : new DatabaseSync(path);
14776
+ function openDatabase(path2, opts) {
14777
+ const db = opts ? new DatabaseSync(path2, opts) : new DatabaseSync(path2);
14778
14778
  try {
14779
14779
  db.exec("PRAGMA foreign_keys = ON");
14780
14780
  } catch {
14781
14781
  }
14782
- if (path !== ":memory:" && !opts?.readOnly) {
14782
+ if (path2 !== ":memory:" && !opts?.readOnly) {
14783
14783
  try {
14784
14784
  db.exec("PRAGMA journal_mode = WAL");
14785
14785
  db.exec("PRAGMA synchronous = NORMAL");
@@ -15093,6 +15093,38 @@ function installHistoryAttrSlim(db) {
15093
15093
  db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(HISTORY_ATTR_SLIM_KEY, "done");
15094
15094
  }
15095
15095
 
15096
+ // ../../packages/local-graph/src/text-index.ts
15097
+ var TEXT_INDEX_KEY = "text-index-trigram-1";
15098
+ var TEXT_INDEX_MIN_TERM = 3;
15099
+ function installTextIndex(db) {
15100
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(TEXT_INDEX_KEY)) return;
15101
+ try {
15102
+ db.exec(`CREATE VIRTUAL TABLE temp.fts5_probe USING fts5(x, tokenize='trigram'); DROP TABLE temp.fts5_probe`);
15103
+ } catch {
15104
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(TEXT_INDEX_KEY, "unavailable");
15105
+ return;
15106
+ }
15107
+ db.transaction(() => {
15108
+ db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS nodes_text
15109
+ USING fts5(description, content='nodes', content_rowid='rowid', tokenize='trigram')`);
15110
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_insert AFTER INSERT ON nodes WHEN NEW.valid_to IS NULL
15111
+ BEGIN INSERT INTO nodes_text(rowid, description) VALUES (NEW.rowid, NEW.description); END;`);
15112
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_update_out AFTER UPDATE OF description, valid_to ON nodes
15113
+ WHEN OLD.valid_to IS NULL
15114
+ BEGIN INSERT INTO nodes_text(nodes_text, rowid, description) VALUES ('delete', OLD.rowid, OLD.description); END;`);
15115
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_update_in AFTER UPDATE OF description, valid_to ON nodes
15116
+ WHEN NEW.valid_to IS NULL
15117
+ BEGIN INSERT INTO nodes_text(rowid, description) VALUES (NEW.rowid, NEW.description); END;`);
15118
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_delete AFTER DELETE ON nodes WHEN OLD.valid_to IS NULL
15119
+ BEGIN INSERT INTO nodes_text(nodes_text, rowid, description) VALUES ('delete', OLD.rowid, OLD.description); END;`);
15120
+ db.exec(`INSERT INTO nodes_text(rowid, description) SELECT rowid, description FROM nodes WHERE valid_to IS NULL`);
15121
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(TEXT_INDEX_KEY, "installed");
15122
+ });
15123
+ }
15124
+ function textIndexReady(db) {
15125
+ return db.prepare("SELECT value FROM store_meta WHERE key = ?").get(TEXT_INDEX_KEY)?.["value"] === "installed";
15126
+ }
15127
+
15096
15128
  // ../../packages/math/src/relevance.ts
15097
15129
  function pageRankScale(ranks) {
15098
15130
  const positive = [...ranks].filter((r) => Number.isFinite(r) && r > 0).sort((a, b) => a - b);
@@ -15103,6 +15135,140 @@ function pageRankScale(ranks) {
15103
15135
  var DEMAND_HOT = Math.log1p(10);
15104
15136
  var DEMAND_WARM = Math.log1p(5);
15105
15137
 
15138
+ // ../../packages/local-graph/src/node-select.ts
15139
+ var EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
15140
+ var KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
15141
+ var COLUMNS = /* @__PURE__ */ new Set([
15142
+ "created_at",
15143
+ "last_updated_at",
15144
+ "page_rank",
15145
+ "created_at_seq",
15146
+ "last_reinforced_at_seq",
15147
+ "cumulative_hits",
15148
+ "extraction_confidence"
15149
+ ]);
15150
+ function path(key) {
15151
+ if (!KEY.test(key)) throw new Error(`selectNodes: bad attr key ${key}`);
15152
+ return `'$.${key}'`;
15153
+ }
15154
+ function column(c) {
15155
+ if (!COLUMNS.has(c)) throw new Error(`selectNodes: bad column ${c}`);
15156
+ return c;
15157
+ }
15158
+ function compileNodeWhere(q) {
15159
+ if (q.labels.length === 0) throw new Error("selectNodes: no labels");
15160
+ const params = [...q.labels];
15161
+ const conds = [`label IN (${q.labels.map(() => "?").join(", ")})`];
15162
+ if (!q.includeClosed) conds.push("valid_to IS NULL");
15163
+ for (const w of q.where ?? []) {
15164
+ if ("embedding" in w) {
15165
+ conds.push(`${EMBEDDING_DIM_SQL} ${w.embedding === "present" ? ">" : "="} 0`);
15166
+ } else if ("idPrefix" in w) {
15167
+ conds.push("substr(id, 1, ?) = ?");
15168
+ params.push(w.idPrefix.length, w.idPrefix);
15169
+ } else if ("descriptionIn" in w) {
15170
+ if (w.descriptionIn.length === 0) conds.push("0");
15171
+ else {
15172
+ conds.push(`description IN (${w.descriptionIn.map(() => "?").join(", ")})`);
15173
+ params.push(...w.descriptionIn);
15174
+ }
15175
+ } else if ("column" in w) {
15176
+ const c = column(w.column);
15177
+ for (const [op, sym] of [["gte", ">="], ["gt", ">"], ["lte", "<="], ["lt", "<"]]) {
15178
+ const v = w[op];
15179
+ if (v !== void 0) {
15180
+ conds.push(`${c} ${sym} ?`);
15181
+ params.push(v);
15182
+ }
15183
+ }
15184
+ } else {
15185
+ const p = path(w.attr);
15186
+ if ("absent" in w) conds.push(`json_type(attrs_json, ${p}) IS NULL`);
15187
+ else if ("present" in w) conds.push(`json_type(attrs_json, ${p}) IS NOT NULL`);
15188
+ else if ("nullish" in w) conds.push(`json_extract(attrs_json, ${p}) IS NULL`);
15189
+ else if ("notNullish" in w) conds.push(`json_extract(attrs_json, ${p}) IS NOT NULL`);
15190
+ else if ("eq" in w || "ne" in w) {
15191
+ const v = "eq" in w ? w.eq : w.ne;
15192
+ const neg = "ne" in w;
15193
+ if (typeof v === "boolean") {
15194
+ conds.push(`json_type(attrs_json, ${p}) ${neg ? "IS NOT" : "="} ?`);
15195
+ params.push(v ? "true" : "false");
15196
+ } else {
15197
+ conds.push(neg ? `json_extract(attrs_json, ${p}) IS NOT ?` : `json_extract(attrs_json, ${p}) = ?`);
15198
+ params.push(v);
15199
+ }
15200
+ }
15201
+ }
15202
+ }
15203
+ return { where: conds.join(" AND "), params };
15204
+ }
15205
+ function attrValueSql(p) {
15206
+ return `CASE json_type(attrs_json, ${p}) WHEN 'integer' THEN CAST(json_extract(attrs_json, ${p}) AS REAL) ELSE json_extract(attrs_json, ${p}) END`;
15207
+ }
15208
+ function compileNodeSelect(q) {
15209
+ const { where, params } = compileNodeWhere(q);
15210
+ const attrs = q.attrs ?? [];
15211
+ const attrCols = attrs.map((k, i) => `, ${attrValueSql(path(k))} AS a${i}, json_type(attrs_json, ${path(k)}) AS t${i}`).join("");
15212
+ let order;
15213
+ if (q.orderBy && "column" in q.orderBy) {
15214
+ order = `${column(q.orderBy.column)} ${q.orderBy.desc ? "DESC" : "ASC"}, rowid`;
15215
+ } else if (q.orderBy) {
15216
+ const p = path(q.orderBy.attr);
15217
+ order = `json_extract(attrs_json, ${p}) IS NULL, json_extract(attrs_json, ${p}) ${q.orderBy.desc ? "DESC" : "ASC"}, rowid`;
15218
+ } else if (q.labels.length > 1) {
15219
+ order = `CASE label ${q.labels.map((_, i) => `WHEN ? THEN ${i}`).join(" ")} END, rowid`;
15220
+ } else {
15221
+ order = "rowid";
15222
+ }
15223
+ const orderParams = !q.orderBy && q.labels.length > 1 ? [...q.labels] : [];
15224
+ const limit = q.limit !== void 0 ? ` LIMIT ${Math.max(0, Math.floor(q.limit))}` : "";
15225
+ const sql = `SELECT id, label, description, created_at, last_updated_at, page_rank, cumulative_hits, extraction_confidence, extraction_source, community, created_at_seq, last_reinforced_at_seq, valid_to, ${EMBEDDING_DIM_SQL} AS embedding_dim${q.withEmbedding ? ", embedding_blob, embedding_json" : ""}${attrCols} FROM nodes WHERE ${where} ORDER BY ${order}${limit}`;
15226
+ return { sql, params: [...params, ...orderParams] };
15227
+ }
15228
+ function decodeAttr(value, type) {
15229
+ switch (type) {
15230
+ case null:
15231
+ case void 0:
15232
+ return void 0;
15233
+ case "true":
15234
+ return true;
15235
+ case "false":
15236
+ return false;
15237
+ case "null":
15238
+ return null;
15239
+ case "object":
15240
+ case "array":
15241
+ return typeof value === "string" ? JSON.parse(value) : value;
15242
+ default:
15243
+ return value;
15244
+ }
15245
+ }
15246
+ function decodeSelectedRow(r, attrs, decodeVector) {
15247
+ const out = {};
15248
+ attrs.forEach((k, i) => {
15249
+ const v = decodeAttr(r[`a${i}`], r[`t${i}`]);
15250
+ if (v !== void 0) out[k] = v;
15251
+ });
15252
+ return {
15253
+ id: r["id"],
15254
+ label: r["label"],
15255
+ description: r["description"] ?? "",
15256
+ createdAt: r["created_at"],
15257
+ lastUpdatedAt: r["last_updated_at"],
15258
+ pageRank: r["page_rank"],
15259
+ cumulativeHits: r["cumulative_hits"],
15260
+ extractionConfidence: r["extraction_confidence"],
15261
+ extractionSource: r["extraction_source"],
15262
+ community: r["community"] ?? null,
15263
+ ...r["created_at_seq"] != null ? { createdAtSeq: r["created_at_seq"] } : {},
15264
+ ...r["last_reinforced_at_seq"] != null ? { lastReinforcedAtSeq: r["last_reinforced_at_seq"] } : {},
15265
+ validTo: r["valid_to"] ?? null,
15266
+ embeddingDim: Number(r["embedding_dim"] ?? 0),
15267
+ ...decodeVector ? { embedding: decodeVector(r["embedding_blob"], r["embedding_json"] ?? "[]") } : {},
15268
+ attrs: out
15269
+ };
15270
+ }
15271
+
15106
15272
  // ../../packages/local-graph/src/store.ts
15107
15273
  var PAGE_RANK_SCALE_KEY = "pageRankScale.p95.v1";
15108
15274
  var TEXT_SEARCH_COLUMNS = `id, label, description, page_rank,
@@ -15291,6 +15457,11 @@ CREATE INDEX IF NOT EXISTS nodes_cloud_node_id ON nodes(json_extract(attrs_json,
15291
15457
  -- Solution's and Problem's attrs per call. Not partial: the Problem pull reads
15292
15458
  -- closed versions too.
15293
15459
  CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_json, '$.enrichmentPending'));
15460
+ -- Revisit flags, any label, any version: listNeedsRevisit's as-of read runs on
15461
+ -- every context render and otherwise json-checks every row (10.3 s on a 324k-row
15462
+ -- store, to return zero flags). The predicate must stay textually identical to
15463
+ -- nodesAsOfWhereTrue's or the planner will not use it.
15464
+ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_type(attrs_json, '$.revisit') = 'true';
15294
15465
  `;
15295
15466
  function encodeEmbedding(emb) {
15296
15467
  if (!emb || emb.length === 0) return null;
@@ -15391,6 +15562,7 @@ var SqliteGraphStore = class {
15391
15562
  installEditPlaceholderRetirement(this.db);
15392
15563
  installCloudAttrCompaction(this.db);
15393
15564
  installHistoryAttrSlim(this.db);
15565
+ installTextIndex(this.db);
15394
15566
  if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
15395
15567
  this.db.transaction(() => {
15396
15568
  this.repairSessionAliases();
@@ -15768,8 +15940,8 @@ var SqliteGraphStore = class {
15768
15940
  setLandmark(id, isLandmark) {
15769
15941
  this.stmts.setLandmark.run({ id, v: isLandmark ? 1 : 0 });
15770
15942
  }
15771
- setLocalCommunity(id, community, column) {
15772
- this.stmts.setLocalCommunity.run({ id, v: community, col: column ? 1 : 0 });
15943
+ setLocalCommunity(id, community, column2) {
15944
+ this.stmts.setLocalCommunity.run({ id, v: community, col: column2 ? 1 : 0 });
15773
15945
  }
15774
15946
  fieldStmts = /* @__PURE__ */ new Map();
15775
15947
  findNodeFieldsByLabel(label, attrKeys) {
@@ -15777,7 +15949,7 @@ var SqliteGraphStore = class {
15777
15949
  const cacheKey = attrKeys.join(",");
15778
15950
  let stmt = this.fieldStmts.get(cacheKey);
15779
15951
  if (!stmt) {
15780
- const cols = attrKeys.map((k, i) => `, json_extract(attrs_json, '$.${k}') AS a${i}`).join("");
15952
+ const cols = attrKeys.map((k, i) => `, ${attrValueSql(`'$.${k}'`)} AS a${i}, json_type(attrs_json, '$.${k}') AS t${i}`).join("");
15781
15953
  stmt = this.db.prepare(
15782
15954
  `SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL`
15783
15955
  );
@@ -15786,8 +15958,8 @@ var SqliteGraphStore = class {
15786
15958
  return stmt.all(label).map((r) => {
15787
15959
  const attrs = {};
15788
15960
  attrKeys.forEach((k, i) => {
15789
- const v = r[`a${i}`];
15790
- if (v !== null && v !== void 0) attrs[k] = v;
15961
+ const v = decodeAttr(r[`a${i}`], r[`t${i}`]);
15962
+ if (v !== void 0) attrs[k] = v;
15791
15963
  });
15792
15964
  return {
15793
15965
  id: r["id"],
@@ -15798,6 +15970,15 @@ var SqliteGraphStore = class {
15798
15970
  };
15799
15971
  });
15800
15972
  }
15973
+ selectNodes(q) {
15974
+ const { sql, params } = compileNodeSelect(q);
15975
+ const rows = this.db.prepare(sql).all(...params);
15976
+ return rows.map((r) => decodeSelectedRow(r, q.attrs ?? [], q.withEmbedding ? decodeEmbedding : void 0));
15977
+ }
15978
+ countNodes(q) {
15979
+ const { where, params } = compileNodeWhere(q);
15980
+ return Number(this.db.prepare(`SELECT COUNT(*) AS n FROM nodes WHERE ${where}`).get(...params).n);
15981
+ }
15801
15982
  setCommunity(id, community) {
15802
15983
  this.stmts.setCommunity.run({ id, v: community });
15803
15984
  }
@@ -16045,6 +16226,20 @@ var SqliteGraphStore = class {
16045
16226
  }
16046
16227
  searchTextCandidates(terms) {
16047
16228
  if (terms.length === 0) return [];
16229
+ const indexed = terms.filter((t) => t.length >= TEXT_INDEX_MIN_TERM);
16230
+ if (indexed.length > 0 && textIndexReady(this.db)) {
16231
+ const short = terms.filter((t) => t.length < TEXT_INDEX_MIN_TERM).map((t) => t.toLowerCase());
16232
+ const rows2 = this.db.prepare(`WITH hits AS MATERIALIZED (
16233
+ SELECT t.rowid AS rid, COUNT(*) AS matched FROM json_each(:terms) q, nodes_text t
16234
+ WHERE t.description LIKE '%' || q.value || '%' GROUP BY t.rowid
16235
+ ) SELECT ${TEXT_SEARCH_COLUMNS}, hits.matched FROM hits JOIN nodes ON nodes.rowid = hits.rid
16236
+ WHERE nodes.valid_to IS NULL ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(indexed) });
16237
+ return rows2.map((row) => {
16238
+ const text = row.description.toLowerCase();
16239
+ const extra = short.filter((t) => text.includes(t)).length;
16240
+ return { node: textSearchNode(row), matched: row.matched + extra };
16241
+ });
16242
+ }
16048
16243
  const rows = this.db.prepare(`WITH matches AS MATERIALIZED (
16049
16244
  SELECT n.id, COUNT(*) AS matched FROM nodes n INDEXED BY nodes_live_description, json_each(:terms) t
16050
16245
  WHERE n.valid_to IS NULL AND n.description LIKE '%' || t.value || '%'
@@ -16053,6 +16248,18 @@ var SqliteGraphStore = class {
16053
16248
  JOIN matches USING (id) ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(terms) });
16054
16249
  return rows.map((row) => ({ node: textSearchNode(row), matched: row.matched }));
16055
16250
  }
16251
+ commentAnchors(commentIds) {
16252
+ const out = /* @__PURE__ */ new Map();
16253
+ if (commentIds.length === 0) return out;
16254
+ const rows = this.db.prepare(`WITH a AS MATERIALIZED (
16255
+ SELECT q.value AS cid, COALESCE(
16256
+ (SELECT to_id FROM edges WHERE from_id = q.value AND type IN ('EXPLAINS', 'ANNOTATES') AND valid_to IS NULL LIMIT 1),
16257
+ (SELECT from_id FROM edges WHERE to_id = q.value AND type = 'DOCUMENTED_BY' AND valid_to IS NULL LIMIT 1)
16258
+ ) AS aid FROM json_each(:ids) q
16259
+ ) SELECT a.cid AS cid, ${TEXT_SEARCH_COLUMNS} FROM a JOIN nodes ON nodes.id = a.aid AND nodes.valid_to IS NULL`).all({ ids: JSON.stringify(commentIds) });
16260
+ for (const row of rows) out.set(row.cid, textSearchNode(row));
16261
+ return out;
16262
+ }
16056
16263
  getTextSearchNode(id) {
16057
16264
  const row = this.db.prepare(`SELECT ${TEXT_SEARCH_COLUMNS} FROM nodes WHERE id = ? AND valid_to IS NULL`).get(id);
16058
16265
  return row ? textSearchNode(row) : null;
@@ -16448,7 +16655,8 @@ var SqliteGraphStore = class {
16448
16655
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(attr)) throw new Error(`nodesAsOfWhereTrue: bad attr ${JSON.stringify(attr)}`);
16449
16656
  const rows = this.db.prepare(
16450
16657
  `SELECT * FROM nodes WHERE valid_from <= :t AND (valid_to IS NULL OR valid_to > :t)
16451
- AND json_type(attrs_json, '$.${attr}') = 'true'`
16658
+ AND json_type(attrs_json, '$.${attr}') = 'true'
16659
+ ORDER BY rowid`
16452
16660
  ).all({ t });
16453
16661
  return rows.map(rowToNode);
16454
16662
  }
@@ -17409,11 +17617,11 @@ function generalizeSymbols(text, lexicon, level = 1, fileLexicon) {
17409
17617
 
17410
17618
  // src/generalize-worker.ts
17411
17619
  var stores = /* @__PURE__ */ new Map();
17412
- function storeAt(path) {
17413
- let s = stores.get(path);
17620
+ function storeAt(path2) {
17621
+ let s = stores.get(path2);
17414
17622
  if (!s) {
17415
- s = openGraphStore({ path });
17416
- stores.set(path, s);
17623
+ s = openGraphStore({ path: path2 });
17624
+ stores.set(path2, s);
17417
17625
  }
17418
17626
  return s;
17419
17627
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.22-dev.4020",
3
+ "version": "2.0.22-dev.4054",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {