@inerrata-corporation/errata 2.0.21-dev.3975 → 2.0.21-dev.3996

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.21-dev.3975",
3
+ "version": "2.0.21-dev.3996",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -16639,7 +16639,7 @@ function hasForkedDrift(currentHex, birthHex, maxSimRatio = DRIFT_FORK_RATIO) {
16639
16639
  if (!currentHex || !birthHex) return false;
16640
16640
  return simRatio(fromHex(currentHex), fromHex(birthHex)) < maxSimRatio;
16641
16641
  }
16642
- function jaccard(a, b) {
16642
+ function jaccard2(a, b) {
16643
16643
  if (a.size === 0 && b.size === 0) return 0;
16644
16644
  let inter = 0;
16645
16645
  for (const x of a) if (b.has(x)) inter++;
@@ -16673,7 +16673,7 @@ function score(a, b) {
16673
16673
  weighted += body2 * WEIGHTS.body;
16674
16674
  total += WEIGHTS.body;
16675
16675
  if (a.callees.size > 0 || b.callees.size > 0) {
16676
- const topo = jaccard(a.callees, b.callees);
16676
+ const topo = jaccard2(a.callees, b.callees);
16677
16677
  evidence["topology"] = round(topo);
16678
16678
  weighted += topo * WEIGHTS.topology;
16679
16679
  total += WEIGHTS.topology;
@@ -25728,6 +25728,26 @@ function detectCommunitiesLeiden(input, opts = {}) {
25728
25728
  return normalize(assignment);
25729
25729
  }
25730
25730
 
25731
+ // ../../packages/math/src/community-floor.ts
25732
+ var COMMUNITY_MIN_SIZE = 2;
25733
+ var COMMUNITY_FLOOR_SCALE = 0.5;
25734
+ function communitySizeFloor(domainSize) {
25735
+ if (!(domainSize > 1)) return COMMUNITY_MIN_SIZE;
25736
+ return Math.max(COMMUNITY_MIN_SIZE, Math.ceil(COMMUNITY_FLOOR_SCALE * Math.log(domainSize)));
25737
+ }
25738
+ function communityDomain(memberDomains, domainSize) {
25739
+ const held = /* @__PURE__ */ new Map();
25740
+ for (const domains of memberDomains) for (const d of new Set(domains)) held.set(d, (held.get(d) ?? 0) + 1);
25741
+ let best = null;
25742
+ for (const [d, n] of held) {
25743
+ if (n * 2 < memberDomains.length) continue;
25744
+ const size = domainSize.get(d) ?? Infinity;
25745
+ const bestSize = best === null ? Infinity : domainSize.get(best) ?? Infinity;
25746
+ if (best === null || size < bestSize || size === bestSize && d < best) best = d;
25747
+ }
25748
+ return best;
25749
+ }
25750
+
25731
25751
  // ../../packages/math/src/void-demand.ts
25732
25752
  var DEMAND_HOT = Math.log1p(10);
25733
25753
  var DEMAND_WARM = Math.log1p(5);
@@ -25777,8 +25797,10 @@ function a2MotifQuality(input) {
25777
25797
  // ../../packages/math/src/motif-gate.ts
25778
25798
  var MOTIF_MIN_MEMBERS = 5;
25779
25799
  var MOTIF_MIN_SURVIVED = 2;
25800
+ var MOTIF_MIN_COHERENCE = 0.5;
25780
25801
  function motifDecision(input) {
25781
- if (input.memberCount < MOTIF_MIN_MEMBERS) {
25802
+ const isIncoherent = input.coherence !== void 0 && input.coherence < MOTIF_MIN_COHERENCE;
25803
+ if (input.memberCount < MOTIF_MIN_MEMBERS || isIncoherent) {
25782
25804
  return {
25783
25805
  isCandidate: false,
25784
25806
  survivedRuns: input.priorSurvivedRuns,
@@ -28300,6 +28322,137 @@ var DRIFT_VALUES = new Set(Object.values(DRIFT_KIND));
28300
28322
 
28301
28323
  // ../../packages/local-graph/src/community.ts
28302
28324
  init_src2();
28325
+ var JOINT_COMMUNITY_LABELS = [
28326
+ "Problem",
28327
+ "Vulnerability",
28328
+ "Solution",
28329
+ "RootCause",
28330
+ "Pattern"
28331
+ ];
28332
+ var JOINT_COMMUNITY_EDGES = [
28333
+ "CAUSED_BY",
28334
+ "SOLVED_BY",
28335
+ "FIXED_BY",
28336
+ "CONTRADICTS",
28337
+ "INSTANCE_OF",
28338
+ "MATCHES",
28339
+ "IMPLEMENTS",
28340
+ "TRIAGED_BY",
28341
+ "INDICATES",
28342
+ "CONFIRMS",
28343
+ "RELATES_TO"
28344
+ ];
28345
+ var DOMAIN_EDGES = ["DEPENDS_ON", "CONCERNS", "OCCURS_IN"];
28346
+ var DOMAIN_INHERIT_EDGES = ["CAUSED_BY", "SOLVED_BY", "FIXED_BY"];
28347
+ function domainKey(id) {
28348
+ return id.replace(/(.)@[^@/]*$/, "$1");
28349
+ }
28350
+ function candidateDomains(store2, ids, labelOf) {
28351
+ const own = /* @__PURE__ */ new Map();
28352
+ for (const id of ids) {
28353
+ const label = labelOf.get(id);
28354
+ if (label !== "Problem" && label !== "Vulnerability") continue;
28355
+ const domains = store2.outEdges(id, DOMAIN_EDGES).map((e) => domainKey(e.to));
28356
+ if (domains.length > 0) own.set(id, domains);
28357
+ }
28358
+ const out2 = new Map(own);
28359
+ for (const id of ids) {
28360
+ const label = labelOf.get(id);
28361
+ if (label !== "RootCause" && label !== "Solution") continue;
28362
+ const inherited = store2.inEdges(id, DOMAIN_INHERIT_EDGES).flatMap((e) => own.get(e.from) ?? []);
28363
+ if (inherited.length > 0) out2.set(id, [...new Set(inherited)]);
28364
+ }
28365
+ return out2;
28366
+ }
28367
+ function detectLocalCommunities(store2, opts = {}) {
28368
+ const report = { candidates: 0, communities: 0, joint: 0, assigned: 0, belowFloor: 0, cleared: 0 };
28369
+ const nodes = /* @__PURE__ */ new Map();
28370
+ const unowned = [];
28371
+ for (const label of JOINT_COMMUNITY_LABELS) {
28372
+ for (const n of store2.findNodesByLabel(label)) {
28373
+ if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) unowned.push(n);
28374
+ else nodes.set(n.id, n);
28375
+ }
28376
+ }
28377
+ const ids = new Set(nodes.keys());
28378
+ report.candidates = ids.size;
28379
+ for (const label of SEMANTIC_NODE_LABELS) {
28380
+ if (!JOINT_COMMUNITY_LABELS.includes(label)) unowned.push(...store2.findNodesByLabel(label));
28381
+ }
28382
+ store2.transaction(() => {
28383
+ for (const n of unowned) {
28384
+ if (n.attrs["localCommunity"] !== void 0) {
28385
+ const { localCommunity: _gone, ...rest } = n.attrs;
28386
+ store2.updateNode(n.id, { attrs: rest });
28387
+ }
28388
+ if (!n.community || n.attrs["source"] === "cloud") continue;
28389
+ store2.setCommunity(n.id, null);
28390
+ report.cleared++;
28391
+ }
28392
+ });
28393
+ if (ids.size === 0) return report;
28394
+ const adj = /* @__PURE__ */ new Map();
28395
+ const protect = [];
28396
+ const add = (a, b, w) => {
28397
+ const l = adj.get(a) ?? [];
28398
+ l.push({ to: b, weight: w });
28399
+ adj.set(a, l);
28400
+ };
28401
+ for (const id of ids) {
28402
+ for (const e of store2.outEdges(id, [...JOINT_COMMUNITY_EDGES])) {
28403
+ if (!ids.has(e.to)) continue;
28404
+ if (e.type === "INSTANCE_OF" && e.extractionSource === "bko-inferred") continue;
28405
+ const conf = e.confidence > 0 ? e.confidence : 0.5;
28406
+ const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
28407
+ add(id, e.to, w);
28408
+ add(e.to, id, w);
28409
+ if (isCausalProtected(e.type)) protect.push([id, e.to]);
28410
+ }
28411
+ }
28412
+ const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
28413
+ const members = /* @__PURE__ */ new Map();
28414
+ for (const [id, c] of comm.community) {
28415
+ const l = members.get(c) ?? [];
28416
+ l.push(id);
28417
+ members.set(c, l);
28418
+ }
28419
+ const domains = candidateDomains(store2, ids, new Map([...nodes].map(([id, n]) => [id, n.label])));
28420
+ const domainSize = /* @__PURE__ */ new Map();
28421
+ for (const ds of domains.values()) for (const d of new Set(ds)) domainSize.set(d, (domainSize.get(d) ?? 0) + 1);
28422
+ const floorOf = (mem) => {
28423
+ if (opts.minCommunitySize !== void 0) return opts.minCommunitySize;
28424
+ const domain2 = communityDomain(mem.map((id) => domains.get(id) ?? []), domainSize);
28425
+ return communitySizeFloor(domain2 === null ? ids.size : domainSize.get(domain2));
28426
+ };
28427
+ store2.transaction(() => {
28428
+ for (const [cid, mem] of members) {
28429
+ const qualifies = mem.length >= floorOf(mem);
28430
+ if (!qualifies && mem.length >= 2) report.belowFloor++;
28431
+ let hasLocal = false;
28432
+ let hasCloud = false;
28433
+ for (const id of mem) {
28434
+ const n = nodes.get(id);
28435
+ const pulled = n.attrs["source"] === "cloud";
28436
+ if (pulled) hasCloud = true;
28437
+ else hasLocal = true;
28438
+ const want = qualifies ? cid : void 0;
28439
+ if (n.attrs["localCommunity"] !== want) {
28440
+ const nextAttrs = { ...n.attrs };
28441
+ if (want) nextAttrs["localCommunity"] = want;
28442
+ else delete nextAttrs["localCommunity"];
28443
+ store2.updateNode(id, { attrs: nextAttrs });
28444
+ }
28445
+ if (!pulled && (n.community ?? null) !== (want ?? null)) store2.setCommunity(id, want ?? null);
28446
+ }
28447
+ if (qualifies) {
28448
+ report.communities++;
28449
+ report.assigned += mem.length;
28450
+ if (hasLocal && hasCloud) report.joint++;
28451
+ }
28452
+ }
28453
+ });
28454
+ return report;
28455
+ }
28303
28456
 
28304
28457
  // ../../packages/local-graph/src/tools.ts
28305
28458
  init_src();
@@ -28707,14 +28860,16 @@ init_src2();
28707
28860
  init_src2();
28708
28861
  init_src();
28709
28862
  var MEMBER_LABELS = ["Problem", "RootCause", "Solution"];
28863
+ var MOTIF_LABELS = ["Pattern", "Technique", "AntiPattern"];
28864
+ var LINEAGE_MIN_JACCARD = 0.5;
28710
28865
  function layerOf(kind) {
28711
28866
  return kind === "Technique" ? "technique" : kind === "AntiPattern" ? "antipattern" : "pattern";
28712
28867
  }
28713
- function motifTitle(members, layer, instanceCount) {
28714
- const top = [...members].sort(
28715
- (a, b) => b.extractionConfidence - a.extractionConfidence
28716
- )[0];
28717
- return `${layer} \xD7${instanceCount} (exemplar): ${top?.description ?? "recurring problem cluster"}`;
28868
+ function motifTitle(exemplar, layer, instanceCount) {
28869
+ return `${layer} \xD7${instanceCount} (exemplar): ${exemplar?.description ?? "recurring problem cluster"}`;
28870
+ }
28871
+ function exemplarOf(members) {
28872
+ return [...members].sort((a, b) => b.extractionConfidence - a.extractionConfidence || a.id.localeCompare(b.id))[0];
28718
28873
  }
28719
28874
  function classifyMotif(store2, instances, promoted) {
28720
28875
  if (!promoted || instances.length === 0) return "Pattern";
@@ -28723,70 +28878,141 @@ function classifyMotif(store2, instances, promoted) {
28723
28878
  if (solvedShare <= 0.2) return "AntiPattern";
28724
28879
  return "Pattern";
28725
28880
  }
28881
+ function isDerived(e) {
28882
+ return e.extractionSource === "bko-inferred";
28883
+ }
28884
+ function motifCoherence(store2, members, instances) {
28885
+ if (instances.length === 0) return 0;
28886
+ const types = [...JOINT_COMMUNITY_EDGES];
28887
+ const near = /* @__PURE__ */ new Map();
28888
+ const link = (a, b) => {
28889
+ const s = near.get(a) ?? /* @__PURE__ */ new Set();
28890
+ s.add(b);
28891
+ near.set(a, s);
28892
+ };
28893
+ for (const id of members) {
28894
+ for (const e of store2.outEdges(id, types)) {
28895
+ if (!members.has(e.to) || isDerived(e)) continue;
28896
+ link(id, e.to);
28897
+ link(e.to, id);
28898
+ }
28899
+ }
28900
+ const isInstance = new Set(instances);
28901
+ let bound = 0;
28902
+ for (const p of instances) {
28903
+ const hop1 = near.get(p) ?? /* @__PURE__ */ new Set();
28904
+ const reached = [...hop1, ...[...hop1].flatMap((x) => [...near.get(x) ?? []])];
28905
+ if (reached.some((q) => q !== p && isInstance.has(q))) bound++;
28906
+ }
28907
+ return bound / instances.length;
28908
+ }
28909
+ function jaccard(a, b) {
28910
+ if (a.size === 0 && b.size === 0) return 0;
28911
+ let both = 0;
28912
+ for (const x of a) if (b.has(x)) both++;
28913
+ return both / (a.size + b.size - both);
28914
+ }
28726
28915
  function promoteMotifs(store2, t) {
28916
+ const report = { communities: 0, candidates: 0, incoherent: 0, promoted: 0, techniques: 0, antipatterns: 0, retracted: 0, retired: 0 };
28727
28917
  const byCommunity = /* @__PURE__ */ new Map();
28728
28918
  for (const label of MEMBER_LABELS) {
28729
28919
  for (const n of store2.findNodesByLabel(label)) {
28730
28920
  if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
28731
- const c = n.community;
28732
- if (!c) continue;
28921
+ const c = n.attrs["localCommunity"];
28922
+ if (typeof c !== "string") continue;
28733
28923
  const g = byCommunity.get(c) ?? [];
28734
28924
  g.push(n);
28735
28925
  byCommunity.set(c, g);
28736
28926
  }
28737
28927
  }
28738
- let candidates = 0;
28739
- let promoted = 0;
28740
- let techniques = 0;
28741
- let antipatterns = 0;
28928
+ report.communities = byCommunity.size;
28929
+ const existing = /* @__PURE__ */ new Map();
28930
+ for (const label of MOTIF_LABELS) {
28931
+ for (const node of store2.findNodesByLabel(label)) {
28932
+ if (!node.id.startsWith("motif_")) continue;
28933
+ const edges = store2.inEdges(node.id, ["INSTANCE_OF"]).filter(isDerived);
28934
+ const remembered = node.attrs["memberIds"];
28935
+ const members = new Set(Array.isArray(remembered) ? remembered : edges.map((e) => e.from));
28936
+ existing.set(node.id, { node, edges, members });
28937
+ }
28938
+ }
28939
+ const pairs = [];
28940
+ for (const [cid, members] of byCommunity) {
28941
+ const instances = new Set(members.filter((m) => m.label === "Problem").map((m) => m.id));
28942
+ for (const [motifId, m] of existing) {
28943
+ const j = jaccard(instances, m.members);
28944
+ if (j >= LINEAGE_MIN_JACCARD) pairs.push({ cid, motifId, j });
28945
+ }
28946
+ }
28947
+ pairs.sort((a, b) => b.j - a.j || a.motifId.localeCompare(b.motifId));
28948
+ const motifOf = /* @__PURE__ */ new Map();
28949
+ const claimed = /* @__PURE__ */ new Set();
28950
+ for (const p of pairs) {
28951
+ if (motifOf.has(p.cid) || claimed.has(p.motifId)) continue;
28952
+ motifOf.set(p.cid, p.motifId);
28953
+ claimed.add(p.motifId);
28954
+ }
28955
+ const kept = /* @__PURE__ */ new Set();
28742
28956
  store2.transaction(() => {
28743
28957
  for (const [cid, members] of byCommunity) {
28744
28958
  const instances = members.filter((m) => m.label === "Problem");
28745
28959
  const instanceCount = instances.length || members.length;
28746
- const motifId = `motif_${cid}`;
28747
- const existing = store2.getNode(motifId);
28960
+ const motifId = motifOf.get(cid) ?? (claimed.has(`motif_${cid}`) ? `motif_${cid}_${digest(instances.map((m) => m.id).sort()).slice(0, 8)}` : `motif_${cid}`);
28961
+ const prior = existing.get(motifId);
28962
+ const coherence = motifCoherence(store2, new Set(members.map((m) => m.id)), instances.map((m) => m.id));
28748
28963
  const d = motifDecision({
28749
- instances: members.map((m) => ({
28750
- confidence: m.extractionConfidence,
28751
- failed: false
28752
- })),
28964
+ instances: members.map((m) => ({ confidence: m.extractionConfidence, failed: false })),
28753
28965
  memberCount: members.length,
28754
28966
  instanceCount,
28755
- priorSurvivedRuns: existing?.attrs["survivedRuns"] ?? 0
28967
+ priorSurvivedRuns: prior?.node.attrs["survivedRuns"] ?? 0,
28968
+ coherence
28756
28969
  });
28757
- if (!d.isCandidate) continue;
28758
- candidates++;
28970
+ if (!d.isCandidate) {
28971
+ if (members.length >= 5) report.incoherent++;
28972
+ continue;
28973
+ }
28974
+ report.candidates++;
28975
+ kept.add(motifId);
28759
28976
  const kind = classifyMotif(store2, instances, d.promoted);
28977
+ const exemplar = exemplarOf(members);
28760
28978
  const motif = {
28761
28979
  id: motifId,
28762
28980
  label: kind,
28763
28981
  // Refresh the deterministic title every run (exemplar/count/kind drift),
28764
28982
  // but never clobber a distilled one — a distillation pass owns it then.
28765
- description: existing?.attrs["titleDistilled"] === true ? existing.description : motifTitle(members, layerOf(kind), instanceCount),
28983
+ description: prior?.node.attrs["titleDistilled"] === true ? prior.node.description : motifTitle(exemplar, layerOf(kind), instanceCount),
28766
28984
  extractionConfidence: d.motifConfidence,
28767
28985
  extractionSource: "bko-inferred",
28768
- embedding: existing?.embedding ?? [],
28769
- cumulativeSurprise: existing?.cumulativeSurprise ?? 0,
28770
- peakSurprise: existing?.peakSurprise ?? 0,
28986
+ embedding: prior?.node.embedding ?? [],
28987
+ cumulativeSurprise: prior?.node.cumulativeSurprise ?? 0,
28988
+ peakSurprise: prior?.node.peakSurprise ?? 0,
28771
28989
  cumulativeHits: instanceCount,
28772
28990
  lastUpdatedAt: t,
28773
- createdAt: existing?.createdAt ?? t,
28774
- memoryTier: existing?.memoryTier ?? "short-term",
28775
- pageRank: existing?.pageRank ?? 0,
28991
+ createdAt: prior?.node.createdAt ?? t,
28992
+ memoryTier: prior?.node.memoryTier ?? "short-term",
28993
+ pageRank: prior?.node.pageRank ?? 0,
28776
28994
  isLandmark: d.promoted,
28777
- community: cid,
28995
+ // The community column belongs to the joint pass alone; a motif names
28996
+ // its community in attrs.communityId.
28997
+ community: null,
28778
28998
  stability: d.stable ? "stable" : "forming",
28779
28999
  attrs: {
29000
+ ...prior?.node.attrs ?? {},
28780
29001
  layer: layerOf(kind),
28781
29002
  communityId: cid,
28782
29003
  survivedRuns: d.survivedRuns,
28783
29004
  motifConfidence: d.motifConfidence,
28784
29005
  memberCount: members.length,
28785
29006
  instanceCount,
29007
+ coherence: Math.round(coherence * 100) / 100,
29008
+ memberIds: instances.map((m) => m.id),
29009
+ ...exemplar ? { exemplarId: exemplar.id } : {},
29010
+ missedRuns: 0,
28786
29011
  promoted: d.promoted
28787
29012
  }
28788
29013
  };
28789
29014
  store2.mergeNode(motif);
29015
+ const now = new Set(instances.map((m) => m.id));
28790
29016
  for (const m of instances) {
28791
29017
  store2.mergeEdge({
28792
29018
  id: `edge_${digest({ from: m.id, type: "INSTANCE_OF", to: motifId })}`.slice(0, 24),
@@ -28802,12 +29028,33 @@ function promoteMotifs(store2, t) {
28802
29028
  attrs: {}
28803
29029
  });
28804
29030
  }
28805
- if (d.promoted) promoted++;
28806
- if (kind === "Technique") techniques++;
28807
- if (kind === "AntiPattern") antipatterns++;
29031
+ for (const e of prior?.edges ?? []) {
29032
+ if (now.has(e.from)) continue;
29033
+ store2.closeEdge(e.id, t);
29034
+ report.retracted++;
29035
+ }
29036
+ if (d.promoted) report.promoted++;
29037
+ if (kind === "Technique") report.techniques++;
29038
+ if (kind === "AntiPattern") report.antipatterns++;
29039
+ }
29040
+ for (const [motifId, m] of existing) {
29041
+ if (kept.has(motifId)) continue;
29042
+ for (const e of m.edges) {
29043
+ store2.closeEdge(e.id, t);
29044
+ report.retracted++;
29045
+ }
29046
+ const missedRuns = (m.node.attrs["missedRuns"] ?? 0) + 1;
29047
+ const evidenced = store2.inEdges(motifId, ["INSTANCE_OF"]).some((e) => !isDerived(e));
29048
+ if (missedRuns >= MOTIF_MIN_SURVIVED && !evidenced) {
29049
+ for (const e of [...store2.outEdges(motifId), ...store2.inEdges(motifId)]) store2.closeEdge(e.id, t);
29050
+ store2.closeNode(motifId, t);
29051
+ report.retired++;
29052
+ } else {
29053
+ store2.updateNode(motifId, { attrs: { ...m.node.attrs, missedRuns, promoted: false } });
29054
+ }
28808
29055
  }
28809
29056
  });
28810
- return { communities: byCommunity.size, candidates, promoted, techniques, antipatterns };
29057
+ return report;
28811
29058
  }
28812
29059
 
28813
29060
  // ../../packages/generalizer/src/nightly.ts
@@ -29025,44 +29272,14 @@ function runFullRescore(store2) {
29025
29272
  landmarkFlips++;
29026
29273
  }
29027
29274
  });
29028
- const MOTIF_LABELS = /* @__PURE__ */ new Set(["Pattern", "Technique", "AntiPattern"]);
29029
- const semanticIds = /* @__PURE__ */ new Set();
29030
- for (const label of SEMANTIC_NODE_LABELS) {
29031
- if (MOTIF_LABELS.has(label)) continue;
29032
- for (const n of store2.findNodesByLabel(label)) semanticIds.add(n.id);
29033
- }
29034
- const semAdj = /* @__PURE__ */ new Map();
29035
- const protect = [];
29036
- const addAdj = (a, b, w) => {
29037
- const l = semAdj.get(a) ?? [];
29038
- l.push({ to: b, weight: w });
29039
- semAdj.set(a, l);
29040
- };
29041
- for (const id of semanticIds) {
29042
- for (const e of store2.outEdges(id)) {
29043
- if (!semanticIds.has(e.to)) continue;
29044
- const conf = e.confidence > 0 ? e.confidence : 0.5;
29045
- const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
29046
- addAdj(id, e.to, w);
29047
- addAdj(e.to, id, w);
29048
- if (isCausalProtected(e.type)) protect.push([id, e.to]);
29049
- }
29050
- }
29051
- for (const { a, b, weight } of codeAnchorProjection(store2, semanticIds)) {
29052
- addAdj(a, b, weight);
29053
- addAdj(b, a, weight);
29054
- }
29055
- const comm = detectCommunitiesLeiden({ nodeIds: [...semanticIds], adj: semAdj }, { protect });
29056
- store2.transaction(() => {
29057
- for (const [id, c] of comm.community) store2.updateNode(id, { community: c });
29058
- });
29275
+ const lc = detectLocalCommunities(store2);
29059
29276
  const motifs = promoteMotifs(store2, started);
29060
29277
  return {
29061
29278
  scoredNodes: scored,
29062
29279
  iterations: result.iterations,
29063
29280
  converged: result.converged,
29064
29281
  landmarks: allLandmarks.size,
29065
- communities: comm.count,
29282
+ communities: lc.communities,
29066
29283
  motifsPromoted: motifs.promoted,
29067
29284
  techniques: motifs.techniques,
29068
29285
  antipatterns: motifs.antipatterns,
@@ -29121,28 +29338,6 @@ function runNightlyPipeline(store2) {
29121
29338
  durationMs: Date.now() - started
29122
29339
  };
29123
29340
  }
29124
- function codeAnchorProjection(store2, semanticIds, opts = {}) {
29125
- const anchorToNodes = /* @__PURE__ */ new Map();
29126
- for (const id of semanticIds) {
29127
- for (const e of store2.outEdges(id, ["ANCHORED_AT"])) {
29128
- if (semanticIds.has(e.to)) continue;
29129
- const l = anchorToNodes.get(e.to) ?? [];
29130
- l.push(id);
29131
- anchorToNodes.set(e.to, l);
29132
- }
29133
- }
29134
- const hubCap = opts.hubCap ?? Math.max(8, Math.floor(semanticIds.size * 0.03));
29135
- const base = opts.weight ?? 1;
29136
- const out2 = [];
29137
- for (const nodes of anchorToNodes.values()) {
29138
- if (nodes.length < 2 || nodes.length > hubCap) continue;
29139
- const w = base / Math.log2(nodes.length + 1);
29140
- for (let i2 = 0; i2 < nodes.length; i2++) {
29141
- for (let j = i2 + 1; j < nodes.length; j++) out2.push({ a: nodes[i2], b: nodes[j], weight: w });
29142
- }
29143
- }
29144
- return out2;
29145
- }
29146
29341
 
29147
29342
  // ../../packages/generalizer/src/embed-code.ts
29148
29343
  init_src();
@@ -29151,6 +29346,9 @@ init_src();
29151
29346
  init_src();
29152
29347
  var BURST_ANCHORED_AT_CONDUCTANCE = 1 / 3;
29153
29348
 
29349
+ // ../../packages/generalizer/src/motif-signal.ts
29350
+ var KNOWLEDGE_EDGES = [...JOINT_COMMUNITY_EDGES, "MAY_RESOLVE", "REGRESSION_OF", "BUILDS_ON"];
29351
+
29154
29352
  // ../../packages/context-writer/src/agents-md.ts
29155
29353
  init_src();
29156
29354
 
@@ -29176,6 +29374,12 @@ var AGENTS_POINTER_BODY = [
29176
29374
  // ../../packages/context-writer/src/render.ts
29177
29375
  init_src2();
29178
29376
  init_src();
29377
+ var MOTIF_BAND = 10;
29378
+ var MOTIF_POOL = 1e3;
29379
+ function rankMotifs(pool, signal, k = MOTIF_BAND) {
29380
+ if (!signal) return pool.slice(0, k);
29381
+ return pool.filter((m) => (signal.get(m.id) ?? 0) > 0).sort((a, b) => signal.get(b.id) - signal.get(a.id) || b.pageRank - a.pageRank).slice(0, k);
29382
+ }
29179
29383
  function buildSnapshot(opts) {
29180
29384
  const problems = [...opts.store.findNodesByLabel("Problem"), ...opts.store.findNodesByLabel("Vulnerability")].filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
29181
29385
  const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
@@ -29206,11 +29410,12 @@ function buildSnapshot(opts) {
29206
29410
  return { node: p, ...solution ? { solution } : {} };
29207
29411
  });
29208
29412
  const recentResolved = resolvedPool.slice(0, RECENT_RESOLVED);
29209
- const motifs = [
29413
+ const motifPool = [
29210
29414
  ...opts.store.findNodesByLabel("Pattern"),
29211
29415
  ...opts.store.findNodesByLabel("Technique"),
29212
29416
  ...opts.store.findNodesByLabel("AntiPattern")
29213
- ].filter((n) => historyReadPolicy(n, { mode: "passive", atCommit: opts.atCommit }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
29417
+ ].filter((n) => historyReadPolicy(n, { mode: "passive", atCommit: opts.atCommit }).allow).filter((n) => !(Number(n.attrs["missedRuns"] ?? 0) > 0)).sort((a, b) => b.pageRank - a.pageRank).slice(0, MOTIF_POOL).map((n) => n.embedding.length > 0 ? { ...n, embedding: [] } : n);
29418
+ const motifs = rankMotifs(motifPool, void 0);
29214
29419
  const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile, opts.atCommit) : void 0;
29215
29420
  const byEpisode = /* @__PURE__ */ new Map();
29216
29421
  for (const sol of opts.store.findNodesByLabel("Solution")) {
@@ -29277,6 +29482,7 @@ function buildSnapshot(opts) {
29277
29482
  ...opts.selfCiteSkips && opts.selfCiteSkips > 0 ? { selfCiteSkips: opts.selfCiteSkips } : {},
29278
29483
  ...domainNudge ? { domainNudge } : {},
29279
29484
  motifs,
29485
+ motifPool,
29280
29486
  reviewCount: opts.reviewCount,
29281
29487
  reviewUiUrl: opts.reviewUiUrl,
29282
29488
  ...workingFile ? { workingFile } : {},
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "errata-minimap",
3
- "version": "0.1.0",
3
+ "version": "0.3.1",
4
4
  "author": { "name": "inErrata", "url": "https://inerrata.ai" },
5
- "description": "Side pane: an errata graph minimap of the latest burst neighborhood that entered the agent's context.",
5
+ "description": "The errata library: the causal chains of the latest burst that entered the agent's context, in bookcases by technology with a catalog card — and errata's inline tags, tidied in the chat.",
6
6
  "types": "./types/index.d.ts"
7
7
  }