@inerrata-corporation/errata 2.0.21-dev.3745 → 2.0.21-dev.3749
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 +229 -177
- package/errata.mjs +4454 -4397
- package/generalize-worker.mjs +52 -0
- package/package.json +1 -1
- package/pass-worker.mjs +1892 -1838
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/consolidate-worker.mjs
CHANGED
|
@@ -16396,7 +16396,204 @@ function installEditPlaceholderRetirement(db) {
|
|
|
16396
16396
|
});
|
|
16397
16397
|
}
|
|
16398
16398
|
|
|
16399
|
+
// ../../packages/math/src/constants.ts
|
|
16400
|
+
var NEMORI_DEDUP_COSINE = 0.88;
|
|
16401
|
+
|
|
16402
|
+
// ../../packages/math/src/triage.ts
|
|
16403
|
+
var TRIAGE_GLOBAL_BUCKET = "*";
|
|
16404
|
+
function triageContextBuckets(ctx) {
|
|
16405
|
+
const out = [];
|
|
16406
|
+
for (const s of ctx.stack ?? []) {
|
|
16407
|
+
const t = s.trim().toLowerCase();
|
|
16408
|
+
if (t) out.push(`stack:${t}`);
|
|
16409
|
+
}
|
|
16410
|
+
const domains = Array.isArray(ctx.domain) ? ctx.domain : typeof ctx.domain === "string" ? [ctx.domain] : [];
|
|
16411
|
+
for (const d of domains) {
|
|
16412
|
+
const t = d.trim().toLowerCase();
|
|
16413
|
+
if (t) out.push(`domain:${t}`);
|
|
16414
|
+
}
|
|
16415
|
+
return out;
|
|
16416
|
+
}
|
|
16417
|
+
|
|
16418
|
+
// ../../packages/math/src/relevance.ts
|
|
16419
|
+
function pageRankScale(ranks) {
|
|
16420
|
+
const positive = [...ranks].filter((r) => Number.isFinite(r) && r > 0).sort((a, b) => a - b);
|
|
16421
|
+
return positive.length ? Math.max(1e-9, positive[Math.floor((positive.length - 1) * 0.95)]) : 1;
|
|
16422
|
+
}
|
|
16423
|
+
|
|
16424
|
+
// ../../packages/math/src/leiden.ts
|
|
16425
|
+
function buildGraph(nodeIds, adj) {
|
|
16426
|
+
const nbr = /* @__PURE__ */ new Map();
|
|
16427
|
+
const deg = /* @__PURE__ */ new Map();
|
|
16428
|
+
const present = new Set(nodeIds);
|
|
16429
|
+
for (const id of nodeIds) {
|
|
16430
|
+
nbr.set(id, /* @__PURE__ */ new Map());
|
|
16431
|
+
deg.set(id, 0);
|
|
16432
|
+
}
|
|
16433
|
+
let m2 = 0;
|
|
16434
|
+
for (const id of nodeIds) {
|
|
16435
|
+
for (const { to, weight } of adj.get(id) ?? []) {
|
|
16436
|
+
if (!present.has(to)) continue;
|
|
16437
|
+
const row = nbr.get(id);
|
|
16438
|
+
row.set(to, (row.get(to) ?? 0) + weight);
|
|
16439
|
+
deg.set(id, (deg.get(id) ?? 0) + weight);
|
|
16440
|
+
m2 += weight;
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
return { nbr, deg, m2 };
|
|
16444
|
+
}
|
|
16445
|
+
function localMoving(nodeIds, g) {
|
|
16446
|
+
const community = new Map(nodeIds.map((n) => [n, n]));
|
|
16447
|
+
const comTot = new Map(nodeIds.map((n) => [n, g.deg.get(n) ?? 0]));
|
|
16448
|
+
const order = [...nodeIds].sort();
|
|
16449
|
+
const m2 = g.m2 > 0 ? g.m2 : 1;
|
|
16450
|
+
let improved = true;
|
|
16451
|
+
let iter = 0;
|
|
16452
|
+
while (improved && iter < 100) {
|
|
16453
|
+
improved = false;
|
|
16454
|
+
iter++;
|
|
16455
|
+
for (const node of order) {
|
|
16456
|
+
const ci = community.get(node);
|
|
16457
|
+
const ki = g.deg.get(node) ?? 0;
|
|
16458
|
+
comTot.set(ci, (comTot.get(ci) ?? 0) - ki);
|
|
16459
|
+
const wToComm = /* @__PURE__ */ new Map();
|
|
16460
|
+
for (const [nb, w] of g.nbr.get(node) ?? []) {
|
|
16461
|
+
if (nb === node) continue;
|
|
16462
|
+
const c = community.get(nb);
|
|
16463
|
+
wToComm.set(c, (wToComm.get(c) ?? 0) + w);
|
|
16464
|
+
}
|
|
16465
|
+
let bestC = ci;
|
|
16466
|
+
let bestGain = (wToComm.get(ci) ?? 0) - (comTot.get(ci) ?? 0) * ki / m2;
|
|
16467
|
+
for (const [c, kiIn] of [...wToComm.entries()].sort(
|
|
16468
|
+
(a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0
|
|
16469
|
+
)) {
|
|
16470
|
+
const gain = kiIn - (comTot.get(c) ?? 0) * ki / m2;
|
|
16471
|
+
if (gain > bestGain) {
|
|
16472
|
+
bestGain = gain;
|
|
16473
|
+
bestC = c;
|
|
16474
|
+
}
|
|
16475
|
+
}
|
|
16476
|
+
community.set(node, bestC);
|
|
16477
|
+
comTot.set(bestC, (comTot.get(bestC) ?? 0) + ki);
|
|
16478
|
+
if (bestC !== ci) improved = true;
|
|
16479
|
+
}
|
|
16480
|
+
}
|
|
16481
|
+
return community;
|
|
16482
|
+
}
|
|
16483
|
+
function refineConnectivity(community, g) {
|
|
16484
|
+
const members = /* @__PURE__ */ new Map();
|
|
16485
|
+
for (const [id, c] of community) {
|
|
16486
|
+
const l = members.get(c) ?? [];
|
|
16487
|
+
l.push(id);
|
|
16488
|
+
members.set(c, l);
|
|
16489
|
+
}
|
|
16490
|
+
const refined = /* @__PURE__ */ new Map();
|
|
16491
|
+
for (const [, group] of members) {
|
|
16492
|
+
const inGroup = new Set(group);
|
|
16493
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16494
|
+
for (const start of [...group].sort()) {
|
|
16495
|
+
if (seen.has(start)) continue;
|
|
16496
|
+
const comp = [];
|
|
16497
|
+
const stack = [start];
|
|
16498
|
+
seen.add(start);
|
|
16499
|
+
while (stack.length) {
|
|
16500
|
+
const cur = stack.pop();
|
|
16501
|
+
comp.push(cur);
|
|
16502
|
+
for (const [nb] of g.nbr.get(cur) ?? []) {
|
|
16503
|
+
if (inGroup.has(nb) && !seen.has(nb)) {
|
|
16504
|
+
seen.add(nb);
|
|
16505
|
+
stack.push(nb);
|
|
16506
|
+
}
|
|
16507
|
+
}
|
|
16508
|
+
}
|
|
16509
|
+
const anchor = [...comp].sort()[0];
|
|
16510
|
+
for (const id of comp) refined.set(id, anchor);
|
|
16511
|
+
}
|
|
16512
|
+
}
|
|
16513
|
+
return refined;
|
|
16514
|
+
}
|
|
16515
|
+
function normalize(assignment) {
|
|
16516
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16517
|
+
for (const [id, c] of assignment) {
|
|
16518
|
+
const l = groups.get(c) ?? [];
|
|
16519
|
+
l.push(id);
|
|
16520
|
+
groups.set(c, l);
|
|
16521
|
+
}
|
|
16522
|
+
const community = /* @__PURE__ */ new Map();
|
|
16523
|
+
for (const grp of groups.values()) {
|
|
16524
|
+
const anchor = [...grp].sort()[0];
|
|
16525
|
+
const cid = `community_${anchor}`;
|
|
16526
|
+
for (const m of grp) community.set(m, cid);
|
|
16527
|
+
}
|
|
16528
|
+
return { community, count: groups.size, iterations: 1 };
|
|
16529
|
+
}
|
|
16530
|
+
function causalComponents(nodeIds, pairs) {
|
|
16531
|
+
const parent = new Map(nodeIds.map((n) => [n, n]));
|
|
16532
|
+
const find = (x) => {
|
|
16533
|
+
let r = x;
|
|
16534
|
+
while (parent.get(r) !== r) r = parent.get(r);
|
|
16535
|
+
let c = x;
|
|
16536
|
+
while (parent.get(c) !== r) {
|
|
16537
|
+
const next = parent.get(c);
|
|
16538
|
+
parent.set(c, r);
|
|
16539
|
+
c = next;
|
|
16540
|
+
}
|
|
16541
|
+
return r;
|
|
16542
|
+
};
|
|
16543
|
+
for (const [a, b] of pairs) {
|
|
16544
|
+
const ra = find(a);
|
|
16545
|
+
const rb = find(b);
|
|
16546
|
+
if (ra !== rb) parent.set(ra < rb ? rb : ra, ra < rb ? ra : rb);
|
|
16547
|
+
}
|
|
16548
|
+
return find;
|
|
16549
|
+
}
|
|
16550
|
+
function detectCommunitiesLeiden(input, opts = {}) {
|
|
16551
|
+
const idSet = new Set(input.nodeIds);
|
|
16552
|
+
const protect = [...opts.protect ?? []].filter(
|
|
16553
|
+
([a, b]) => a !== b && idSet.has(a) && idSet.has(b)
|
|
16554
|
+
);
|
|
16555
|
+
if (protect.length === 0) {
|
|
16556
|
+
const g = buildGraph(input.nodeIds, input.adj);
|
|
16557
|
+
return normalize(refineConnectivity(localMoving(input.nodeIds, g), g));
|
|
16558
|
+
}
|
|
16559
|
+
const rep = causalComponents(input.nodeIds, protect);
|
|
16560
|
+
const superIds = [...new Set(input.nodeIds.map(rep))];
|
|
16561
|
+
const superAdj = /* @__PURE__ */ new Map();
|
|
16562
|
+
const acc = /* @__PURE__ */ new Map();
|
|
16563
|
+
for (const id of input.nodeIds) {
|
|
16564
|
+
const ra = rep(id);
|
|
16565
|
+
for (const { to, weight } of input.adj.get(id) ?? []) {
|
|
16566
|
+
if (!idSet.has(to)) continue;
|
|
16567
|
+
const rb = rep(to);
|
|
16568
|
+
if (ra === rb) continue;
|
|
16569
|
+
const row = acc.get(ra) ?? /* @__PURE__ */ new Map();
|
|
16570
|
+
row.set(rb, (row.get(rb) ?? 0) + weight);
|
|
16571
|
+
acc.set(ra, row);
|
|
16572
|
+
}
|
|
16573
|
+
}
|
|
16574
|
+
for (const [a, row] of acc) superAdj.set(a, [...row].map(([to, weight]) => ({ to, weight })));
|
|
16575
|
+
const sg = buildGraph(superIds, superAdj);
|
|
16576
|
+
const superComm = refineConnectivity(localMoving(superIds, sg), sg);
|
|
16577
|
+
const assignment = /* @__PURE__ */ new Map();
|
|
16578
|
+
for (const id of input.nodeIds) assignment.set(id, superComm.get(rep(id)) ?? rep(id));
|
|
16579
|
+
return normalize(assignment);
|
|
16580
|
+
}
|
|
16581
|
+
|
|
16399
16582
|
// ../../packages/local-graph/src/store.ts
|
|
16583
|
+
var PAGE_RANK_SCALE_KEY = "pageRankScale.p95.v1";
|
|
16584
|
+
var TEXT_SEARCH_COLUMNS = `id, label, description, page_rank,
|
|
16585
|
+
json_object('test', json(CASE WHEN json_type(attrs_json, '$.test') = 'true' THEN 'true' ELSE 'false' END),
|
|
16586
|
+
'relPath', json_extract(attrs_json, '$.relPath'),
|
|
16587
|
+
'resolutionSuspect', json(CASE WHEN json_type(attrs_json, '$.resolutionSuspect') = 'true' THEN 'true' ELSE 'false' END),
|
|
16588
|
+
'resolvedAt', json_extract(attrs_json, '$.resolvedAt'),
|
|
16589
|
+
'refutedAt', json_extract(attrs_json, '$.refutedAt'),
|
|
16590
|
+
'refuteReasons', json_extract(attrs_json, '$.refuteReasons'),
|
|
16591
|
+
'reopenedFrom', json_extract(attrs_json, '$.reopenedFrom'),
|
|
16592
|
+
'resolvedAs', json_extract(attrs_json, '$.resolvedAs')) AS search_attrs`;
|
|
16593
|
+
function textSearchNode(row) {
|
|
16594
|
+
const attrs = JSON.parse(row.search_attrs);
|
|
16595
|
+
return { id: row.id, label: row.label, description: row.description, pageRank: row.page_rank, attrs };
|
|
16596
|
+
}
|
|
16400
16597
|
var LOCAL_RULE_OVERRIDES = {
|
|
16401
16598
|
ANCHORED_AT: {
|
|
16402
16599
|
from: EDGE_RULES["ANCHORED_AT"]?.from,
|
|
@@ -16540,6 +16737,9 @@ CREATE INDEX IF NOT EXISTS edges_session_evidence ON edges(id) WHERE ${SESSION_E
|
|
|
16540
16737
|
DROP INDEX IF EXISTS nodes_live_fingerprint;
|
|
16541
16738
|
DROP INDEX IF EXISTS nodes_instance_fingerprint;
|
|
16542
16739
|
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');
|
|
16740
|
+
-- Calibrate rank from a covering scalar index; the global page-rank index
|
|
16741
|
+
-- requires a table lookup per node to exclude frozen versions.
|
|
16742
|
+
CREATE INDEX IF NOT EXISTS nodes_live_page_rank ON nodes(valid_to, page_rank);
|
|
16543
16743
|
CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
|
|
16544
16744
|
CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
|
|
16545
16745
|
-- Expression index on the per-node relPath (stored in attrs_json) so the
|
|
@@ -16638,6 +16838,7 @@ var SqliteGraphStore = class {
|
|
|
16638
16838
|
* ALL upserts incl. code reindex) — this counter is the knowledge-arrival axis
|
|
16639
16839
|
* Δseq is measured over, so code reindex churn must NOT advance it. */
|
|
16640
16840
|
ingestSeq = 0;
|
|
16841
|
+
initialPageRankScale;
|
|
16641
16842
|
constructor(opts) {
|
|
16642
16843
|
this.db = openDatabase(opts.path);
|
|
16643
16844
|
this.db.exec(SCHEMA_SQL);
|
|
@@ -17257,6 +17458,34 @@ var SqliteGraphStore = class {
|
|
|
17257
17458
|
).all(...terms.map((t) => `%${t}%`), Math.max(1, limit));
|
|
17258
17459
|
return rows.map((r) => ({ node: rowToNode(r), matched: Number(r.matched) }));
|
|
17259
17460
|
}
|
|
17461
|
+
searchTextCandidates(terms) {
|
|
17462
|
+
if (terms.length === 0) return [];
|
|
17463
|
+
const rows = this.db.prepare(`WITH matches AS MATERIALIZED (
|
|
17464
|
+
SELECT n.id, COUNT(*) AS matched FROM nodes n INDEXED BY nodes_live_description, json_each(:terms) t
|
|
17465
|
+
WHERE n.valid_to IS NULL AND n.description LIKE '%' || t.value || '%'
|
|
17466
|
+
GROUP BY n.id
|
|
17467
|
+
) SELECT ${TEXT_SEARCH_COLUMNS}, matches.matched FROM nodes
|
|
17468
|
+
JOIN matches USING (id) ORDER BY page_rank DESC, last_updated_at DESC`).all({ terms: JSON.stringify(terms) });
|
|
17469
|
+
return rows.map((row) => ({ node: textSearchNode(row), matched: row.matched }));
|
|
17470
|
+
}
|
|
17471
|
+
getTextSearchNode(id) {
|
|
17472
|
+
const row = this.db.prepare(`SELECT ${TEXT_SEARCH_COLUMNS} FROM nodes WHERE id = ? AND valid_to IS NULL`).get(id);
|
|
17473
|
+
return row ? textSearchNode(row) : null;
|
|
17474
|
+
}
|
|
17475
|
+
readPageRankScale() {
|
|
17476
|
+
const rows = this.db.prepare("SELECT page_rank FROM nodes WHERE valid_to IS NULL AND page_rank > 0").all();
|
|
17477
|
+
return pageRankScale(rows.map((row) => row.page_rank));
|
|
17478
|
+
}
|
|
17479
|
+
pageRankScale() {
|
|
17480
|
+
const value = Number(this.getMeta(PAGE_RANK_SCALE_KEY));
|
|
17481
|
+
if (Number.isFinite(value) && value > 0) return value;
|
|
17482
|
+
return this.initialPageRankScale ??= this.readPageRankScale();
|
|
17483
|
+
}
|
|
17484
|
+
refreshPageRankScale() {
|
|
17485
|
+
const scale = this.readPageRankScale();
|
|
17486
|
+
this.setMeta(PAGE_RANK_SCALE_KEY, String(scale));
|
|
17487
|
+
return scale;
|
|
17488
|
+
}
|
|
17260
17489
|
typedEdgeStmt(sql) {
|
|
17261
17490
|
let stmt = this.typedEdgeStmts.get(sql);
|
|
17262
17491
|
if (!stmt) {
|
|
@@ -17802,183 +18031,6 @@ function percolate(l1, l2, opts) {
|
|
|
17802
18031
|
init_src();
|
|
17803
18032
|
init_src2();
|
|
17804
18033
|
|
|
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
18034
|
// ../../packages/local-graph/src/triage.ts
|
|
17983
18035
|
init_src();
|
|
17984
18036
|
init_src();
|