@inerrata-corporation/errata 2.0.21-dev.3745 → 2.0.21-dev.3763
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 +271 -177
- package/errata.mjs +4517 -4407
- package/generalize-worker.mjs +94 -0
- package/package.json +1 -1
- package/pass-worker.mjs +1934 -1838
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/consolidate-worker.mjs
CHANGED
|
@@ -15726,10 +15726,12 @@ var init_history_quality = __esm({
|
|
|
15726
15726
|
});
|
|
15727
15727
|
|
|
15728
15728
|
// ../../packages/shared/src/history-read.ts
|
|
15729
|
+
var CLOUD_ATTR_DUPLICATE_KEYS;
|
|
15729
15730
|
var init_history_read = __esm({
|
|
15730
15731
|
"../../packages/shared/src/history-read.ts"() {
|
|
15731
15732
|
"use strict";
|
|
15732
15733
|
init_history_dependencies();
|
|
15734
|
+
CLOUD_ATTR_DUPLICATE_KEYS = ["attrsJson", "embedding"];
|
|
15733
15735
|
}
|
|
15734
15736
|
});
|
|
15735
15737
|
|
|
@@ -16396,7 +16398,237 @@ function installEditPlaceholderRetirement(db) {
|
|
|
16396
16398
|
});
|
|
16397
16399
|
}
|
|
16398
16400
|
|
|
16401
|
+
// ../../packages/local-graph/src/cloud-attr-compaction.ts
|
|
16402
|
+
init_src2();
|
|
16403
|
+
var CLOUD_ATTR_COMPACTION_KEY = "cloud-attr-compaction-1";
|
|
16404
|
+
var DUPES = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `'${k}'`).join(",");
|
|
16405
|
+
function compacted(row) {
|
|
16406
|
+
const packed = `json_extract(${row}.attrs_json, '$.attrsJson')`;
|
|
16407
|
+
const nested = `CASE WHEN json_type(${row}.attrs_json, '$.attrsJson') = 'text' AND json_valid(${packed})
|
|
16408
|
+
AND json_type(${packed}) = 'object' THEN ${packed} ELSE '{}' END`;
|
|
16409
|
+
const value = `CASE WHEN type IN ('array','object') THEN json(value) WHEN type IN ('true','false') THEN json(type) ELSE value END`;
|
|
16410
|
+
return `(SELECT json_group_object(key, ${value}) FROM (
|
|
16411
|
+
SELECT key, value, type, min(pri) FROM (
|
|
16412
|
+
SELECT key, value, type, 0 AS pri FROM json_each(${row}.attrs_json)
|
|
16413
|
+
UNION ALL
|
|
16414
|
+
SELECT key, value, type, 1 AS pri FROM json_each(${nested})
|
|
16415
|
+
) WHERE key NOT IN (${DUPES}) GROUP BY key))`;
|
|
16416
|
+
}
|
|
16417
|
+
function dirty(row) {
|
|
16418
|
+
const has = CLOUD_ATTR_DUPLICATE_KEYS.map((k) => `json_type(${row}.attrs_json, '$.${k}') IS NOT NULL`).join(" OR ");
|
|
16419
|
+
return `json_extract(${row}.attrs_json, '$.source') = 'cloud' AND (${has})`;
|
|
16420
|
+
}
|
|
16421
|
+
function installCloudAttrCompaction(db) {
|
|
16422
|
+
if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(CLOUD_ATTR_COMPACTION_KEY)) return;
|
|
16423
|
+
db.transaction(() => {
|
|
16424
|
+
for (const operation of ["INSERT", "UPDATE"]) {
|
|
16425
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS cloud_attr_compact_${operation.toLowerCase()}
|
|
16426
|
+
AFTER ${operation} ON nodes WHEN ${dirty("NEW")}
|
|
16427
|
+
BEGIN UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE id = NEW.id; END;`);
|
|
16428
|
+
}
|
|
16429
|
+
db.exec(`UPDATE nodes SET attrs_json = ${compacted("nodes")} WHERE ${dirty("nodes")}`);
|
|
16430
|
+
db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(CLOUD_ATTR_COMPACTION_KEY, "installed");
|
|
16431
|
+
});
|
|
16432
|
+
}
|
|
16433
|
+
|
|
16434
|
+
// ../../packages/math/src/constants.ts
|
|
16435
|
+
var NEMORI_DEDUP_COSINE = 0.88;
|
|
16436
|
+
|
|
16437
|
+
// ../../packages/math/src/triage.ts
|
|
16438
|
+
var TRIAGE_GLOBAL_BUCKET = "*";
|
|
16439
|
+
function triageContextBuckets(ctx) {
|
|
16440
|
+
const out = [];
|
|
16441
|
+
for (const s of ctx.stack ?? []) {
|
|
16442
|
+
const t = s.trim().toLowerCase();
|
|
16443
|
+
if (t) out.push(`stack:${t}`);
|
|
16444
|
+
}
|
|
16445
|
+
const domains = Array.isArray(ctx.domain) ? ctx.domain : typeof ctx.domain === "string" ? [ctx.domain] : [];
|
|
16446
|
+
for (const d of domains) {
|
|
16447
|
+
const t = d.trim().toLowerCase();
|
|
16448
|
+
if (t) out.push(`domain:${t}`);
|
|
16449
|
+
}
|
|
16450
|
+
return out;
|
|
16451
|
+
}
|
|
16452
|
+
|
|
16453
|
+
// ../../packages/math/src/relevance.ts
|
|
16454
|
+
function pageRankScale(ranks) {
|
|
16455
|
+
const positive = [...ranks].filter((r) => Number.isFinite(r) && r > 0).sort((a, b) => a - b);
|
|
16456
|
+
return positive.length ? Math.max(1e-9, positive[Math.floor((positive.length - 1) * 0.95)]) : 1;
|
|
16457
|
+
}
|
|
16458
|
+
|
|
16459
|
+
// ../../packages/math/src/leiden.ts
|
|
16460
|
+
function buildGraph(nodeIds, adj) {
|
|
16461
|
+
const nbr = /* @__PURE__ */ new Map();
|
|
16462
|
+
const deg = /* @__PURE__ */ new Map();
|
|
16463
|
+
const present = new Set(nodeIds);
|
|
16464
|
+
for (const id of nodeIds) {
|
|
16465
|
+
nbr.set(id, /* @__PURE__ */ new Map());
|
|
16466
|
+
deg.set(id, 0);
|
|
16467
|
+
}
|
|
16468
|
+
let m2 = 0;
|
|
16469
|
+
for (const id of nodeIds) {
|
|
16470
|
+
for (const { to, weight } of adj.get(id) ?? []) {
|
|
16471
|
+
if (!present.has(to)) continue;
|
|
16472
|
+
const row = nbr.get(id);
|
|
16473
|
+
row.set(to, (row.get(to) ?? 0) + weight);
|
|
16474
|
+
deg.set(id, (deg.get(id) ?? 0) + weight);
|
|
16475
|
+
m2 += weight;
|
|
16476
|
+
}
|
|
16477
|
+
}
|
|
16478
|
+
return { nbr, deg, m2 };
|
|
16479
|
+
}
|
|
16480
|
+
function localMoving(nodeIds, g) {
|
|
16481
|
+
const community = new Map(nodeIds.map((n) => [n, n]));
|
|
16482
|
+
const comTot = new Map(nodeIds.map((n) => [n, g.deg.get(n) ?? 0]));
|
|
16483
|
+
const order = [...nodeIds].sort();
|
|
16484
|
+
const m2 = g.m2 > 0 ? g.m2 : 1;
|
|
16485
|
+
let improved = true;
|
|
16486
|
+
let iter = 0;
|
|
16487
|
+
while (improved && iter < 100) {
|
|
16488
|
+
improved = false;
|
|
16489
|
+
iter++;
|
|
16490
|
+
for (const node of order) {
|
|
16491
|
+
const ci = community.get(node);
|
|
16492
|
+
const ki = g.deg.get(node) ?? 0;
|
|
16493
|
+
comTot.set(ci, (comTot.get(ci) ?? 0) - ki);
|
|
16494
|
+
const wToComm = /* @__PURE__ */ new Map();
|
|
16495
|
+
for (const [nb, w] of g.nbr.get(node) ?? []) {
|
|
16496
|
+
if (nb === node) continue;
|
|
16497
|
+
const c = community.get(nb);
|
|
16498
|
+
wToComm.set(c, (wToComm.get(c) ?? 0) + w);
|
|
16499
|
+
}
|
|
16500
|
+
let bestC = ci;
|
|
16501
|
+
let bestGain = (wToComm.get(ci) ?? 0) - (comTot.get(ci) ?? 0) * ki / m2;
|
|
16502
|
+
for (const [c, kiIn] of [...wToComm.entries()].sort(
|
|
16503
|
+
(a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0
|
|
16504
|
+
)) {
|
|
16505
|
+
const gain = kiIn - (comTot.get(c) ?? 0) * ki / m2;
|
|
16506
|
+
if (gain > bestGain) {
|
|
16507
|
+
bestGain = gain;
|
|
16508
|
+
bestC = c;
|
|
16509
|
+
}
|
|
16510
|
+
}
|
|
16511
|
+
community.set(node, bestC);
|
|
16512
|
+
comTot.set(bestC, (comTot.get(bestC) ?? 0) + ki);
|
|
16513
|
+
if (bestC !== ci) improved = true;
|
|
16514
|
+
}
|
|
16515
|
+
}
|
|
16516
|
+
return community;
|
|
16517
|
+
}
|
|
16518
|
+
function refineConnectivity(community, g) {
|
|
16519
|
+
const members = /* @__PURE__ */ new Map();
|
|
16520
|
+
for (const [id, c] of community) {
|
|
16521
|
+
const l = members.get(c) ?? [];
|
|
16522
|
+
l.push(id);
|
|
16523
|
+
members.set(c, l);
|
|
16524
|
+
}
|
|
16525
|
+
const refined = /* @__PURE__ */ new Map();
|
|
16526
|
+
for (const [, group] of members) {
|
|
16527
|
+
const inGroup = new Set(group);
|
|
16528
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16529
|
+
for (const start of [...group].sort()) {
|
|
16530
|
+
if (seen.has(start)) continue;
|
|
16531
|
+
const comp = [];
|
|
16532
|
+
const stack = [start];
|
|
16533
|
+
seen.add(start);
|
|
16534
|
+
while (stack.length) {
|
|
16535
|
+
const cur = stack.pop();
|
|
16536
|
+
comp.push(cur);
|
|
16537
|
+
for (const [nb] of g.nbr.get(cur) ?? []) {
|
|
16538
|
+
if (inGroup.has(nb) && !seen.has(nb)) {
|
|
16539
|
+
seen.add(nb);
|
|
16540
|
+
stack.push(nb);
|
|
16541
|
+
}
|
|
16542
|
+
}
|
|
16543
|
+
}
|
|
16544
|
+
const anchor = [...comp].sort()[0];
|
|
16545
|
+
for (const id of comp) refined.set(id, anchor);
|
|
16546
|
+
}
|
|
16547
|
+
}
|
|
16548
|
+
return refined;
|
|
16549
|
+
}
|
|
16550
|
+
function normalize(assignment) {
|
|
16551
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16552
|
+
for (const [id, c] of assignment) {
|
|
16553
|
+
const l = groups.get(c) ?? [];
|
|
16554
|
+
l.push(id);
|
|
16555
|
+
groups.set(c, l);
|
|
16556
|
+
}
|
|
16557
|
+
const community = /* @__PURE__ */ new Map();
|
|
16558
|
+
for (const grp of groups.values()) {
|
|
16559
|
+
const anchor = [...grp].sort()[0];
|
|
16560
|
+
const cid = `community_${anchor}`;
|
|
16561
|
+
for (const m of grp) community.set(m, cid);
|
|
16562
|
+
}
|
|
16563
|
+
return { community, count: groups.size, iterations: 1 };
|
|
16564
|
+
}
|
|
16565
|
+
function causalComponents(nodeIds, pairs) {
|
|
16566
|
+
const parent = new Map(nodeIds.map((n) => [n, n]));
|
|
16567
|
+
const find = (x) => {
|
|
16568
|
+
let r = x;
|
|
16569
|
+
while (parent.get(r) !== r) r = parent.get(r);
|
|
16570
|
+
let c = x;
|
|
16571
|
+
while (parent.get(c) !== r) {
|
|
16572
|
+
const next = parent.get(c);
|
|
16573
|
+
parent.set(c, r);
|
|
16574
|
+
c = next;
|
|
16575
|
+
}
|
|
16576
|
+
return r;
|
|
16577
|
+
};
|
|
16578
|
+
for (const [a, b] of pairs) {
|
|
16579
|
+
const ra = find(a);
|
|
16580
|
+
const rb = find(b);
|
|
16581
|
+
if (ra !== rb) parent.set(ra < rb ? rb : ra, ra < rb ? ra : rb);
|
|
16582
|
+
}
|
|
16583
|
+
return find;
|
|
16584
|
+
}
|
|
16585
|
+
function detectCommunitiesLeiden(input, opts = {}) {
|
|
16586
|
+
const idSet = new Set(input.nodeIds);
|
|
16587
|
+
const protect = [...opts.protect ?? []].filter(
|
|
16588
|
+
([a, b]) => a !== b && idSet.has(a) && idSet.has(b)
|
|
16589
|
+
);
|
|
16590
|
+
if (protect.length === 0) {
|
|
16591
|
+
const g = buildGraph(input.nodeIds, input.adj);
|
|
16592
|
+
return normalize(refineConnectivity(localMoving(input.nodeIds, g), g));
|
|
16593
|
+
}
|
|
16594
|
+
const rep = causalComponents(input.nodeIds, protect);
|
|
16595
|
+
const superIds = [...new Set(input.nodeIds.map(rep))];
|
|
16596
|
+
const superAdj = /* @__PURE__ */ new Map();
|
|
16597
|
+
const acc = /* @__PURE__ */ new Map();
|
|
16598
|
+
for (const id of input.nodeIds) {
|
|
16599
|
+
const ra = rep(id);
|
|
16600
|
+
for (const { to, weight } of input.adj.get(id) ?? []) {
|
|
16601
|
+
if (!idSet.has(to)) continue;
|
|
16602
|
+
const rb = rep(to);
|
|
16603
|
+
if (ra === rb) continue;
|
|
16604
|
+
const row = acc.get(ra) ?? /* @__PURE__ */ new Map();
|
|
16605
|
+
row.set(rb, (row.get(rb) ?? 0) + weight);
|
|
16606
|
+
acc.set(ra, row);
|
|
16607
|
+
}
|
|
16608
|
+
}
|
|
16609
|
+
for (const [a, row] of acc) superAdj.set(a, [...row].map(([to, weight]) => ({ to, weight })));
|
|
16610
|
+
const sg = buildGraph(superIds, superAdj);
|
|
16611
|
+
const superComm = refineConnectivity(localMoving(superIds, sg), sg);
|
|
16612
|
+
const assignment = /* @__PURE__ */ new Map();
|
|
16613
|
+
for (const id of input.nodeIds) assignment.set(id, superComm.get(rep(id)) ?? rep(id));
|
|
16614
|
+
return normalize(assignment);
|
|
16615
|
+
}
|
|
16616
|
+
|
|
16399
16617
|
// ../../packages/local-graph/src/store.ts
|
|
16618
|
+
var PAGE_RANK_SCALE_KEY = "pageRankScale.p95.v1";
|
|
16619
|
+
var TEXT_SEARCH_COLUMNS = `id, label, description, page_rank,
|
|
16620
|
+
json_object('test', json(CASE WHEN json_type(attrs_json, '$.test') = 'true' THEN 'true' ELSE 'false' END),
|
|
16621
|
+
'relPath', json_extract(attrs_json, '$.relPath'),
|
|
16622
|
+
'resolutionSuspect', json(CASE WHEN json_type(attrs_json, '$.resolutionSuspect') = 'true' THEN 'true' ELSE 'false' END),
|
|
16623
|
+
'resolvedAt', json_extract(attrs_json, '$.resolvedAt'),
|
|
16624
|
+
'refutedAt', json_extract(attrs_json, '$.refutedAt'),
|
|
16625
|
+
'refuteReasons', json_extract(attrs_json, '$.refuteReasons'),
|
|
16626
|
+
'reopenedFrom', json_extract(attrs_json, '$.reopenedFrom'),
|
|
16627
|
+
'resolvedAs', json_extract(attrs_json, '$.resolvedAs')) AS search_attrs`;
|
|
16628
|
+
function textSearchNode(row) {
|
|
16629
|
+
const attrs = JSON.parse(row.search_attrs);
|
|
16630
|
+
return { id: row.id, label: row.label, description: row.description, pageRank: row.page_rank, attrs };
|
|
16631
|
+
}
|
|
16400
16632
|
var LOCAL_RULE_OVERRIDES = {
|
|
16401
16633
|
ANCHORED_AT: {
|
|
16402
16634
|
from: EDGE_RULES["ANCHORED_AT"]?.from,
|
|
@@ -16540,6 +16772,9 @@ CREATE INDEX IF NOT EXISTS edges_session_evidence ON edges(id) WHERE ${SESSION_E
|
|
|
16540
16772
|
DROP INDEX IF EXISTS nodes_live_fingerprint;
|
|
16541
16773
|
DROP INDEX IF EXISTS nodes_instance_fingerprint;
|
|
16542
16774
|
CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
|
|
16775
|
+
-- Calibrate rank from a covering scalar index; the global page-rank index
|
|
16776
|
+
-- requires a table lookup per node to exclude frozen versions.
|
|
16777
|
+
CREATE INDEX IF NOT EXISTS nodes_live_page_rank ON nodes(valid_to, page_rank);
|
|
16543
16778
|
CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
|
|
16544
16779
|
CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
|
|
16545
16780
|
-- Expression index on the per-node relPath (stored in attrs_json) so the
|
|
@@ -16552,6 +16787,12 @@ CREATE INDEX IF NOT EXISTS nodes_live_description ON nodes(description, label) W
|
|
|
16552
16787
|
-- Problems by the file their anchor hint names: the harvest upgrades hints for
|
|
16553
16788
|
-- every edited file of every turn, and a scan parses every Problem's attrs.
|
|
16554
16789
|
CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_json, '$.anchorHint.path')) WHERE valid_to IS NULL;
|
|
16790
|
+
-- Problems by the command / checker / file that opened them. The generalizer
|
|
16791
|
+
-- looked these up per shell or tool EVENT by hydrating every Problem: ~12s of
|
|
16792
|
+
-- every minute of daemon main-thread time on a 3.4k-Problem store (2026-10-05).
|
|
16793
|
+
CREATE INDEX IF NOT EXISTS nodes_command_signature ON nodes(json_extract(attrs_json, '$.commandSignature')) WHERE valid_to IS NULL;
|
|
16794
|
+
CREATE INDEX IF NOT EXISTS nodes_diag_command ON nodes(json_extract(attrs_json, '$.diagCommand')) WHERE valid_to IS NULL;
|
|
16795
|
+
CREATE INDEX IF NOT EXISTS nodes_lsp_rel_path ON nodes(json_extract(attrs_json, '$.lspRelPath')) WHERE valid_to IS NULL;
|
|
16555
16796
|
-- Nodes still waiting on a root-cause ask. The MCP server checks this on EVERY
|
|
16556
16797
|
-- tool response (the enrichment piggyback), so it must not parse every
|
|
16557
16798
|
-- Solution's and Problem's attrs per call. Not partial: the Problem pull reads
|
|
@@ -16638,6 +16879,7 @@ var SqliteGraphStore = class {
|
|
|
16638
16879
|
* ALL upserts incl. code reindex) — this counter is the knowledge-arrival axis
|
|
16639
16880
|
* Δseq is measured over, so code reindex churn must NOT advance it. */
|
|
16640
16881
|
ingestSeq = 0;
|
|
16882
|
+
initialPageRankScale;
|
|
16641
16883
|
constructor(opts) {
|
|
16642
16884
|
this.db = openDatabase(opts.path);
|
|
16643
16885
|
this.db.exec(SCHEMA_SQL);
|
|
@@ -16654,6 +16896,7 @@ var SqliteGraphStore = class {
|
|
|
16654
16896
|
this.db.exec(TEMPORAL_INDEX_SQL);
|
|
16655
16897
|
installHistoryCacheFloor(this.db);
|
|
16656
16898
|
installEditPlaceholderRetirement(this.db);
|
|
16899
|
+
installCloudAttrCompaction(this.db);
|
|
16657
16900
|
if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
|
|
16658
16901
|
this.db.transaction(() => {
|
|
16659
16902
|
this.repairSessionAliases();
|
|
@@ -17257,6 +17500,34 @@ var SqliteGraphStore = class {
|
|
|
17257
17500
|
).all(...terms.map((t) => `%${t}%`), Math.max(1, limit));
|
|
17258
17501
|
return rows.map((r) => ({ node: rowToNode(r), matched: Number(r.matched) }));
|
|
17259
17502
|
}
|
|
17503
|
+
searchTextCandidates(terms) {
|
|
17504
|
+
if (terms.length === 0) return [];
|
|
17505
|
+
const rows = this.db.prepare(`WITH matches AS MATERIALIZED (
|
|
17506
|
+
SELECT n.id, COUNT(*) AS matched FROM nodes n INDEXED BY nodes_live_description, json_each(:terms) t
|
|
17507
|
+
WHERE n.valid_to IS NULL AND n.description LIKE '%' || t.value || '%'
|
|
17508
|
+
GROUP BY n.id
|
|
17509
|
+
) SELECT ${TEXT_SEARCH_COLUMNS}, matches.matched FROM nodes
|
|
17510
|
+
JOIN matches USING (id) ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(terms) });
|
|
17511
|
+
return rows.map((row) => ({ node: textSearchNode(row), matched: row.matched }));
|
|
17512
|
+
}
|
|
17513
|
+
getTextSearchNode(id) {
|
|
17514
|
+
const row = this.db.prepare(`SELECT ${TEXT_SEARCH_COLUMNS} FROM nodes WHERE id = ? AND valid_to IS NULL`).get(id);
|
|
17515
|
+
return row ? textSearchNode(row) : null;
|
|
17516
|
+
}
|
|
17517
|
+
readPageRankScale() {
|
|
17518
|
+
const rows = this.db.prepare("SELECT page_rank FROM nodes WHERE valid_to IS NULL AND page_rank > 0").all();
|
|
17519
|
+
return pageRankScale(rows.map((row) => row.page_rank));
|
|
17520
|
+
}
|
|
17521
|
+
pageRankScale() {
|
|
17522
|
+
const value = Number(this.getMeta(PAGE_RANK_SCALE_KEY));
|
|
17523
|
+
if (Number.isFinite(value) && value > 0) return value;
|
|
17524
|
+
return this.initialPageRankScale ??= this.readPageRankScale();
|
|
17525
|
+
}
|
|
17526
|
+
refreshPageRankScale() {
|
|
17527
|
+
const scale = this.readPageRankScale();
|
|
17528
|
+
this.setMeta(PAGE_RANK_SCALE_KEY, String(scale));
|
|
17529
|
+
return scale;
|
|
17530
|
+
}
|
|
17260
17531
|
typedEdgeStmt(sql) {
|
|
17261
17532
|
let stmt = this.typedEdgeStmts.get(sql);
|
|
17262
17533
|
if (!stmt) {
|
|
@@ -17802,183 +18073,6 @@ function percolate(l1, l2, opts) {
|
|
|
17802
18073
|
init_src();
|
|
17803
18074
|
init_src2();
|
|
17804
18075
|
|
|
17805
|
-
// ../../packages/math/src/constants.ts
|
|
17806
|
-
var NEMORI_DEDUP_COSINE = 0.88;
|
|
17807
|
-
|
|
17808
|
-
// ../../packages/math/src/triage.ts
|
|
17809
|
-
var TRIAGE_GLOBAL_BUCKET = "*";
|
|
17810
|
-
function triageContextBuckets(ctx) {
|
|
17811
|
-
const out = [];
|
|
17812
|
-
for (const s of ctx.stack ?? []) {
|
|
17813
|
-
const t = s.trim().toLowerCase();
|
|
17814
|
-
if (t) out.push(`stack:${t}`);
|
|
17815
|
-
}
|
|
17816
|
-
const domains = Array.isArray(ctx.domain) ? ctx.domain : typeof ctx.domain === "string" ? [ctx.domain] : [];
|
|
17817
|
-
for (const d of domains) {
|
|
17818
|
-
const t = d.trim().toLowerCase();
|
|
17819
|
-
if (t) out.push(`domain:${t}`);
|
|
17820
|
-
}
|
|
17821
|
-
return out;
|
|
17822
|
-
}
|
|
17823
|
-
|
|
17824
|
-
// ../../packages/math/src/leiden.ts
|
|
17825
|
-
function buildGraph(nodeIds, adj) {
|
|
17826
|
-
const nbr = /* @__PURE__ */ new Map();
|
|
17827
|
-
const deg = /* @__PURE__ */ new Map();
|
|
17828
|
-
const present = new Set(nodeIds);
|
|
17829
|
-
for (const id of nodeIds) {
|
|
17830
|
-
nbr.set(id, /* @__PURE__ */ new Map());
|
|
17831
|
-
deg.set(id, 0);
|
|
17832
|
-
}
|
|
17833
|
-
let m2 = 0;
|
|
17834
|
-
for (const id of nodeIds) {
|
|
17835
|
-
for (const { to, weight } of adj.get(id) ?? []) {
|
|
17836
|
-
if (!present.has(to)) continue;
|
|
17837
|
-
const row = nbr.get(id);
|
|
17838
|
-
row.set(to, (row.get(to) ?? 0) + weight);
|
|
17839
|
-
deg.set(id, (deg.get(id) ?? 0) + weight);
|
|
17840
|
-
m2 += weight;
|
|
17841
|
-
}
|
|
17842
|
-
}
|
|
17843
|
-
return { nbr, deg, m2 };
|
|
17844
|
-
}
|
|
17845
|
-
function localMoving(nodeIds, g) {
|
|
17846
|
-
const community = new Map(nodeIds.map((n) => [n, n]));
|
|
17847
|
-
const comTot = new Map(nodeIds.map((n) => [n, g.deg.get(n) ?? 0]));
|
|
17848
|
-
const order = [...nodeIds].sort();
|
|
17849
|
-
const m2 = g.m2 > 0 ? g.m2 : 1;
|
|
17850
|
-
let improved = true;
|
|
17851
|
-
let iter = 0;
|
|
17852
|
-
while (improved && iter < 100) {
|
|
17853
|
-
improved = false;
|
|
17854
|
-
iter++;
|
|
17855
|
-
for (const node of order) {
|
|
17856
|
-
const ci = community.get(node);
|
|
17857
|
-
const ki = g.deg.get(node) ?? 0;
|
|
17858
|
-
comTot.set(ci, (comTot.get(ci) ?? 0) - ki);
|
|
17859
|
-
const wToComm = /* @__PURE__ */ new Map();
|
|
17860
|
-
for (const [nb, w] of g.nbr.get(node) ?? []) {
|
|
17861
|
-
if (nb === node) continue;
|
|
17862
|
-
const c = community.get(nb);
|
|
17863
|
-
wToComm.set(c, (wToComm.get(c) ?? 0) + w);
|
|
17864
|
-
}
|
|
17865
|
-
let bestC = ci;
|
|
17866
|
-
let bestGain = (wToComm.get(ci) ?? 0) - (comTot.get(ci) ?? 0) * ki / m2;
|
|
17867
|
-
for (const [c, kiIn] of [...wToComm.entries()].sort(
|
|
17868
|
-
(a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0
|
|
17869
|
-
)) {
|
|
17870
|
-
const gain = kiIn - (comTot.get(c) ?? 0) * ki / m2;
|
|
17871
|
-
if (gain > bestGain) {
|
|
17872
|
-
bestGain = gain;
|
|
17873
|
-
bestC = c;
|
|
17874
|
-
}
|
|
17875
|
-
}
|
|
17876
|
-
community.set(node, bestC);
|
|
17877
|
-
comTot.set(bestC, (comTot.get(bestC) ?? 0) + ki);
|
|
17878
|
-
if (bestC !== ci) improved = true;
|
|
17879
|
-
}
|
|
17880
|
-
}
|
|
17881
|
-
return community;
|
|
17882
|
-
}
|
|
17883
|
-
function refineConnectivity(community, g) {
|
|
17884
|
-
const members = /* @__PURE__ */ new Map();
|
|
17885
|
-
for (const [id, c] of community) {
|
|
17886
|
-
const l = members.get(c) ?? [];
|
|
17887
|
-
l.push(id);
|
|
17888
|
-
members.set(c, l);
|
|
17889
|
-
}
|
|
17890
|
-
const refined = /* @__PURE__ */ new Map();
|
|
17891
|
-
for (const [, group] of members) {
|
|
17892
|
-
const inGroup = new Set(group);
|
|
17893
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17894
|
-
for (const start of [...group].sort()) {
|
|
17895
|
-
if (seen.has(start)) continue;
|
|
17896
|
-
const comp = [];
|
|
17897
|
-
const stack = [start];
|
|
17898
|
-
seen.add(start);
|
|
17899
|
-
while (stack.length) {
|
|
17900
|
-
const cur = stack.pop();
|
|
17901
|
-
comp.push(cur);
|
|
17902
|
-
for (const [nb] of g.nbr.get(cur) ?? []) {
|
|
17903
|
-
if (inGroup.has(nb) && !seen.has(nb)) {
|
|
17904
|
-
seen.add(nb);
|
|
17905
|
-
stack.push(nb);
|
|
17906
|
-
}
|
|
17907
|
-
}
|
|
17908
|
-
}
|
|
17909
|
-
const anchor = [...comp].sort()[0];
|
|
17910
|
-
for (const id of comp) refined.set(id, anchor);
|
|
17911
|
-
}
|
|
17912
|
-
}
|
|
17913
|
-
return refined;
|
|
17914
|
-
}
|
|
17915
|
-
function normalize(assignment) {
|
|
17916
|
-
const groups = /* @__PURE__ */ new Map();
|
|
17917
|
-
for (const [id, c] of assignment) {
|
|
17918
|
-
const l = groups.get(c) ?? [];
|
|
17919
|
-
l.push(id);
|
|
17920
|
-
groups.set(c, l);
|
|
17921
|
-
}
|
|
17922
|
-
const community = /* @__PURE__ */ new Map();
|
|
17923
|
-
for (const grp of groups.values()) {
|
|
17924
|
-
const anchor = [...grp].sort()[0];
|
|
17925
|
-
const cid = `community_${anchor}`;
|
|
17926
|
-
for (const m of grp) community.set(m, cid);
|
|
17927
|
-
}
|
|
17928
|
-
return { community, count: groups.size, iterations: 1 };
|
|
17929
|
-
}
|
|
17930
|
-
function causalComponents(nodeIds, pairs) {
|
|
17931
|
-
const parent = new Map(nodeIds.map((n) => [n, n]));
|
|
17932
|
-
const find = (x) => {
|
|
17933
|
-
let r = x;
|
|
17934
|
-
while (parent.get(r) !== r) r = parent.get(r);
|
|
17935
|
-
let c = x;
|
|
17936
|
-
while (parent.get(c) !== r) {
|
|
17937
|
-
const next = parent.get(c);
|
|
17938
|
-
parent.set(c, r);
|
|
17939
|
-
c = next;
|
|
17940
|
-
}
|
|
17941
|
-
return r;
|
|
17942
|
-
};
|
|
17943
|
-
for (const [a, b] of pairs) {
|
|
17944
|
-
const ra = find(a);
|
|
17945
|
-
const rb = find(b);
|
|
17946
|
-
if (ra !== rb) parent.set(ra < rb ? rb : ra, ra < rb ? ra : rb);
|
|
17947
|
-
}
|
|
17948
|
-
return find;
|
|
17949
|
-
}
|
|
17950
|
-
function detectCommunitiesLeiden(input, opts = {}) {
|
|
17951
|
-
const idSet = new Set(input.nodeIds);
|
|
17952
|
-
const protect = [...opts.protect ?? []].filter(
|
|
17953
|
-
([a, b]) => a !== b && idSet.has(a) && idSet.has(b)
|
|
17954
|
-
);
|
|
17955
|
-
if (protect.length === 0) {
|
|
17956
|
-
const g = buildGraph(input.nodeIds, input.adj);
|
|
17957
|
-
return normalize(refineConnectivity(localMoving(input.nodeIds, g), g));
|
|
17958
|
-
}
|
|
17959
|
-
const rep = causalComponents(input.nodeIds, protect);
|
|
17960
|
-
const superIds = [...new Set(input.nodeIds.map(rep))];
|
|
17961
|
-
const superAdj = /* @__PURE__ */ new Map();
|
|
17962
|
-
const acc = /* @__PURE__ */ new Map();
|
|
17963
|
-
for (const id of input.nodeIds) {
|
|
17964
|
-
const ra = rep(id);
|
|
17965
|
-
for (const { to, weight } of input.adj.get(id) ?? []) {
|
|
17966
|
-
if (!idSet.has(to)) continue;
|
|
17967
|
-
const rb = rep(to);
|
|
17968
|
-
if (ra === rb) continue;
|
|
17969
|
-
const row = acc.get(ra) ?? /* @__PURE__ */ new Map();
|
|
17970
|
-
row.set(rb, (row.get(rb) ?? 0) + weight);
|
|
17971
|
-
acc.set(ra, row);
|
|
17972
|
-
}
|
|
17973
|
-
}
|
|
17974
|
-
for (const [a, row] of acc) superAdj.set(a, [...row].map(([to, weight]) => ({ to, weight })));
|
|
17975
|
-
const sg = buildGraph(superIds, superAdj);
|
|
17976
|
-
const superComm = refineConnectivity(localMoving(superIds, sg), sg);
|
|
17977
|
-
const assignment = /* @__PURE__ */ new Map();
|
|
17978
|
-
for (const id of input.nodeIds) assignment.set(id, superComm.get(rep(id)) ?? rep(id));
|
|
17979
|
-
return normalize(assignment);
|
|
17980
|
-
}
|
|
17981
|
-
|
|
17982
18076
|
// ../../packages/local-graph/src/triage.ts
|
|
17983
18077
|
init_src();
|
|
17984
18078
|
init_src();
|