@inerrata-corporation/errata 2.0.1-dev.60 → 2.0.1-dev.99

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 +39 -146
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -21851,14 +21851,8 @@ var init_client = __esm({
21851
21851
  * the per-decision response into flush accounting.
21852
21852
  *
21853
21853
  * The v1 door caps a payload at `MAX_NODES_PER_PAYLOAD` / `MAX_EDGES_PER_PAYLOAD`
21854
- * (413 over). A batch above the cap is split and drained across calls, every
21855
- * NODE chunk first (edges empty), then EDGE chunks (nodes empty). Each chunk
21856
- * gets its OWN runId: the door's durable idempotency claim is keyed on
21857
- * (agent, org, runId) with the payload digest, so reusing one runId across
21858
- * different chunk payloads 409s "runId was already used with a different
21859
- * payload" on the second chunk — exactly how the first real >25-node drain
21860
- * died (2026-07-22). The runId never grouped anything server-side; it exists
21861
- * for duplicate-POST protection, which is per-request by nature.
21854
+ * (413 over). A batch above the cap is split and drained across calls under ONE
21855
+ * runId: every NODE chunk first (edges empty), then EDGE chunks (nodes empty).
21862
21856
  * Recognition resolves an edge's endpoints against nodes already ingested this
21863
21857
  * drain (endpoint-label validation is deferred to the service when an endpoint
21864
21858
  * isn't in-payload), so the split never orphans an edge. Sub-results concat into
@@ -21871,7 +21865,6 @@ var init_client = __esm({
21871
21865
  }
21872
21866
  const merged = { runId, nodes: [], edges: [] };
21873
21867
  let pendingEdges = [...batch.edges];
21874
- const echoedCloudId = /* @__PURE__ */ new Map();
21875
21868
  for (const nodeChunk of chunkArray(batch.nodes, INGEST_NODE_CHUNK)) {
21876
21869
  const ids = new Set(nodeChunk.map((n) => n.id));
21877
21870
  const inChunk = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, MAX_EDGES_PER_PAYLOAD);
@@ -21879,23 +21872,15 @@ var init_client = __esm({
21879
21872
  const shipped = new Set(inChunk);
21880
21873
  pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
21881
21874
  }
21882
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, randomUUID()));
21875
+ const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, runId));
21883
21876
  merged.nodes.push(...r.nodes);
21884
21877
  merged.edges.push(...r.edges);
21885
- for (const rn of r.nodes) {
21886
- if (rn.nodeId && rn.nodeId !== rn.canonicalId) echoedCloudId.set(rn.canonicalId, rn.nodeId);
21887
- }
21888
21878
  if (r.patternReconciliation) {
21889
21879
  merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
21890
21880
  }
21891
21881
  }
21892
21882
  for (const edgeChunk of chunkArray(pendingEdges, MAX_EDGES_PER_PAYLOAD)) {
21893
- const rewritten = edgeChunk.map((e) => ({
21894
- ...e,
21895
- from: echoedCloudId.get(e.from) ?? e.from,
21896
- to: echoedCloudId.get(e.to) ?? e.to
21897
- }));
21898
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: rewritten }, randomUUID()));
21883
+ const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: edgeChunk }, runId));
21899
21884
  merged.edges.push(...r.edges);
21900
21885
  }
21901
21886
  return { ...summarizeIngestResult(merged), result: merged };
@@ -51664,7 +51649,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51664
51649
  }
51665
51650
 
51666
51651
  // src/engine.ts
51667
- var DAEMON_VERSION = true ? "2.0.1-dev.60" : "2.0.0-alpha.0";
51652
+ var DAEMON_VERSION = true ? "2.0.1-dev.99" : "2.0.0-alpha.0";
51668
51653
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
51669
51654
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
51670
51655
  var GIT_OP_MUTE_MS = 4e3;
