@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.
@@ -1114,10 +1114,10 @@ function mergeDefs(...defs) {
1114
1114
  function cloneDef(schema) {
1115
1115
  return mergeDefs(schema._zod.def);
1116
1116
  }
1117
- function getElementAtPath(obj, path) {
1118
- if (!path)
1117
+ function getElementAtPath(obj, path2) {
1118
+ if (!path2)
1119
1119
  return obj;
1120
- return path.reduce((acc, key) => acc?.[key], obj);
1120
+ return path2.reduce((acc, key) => acc?.[key], obj);
1121
1121
  }
1122
1122
  function promiseAllObject(promisesObj) {
1123
1123
  const keys = Object.keys(promisesObj);
@@ -1429,11 +1429,11 @@ function aborted(x, startIndex = 0) {
1429
1429
  }
1430
1430
  return false;
1431
1431
  }
1432
- function prefixIssues(path, issues) {
1432
+ function prefixIssues(path2, issues) {
1433
1433
  return issues.map((iss) => {
1434
1434
  var _a2;
1435
1435
  (_a2 = iss).path ?? (_a2.path = []);
1436
- iss.path.unshift(path);
1436
+ iss.path.unshift(path2);
1437
1437
  return iss;
1438
1438
  });
1439
1439
  }
@@ -1675,7 +1675,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
1675
1675
  }
1676
1676
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
1677
1677
  const result = { errors: [] };
1678
- const processError = (error49, path = []) => {
1678
+ const processError = (error49, path2 = []) => {
1679
1679
  var _a2, _b;
1680
1680
  for (const issue2 of error49.issues) {
1681
1681
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -1685,7 +1685,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1685
1685
  } else if (issue2.code === "invalid_element") {
1686
1686
  processError({ issues: issue2.issues }, issue2.path);
1687
1687
  } else {
1688
- const fullpath = [...path, ...issue2.path];
1688
+ const fullpath = [...path2, ...issue2.path];
1689
1689
  if (fullpath.length === 0) {
1690
1690
  result.errors.push(mapper(issue2));
1691
1691
  continue;
@@ -1717,8 +1717,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1717
1717
  }
1718
1718
  function toDotPath(_path) {
1719
1719
  const segs = [];
1720
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1721
- for (const seg of path) {
1720
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1721
+ for (const seg of path2) {
1722
1722
  if (typeof seg === "number")
1723
1723
  segs.push(`[${seg}]`);
1724
1724
  else if (typeof seg === "symbol")
@@ -14412,13 +14412,13 @@ function resolveRef(ref, ctx) {
14412
14412
  if (!ref.startsWith("#")) {
14413
14413
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14414
14414
  }
14415
- const path = ref.slice(1).split("/").filter(Boolean);
14416
- if (path.length === 0) {
14415
+ const path2 = ref.slice(1).split("/").filter(Boolean);
14416
+ if (path2.length === 0) {
14417
14417
  return ctx.rootSchema;
14418
14418
  }
14419
14419
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14420
- if (path[0] === defsKey) {
14421
- const key = path[1];
14420
+ if (path2[0] === defsKey) {
14421
+ const key = path2[1];
14422
14422
  if (!key || !ctx.defs[key]) {
14423
14423
  throw new Error(`Reference not found: ${ref}`);
14424
14424
  }
@@ -15737,8 +15737,8 @@ function normalizeSymbolPath(relPath) {
15737
15737
  return relPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\.\//, "").replace(/^\//, "");
15738
15738
  }
15739
15739
  function projectSymbolId(projectSalt, projectId, relPath, qname, kind) {
15740
- const path = normalizeSymbolPath(relPath);
15741
- return `sym_${createHmac("sha256", projectSalt).update(`${projectId}:${path}:${qname}:${kind}`).digest("hex").slice(0, 24)}`;
15740
+ const path2 = normalizeSymbolPath(relPath);
15741
+ return `sym_${createHmac("sha256", projectSalt).update(`${projectId}:${path2}:${qname}:${kind}`).digest("hex").slice(0, 24)}`;
15742
15742
  }
15743
15743
  var init_project_symbol = __esm({
15744
15744
  "../../packages/shared/src/project-symbol.ts"() {
@@ -15995,13 +15995,13 @@ function loadNodeSqlite() {
15995
15995
  process.emitWarning = original;
15996
15996
  }
15997
15997
  }
15998
- function openDatabase(path, opts) {
15999
- const db = opts ? new DatabaseSync(path, opts) : new DatabaseSync(path);
15998
+ function openDatabase(path2, opts) {
15999
+ const db = opts ? new DatabaseSync(path2, opts) : new DatabaseSync(path2);
16000
16000
  try {
16001
16001
  db.exec("PRAGMA foreign_keys = ON");
16002
16002
  } catch {
16003
16003
  }
16004
- if (path !== ":memory:" && !opts?.readOnly) {
16004
+ if (path2 !== ":memory:" && !opts?.readOnly) {
16005
16005
  try {
16006
16006
  db.exec("PRAGMA journal_mode = WAL");
16007
16007
  db.exec("PRAGMA synchronous = NORMAL");
@@ -16508,6 +16508,38 @@ function installHistoryAttrSlim(db) {
16508
16508
  db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(HISTORY_ATTR_SLIM_KEY, "done");
16509
16509
  }
16510
16510
 
16511
+ // ../../packages/local-graph/src/text-index.ts
16512
+ var TEXT_INDEX_KEY = "text-index-trigram-1";
16513
+ var TEXT_INDEX_MIN_TERM = 3;
16514
+ function installTextIndex(db) {
16515
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(TEXT_INDEX_KEY)) return;
16516
+ try {
16517
+ db.exec(`CREATE VIRTUAL TABLE temp.fts5_probe USING fts5(x, tokenize='trigram'); DROP TABLE temp.fts5_probe`);
16518
+ } catch {
16519
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(TEXT_INDEX_KEY, "unavailable");
16520
+ return;
16521
+ }
16522
+ db.transaction(() => {
16523
+ db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS nodes_text
16524
+ USING fts5(description, content='nodes', content_rowid='rowid', tokenize='trigram')`);
16525
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_insert AFTER INSERT ON nodes WHEN NEW.valid_to IS NULL
16526
+ BEGIN INSERT INTO nodes_text(rowid, description) VALUES (NEW.rowid, NEW.description); END;`);
16527
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_update_out AFTER UPDATE OF description, valid_to ON nodes
16528
+ WHEN OLD.valid_to IS NULL
16529
+ BEGIN INSERT INTO nodes_text(nodes_text, rowid, description) VALUES ('delete', OLD.rowid, OLD.description); END;`);
16530
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_update_in AFTER UPDATE OF description, valid_to ON nodes
16531
+ WHEN NEW.valid_to IS NULL
16532
+ BEGIN INSERT INTO nodes_text(rowid, description) VALUES (NEW.rowid, NEW.description); END;`);
16533
+ db.exec(`CREATE TRIGGER IF NOT EXISTS nodes_text_delete AFTER DELETE ON nodes WHEN OLD.valid_to IS NULL
16534
+ BEGIN INSERT INTO nodes_text(nodes_text, rowid, description) VALUES ('delete', OLD.rowid, OLD.description); END;`);
16535
+ db.exec(`INSERT INTO nodes_text(rowid, description) SELECT rowid, description FROM nodes WHERE valid_to IS NULL`);
16536
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(TEXT_INDEX_KEY, "installed");
16537
+ });
16538
+ }
16539
+ function textIndexReady(db) {
16540
+ return db.prepare("SELECT value FROM store_meta WHERE key = ?").get(TEXT_INDEX_KEY)?.["value"] === "installed";
16541
+ }
16542
+
16511
16543
  // ../../packages/math/src/constants.ts
16512
16544
  var NEMORI_DEDUP_COSINE = 0.88;
16513
16545
 
@@ -16695,6 +16727,140 @@ function detectCommunitiesLeiden(input, opts = {}) {
16695
16727
  var DEMAND_HOT = Math.log1p(10);
16696
16728
  var DEMAND_WARM = Math.log1p(5);
16697
16729
 
16730
+ // ../../packages/local-graph/src/node-select.ts
16731
+ var EMBEDDING_DIM_SQL = "(CASE WHEN length(embedding_blob) >= 4 THEN length(embedding_blob) / 4 ELSE COALESCE(json_array_length(embedding_json), 0) END)";
16732
+ var KEY = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
16733
+ var COLUMNS = /* @__PURE__ */ new Set([
16734
+ "created_at",
16735
+ "last_updated_at",
16736
+ "page_rank",
16737
+ "created_at_seq",
16738
+ "last_reinforced_at_seq",
16739
+ "cumulative_hits",
16740
+ "extraction_confidence"
16741
+ ]);
16742
+ function path(key) {
16743
+ if (!KEY.test(key)) throw new Error(`selectNodes: bad attr key ${key}`);
16744
+ return `'$.${key}'`;
16745
+ }
16746
+ function column(c) {
16747
+ if (!COLUMNS.has(c)) throw new Error(`selectNodes: bad column ${c}`);
16748
+ return c;
16749
+ }
16750
+ function compileNodeWhere(q) {
16751
+ if (q.labels.length === 0) throw new Error("selectNodes: no labels");
16752
+ const params = [...q.labels];
16753
+ const conds = [`label IN (${q.labels.map(() => "?").join(", ")})`];
16754
+ if (!q.includeClosed) conds.push("valid_to IS NULL");
16755
+ for (const w of q.where ?? []) {
16756
+ if ("embedding" in w) {
16757
+ conds.push(`${EMBEDDING_DIM_SQL} ${w.embedding === "present" ? ">" : "="} 0`);
16758
+ } else if ("idPrefix" in w) {
16759
+ conds.push("substr(id, 1, ?) = ?");
16760
+ params.push(w.idPrefix.length, w.idPrefix);
16761
+ } else if ("descriptionIn" in w) {
16762
+ if (w.descriptionIn.length === 0) conds.push("0");
16763
+ else {
16764
+ conds.push(`description IN (${w.descriptionIn.map(() => "?").join(", ")})`);
16765
+ params.push(...w.descriptionIn);
16766
+ }
16767
+ } else if ("column" in w) {
16768
+ const c = column(w.column);
16769
+ for (const [op, sym] of [["gte", ">="], ["gt", ">"], ["lte", "<="], ["lt", "<"]]) {
16770
+ const v = w[op];
16771
+ if (v !== void 0) {
16772
+ conds.push(`${c} ${sym} ?`);
16773
+ params.push(v);
16774
+ }
16775
+ }
16776
+ } else {
16777
+ const p = path(w.attr);
16778
+ if ("absent" in w) conds.push(`json_type(attrs_json, ${p}) IS NULL`);
16779
+ else if ("present" in w) conds.push(`json_type(attrs_json, ${p}) IS NOT NULL`);
16780
+ else if ("nullish" in w) conds.push(`json_extract(attrs_json, ${p}) IS NULL`);
16781
+ else if ("notNullish" in w) conds.push(`json_extract(attrs_json, ${p}) IS NOT NULL`);
16782
+ else if ("eq" in w || "ne" in w) {
16783
+ const v = "eq" in w ? w.eq : w.ne;
16784
+ const neg = "ne" in w;
16785
+ if (typeof v === "boolean") {
16786
+ conds.push(`json_type(attrs_json, ${p}) ${neg ? "IS NOT" : "="} ?`);
16787
+ params.push(v ? "true" : "false");
16788
+ } else {
16789
+ conds.push(neg ? `json_extract(attrs_json, ${p}) IS NOT ?` : `json_extract(attrs_json, ${p}) = ?`);
16790
+ params.push(v);
16791
+ }
16792
+ }
16793
+ }
16794
+ }
16795
+ return { where: conds.join(" AND "), params };
16796
+ }
16797
+ function attrValueSql(p) {
16798
+ 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`;
16799
+ }
16800
+ function compileNodeSelect(q) {
16801
+ const { where, params } = compileNodeWhere(q);
16802
+ const attrs = q.attrs ?? [];
16803
+ const attrCols = attrs.map((k, i) => `, ${attrValueSql(path(k))} AS a${i}, json_type(attrs_json, ${path(k)}) AS t${i}`).join("");
16804
+ let order;
16805
+ if (q.orderBy && "column" in q.orderBy) {
16806
+ order = `${column(q.orderBy.column)} ${q.orderBy.desc ? "DESC" : "ASC"}, rowid`;
16807
+ } else if (q.orderBy) {
16808
+ const p = path(q.orderBy.attr);
16809
+ order = `json_extract(attrs_json, ${p}) IS NULL, json_extract(attrs_json, ${p}) ${q.orderBy.desc ? "DESC" : "ASC"}, rowid`;
16810
+ } else if (q.labels.length > 1) {
16811
+ order = `CASE label ${q.labels.map((_, i) => `WHEN ? THEN ${i}`).join(" ")} END, rowid`;
16812
+ } else {
16813
+ order = "rowid";
16814
+ }
16815
+ const orderParams = !q.orderBy && q.labels.length > 1 ? [...q.labels] : [];
16816
+ const limit = q.limit !== void 0 ? ` LIMIT ${Math.max(0, Math.floor(q.limit))}` : "";
16817
+ 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}`;
16818
+ return { sql, params: [...params, ...orderParams] };
16819
+ }
16820
+ function decodeAttr(value, type) {
16821
+ switch (type) {
16822
+ case null:
16823
+ case void 0:
16824
+ return void 0;
16825
+ case "true":
16826
+ return true;
16827
+ case "false":
16828
+ return false;
16829
+ case "null":
16830
+ return null;
16831
+ case "object":
16832
+ case "array":
16833
+ return typeof value === "string" ? JSON.parse(value) : value;
16834
+ default:
16835
+ return value;
16836
+ }
16837
+ }
16838
+ function decodeSelectedRow(r, attrs, decodeVector) {
16839
+ const out = {};
16840
+ attrs.forEach((k, i) => {
16841
+ const v = decodeAttr(r[`a${i}`], r[`t${i}`]);
16842
+ if (v !== void 0) out[k] = v;
16843
+ });
16844
+ return {
16845
+ id: r["id"],
16846
+ label: r["label"],
16847
+ description: r["description"] ?? "",
16848
+ createdAt: r["created_at"],
16849
+ lastUpdatedAt: r["last_updated_at"],
16850
+ pageRank: r["page_rank"],
16851
+ cumulativeHits: r["cumulative_hits"],
16852
+ extractionConfidence: r["extraction_confidence"],
16853
+ extractionSource: r["extraction_source"],
16854
+ community: r["community"] ?? null,
16855
+ ...r["created_at_seq"] != null ? { createdAtSeq: r["created_at_seq"] } : {},
16856
+ ...r["last_reinforced_at_seq"] != null ? { lastReinforcedAtSeq: r["last_reinforced_at_seq"] } : {},
16857
+ validTo: r["valid_to"] ?? null,
16858
+ embeddingDim: Number(r["embedding_dim"] ?? 0),
16859
+ ...decodeVector ? { embedding: decodeVector(r["embedding_blob"], r["embedding_json"] ?? "[]") } : {},
16860
+ attrs: out
16861
+ };
16862
+ }
16863
+
16698
16864
  // ../../packages/local-graph/src/store.ts
16699
16865
  var PAGE_RANK_SCALE_KEY = "pageRankScale.p95.v1";
16700
16866
  var TEXT_SEARCH_COLUMNS = `id, label, description, page_rank,
@@ -16883,6 +17049,11 @@ CREATE INDEX IF NOT EXISTS nodes_cloud_node_id ON nodes(json_extract(attrs_json,
16883
17049
  -- Solution's and Problem's attrs per call. Not partial: the Problem pull reads
16884
17050
  -- closed versions too.
16885
17051
  CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_json, '$.enrichmentPending'));
17052
+ -- Revisit flags, any label, any version: listNeedsRevisit's as-of read runs on
17053
+ -- every context render and otherwise json-checks every row (10.3 s on a 324k-row
17054
+ -- store, to return zero flags). The predicate must stay textually identical to
17055
+ -- nodesAsOfWhereTrue's or the planner will not use it.
17056
+ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_type(attrs_json, '$.revisit') = 'true';
16886
17057
  `;
16887
17058
  function encodeEmbedding(emb) {
16888
17059
  if (!emb || emb.length === 0) return null;
@@ -16983,6 +17154,7 @@ var SqliteGraphStore = class {
16983
17154
  installEditPlaceholderRetirement(this.db);
16984
17155
  installCloudAttrCompaction(this.db);
16985
17156
  installHistoryAttrSlim(this.db);
17157
+ installTextIndex(this.db);
16986
17158
  if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
16987
17159
  this.db.transaction(() => {
16988
17160
  this.repairSessionAliases();
@@ -17360,8 +17532,8 @@ var SqliteGraphStore = class {
17360
17532
  setLandmark(id, isLandmark) {
17361
17533
  this.stmts.setLandmark.run({ id, v: isLandmark ? 1 : 0 });
17362
17534
  }
17363
- setLocalCommunity(id, community, column) {
17364
- this.stmts.setLocalCommunity.run({ id, v: community, col: column ? 1 : 0 });
17535
+ setLocalCommunity(id, community, column2) {
17536
+ this.stmts.setLocalCommunity.run({ id, v: community, col: column2 ? 1 : 0 });
17365
17537
  }
17366
17538
  fieldStmts = /* @__PURE__ */ new Map();
17367
17539
  findNodeFieldsByLabel(label, attrKeys) {
@@ -17369,7 +17541,7 @@ var SqliteGraphStore = class {
17369
17541
  const cacheKey = attrKeys.join(",");
17370
17542
  let stmt = this.fieldStmts.get(cacheKey);
17371
17543
  if (!stmt) {
17372
- const cols = attrKeys.map((k, i) => `, json_extract(attrs_json, '$.${k}') AS a${i}`).join("");
17544
+ const cols = attrKeys.map((k, i) => `, ${attrValueSql(`'$.${k}'`)} AS a${i}, json_type(attrs_json, '$.${k}') AS t${i}`).join("");
17373
17545
  stmt = this.db.prepare(
17374
17546
  `SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL`
17375
17547
  );
@@ -17378,8 +17550,8 @@ var SqliteGraphStore = class {
17378
17550
  return stmt.all(label).map((r) => {
17379
17551
  const attrs = {};
17380
17552
  attrKeys.forEach((k, i) => {
17381
- const v = r[`a${i}`];
17382
- if (v !== null && v !== void 0) attrs[k] = v;
17553
+ const v = decodeAttr(r[`a${i}`], r[`t${i}`]);
17554
+ if (v !== void 0) attrs[k] = v;
17383
17555
  });
17384
17556
  return {
17385
17557
  id: r["id"],
@@ -17390,6 +17562,15 @@ var SqliteGraphStore = class {
17390
17562
  };
17391
17563
  });
17392
17564
  }
17565
+ selectNodes(q) {
17566
+ const { sql, params } = compileNodeSelect(q);
17567
+ const rows = this.db.prepare(sql).all(...params);
17568
+ return rows.map((r) => decodeSelectedRow(r, q.attrs ?? [], q.withEmbedding ? decodeEmbedding : void 0));
17569
+ }
17570
+ countNodes(q) {
17571
+ const { where, params } = compileNodeWhere(q);
17572
+ return Number(this.db.prepare(`SELECT COUNT(*) AS n FROM nodes WHERE ${where}`).get(...params).n);
17573
+ }
17393
17574
  setCommunity(id, community) {
17394
17575
  this.stmts.setCommunity.run({ id, v: community });
17395
17576
  }
@@ -17637,6 +17818,20 @@ var SqliteGraphStore = class {
17637
17818
  }
17638
17819
  searchTextCandidates(terms) {
17639
17820
  if (terms.length === 0) return [];
17821
+ const indexed = terms.filter((t) => t.length >= TEXT_INDEX_MIN_TERM);
17822
+ if (indexed.length > 0 && textIndexReady(this.db)) {
17823
+ const short = terms.filter((t) => t.length < TEXT_INDEX_MIN_TERM).map((t) => t.toLowerCase());
17824
+ const rows2 = this.db.prepare(`WITH hits AS MATERIALIZED (
17825
+ SELECT t.rowid AS rid, COUNT(*) AS matched FROM json_each(:terms) q, nodes_text t
17826
+ WHERE t.description LIKE '%' || q.value || '%' GROUP BY t.rowid
17827
+ ) SELECT ${TEXT_SEARCH_COLUMNS}, hits.matched FROM hits JOIN nodes ON nodes.rowid = hits.rid
17828
+ WHERE nodes.valid_to IS NULL ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(indexed) });
17829
+ return rows2.map((row) => {
17830
+ const text = row.description.toLowerCase();
17831
+ const extra = short.filter((t) => text.includes(t)).length;
17832
+ return { node: textSearchNode(row), matched: row.matched + extra };
17833
+ });
17834
+ }
17640
17835
  const rows = this.db.prepare(`WITH matches AS MATERIALIZED (
17641
17836
  SELECT n.id, COUNT(*) AS matched FROM nodes n INDEXED BY nodes_live_description, json_each(:terms) t
17642
17837
  WHERE n.valid_to IS NULL AND n.description LIKE '%' || t.value || '%'
@@ -17645,6 +17840,18 @@ var SqliteGraphStore = class {
17645
17840
  JOIN matches USING (id) ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(terms) });
17646
17841
  return rows.map((row) => ({ node: textSearchNode(row), matched: row.matched }));
17647
17842
  }
17843
+ commentAnchors(commentIds) {
17844
+ const out = /* @__PURE__ */ new Map();
17845
+ if (commentIds.length === 0) return out;
17846
+ const rows = this.db.prepare(`WITH a AS MATERIALIZED (
17847
+ SELECT q.value AS cid, COALESCE(
17848
+ (SELECT to_id FROM edges WHERE from_id = q.value AND type IN ('EXPLAINS', 'ANNOTATES') AND valid_to IS NULL LIMIT 1),
17849
+ (SELECT from_id FROM edges WHERE to_id = q.value AND type = 'DOCUMENTED_BY' AND valid_to IS NULL LIMIT 1)
17850
+ ) AS aid FROM json_each(:ids) q
17851
+ ) 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) });
17852
+ for (const row of rows) out.set(row.cid, textSearchNode(row));
17853
+ return out;
17854
+ }
17648
17855
  getTextSearchNode(id) {
17649
17856
  const row = this.db.prepare(`SELECT ${TEXT_SEARCH_COLUMNS} FROM nodes WHERE id = ? AND valid_to IS NULL`).get(id);
17650
17857
  return row ? textSearchNode(row) : null;
@@ -18040,7 +18247,8 @@ var SqliteGraphStore = class {
18040
18247
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(attr)) throw new Error(`nodesAsOfWhereTrue: bad attr ${JSON.stringify(attr)}`);
18041
18248
  const rows = this.db.prepare(
18042
18249
  `SELECT * FROM nodes WHERE valid_from <= :t AND (valid_to IS NULL OR valid_to > :t)
18043
- AND json_type(attrs_json, '$.${attr}') = 'true'`
18250
+ AND json_type(attrs_json, '$.${attr}') = 'true'
18251
+ ORDER BY rowid`
18044
18252
  ).all({ t });
18045
18253
  return rows.map(rowToNode);
18046
18254
  }
@@ -18370,32 +18578,35 @@ function projectsOf(attrs) {
18370
18578
  function induceTriage(l2, opts) {
18371
18579
  const report = { episodes: 0, observations: 0, skippedRefinement: 0 };
18372
18580
  const episodes = [];
18373
- for (const label of ["Problem", "Solution", "Claim"]) {
18374
- for (const n of l2.findNodesByLabel(label)) {
18375
- if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
18376
- continue;
18377
- }
18378
- if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.INVALID && n.attrs[INDUCTED_MARK] !== true) {
18379
- episodes.push({
18380
- assumedId: n.id,
18381
- actualId: `dcause_dissolve_${n.id}`.slice(0, 56),
18382
- driftKind: DRIFT_KIND.DISSOLUTION,
18383
- projects: projectsOf(n.attrs),
18384
- dissolution: true,
18385
- markNode: n.id
18386
- });
18387
- }
18388
- for (const e of l2.outEdges(n.id)) {
18389
- if (e.attrs["reframe"] !== true || e.attrs[INDUCTED_MARK] === true) continue;
18390
- episodes.push({
18391
- assumedId: String(e.attrs["assumed"] ?? e.from),
18392
- actualId: String(e.attrs["actual"] ?? e.to),
18393
- driftKind: String(e.attrs["driftKind"] ?? ""),
18394
- projects: projectsOf(e.attrs),
18395
- dissolution: false,
18396
- markEdge: e.id
18397
- });
18398
- }
18581
+ const sources = l2.selectNodes({
18582
+ labels: ["Problem", "Solution", "Claim"],
18583
+ attrs: ["resolvedAs", INDUCTED_MARK, "observedInProjects"]
18584
+ });
18585
+ for (const n of sources) {
18586
+ const label = n.label;
18587
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
18588
+ continue;
18589
+ }
18590
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.INVALID && n.attrs[INDUCTED_MARK] !== true) {
18591
+ episodes.push({
18592
+ assumedId: n.id,
18593
+ actualId: `dcause_dissolve_${n.id}`.slice(0, 56),
18594
+ driftKind: DRIFT_KIND.DISSOLUTION,
18595
+ projects: projectsOf(n.attrs),
18596
+ dissolution: true,
18597
+ markNode: n.id
18598
+ });
18599
+ }
18600
+ for (const e of l2.outEdges(n.id)) {
18601
+ if (e.attrs["reframe"] !== true || e.attrs[INDUCTED_MARK] === true) continue;
18602
+ episodes.push({
18603
+ assumedId: String(e.attrs["assumed"] ?? e.from),
18604
+ actualId: String(e.attrs["actual"] ?? e.to),
18605
+ driftKind: String(e.attrs["driftKind"] ?? ""),
18606
+ projects: projectsOf(e.attrs),
18607
+ dissolution: false,
18608
+ markEdge: e.id
18609
+ });
18399
18610
  }
18400
18611
  }
18401
18612
  for (const ep of episodes) {
@@ -18446,7 +18657,7 @@ function revisitStaleRoutes(l2, ts, opts = {}) {
18446
18657
  const minNavFailures = opts.minNavFailures ?? 3;
18447
18658
  const report = { flagged: 0, demoted: 0 };
18448
18659
  l2.transaction(() => {
18449
- for (const tri of l2.findNodesByLabel("Triage")) {
18660
+ for (const tri of l2.selectNodes({ labels: ["Triage"] })) {
18450
18661
  for (const e of l2.outEdges(tri.id, [...ROUTE_EDGE_TYPES])) {
18451
18662
  if (e.attrs["revisit"] === true) continue;
18452
18663
  let reason = "";
@@ -18552,6 +18763,7 @@ function mergeGeneralizes(store, principleId, memberId, ts) {
18552
18763
  attrs: { provisional: true }
18553
18764
  });
18554
18765
  }
18766
+ var CONCRETE_MEMBER_KEYS = ["retiredReason", "abstractionLevel", "resolvedAs", "rationale"];
18555
18767
  function induceAbstractions(l2, opts) {
18556
18768
  const K = opts.minClusterSize ?? DEFAULT_MIN_CLUSTER_SIZE;
18557
18769
  const minCtx = opts.minDistinctContexts ?? DEFAULT_MIN_DISTINCT_CONTEXTS;
@@ -18564,15 +18776,13 @@ function induceAbstractions(l2, opts) {
18564
18776
  generalizesEdges: 0
18565
18777
  };
18566
18778
  const ids = /* @__PURE__ */ new Set();
18567
- for (const label of PERCOLATING_LABELS) {
18568
- for (const n of l2.findNodesByLabel(label)) {
18569
- if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"] || n.validTo != null) continue;
18570
- if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
18571
- continue;
18572
- }
18573
- if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
18574
- ids.add(n.id);
18779
+ for (const n of l2.selectNodes({ labels: PERCOLATING_LABELS, attrs: CONCRETE_MEMBER_KEYS })) {
18780
+ if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"] || n.validTo != null) continue;
18781
+ if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
18782
+ continue;
18575
18783
  }
18784
+ if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
18785
+ ids.add(n.id);
18576
18786
  }
18577
18787
  if (ids.size === 0) return report;
18578
18788
  const adj = /* @__PURE__ */ new Map();
@@ -18640,7 +18850,7 @@ function induceAbstractions(l2, opts) {
18640
18850
  function revisitContradictedPrinciples(l2, ts) {
18641
18851
  const report = { flagged: 0 };
18642
18852
  l2.transaction(() => {
18643
- for (const n of l2.findNodesByLabel("Claim")) {
18853
+ for (const n of l2.selectNodes({ labels: ["Claim"], attrs: ["abstractionLevel", "revisit", "members"] })) {
18644
18854
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
18645
18855
  if (n.attrs["revisit"] === true) continue;
18646
18856
  const members = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
@@ -18666,9 +18876,11 @@ function revisitContradictedPrinciples(l2, ts) {
18666
18876
  }
18667
18877
  }
18668
18878
  if (!reason) continue;
18879
+ const principle = l2.getNode(n.id);
18880
+ if (!principle) continue;
18669
18881
  l2.updateNode(n.id, {
18670
18882
  attrs: {
18671
- ...n.attrs,
18883
+ ...principle.attrs,
18672
18884
  revisit: true,
18673
18885
  revisitReason: reason,
18674
18886
  revisitSinceTs: ts,
@@ -18704,6 +18916,7 @@ function findStrandedSymbols(store) {
18704
18916
 
18705
18917
  // src/package-index.ts
18706
18918
  init_src();
18919
+ var CONTEXT_GATE_ATTRS = ["source", "name", "contributedAtSeq"];
18707
18920
  function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
18708
18921
  const labels = opts.includePackages === false ? ["Language"] : ["Package", "Language"];
18709
18922
  const ignored = (s) => ignorePatterns.length > 0 && ignorePatterns.some((p) => s.toLowerCase().includes(p));
@@ -18711,10 +18924,12 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
18711
18924
  const seen = /* @__PURE__ */ new Set();
18712
18925
  const localIdByWireId = {};
18713
18926
  for (const label of labels) {
18714
- for (const n of store.findNodesByLabel(label)) {
18715
- if (n.attrs["source"] === "cloud") continue;
18716
- if (ignored(n.description) || ignored(String(n.attrs["name"] ?? ""))) continue;
18717
- if (typeof n.attrs["contributedAtSeq"] === "number") continue;
18927
+ for (const row of store.selectNodes({ labels: [label], attrs: CONTEXT_GATE_ATTRS })) {
18928
+ if (row.attrs["source"] === "cloud") continue;
18929
+ if (ignored(row.description) || ignored(String(row.attrs["name"] ?? ""))) continue;
18930
+ if (typeof row.attrs["contributedAtSeq"] === "number") continue;
18931
+ const n = store.getNode(row.id);
18932
+ if (!n) continue;
18718
18933
  nodes.push({
18719
18934
  ...n,
18720
18935
  // Language wire id = the shared `languageCanonicalId` (warming-spine
@@ -19147,7 +19362,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
19147
19362
  });
19148
19363
  const internal = internalPackageNames(workspaceRoot);
19149
19364
  const bareModules = /* @__PURE__ */ new Set();
19150
- for (const mod of store.findNodesByLabel("Module")) {
19365
+ for (const mod of store.selectNodes({ labels: ["Module"] })) {
19151
19366
  if (isBareExternal(mod.description, internal)) bareModules.add(mod.id);
19152
19367
  }
19153
19368
  const files = /* @__PURE__ */ new Set();
@@ -20457,11 +20672,11 @@ function buildDrainInstances(store, sharedStore, input) {
20457
20672
 
20458
20673
  // src/consolidate-worker.ts
20459
20674
  var stores = /* @__PURE__ */ new Map();
20460
- function storeAt(path) {
20461
- let s = stores.get(path);
20675
+ function storeAt(path2) {
20676
+ let s = stores.get(path2);
20462
20677
  if (!s) {
20463
- s = openGraphStore({ path });
20464
- stores.set(path, s);
20678
+ s = openGraphStore({ path: path2 });
20679
+ stores.set(path2, s);
20465
20680
  }
20466
20681
  return s;
20467
20682
  }