@inerrata-corporation/errata 2.0.0-dev.22 → 2.0.0-dev.23

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.
Files changed (2) hide show
  1. package/errata.mjs +102 -17
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -790,6 +790,12 @@ function identityId(input) {
790
790
  );
791
791
  }
792
792
  }
793
+ function genericCanonicalId(prefix, content) {
794
+ return `${prefix}_${digest(content)}`.slice(0, 56);
795
+ }
796
+ function languageCanonicalId(name2) {
797
+ return genericCanonicalId("Language", { name: name2.trim().toLowerCase() });
798
+ }
793
799
  var DESIGN_PROBLEM_PREFIX, DESIGN_PROBLEM_ID_LENGTH, DIAGNOSTIC_PROBLEM_PREFIX, DIAGNOSTIC_HASH_LENGTH, TRIAGE_PREFIX, TRIAGE_ID_LENGTH;
794
800
  var init_identity = __esm({
795
801
  "../../packages/shared/src/identity.ts"() {
@@ -20117,14 +20123,22 @@ var init_client = __esm({
20117
20123
  return { ...summarizeIngestResult(result), result };
20118
20124
  }
20119
20125
  const merged = { runId, nodes: [], edges: [] };
20126
+ let pendingEdges = [...batch.edges];
20120
20127
  for (const nodeChunk of chunkArray(batch.nodes, INGEST_NODE_CHUNK)) {
20121
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: [] }, runId));
20128
+ const ids = new Set(nodeChunk.map((n) => n.id));
20129
+ const inChunk = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, MAX_EDGES_PER_PAYLOAD);
20130
+ if (inChunk.length > 0) {
20131
+ const shipped = new Set(inChunk);
20132
+ pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
20133
+ }
20134
+ const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, runId));
20122
20135
  merged.nodes.push(...r.nodes);
20136
+ merged.edges.push(...r.edges);
20123
20137
  if (r.patternReconciliation) {
20124
20138
  merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
20125
20139
  }
20126
20140
  }
20127
- for (const edgeChunk of chunkArray(batch.edges, MAX_EDGES_PER_PAYLOAD)) {
20141
+ for (const edgeChunk of chunkArray(pendingEdges, MAX_EDGES_PER_PAYLOAD)) {
20128
20142
  const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: edgeChunk }, runId));
20129
20143
  merged.edges.push(...r.edges);
20130
20144
  }
@@ -41077,7 +41091,7 @@ function maybeFlushDigests() {
41077
41091
  }
41078
41092
 
41079
41093
  // src/engine.ts
41080
- var DAEMON_VERSION = true ? "2.0.0-dev.22" : "2.0.0-alpha.0";
41094
+ var DAEMON_VERSION = true ? "2.0.0-dev.23" : "2.0.0-alpha.0";
41081
41095
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41082
41096
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41083
41097
  var GIT_OP_MUTE_MS = 4e3;
@@ -42367,6 +42381,10 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
42367
42381
  if (ignored(n.description) || ignored(String(n.attrs["name"] ?? ""))) continue;