@@ -53253,13 +53238,10 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
53253
53238
  // Package ids are already the purl (= the cross-stratum canonicalId).
53254
53239
  id: label === "Language" ? languageCanonicalId(String(n.attrs["name"] ?? "").trim() || n.description) : n.id,
53255
53240
  embedding: [],
53256
- // No `version` attr on the wire: the purl already encodes the resolved
53257
- // version, and the door's temporal guard rejects ANY `attrs.version` as
53258
- // bi-temporal bookkeeping (ingest-temporal-guard.ts) — shipping it 422s
53259
- // the whole batch. `resolved` still travels (range-vs-lockfile signal).
53260
53241
  attrs: label === "Package" ? {
53261
53242
  purl: n.attrs["purl"],
53262
53243
  name: n.attrs["name"],
53244
+ version: n.attrs["version"],
53263
53245
  ecosystem: n.attrs["ecosystem"],
53264
53246
  resolved: n.attrs["resolved"]
53265
53247
  } : { name: n.attrs["name"] }
@@ -53374,10 +53356,9 @@ function wireContextId(n) {
53374
53356
  }
53375
53357
  function shareableContext(n, wireId) {
53376
53358
  const attrs = n.label === "Package" ? {
53377
- // No `version` attr: the purl encodes it, and the door's temporal
53378
- // guard 422s any `attrs.version` (mirrors buildContextIngest).
53379
53359
  purl: n.attrs["purl"],
53380
53360
  name: n.attrs["name"],
53361
+ version: n.attrs["version"],
53381
53362
  ecosystem: n.attrs["ecosystem"],
53382
53363
  resolved: n.attrs["resolved"]
53383
53364
  } : n.label === "Domain" ? { name: n.description, canonicalId: n.attrs["canonicalId"] } : { name: n.attrs["name"] };
@@ -53444,13 +53425,10 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53444
53425
  }
53445
53426
  if (targets.length === 0) continue;
53446
53427
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
53447
- const sourceNode = store.getNode(sourceId);
53448
- if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
53428
+ if (store.getNode(sourceId)?.attrs["anchorsContributedDigest"] === dg) continue;
53449
53429
  anchorDigests[sourceId] = dg;
53450
- const skippedCloudId = !seen.has(sourceId) ? sourceNode?.attrs["cloudNodeId"] : void 0;
53451
- const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
53452
53430
  for (const { e, t, wireId } of targets) {
53453
- anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
53431
+ anchorEdges.push({ ...e, to: wireId, attrs: {} });
53454
53432
  if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
53455
53433
  contextSeen.add(wireId);
53456
53434
  contextNodes.push(shareableContext(t, wireId));
@@ -53462,8 +53440,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53462
53440
  for (const sourceId of anchorSources) {
53463
53441
  const source = store.getNode(sourceId);
53464
53442
  if (!source) continue;
53465
- const skippedCloudId = !seen.has(sourceId) ? source.attrs["cloudNodeId"] : void 0;
53466
- const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
53467
53443
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
53468
53444
  const target = store.getNode(e.to);
53469
53445
  if (!target) continue;
@@ -53498,7 +53474,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53498
53474
  stability: "unstable"
53499
53475
  });
53500
53476
  }
53501
- anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: {} });
53477
+ anchorEdges.push({ ...e, to: symId, attrs: {} });
53502
53478
  }
53503
53479
  }
53504
53480
  }
@@ -53546,46 +53522,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53546
53522
  return { ...base, payloadDigest: digest(base), anchorDigests };
53547
53523
  }
53548
53524
 
