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

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
@@ -19028,6 +19028,14 @@ var init_spectral = __esm({
19028
19028
  }
19029
19029
  });
19030
19030
 
19031
+ // ../../packages/math/src/community-health.ts
19032
+ var init_community_health = __esm({
19033
+ "../../packages/math/src/community-health.ts"() {
19034
+ "use strict";
19035
+ init_spectral();
19036
+ }
19037
+ });
19038
+
19031
19039
  // ../../packages/math/src/void-demand.ts
19032
19040
  var DEMAND_HOT, DEMAND_WARM;
19033
19041
  var init_void_demand = __esm({
@@ -19285,6 +19293,7 @@ var init_src3 = __esm({
19285
19293
  init_relevance();
19286
19294
  init_leiden();
19287
19295
  init_spectral();
19296
+ init_community_health();
19288
19297
  init_void_demand();
19289
19298
  init_motif_gate();
19290
19299
  init_bko();
@@ -27407,7 +27416,8 @@ var init_client = __esm({
27407
27416
  nodes,
27408
27417
  edges,
27409
27418
  generatedAt: res.generatedAt,
27410
- ...res.voidSignal ? { voidSignal: res.voidSignal } : {}
27419
+ ...res.voidSignal ? { voidSignal: res.voidSignal } : {},
27420
+ ...res.seeds ? { seeds: res.seeds } : {}
27411
27421
  };
27412
27422
  }
27413
27423
  /**
@@ -27552,6 +27562,15 @@ var init_client = __esm({
27552
27562
  throw err2;
27553
27563
  }
27554
27564
  }
27565
+ /** One graph node's detail — label, full description, evidence counters,
27566
+ * §5.4 posterior and causal neighbours in both directions — via the
27567
+ * inspector read of `GET /v2/nodes` (keys on the graph node id, not the
27568
+ * canonicalId). Null when the node is absent or outside the caller's scope. */
27569
+ async getNode(nodeId) {
27570
+ const qs = new URLSearchParams({ ids: nodeId, withRelated: "true", limit: "1" });
27571
+ const res = await this.json("GET", `/v2/nodes?${qs.toString()}`);
27572
+ return res.rows.find((r) => r.id === nodeId) ?? null;
27573
+ }
27555
27574
  async sendTelemetry(batch) {
27556
27575
  return this.json("POST", "/v2/telemetry", batch);
27557
27576
  }
@@ -35098,28 +35117,97 @@ function hasCloudNodeShape(id) {
35098
35117
  return CANONICAL_KNOWLEDGE_ID.test(id) || UUID_ID.test(id) || id.startsWith("pkg:");
35099
35118
  }
35100
35119
  async function collectiveDrilldown(cloud, seedId, limit) {
35120
+ let res;
35101
35121
  try {
35102
- const res = await cloud.search({ stack: [], domains: [], kinds: [], seed: [seedId], limit });
35103
- if (res.nodes.length === 0) return null;
35104
- return {
35105
- seed: seedId,
35106
- nodes: res.nodes.map((n) => ({
35107
- id: n.id,
35108
- label: n.label,
35109
- name: n.description,
35110
- score: Number((n.extractionConfidence ?? 0.5).toFixed(4)),
35111
- hops: 1,
35112
- provenance: "collective"
35113
- })),
35114
- edges: res.edges.map((e) => ({ from: e.from, to: e.to, type: e.type }))
35115
- };
35122
+ res = await cloud.search({ stack: [], domains: [], kinds: [], seed: [seedId], limit });
35116
35123
  } catch (err2) {
35124
+ if (isQuotaError(err2)) {
35125
+ console.warn("[errata] collectiveDrilldown: collective read QUOTA EXCEEDED \u2014 the id's existence is unknown, not refuted.");
35126
+ return { status: "quota" };
35127
+ }
35117
35128
  console.error(
35118
35129
  "[errata] collectiveDrilldown: cloud fallback failed \u2014",
35119
35130
  err2 instanceof Error ? err2.message : err2
35120
35131
  );
35121
- return null;
35132
+ return { status: "offline" };
35122
35133
  }
35134
+ const seedEntry = res.seeds?.find((s) => s.seed === seedId);
35135
+ const resolution = seedEntry?.status;
35136
+ if (resolution === "unresolved") return { status: "no-twin" };
35137
+ if (resolution === "error") return { status: "seed-error" };
35138
+ if (res.nodes.length === 0 && resolution !== "resolved") return { status: "no-twin" };
35139
+ return {
35140
+ status: "resolved",
35141
+ neighborhood: {
35142
+ seed: seedId,
35143
+ ...seedEntry?.nodeId ? { nodeId: seedEntry.nodeId } : {},
35144
+ nodes: res.nodes.map((n) => {
35145
+ const score2 = n.attrs["score"];
35146
+ const uncertainty = n.attrs["uncertainty"];
35147
+ return {
35148
+ id: n.id,
35149
+ label: n.label,
35150
+ name: n.description,
35151
+ ...typeof score2 === "number" ? { score: Number(score2.toFixed(4)) } : {},
35152
+ ...typeof uncertainty === "number" ? { uncertainty: Number(uncertainty.toFixed(4)) } : {},
35153
+ hops: 1,
35154
+ provenance: "collective"
35155
+ };
35156
+ }),
35157
+ edges: res.edges.map((e) => ({ from: e.from, to: e.to, type: e.type }))
35158
+ }
35159
+ };
35160
+ }
35161
+ async function collectiveNodeDetail(cloud, id) {
35162
+ const read2 = async (nodeId) => {
35163
+ try {
35164
+ return await cloud.getNode(nodeId);
35165
+ } catch (err2) {
35166
+ if (isQuotaError(err2)) return "quota";
35167
+ console.error("[errata] collectiveNodeDetail: node read failed \u2014", err2 instanceof Error ? err2.message : err2);
35168
+ return "offline";
35169
+ }
35170
+ };
35171
+ let row = await read2(id);
35172
+ if (row === "quota" || row === "offline") return { status: row };
35173
+ if (!row) {
35174
+ const drill = await collectiveDrilldown(cloud, id, 1);
35175
+ if (drill.status !== "resolved") return drill;
35176
+ const nodeId = drill.neighborhood.nodeId;
35177
+ if (nodeId && nodeId !== id) {
35178
+ row = await read2(nodeId);
35179
+ if (row === "quota" || row === "offline") return { status: row };
35180
+ }
35181
+ if (!row) return { status: "found", node: null };
35182
+ }
35183
+ return {
35184
+ status: "found",
35185
+ node: {
35186
+ id,
35187
+ nodeId: row.id,
35188
+ label: row.label,
35189
+ description: row.description,
35190
+ evidence: {
35191
+ validated: row.validated,
35192
+ acceptedCount: row.accepted,
35193
+ corroborationCount: row.corroborations,
35194
+ failureReportCount: row.refutes,
35195
+ effectivenessScore: row.effectivenessScore ?? null,
35196
+ uncertainty: row.uncertainty?.value ?? null,
35197
+ priorStrength: row.uncertainty?.priorStrength ?? null,
35198
+ trustTier: row.trustTier ?? null
35199
+ },
35200
+ memoryTier: row.memoryTier,
35201
+ reinforcementCount: row.reinforced,
35202
+ hits: row.hits,
35203
+ createdAtMs: row.createdAtMs,
35204
+ lastValidatedAtMs: row.lastValidatedAtMs,
35205
+ visibility: row.visibility,
35206
+ resolvedBy: row.resolvedBy,
35207
+ causalChain: row.causalChain ?? [],
35208
+ related: row.related
35209
+ }
35210
+ };
35123
35211
  }
35124
35212
  function formatDualNodes(merged) {
35125
35213
  return merged.nodes.map((n) => ({
@@ -44411,6 +44499,22 @@ async function collectiveSeedFallback(args2, ctx, defaultLimit) {
44411
44499
  const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? defaultLimit)));
44412
44500
  return collectiveDrilldown(ctx.cloud, seedId, limit);
44413
44501
  }
44502
+ function collectiveSeedStatus(cn) {
44503
+ return cn.nodes.length > 0 ? "cloud-seed" : "cloud-seed-empty";
44504
+ }
44505
+ function collectiveSeedMiss(args2, outcome) {
44506
+ if (!outcome || outcome.status === "no-twin" || outcome.status === "resolved") return unresolved(args2);
44507
+ const { query } = unresolved(args2);
44508
+ const hint = outcome.status === "seed-error" ? "collective reached, but this id's lookup failed server-side \u2014 its existence is unknown; retry" : federationHint(outcome.status);
44509
+ return {
44510
+ found: false,
44511
+ reason: "collective-unreachable",
44512
+ query,
44513
+ collectiveReachable: outcome.status === "seed-error",
44514
+ collectiveStatus: outcome.status === "seed-error" ? "cloud-seed-error" : outcome.status,
44515
+ ...hint ? { collectiveHint: hint } : {}
44516
+ };
44517
+ }
44414
44518
  function resolveSymbol2(store, args2) {
44415
44519
  const id = args2["nodeId"];
44416
44520
  if (typeof id === "string" && store.getNode(id)) return id;
@@ -44761,13 +44865,14 @@ var init_mcp = __esm({
44761
44865
  handler: async (args2, store, ctx) => {
44762
44866
  const id = resolveSymbol2(store, args2);
44763
44867
  if (!id) {
44764
- const cn = await collectiveSeedFallback(args2, ctx, 30);
44765
- if (cn) {
44868
+ const cs = await collectiveSeedFallback(args2, ctx, 30);
44869
+ if (cs?.status === "resolved") {
44870
+ const cn = cs.neighborhood;
44766
44871
  return {
44767
44872
  found: true,
44768
44873
  node: { id: cn.seed, provenance: "collective" },
44769
44874
  collectiveReachable: true,
44770
- collectiveStatus: "cloud-seed",
44875
+ collectiveStatus: collectiveSeedStatus(cn),
44771
44876
  // Seed-touching edge types aren't on the wire (the server's seed
44772
44877
  // burst excludes the seed itself, and edges to nodes outside the
44773
44878
  // result set are dropped), so the collective fallback reports the
@@ -44777,7 +44882,7 @@ var init_mcp = __esm({
44777
44882
  edges: cn.edges
44778
44883
  };
44779
44884
  }
44780
- return unresolved(args2);
44885
+ return collectiveSeedMiss(args2, cs);
44781
44886
  }
44782
44887
  const limit = Math.max(1, Math.min(200, Number(args2["limit"] ?? 30)));
44783
44888
  const node2 = store.getNode(id);
@@ -44825,19 +44930,21 @@ var init_mcp = __esm({
44825
44930
  handler: async (args2, store, ctx) => {
44826
44931
  const id = resolveSymbol2(store, args2);
44827
44932
  if (!id) {
44828
- const cn = await collectiveSeedFallback(args2, ctx, 20);
44829
- if (cn) {
44933
+ const cs = await collectiveSeedFallback(args2, ctx, 20);
44934
+ if (cs?.status === "resolved") {
44935
+ const cn = cs.neighborhood;
44830
44936
  return {
44937
+ found: true,
44831
44938
  seed: cn.seed,
44832
44939
  seedProvenance: "collective",
44833
44940
  collectiveReachable: true,
44834
- collectiveStatus: "cloud-seed",
44941
+ collectiveStatus: collectiveSeedStatus(cn),
44835
44942
  count: cn.nodes.length,
44836
44943
  results: cn.nodes,
44837
44944
  edges: cn.edges
44838
44945
  };
44839
44946
  }
44840
- return unresolved(args2);
44947
+ return collectiveSeedMiss(args2, cs);
44841
44948
  }
44842
44949
  const seedForBurst = store.getNode(id);
44843
44950
  if (seedForBurst && seedForBurst.embedding.length === 0) {
@@ -45007,14 +45114,15 @@ var init_mcp = __esm({
45007
45114
  handler: async (args2, store, ctx) => {
45008
45115
  const id = resolveSymbol2(store, args2);
45009
45116
  if (!id) {
45010
- const cn = await collectiveSeedFallback(args2, ctx, 30);
45011
- if (cn) {
45117
+ const cs = await collectiveSeedFallback(args2, ctx, 30);
45118
+ if (cs?.status === "resolved") {
45119
+ const cn = cs.neighborhood;
45012
45120
  return {
45013
45121
  found: true,
45014
45122
  seedId: cn.seed,
45015
45123
  seedProvenance: "collective",
45016
45124
  collectiveReachable: true,
45017
- collectiveStatus: "cloud-seed",
45125
+ collectiveStatus: collectiveSeedStatus(cn),
45018
45126
  nodes: cn.nodes.map((n) => ({
45019
45127
  id: n.id,
45020
45128
  label: n.label,
@@ -45026,7 +45134,7 @@ var init_mcp = __esm({
45026
45134
  edges: cn.edges
45027
45135
  };
45028
45136
  }
45029
- return unresolved(args2);
45137
+ return collectiveSeedMiss(args2, cs);
45030
45138
  }
45031
45139
  const maxHops = Math.max(1, Math.min(8, Number(args2["maxHops"] ?? 4)));
45032
45140
  const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? 30)));
@@ -45390,7 +45498,7 @@ var init_mcp = __esm({
45390
45498
  },
45391
45499
  {
45392
45500
  name: "errata.show",
45393
- description: "Print the source code for a node. Uses bodyStartByte/endByte if the node has them (Function/Method/Class), else falls back to startByte/endByte (Const/Comment). File nodes return the whole file content. Returns {found, path, signature, calls (in source order), startLine, endLine, source}.",
45501
+ description: "Print the source code for a node. Uses bodyStartByte/endByte if the node has them (Function/Method/Class), else falls back to startByte/endByte (Const/Comment). File nodes return the whole file content. Returns {found, path, signature, calls (in source order), startLine, endLine, source}. A cloud id from search's collective blend (e.g. projn_\u2026, dprob_\u2026) that isn't in the local graph returns the collective node's own record instead: {found, provenance:'collective', node:{label, description, evidence:{validated, acceptedCount, corroborationCount, failureReportCount, effectivenessScore, uncertainty, priorStrength, trustTier}, causalChain, related (causal neighbours, both directions)}}.",
45394
45502
  inputSchema: {
45395
45503
  type: "object",
45396
45504
  properties: {
@@ -45400,9 +45508,21 @@ var init_mcp = __esm({
45400
45508
  maxLines: { type: "number" }
45401
45509
  }
45402
45510
  },
45403
- handler: (args2, store) => {
45511
+ handler: async (args2, store, ctx) => {
45404
45512
  const id = resolveSymbol2(store, args2);
45405
- if (!id) return unresolved(args2);
45513
+ if (!id) {
45514
+ const seedId = typeof args2["nodeId"] === "string" ? args2["nodeId"] : null;
45515
+ if (!seedId || !ctx.cloud || !hasCloudNodeShape(seedId)) return unresolved(args2);
45516
+ const shown = await collectiveNodeDetail(ctx.cloud, seedId);
45517
+ if (shown.status !== "found") return collectiveSeedMiss(args2, shown);
45518
+ return {
45519
+ found: true,
45520
+ provenance: "collective",
45521
+ collectiveReachable: true,
45522
+ collectiveStatus: shown.node ? "cloud-node" : "cloud-node-no-detail",
45523
+ ...shown.node ? { node: shown.node } : { node: { id: seedId } }
45524
+ };
45525
+ }
45406
45526
  const node2 = store.getNode(id);
45407
45527
  if (!node2) return { found: false, reason: "not-found" };
45408
45528
  const maxLines = Math.max(10, Math.min(2e3, Number(args2["maxLines"] ?? 200)));
@@ -83004,7 +83124,7 @@ function createWatchBreaker(deps) {
83004
83124
  }
83005
83125
 
83006
83126
  // src/engine.ts
83007
- var DAEMON_VERSION = true ? "2.0.21-dev.3861" : "2.0.0-alpha.0";
83127
+ var DAEMON_VERSION = true ? "2.0.21-dev.3896" : "2.0.0-alpha.0";
83008
83128
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
83009
83129
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
83010
83130
  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.3861",
3
+ "version": "2.0.21-dev.3896",
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.3861",
3
+ "version": "2.0.21-dev.3896",
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
- bbf0a0c46b3970acd362dc1334f295797bf392b40aebbba35aaeb90e305f1d49 .codex-plugin/plugin.json
1
+ 318e19fc332a3ee22b8c6f8318ee7c7c82b37b03b0624fee47dcabbdee5ddaa9 .codex-plugin/plugin.json
2
2
  a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
3
3
  fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
4
4
  73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js