42368
42382
  nodes.push({
42369
42383
  ...n,
42384
+ // Language wire id = the shared `languageCanonicalId` (warming-spine
42385
+ // parity, EE-cloud-anchors) — the local `lang:<name>` id is internal.
42386
+ // Package ids are already the purl (= the cross-stratum canonicalId).
42387
+ id: label === "Language" ? languageCanonicalId(String(n.attrs["name"] ?? "").trim() || n.description) : n.id,
42370
42388
  embedding: [],
42371
42389
  attrs: label === "Package" ? {
42372
42390
  purl: n.attrs["purl"],
@@ -42596,11 +42614,34 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
42596
42614
  // src/instance-ingest.ts
42597
42615
  var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
42598
42616
  var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
42617
+ var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON"];
42618
+ var ANCHOR_TARGET_LABELS = ["Language", "Package"];
42599
42619
  function stripCodebaseScope(scope) {
42600
42620
  const s = { ...scope ?? {} };
42601
42621
  delete s["codebase"];
42602
42622
  return s;
42603
42623
  }
42624
+ function wireContextId(n) {
42625
+ if (n.label === "Language" && n.attrs["source"] !== "cloud") {
42626
+ const name2 = String(n.attrs["name"] ?? "").trim() || n.description.trim() || n.id.replace(/^lang:/, "");
42627
+ return languageCanonicalId(name2);
42628
+ }
42629
+ return n.id;
42630
+ }
42631
+ function shareableContext(n, wireId) {
42632
+ return {
42633
+ ...n,
42634
+ id: wireId,
42635
+ embedding: [],
42636
+ attrs: n.label === "Package" ? {
42637
+ purl: n.attrs["purl"],
42638
+ name: n.attrs["name"],
42639
+ version: n.attrs["version"],
42640
+ ecosystem: n.attrs["ecosystem"],
42641
+ resolved: n.attrs["resolved"]
42642
+ } : { name: n.attrs["name"] }
42643
+ };
42644
+ }
42604
42645
  function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
42605
42646
  const level = opts.level ?? 1;
42606
42647
  const noveltyOpts = opts.dedupCosine != null ? { dedupCosine: opts.dedupCosine } : {};
@@ -42617,6 +42658,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
42617
42658
  });
42618
42659
  const nodes = [];
42619
42660
  const seen = /* @__PURE__ */ new Set();
42661
+ const anchorSources = /* @__PURE__ */ new Set();
42620
42662
  const includedByLabel = /* @__PURE__ */ new Map();
42621
42663
  for (const label of INSTANCE_LABELS) {
42622
42664
  const ref = [];
@@ -42624,14 +42666,18 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
42624
42666
  for (const n of store.findNodesByLabel(label)) {
42625
42667
  if (seen.has(n.id)) continue;
42626
42668
  if (n.attrs["source"] === "cloud") continue;
42627
- const contributedAtSeq = n.attrs["contributedAtSeq"];
42628
- if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) continue;
42629
42669
  if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
42630
42670
  if (ignored(n.description)) continue;
42671
+ const contributedAtSeq = n.attrs["contributedAtSeq"];
42672
+ if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
42673
+ anchorSources.add(n.id);
42674
+ continue;
42675
+ }
42631
42676
  if (!noveltyAgainst(n, ref, noveltyOpts).ready) continue;
42632
42677
  ref.push(n);
42633
42678
  nodes.push(shareable(n));
42634
42679
  seen.add(n.id);
42680
+ anchorSources.add(n.id);
42635
42681
  }
42636
42682
  }
42637
42683
  for (const n of nodes) {
@@ -42639,20 +42685,50 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
42639
42685
  throw new Error(`buildInstanceIngest: refusing to ship non-instance ${n.id} (${n.label}) \u2014 C7 invariant`);
42640
42686
  }
42641
42687
  }
42642
- if (nodes.length === 0) return null;
42688
+ const anchorEdges = [];
42689
+ const contextNodes = [];
42690
+ const contextSeen = /* @__PURE__ */ new Set();
42691
+ const anchorDigests = {};
42692
+ for (const sourceId of anchorSources) {
42693
+ const targets = [];
42694
+ for (const e of store.outEdges(sourceId, [...ANCHOR_EDGES])) {
42695
+ const t = store.getNode(e.to);
42696
+ if (!t || !ANCHOR_TARGET_LABELS.includes(t.label)) continue;
42697
+ if (e.type === "OCCURS_IN" && t.label !== "Language") continue;
42698
+ if (e.type === "DEPENDS_ON" && t.label !== "Package") continue;
42699
+ if (t.label === "Package" && opts.includePackages !== true) continue;
42700
+ if (ignored(t.description) || ignored(String(t.attrs["name"] ?? ""))) continue;
42701
+ targets.push({ e, t, wireId: wireContextId(t) });
42702
+ }
42703
+ if (targets.length === 0) continue;
42704
+ const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
42705
+ if (store.getNode(sourceId)?.attrs["anchorsContributedDigest"] === dg) continue;
42706
+ anchorDigests[sourceId] = dg;
42707
+ for (const { e, t, wireId } of targets) {
42708
+ anchorEdges.push({ ...e, to: wireId, attrs: {} });
42709
+ if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
42710
+ contextSeen.add(wireId);
42711
+ contextNodes.push(shareableContext(t, wireId));
42712
+ }
42713
+ }
42714
+ if (nodes.length === 0 && anchorEdges.length === 0) return null;
42643
42715
  const edges = [];