53549
- // src/backfill-edges.ts
53550
- init_src();
53551
- init_src2();
53552
- var CAUSAL_LABELS = ["Problem", "Solution", "RootCause"];
53553
- var CAUSAL_EDGES2 = ["SOLVED_BY", "CAUSED_BY", "FIXED_BY"];
53554
- function cloudWireId(store, id) {
53555
- const n = store.getNode(id);
53556
- if (!n || !CAUSAL_LABELS.includes(n.label)) return null;
53557
- if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) return null;
53558
- const cloudNodeId = n.attrs["cloudNodeId"];
53559
- if (typeof cloudNodeId === "string" && cloudNodeId.length > 0) return cloudNodeId;
53560
- if (n.attrs["source"] === "cloud") return n.id;
53561
- return typeof n.attrs["contributedAtSeq"] === "number" ? n.id : null;
53562
- }
53563
- function buildCausalEdgeBackfill(store, profile, daemonVersion) {
53564
- const edges = [];
53565
- const seenEdge = /* @__PURE__ */ new Set();
53566
- for (const label of CAUSAL_LABELS) {
53567
- for (const n of store.findNodesByLabel(label)) {
53568
- for (const e of store.outEdges(n.id, [...CAUSAL_EDGES2])) {
53569
- if (seenEdge.has(e.id)) continue;
53570
- seenEdge.add(e.id);
53571
- const from = cloudWireId(store, e.from);
53572
- const to = cloudWireId(store, e.to);
53573
- if (!from || !to) continue;
53574
- edges.push({ ...e, from, to, attrs: {} });
53575
- }
53576
- }
53577
- }
53578
- if (edges.length === 0) return null;
53579
- const base = {
53580
- daemonVersion,
53581
- profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
53582
- originProject: profile.id,
53583
- nodes: [],
53584
- edges
53585
- };
53586
- return { ...base, payloadDigest: digest(base) };
53587
- }
53588
-
53589
53525
  // src/multi.ts
53590
53526
  init_generalize_graph();
53591
53527
  init_symbol_summaries();
@@ -54597,27 +54533,14 @@ async function startMultiDaemon(opts = {}) {
54597
54533
  const ignore = loadClaimIgnorePatterns(globalDir());
54598
54534
  const client = cloudNow();
54599
54535
  let uploaded = 0;
54600
- const errors = [];
54601
- const lane = async (name2, projectName, run3) => {
54602
- try {
54603
- await run3();
54604
- } catch (err2) {
54605
- const msg = `[${projectName}] ${name2}: ${err2 instanceof Error ? err2.message : String(err2)}`;
54606
- errors.push(msg);
54607
- console.error(`[sync\u2192cloud] ${msg}`);
54608
- }
54609
- };
54610
54536
  for (const r of records) {
54611
54537
  const store = r.engine.store;
54612
- const projectName = r.engine.profile.name ?? r.engine.profile.id;
54613
54538
  const context = buildContextIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
54614
54539
  includePackages: cfg2.consent.contributePackages
54615
54540
  });
54616
54541
  if (context) {
54617
- await lane("context", projectName, async () => {
54618
- const res = await client.ingest(context);
54619
- uploaded += res.accepted;
54620
- });
54542
+ const res = await client.ingest(context);
54543
+ uploaded += res.accepted;
54621
54544
  }
54622
54545
  let lexicon;
54623
54546
  try {
@@ -54640,58 +54563,34 @@ async function startMultiDaemon(opts = {}) {
54640
54563
  });
54641
54564
  if (instances) {
54642
54565
  if (project) instances.projectId = project.projectId;
54643
- await lane("instances", projectName, async () => {
54644
- const res = await client.ingest(instances);
54645
- uploaded += res.accepted;
54646
- const seq = store.currentIngestSeq();
54647
- const cloudIdByLocal = new Map(
54648
- res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
54649
- );
54650
- for (const n of instances.nodes) {
54651
- const local = store.getNode(n.id);
54652
- if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
54653
- const cloudNodeId = cloudIdByLocal.get(n.id);
54654
- store.updateNode(n.id, {
54655
- attrs: {
54656
- ...local.attrs,
54657
- contributedAtSeq: seq,
54658
- ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
54659
- }
54660
- });
54661
- }
54662
- for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
54663
- const local = store.getNode(localId);
54664
- if (!local) continue;
54665
- store.updateNode(localId, {
54666
- attrs: { ...local.attrs, anchorsContributedDigest: dg }
54667
- });
54668
- }
54669
- });
54670
- }
54671
- }
54672
- return { uploaded, ...errors.length > 0 ? { errors } : {} };
54673
- },
54674
- async backfillCausalEdges() {
54675
- if (!loadConfig().consent.sync) return { accepted: 0, rejected: 0, skipped: "consent-off" };
54676
- const client = cloudNow();
54677
- let accepted = 0;
54678
- let rejected = 0;
54679
- const errors = [];
54680
- for (const r of records) {
54681
- const payload = buildCausalEdgeBackfill(r.engine.store, r.engine.profile, DAEMON_VERSION);
54682
- if (!payload) continue;
54683
- try {
54684
- const res = await client.ingest(payload);
54685
- accepted += res.accepted;
54686
- rejected += res.rejected;
54687
- if (res.rejected > 0) errors.push(...res.violations.slice(0, 5));
54688
- } catch (err2) {
54689
- errors.push(
54690
- `[${r.engine.profile.name ?? r.engine.profile.id}] backfill: ${err2 instanceof Error ? err2.message : String(err2)}`
54566
+ const res = await client.ingest(instances);
54567
+ uploaded += res.accepted;
54568
+ const seq = store.currentIngestSeq();
54569
+ const cloudIdByLocal = new Map(
54570
+ res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
54691
54571
  );
54572
+ for (const n of instances.nodes) {
54573
+ const local = store.getNode(n.id);
54574
+ if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
54575
+ const cloudNodeId = cloudIdByLocal.get(n.id);
54576
+ store.updateNode(n.id, {
54577
+ attrs: {
54578
+ ...local.attrs,
54579
+ contributedAtSeq: seq,
54580
+ ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
54581
+ }
54582
+ });
54583
+ }
54584
+ for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
54585
+ const local = store.getNode(localId);
54586
+ if (!local) continue;
54587
+ store.updateNode(localId, {
54588
+ attrs: { ...local.attrs, anchorsContributedDigest: dg }
54589
+ });
54590
+ }
54692
54591
  }
54693
54592
  }
54694
- return { accepted, rejected, ...errors.length > 0 ? { errors } : {} };
54593
+ return { uploaded };
54695
54594
  },
54696
54595
  async pullTriagePublic() {
54697
54596
  if (!loadConfig().consent.sync) return { merged: 0, skipped: "consent-off" };
@@ -54741,12 +54640,7 @@ async function startMultiDaemon(opts = {}) {
54741
54640
  }
54742
54641
  const inst = await daemon.syncInstancesPublic();
54743
54642
  const skills = await daemon.syncSkillsAll();
54744
- return {
54745
- uploaded: inst.uploaded,
54746
- written: skills.written,
54747
- pruned: skills.pruned,
54748
- ...inst.errors ? { errors: inst.errors } : {}
54749
- };
54643
+ return { uploaded: inst.uploaded, written: skills.written, pruned: skills.pruned };
54750
54644
  } finally {
54751
54645
  boundaryFlushing = false;
54752
54646
  }
@@ -54777,8 +54671,7 @@ async function startMultiDaemon(opts = {}) {
54777
54671
  const principles = await daemon.syncPrinciplesPublic();
54778
54672
  const triage = await daemon.syncTriagePublic();
54779
54673
  const instances = await daemon.syncInstancesPublic();
54780
- const edgeBackfill = await daemon.backfillCausalEdges();
54781
- return c.json({ principles, triage, instances, edgeBackfill });
54674
+ return c.json({ principles, triage, instances });
54782
54675
  } catch (err2) {
54783
54676
  return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 500);
54784
54677
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.1-dev.60",
3
+ "version": "2.0.1-dev.99",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {