@inerrata-corporation/errata 2.0.21-dev.3896 → 2.0.21-dev.3918

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/errata.mjs CHANGED
@@ -26722,6 +26722,30 @@ function sidecarForNodes(sidecar, nodes) {
26722
26722
  }
26723
26723
  return count > 0 ? filtered : void 0;
26724
26724
  }
26725
+ function wireVia(value) {
26726
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
26727
+ const v = value;
26728
+ const { edgeType, parentId, forward } = v;
26729
+ if (typeof edgeType !== "string" || !edgeType || typeof parentId !== "string" || !parentId) return null;
26730
+ if (typeof forward !== "boolean") return null;
26731
+ return { edgeType, parentId, forward };
26732
+ }
26733
+ function searchVia(nodes) {
26734
+ const out2 = {};
26735
+ let any2 = false;
26736
+ for (const n of nodes) {
26737
+ const via = wireVia(n.attrs?.["via"]);
26738
+ if (!via || out2[n.canonicalId]) continue;
26739
+ out2[n.canonicalId] = via;
26740
+ any2 = true;
26741
+ }
26742
+ return any2 ? out2 : void 0;
26743
+ }
26744
+ function withoutVia(attrs) {
26745
+ if (!("via" in attrs)) return attrs;
26746
+ const { via: _via, ...rest2 } = attrs;
26747
+ return rest2;
26748
+ }
26725
26749
  function toWirePayload(batch, runId) {
26726
26750
  const droppedNodeIds = new Set(
26727
26751
  batch.nodes.filter((n) => !isCloudWritableNodeLabel(n.label)).map((n) => n.id)
@@ -27398,6 +27422,10 @@ var init_client = __esm({
27398
27422
  if (q.q) qs.set("q", q.q);
27399
27423
  if (q.channel) qs.set("channel", q.channel);
27400
27424
  if (q.includeTriage) qs.set("includeTriage", "true");
27425
+ if (q.scope) qs.set("scope", q.scope);
27426
+ if (q.community) qs.set("community", "true");
27427
+ if (q.bridges) qs.set("bridges", "true");
27428
+ if (q.via) qs.set("via", "true");
27401
27429
  const publicCtx = process.env["ERRATA_PRIMING_PUBLIC_CONTEXT"];
27402
27430
  const usePublicCtx = Boolean(publicCtx && publicCtx !== "0" && q.channel === "priming");
27403
27431
  const UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -27412,10 +27440,12 @@ var init_client = __esm({
27412
27440
  } : void 0
27413
27441
  );
27414
27442
  const { nodes, edges } = this.toCastalia(res);
27443
+ const via = searchVia(res.nodes);
27415
27444
  return {
27416
27445
  nodes,
27417
27446
  edges,
27418
27447
  generatedAt: res.generatedAt,
27448
+ ...via ? { via } : {},
27419
27449
  ...res.voidSignal ? { voidSignal: res.voidSignal } : {},
27420
27450
  ...res.seeds ? { seeds: res.seeds } : {}
27421
27451
  };
@@ -27445,7 +27475,7 @@ var init_client = __esm({
27445
27475
  isLandmark: false,
27446
27476
  community: null,
27447
27477
  stability: "stable",
27448
- attrs: { ...localCloudAttrs(n.attrs), source: "cloud", cloudNodeId: n.nodeId }
27478
+ attrs: { ...withoutVia(localCloudAttrs(n.attrs)), source: "cloud", cloudNodeId: n.nodeId }
27449
27479
  }));
27450
27480
  const edges = res.edges.map((e) => ({
27451
27481
  id: digest({ from: e.fromCanonicalId, type: e.type, to: e.toCanonicalId }),
@@ -34969,6 +34999,7 @@ function mergeDualBurst(local, cloud, opts = {}) {
34969
34999
  provenance: corroborated ? "corroborated" : "local",
34970
35000
  ...twin?.usageCount != null ? { usageCount: twin.usageCount } : {},
34971
35001
  ...twin?.rel ? { rel: twin.rel } : {},
35002
+ ...twin?.community ? { community: twin.community } : {},
34972
35003
  why: l.components,
34973
35004
  ...l.via ? { via: l.via } : {}
34974
35005
  });
@@ -34986,7 +35017,9 @@ function mergeDualBurst(local, cloud, opts = {}) {
34986
35017
  // adapters surface 1-hop neighbors of the seed
34987
35018
  provenance: "collective",
34988
35019
  ...c.usageCount != null ? { usageCount: c.usageCount } : {},
34989
- ...c.rel ? { rel: c.rel } : {}
35020
+ ...c.rel ? { rel: c.rel } : {},
35021
+ ...c.community ? { community: c.community } : {},
35022
+ ...c.via ? { via: c.via } : {}
34990
35023
  });
34991
35024
  }
34992
35025
  nodes.sort((a, b) => b.score - a.score);
@@ -35023,12 +35056,17 @@ function searchResultToCloudHits(result) {
35023
35056
  const usage = node2.attrs?.["usageCount"];
35024
35057
  const s = scores[i2];
35025
35058
  const cloudScore = !Number.isNaN(s) && maxScore > 0 ? s / maxScore : n > 0 ? (n - i2) / n : 0;
35059
+ const communityId = node2.attrs?.["community"];
35060
+ const communityLabel = node2.attrs?.["communityLabel"];
35061
+ const via = result.via?.[node2.id];
35026
35062
  return {
35027
35063
  id: node2.id,
35028
35064
  label: node2.label,
35029
35065
  description: node2.description,
35030
35066
  cloudScore,
35031
- ...typeof usage === "number" ? { usageCount: usage } : {}
35067
+ ...typeof usage === "number" ? { usageCount: usage } : {},
35068
+ ...typeof communityId === "number" ? { community: { id: communityId, label: typeof communityLabel === "string" ? communityLabel : null } } : {},
35069
+ ...via ? { via } : {}
35032
35070
  };
35033
35071
  });
35034
35072
  }
@@ -35075,7 +35113,7 @@ async function dualAugment(opts) {
35075
35113
  }
35076
35114
  if (hardIds.length > 0 || softQ) {
35077
35115
  calls.push(
35078
- cloud.search({ stack: [], domains: [], kinds: [], seed: hardIds, ...softQ ? { q: softQ } : {}, limit }).then((res) => {
35116
+ cloud.search({ stack: [], domains: [], kinds: [], seed: hardIds, ...softQ ? { q: softQ } : {}, limit, community: true, via: true }).then((res) => {
35079
35117
  cloudHits.push(...searchResultToCloudHits(res));
35080
35118
  })
35081
35119
  );
@@ -35116,10 +35154,29 @@ function federationHint(status) {
35116
35154
  function hasCloudNodeShape(id) {
35117
35155
  return CANONICAL_KNOWLEDGE_ID.test(id) || UUID_ID.test(id) || id.startsWith("pkg:");
35118
35156
  }
35119
- async function collectiveDrilldown(cloud, seedId, limit) {
35157
+ function attrsCommunity(attrs) {
35158
+ const id = attrs?.["community"];
35159
+ if (typeof id !== "number") return void 0;
35160
+ const label = attrs?.["communityLabel"];
35161
+ return { id, label: typeof label === "string" ? label : null };
35162
+ }
35163
+ function walkerCommunity(c) {
35164
+ return c ? { id: c.communityId, label: c.label } : null;
35165
+ }
35166
+ async function collectiveDrilldown(cloud, seedId, limit, opts = {}) {
35120
35167
  let res;
35121
35168
  try {
35122
- res = await cloud.search({ stack: [], domains: [], kinds: [], seed: [seedId], limit });
35169
+ res = await cloud.search({
35170
+ stack: [],
35171
+ domains: [],
35172
+ kinds: [],
35173
+ seed: [seedId],
35174
+ limit,
35175
+ community: true,
35176
+ via: true,
35177
+ ...opts.bridges ? { bridges: true } : {},
35178
+ ...opts.scope ? { scope: opts.scope } : {}
35179
+ });
35123
35180
  } catch (err2) {
35124
35181
  if (isQuotaError(err2)) {
35125
35182
  console.warn("[errata] collectiveDrilldown: collective read QUOTA EXCEEDED \u2014 the id's existence is unknown, not refuted.");
@@ -35144,17 +35201,23 @@ async function collectiveDrilldown(cloud, seedId, limit) {
35144
35201
  nodes: res.nodes.map((n) => {
35145
35202
  const score2 = n.attrs["score"];
35146
35203
  const uncertainty = n.attrs["uncertainty"];
35204
+ const community = attrsCommunity(n.attrs);
35205
+ const via = res.via?.[n.id];
35147
35206
  return {
35148
35207
  id: n.id,
35149
35208
  label: n.label,
35150
35209
  name: n.description,
35151
35210
  ...typeof score2 === "number" ? { score: Number(score2.toFixed(4)) } : {},
35152
35211
  ...typeof uncertainty === "number" ? { uncertainty: Number(uncertainty.toFixed(4)) } : {},
35212
+ ...community ? { community } : {},
35153
35213
  hops: 1,
35154
- provenance: "collective"
35214
+ provenance: "collective",
35215
+ ...via ? { via } : {}
35155
35216
  };
35156
35217
  }),
35157
- edges: res.edges.map((e) => ({ from: e.from, to: e.to, type: e.type }))
35218
+ edges: res.edges.map((e) => ({ from: e.from, to: e.to, type: e.type })),
35219
+ ...seedEntry && "community" in seedEntry ? { seedCommunity: walkerCommunity(seedEntry.community) } : {},
35220
+ ...seedEntry?.bridges ? { bridges: seedEntry.bridges } : {}
35158
35221
  }
35159
35222
  };
35160
35223
  }
@@ -35203,6 +35266,7 @@ async function collectiveNodeDetail(cloud, id) {
35203
35266
  createdAtMs: row.createdAtMs,
35204
35267
  lastValidatedAtMs: row.lastValidatedAtMs,
35205
35268
  visibility: row.visibility,
35269
+ ...row.community !== void 0 ? { community: walkerCommunity(row.community) } : {},
35206
35270
  resolvedBy: row.resolvedBy,
35207
35271
  causalChain: row.causalChain ?? [],
35208
35272
  related: row.related
@@ -35219,6 +35283,7 @@ function formatDualNodes(merged) {
35219
35283
  provenance: n.provenance,
35220
35284
  ...n.usageCount != null ? { usageCount: n.usageCount } : {},
35221
35285
  ...n.rel ? { rel: n.rel } : {},
35286
+ ...n.community ? { community: n.community } : {},
35222
35287
  ...n.why ? {
35223
35288
  why: {
35224
35289
  semantic: Number(n.why.semantic.toFixed(3)),
@@ -44493,11 +44558,21 @@ function cosine3(a, b) {
44493
44558
  for (let i2 = 0; i2 < a.length; i2++) dot += a[i2] * b[i2];
44494
44559
  return dot;
44495
44560
  }
44496
- async function collectiveSeedFallback(args2, ctx, defaultLimit) {
44561
+ async function collectiveSeedFallback(args2, ctx, defaultLimit, opts = {}) {
44497
44562
  const seedId = typeof args2["nodeId"] === "string" ? args2["nodeId"] : null;
44498
44563
  if (!seedId || !ctx.cloud || !hasCloudNodeShape(seedId)) return null;
44499
44564
  const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? defaultLimit)));
44500
- return collectiveDrilldown(ctx.cloud, seedId, limit);
44565
+ const scope = args2["scope"];
44566
+ return collectiveDrilldown(ctx.cloud, seedId, limit, {
44567
+ ...opts.allowScope && (scope === "community" || scope === "neighborhood" || scope === "global") ? { scope } : {},
44568
+ ...opts.allowBridges && args2["bridges"] === true ? { bridges: true } : {}
44569
+ });
44570
+ }
44571
+ function collectiveCommunityFields(cn) {
44572
+ return {
44573
+ ...cn.seedCommunity !== void 0 ? { seedCommunity: cn.seedCommunity } : {},
44574
+ ...cn.bridges ? { bridges: cn.bridges } : {}
44575
+ };
44501
44576
  }
44502
44577
  function collectiveSeedStatus(cn) {
44503
44578
  return cn.nodes.length > 0 ? "cloud-seed" : "cloud-seed-empty";
@@ -44873,13 +44948,13 @@ var init_mcp = __esm({
44873
44948
  node: { id: cn.seed, provenance: "collective" },
44874
44949
  collectiveReachable: true,
44875
44950
  collectiveStatus: collectiveSeedStatus(cn),
44876
- // Seed-touching edge types aren't on the wire (the server's seed
44877
- // burst excludes the seed itself, and edges to nodes outside the
44878
- // result set are dropped), so the collective fallback reports the
44879
- // 1-hop neighborhood + its internal topology instead of the local
44880
- // contract's typed out/in lists.
44951
+ // The collective fallback reports the 1-hop neighborhood + its
44952
+ // internal topology instead of the local contract's typed out/in
44953
+ // lists; the seed-touching edge rides on each node's `via` (the
44954
+ // server's seed burst excludes the seed itself, so `edges` can't).
44881
44955
  nearby: cn.nodes,
44882
- edges: cn.edges
44956
+ edges: cn.edges,
44957
+ ...collectiveCommunityFields(cn)
44883
44958
  };
44884
44959
  }
44885
44960
  return collectiveSeedMiss(args2, cs);
@@ -44917,20 +44992,29 @@ var init_mcp = __esm({
44917
44992
  },
44918
44993
  {
44919
44994
  name: "errata.burst",
44920
- description: "Burst-grade local retrieval \u2014 the INTELLIGENT, seed-relative neighborhood (not a flat list). Given a SEED (`nodeId` or `qname`), expand its neighborhood and return the RELEVANT scored subset, ranked by burst-style relevance: semantic similarity to the seed \xD7 centrality \xD7 trust, hop-decayed; semantically-unrelated nodes are gated out. Prefer this over errata.neighbors when you want signal-ranked CONTEXT rather than raw edges. When the SEED is a package and the collective is reachable, results BLEND cross-project knowledge \u2014 each carries `provenance` (local | collective | corroborated) and `usageCount` (projects using it); `corroborated` means your graph and the collective agree (trust it most), `collective` is a cross-project prior to verify. Returns {seed, count, results:[{id,label,name,score,hops,provenance,usageCount?,why?,via?}]} \u2014 `via` is the TOPOLOGY: the edge that reached this result in the walk ({edgeType, parentId, forward}; forward: true \u21D2 parent \u2014edgeType\u2192 node), so you can tell 'FIXED_BY your seed' from 'two hops away via a shared package' and choose whether to dig down a causal chain or turn elsewhere.",
44995
+ description: "Burst-grade local retrieval \u2014 the INTELLIGENT, seed-relative neighborhood (not a flat list). Given a SEED (`nodeId` or `qname`), expand its neighborhood and return the RELEVANT scored subset, ranked by burst-style relevance: semantic similarity to the seed \xD7 centrality \xD7 trust, hop-decayed; semantically-unrelated nodes are gated out. Prefer this over errata.neighbors when you want signal-ranked CONTEXT rather than raw edges. When the SEED is a package and the collective is reachable, results BLEND cross-project knowledge \u2014 each carries `provenance` (local | collective | corroborated) and `usageCount` (projects using it); `corroborated` means your graph and the collective agree (trust it most), `collective` is a cross-project prior to verify. Returns {seed, count, results:[{id,label,name,score,hops,provenance,usageCount?,why?,via?}]} \u2014 `via` is the TOPOLOGY: the edge that reached this result in the walk ({edgeType, parentId, forward}; forward: true \u21D2 parent \u2014edgeType\u2192 node), so you can tell 'FIXED_BY your seed' from 'two hops away via a shared package' and choose whether to dig down a causal chain or turn elsewhere. A COLLECTIVE seed (a cloud id not in your graph) also reports `seedCommunity` {id,label} and each result's `community`; ids are tonight's partition (renumbered nightly \u2014 compare within one walk, never store). Pass `scope` to stay in / leave the seed's community and `bridges:true` for the bordering communities and their crossing edges.",
44921
44996
  inputSchema: {
44922
44997
  type: "object",
44923
44998
  properties: {
44924
44999
  nodeId: { type: "string" },
44925
45000
  qname: { type: "string", description: "Symbol qname (resolved to a node)." },
44926
45001
  maxHops: { type: "number", description: "Neighborhood radius (default 2)." },
44927
- limit: { type: "number", description: "Max results (default 20)." }
45002
+ limit: { type: "number", description: "Max results (default 20)." },
45003
+ scope: {
45004
+ type: "string",
45005
+ enum: ["community", "neighborhood", "global"],
45006
+ description: "Collective seeds only: `community` keeps only the seed's community, `global` ranks cross-community neighbours on par; default `neighborhood`."
45007
+ },
45008
+ bridges: {
45009
+ type: "boolean",
45010
+ description: "Collective seeds only: also return `bridges` \u2014 the communities bordering the seed's, each with its strongest crossing edges (where to go next)."
45011
+ }
44928
45012
  }
44929
45013
  },
44930
45014
  handler: async (args2, store, ctx) => {
44931
45015
  const id = resolveSymbol2(store, args2);
44932
45016
  if (!id) {
44933
- const cs = await collectiveSeedFallback(args2, ctx, 20);
45017
+ const cs = await collectiveSeedFallback(args2, ctx, 20, { allowScope: true, allowBridges: true });
44934
45018
  if (cs?.status === "resolved") {
44935
45019
  const cn = cs.neighborhood;
44936
45020
  return {
@@ -44941,7 +45025,8 @@ var init_mcp = __esm({
44941
45025
  collectiveStatus: collectiveSeedStatus(cn),
44942
45026
  count: cn.nodes.length,
44943
45027
  results: cn.nodes,
44944
- edges: cn.edges
45028
+ edges: cn.edges,
45029
+ ...collectiveCommunityFields(cn)
44945
45030
  };
44946
45031
  }
44947
45032
  return collectiveSeedMiss(args2, cs);
@@ -45129,9 +45214,12 @@ var init_mcp = __esm({
45129
45214
  description: n.name,
45130
45215
  hops: n.hops,
45131
45216
  relevance: n.score,
45132
- provenance: n.provenance
45217
+ provenance: n.provenance,
45218
+ ...n.community ? { community: n.community } : {},
45219
+ ...n.via ? { via: n.via } : {}
45133
45220
  })),
45134
- edges: cn.edges
45221
+ edges: cn.edges,
45222
+ ...collectiveCommunityFields(cn)
45135
45223
  };
45136
45224
  }
45137
45225
  return collectiveSeedMiss(args2, cs);
@@ -83124,7 +83212,7 @@ function createWatchBreaker(deps) {
83124
83212
  }
83125
83213
 
83126
83214
  // src/engine.ts
83127
- var DAEMON_VERSION = true ? "2.0.21-dev.3896" : "2.0.0-alpha.0";
83215
+ var DAEMON_VERSION = true ? "2.0.21-dev.3918" : "2.0.0-alpha.0";
83128
83216
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
83129
83217
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
83130
83218
  var GIT_OP_MUTE_MS = 4e3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.21-dev.3896",
3
+ "version": "2.0.21-dev.3918",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "errata-context",
3
- "version": "2.0.21-dev.3896",
3
+ "version": "2.0.21-dev.3918",
4
4
  "description": "A minimal 3D view of loaded Errata priors and recent graph bursts.",
5
5
  "author": {
6
6
  "name": "inErrata"
@@ -1,4 +1,4 @@
1
- 318e19fc332a3ee22b8c6f8318ee7c7c82b37b03b0624fee47dcabbdee5ddaa9 .codex-plugin/plugin.json
1
+ b107a94e4e9828c1c6f57f4acb3e914b4e2ed683a0c75446defb85835e5010ce .codex-plugin/plugin.json
2
2
  a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
3
3
  fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
4
4
  73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js