42644
42716
  for (const id of seen) {
42645
42717
  for (const e of store.outEdges(id, [...INSTANCE_EDGES])) {
42646
42718
  if (seen.has(e.to)) edges.push({ ...e, attrs: {} });
42647
42719
  }
42648
42720
  }
42721
+ edges.push(...anchorEdges);
42649
42722
  const base = {
42650
42723
  daemonVersion,
42651
42724
  profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
42652
- nodes,
42725
+ // Context nodes FIRST: a chunked drain (cloud-client, 25-node chunks) then
42726
+ // co-locates the few Language/Package stubs with the first instance chunk,
42727
+ // maximizing in-payload endpoint resolution.
42728
+ nodes: [...contextNodes, ...nodes],
42653
42729
  edges
42654
42730
  };
42655
- return { ...base, payloadDigest: digest(base) };
42731
+ return { ...base, payloadDigest: digest(base), anchorDigests };
42656
42732
  }
42657
42733
 
42658
42734
  // src/multi.ts
@@ -43234,7 +43310,16 @@ async function startMultiDaemon(opts = {}) {
43234
43310
  let uploaded = 0;
43235
43311
  for (const r of records) {
43236
43312
  const store = r.engine.store;
43237
- const instances = buildInstanceIngest(store, r.engine.profile, DAEMON_VERSION, ignore);
43313
+ const context = buildContextIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
43314
+ includePackages: cfg2.consent.contributePackages
43315
+ });
43316
+ if (context) {
43317
+ const res = await client.ingest(context);
43318
+ uploaded += res.accepted;
43319
+ }
43320
+ const instances = buildInstanceIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
43321
+ includePackages: cfg2.consent.contributePackages
43322
+ });
43238
43323
  if (instances) {
43239
43324
  const res = await client.ingest(instances);
43240
43325
  uploaded += res.accepted;
@@ -43244,7 +43329,7 @@ async function startMultiDaemon(opts = {}) {
43244
43329
  );
43245
43330
  for (const n of instances.nodes) {
43246
43331
  const local = store.getNode(n.id);
43247
- if (!local) continue;
43332
+ if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
43248
43333
  const cloudNodeId = cloudIdByLocal.get(n.id);
43249
43334
  store.updateNode(n.id, {
43250
43335
  attrs: {
@@ -43254,13 +43339,13 @@ async function startMultiDaemon(opts = {}) {
43254
43339
  }
43255
43340
  });
43256
43341
  }
43257
- }
43258
- const context = buildContextIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
43259
- includePackages: cfg2.consent.contributePackages
43260
- });
43261
- if (context) {
43262
- const res = await client.ingest(context);
43263
- uploaded += res.accepted;
43342
+ for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
43343
+ const local = store.getNode(localId);
43344
+ if (!local) continue;
43345
+ store.updateNode(localId, {
43346
+ attrs: { ...local.attrs, anchorsContributedDigest: dg }
43347
+ });
43348
+ }
43264
43349
  }
43265
43350
  }
43266
43351
  return { uploaded };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.22",
3
+ "version": "2.0.0-dev.23",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {