@inerrata-corporation/errata 2.0.17-dev.3433 → 2.0.17-dev.3447

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 +68 -58
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -26399,7 +26399,7 @@ function parseRestErrorEnvelope(text) {
26399
26399
  return null;
26400
26400
  }
26401
26401
  }
26402
- var asWireCount, INGEST_NODE_CHUNK, E6B_PUBLIC_CONTEXT_SENTINEL, CloudClient, CloudError;
26402
+ var asWireCount, INGEST_NODE_CHUNK, INGEST_EDGE_CHUNK, E6B_PUBLIC_CONTEXT_SENTINEL, CloudClient, CloudError;
26403
26403
  var init_client = __esm({
26404
26404
  "../../packages/cloud-client/src/client.ts"() {
26405
26405
  "use strict";
@@ -26407,6 +26407,7 @@ var init_client = __esm({
26407
26407
  init_src();
26408
26408
  asWireCount = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0 ? Math.floor(n) : null;
26409
26409
  INGEST_NODE_CHUNK = 8;
26410
+ INGEST_EDGE_CHUNK = 32;
26410
26411
  E6B_PUBLIC_CONTEXT_SENTINEL = "00000000-0000-4e6b-8000-000000000e6b";
26411
26412
  CloudClient = class {
26412
26413
  baseUrl;
@@ -26598,42 +26599,45 @@ var init_client = __esm({
26598
26599
  async ingest(batch, opts = {}) {
26599
26600
  const runId = randomUUID();
26600
26601
  const startedAt = Date.now();
26601
- const totalChunks = Math.max(1, Math.ceil(batch.nodes.length / INGEST_NODE_CHUNK)) + Math.ceil(Math.max(0, batch.edges.length - MAX_EDGES_PER_PAYLOAD) / MAX_EDGES_PER_PAYLOAD);
26602
+ const single = batch.nodes.length <= INGEST_NODE_CHUNK && batch.edges.length <= INGEST_EDGE_CHUNK;
26603
+ let pendingEdges = [...batch.edges];
26604
+ const nodePlan = single ? [] : chunkArray(batch.nodes, INGEST_NODE_CHUNK).map((nodes) => {
26605
+ const ids = new Set(nodes.map((n) => n.id));
26606
+ const edges = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, INGEST_EDGE_CHUNK);
26607
+ const shipped = new Set(edges);
26608
+ pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
26609
+ return { nodes, edges };
26610
+ });
26611
+ const totalChunks = single ? 1 : nodePlan.length + Math.ceil(pendingEdges.length / INGEST_EDGE_CHUNK);
26602
26612
  let chunkIndex = 0;
26603
26613
  const blocked = [];
26604
- const emit = (nodeIds, accepted) => {
26614
+ const emit = async (nodeIds, result) => {
26605
26615
  chunkIndex++;
26606
26616
  const refused = blocked.splice(0, blocked.length);
26607
26617
  const refusedSet = new Set(refused);
26608
- opts.onChunk?.({
26618
+ await opts.onChunk?.({
26609
26619
  chunkIndex,
26610
26620
  totalChunks,
26611
26621
  // Watermark only what actually landed — a blocked node never reached the
26612
26622
  // door, and marking it contributed would lose it permanently and silently.
26613
26623
  nodeIds: refusedSet.size ? nodeIds.filter((id) => !refusedSet.has(id)) : nodeIds,
26614
- accepted,
26624
+ accepted: summarizeIngestResult(result).accepted,
26625
+ result,
26615
26626
  elapsedMs: Date.now() - startedAt,
26616
26627
  ...refused.length ? { blockedNodeIds: refused } : {}
26617
26628
  });
26618
26629
  };
26619
- if (batch.nodes.length <= INGEST_NODE_CHUNK && batch.edges.length <= MAX_EDGES_PER_PAYLOAD) {
26630
+ if (single) {
26620
26631
  const result = await this.ingestWithSplit(batch, batch.nodes, batch.edges, blocked);
26621
26632
  const summary = summarizeIngestResult(result);
26622
- emit(batch.nodes.map((n) => n.id), summary.accepted);
26633
+ await emit(batch.nodes.map((n) => n.id), result);
26623
26634
  return { ...summary, result };
26624
26635
  }
26625
26636
  const merged = { runId, nodes: [], edges: [] };
26626
- let pendingEdges = [...batch.edges];
26627
26637
  const echoedCloudId = /* @__PURE__ */ new Map();
26628
- for (const nodeChunk of chunkArray(batch.nodes, INGEST_NODE_CHUNK)) {
26629
- const ids = new Set(nodeChunk.map((n) => n.id));
26630
- const inChunk = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, MAX_EDGES_PER_PAYLOAD);
26631
- if (inChunk.length > 0) {
26632
- const shipped = new Set(inChunk);
26633
- pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
26634
- }
26638
+ for (const { nodes: nodeChunk, edges: inChunk } of nodePlan) {
26635
26639
  const r = await this.ingestWithSplit(batch, nodeChunk, inChunk, blocked);
26636
- emit(nodeChunk.map((n) => n.id), summarizeIngestResult(r).accepted);
26640
+ await emit(nodeChunk.map((n) => n.id), r);
26637
26641
  merged.nodes.push(...r.nodes);
26638
26642
  merged.edges.push(...r.edges);
26639
26643
  for (const rn of r.nodes) {
@@ -26645,7 +26649,7 @@ var init_client = __esm({
26645
26649
  merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
26646
26650
  }
26647
26651
  }
26648
- for (const edgeChunk of chunkArray(pendingEdges, MAX_EDGES_PER_PAYLOAD)) {
26652
+ for (const edgeChunk of chunkArray(pendingEdges, INGEST_EDGE_CHUNK)) {
26649
26653
  const projected = edgeChunk.map((e) => ({
26650
26654
  ...e,
26651
26655
  from: echoedCloudId.get(e.from) ?? e.from,
@@ -26664,11 +26668,11 @@ var init_client = __esm({
26664
26668
  return false;
26665
26669
  });
26666
26670
  if (rewritten.length === 0) {
26667
- emit([], 0);
26671
+ await emit([], { runId, nodes: [], edges: [] });
26668
26672
  continue;
26669
26673
  }
26670
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: rewritten }, randomUUID()));
26671
- emit([], summarizeIngestResult(r).accepted);
26674
+ const r = await this.ingestWithSplit(batch, [], rewritten, blocked);
26675
+ await emit([], r);
26672
26676
  merged.edges.push(...r.edges);
26673
26677
  }
26674
26678
  return { ...summarizeIngestResult(merged), result: merged };
@@ -26697,6 +26701,12 @@ var init_client = __esm({
26697
26701
  } catch (err2) {
26698
26702
  const status = err2 instanceof CloudError ? err2.status : 0;
26699
26703
  const timedOut = status === 502 || status === 504 || status === 408 || status === 0;
26704
+ if (timedOut && nodes.length === 0 && edges.length > 1) {
26705
+ const mid2 = Math.ceil(edges.length / 2);
26706
+ const a2 = await this.ingestWithSplit(batch, [], edges.slice(0, mid2), blocked);
26707
+ const b2 = await this.ingestWithSplit(batch, [], edges.slice(mid2), blocked);
26708
+ return { runId: a2.runId, nodes: [], edges: [...a2.edges, ...b2.edges] };
26709
+ }
26700
26710
  const refusedAtEdge = blocked !== void 0 && isIntermediaryRejection(err2);
26701
26711
  if (refusedAtEdge && nodes.length === 1 && nodes[0]) {
26702
26712
  blocked.push(nodes[0].id);
@@ -82159,7 +82169,7 @@ function createWatchBreaker(deps) {
82159
82169
  }
82160
82170
 
82161
82171
  // src/engine.ts
82162
- var DAEMON_VERSION = true ? "2.0.17-dev.3433" : "2.0.0-alpha.0";
82172
+ var DAEMON_VERSION = true ? "2.0.17-dev.3447" : "2.0.0-alpha.0";
82163
82173
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
82164
82174
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
82165
82175
  var GIT_OP_MUTE_MS = 4e3;
@@ -85076,6 +85086,17 @@ function updateInstanceReceipt(n, destination, patch, mirrorLegacy) {
85076
85086
  function instanceReceiptSequence(n) {
85077
85087
  return Math.max(n.lastReinforcedAtSeq ?? 0, n.createdAtSeq ?? 0);
85078
85088
  }
85089
+ function acceptedInstanceReceipt(current, sent, decision, destination, mirrorLegacy) {
85090
+ if (!["Problem", "Vulnerability", "Solution", "RootCause"].includes(current.label) || !["created", "reinforced"].includes(decision.decision) || !decision.nodeId) return null;
85091
+ return updateInstanceReceipt(current, destination, {
85092
+ contributedAtSeq: instanceReceiptSequence(sent),
85093
+ cloudNodeId: decision.nodeId,
85094
+ shipRefusedSinceSeq: void 0,
85095
+ shipRefusedCount: void 0,
85096
+ shipRefusedReason: void 0,
85097
+ shipRefusedFingerprint: void 0
85098
+ }, mirrorLegacy);
85099
+ }
85079
85100
 
85080
85101
  // src/multi.ts
85081
85102
  init_dist();
@@ -87681,6 +87702,10 @@ async function walk10(root, input, client, opts, readBlob) {
87681
87702
  const launched = /* @__PURE__ */ new Map();
87682
87703
  const cap = opts.maxUnits;
87683
87704
  const edgeParked = /* @__PURE__ */ new Set();
87705
+ const parkedEarlier = new Set((profile.historyStage?.coverageGaps ?? []).filter((g) => g.reason === "edge-blocked").map((g) => `${g.sha}/${g.subIndex}`));
87706
+ units.forEach((u, j) => {
87707
+ if (parkedEarlier.has(`${u.sha}/${u.subIndex}`)) edgeParked.add(j);
87708
+ });
87684
87709
  const predecessor = (k) => {
87685
87710
  for (let j = k - 1; j >= 0; j--) if (!units[j].skip && !edgeParked.has(j)) return units[j];
87686
87711
  return void 0;
@@ -87746,7 +87771,7 @@ async function walk10(root, input, client, opts, readBlob) {
87746
87771
  let ahead = 0;
87747
87772
  for (let j = k + 1; j < units.length && ahead < lookahead; j++) {
87748
87773
  if (cap !== void 0 && processed + (j - k) >= cap) break;
87749
- if (units[j].skip) continue;
87774
+ if (units[j].skip || edgeParked.has(j)) continue;
87750
87775
  ahead += 1;
87751
87776
  await launch(j);
87752
87777
  }
@@ -87767,6 +87792,13 @@ async function walk10(root, input, client, opts, readBlob) {
87767
87792
  log(`[errata] history ${label} skipped (${u.skip})`);
87768
87793
  continue;
87769
87794
  }
87795
+ if (edgeParked.has(k)) {
87796
+ profile = stage(profile, { state: dryRun ? "extracting" : "contributing", unitsDone: doneSoFar, counts, ...lastInPosition ? { watermarkSha: positionSha } : {} }, now);
87797
+ persist(profile);
87798
+ processed += 1;
87799
+ log(`[errata] history ${label}: edge-blocked on an earlier run; gap kept, not re-sent`);
87800
+ continue;
87801
+ }
87770
87802
  const { body: body2, prepMs } = await prepare(k);
87771
87803
  profile = stage(profile, { state: dryRun ? "extracting" : "contributing", unitsDone: doneSoFar - 1, lastError: void 0 }, now);
87772
87804
  persist(profile);
@@ -90279,10 +90311,24 @@ async function startMultiDaemon(opts = {}) {
90279
90311
  if (project) instances.projectId = project.projectId;
90280
90312
  const shipStartedAt = Date.now();
90281
90313
  await lane("instances", projectName, async () => {
90314
+ const owningStore = (id) => {
90315
+ const w = store.getNode(id);
90316
+ if (w) return { s: store, n: w };
90317
+ const sh = sharedStore.getNode(id);
90318
+ return sh ? { s: sharedStore, n: sh } : null;
90319
+ };
90320
+ const sentById = new Map(instances.nodes.map((n) => [n.id, n]));
90282
90321
  const blocked = /* @__PURE__ */ new Set();
90283
90322
  const res = await client.ingest(instances, {
90284
90323
  onChunk: (p) => {
90285
90324
  for (const id of p.blockedNodeIds ?? []) blocked.add(id);
90325
+ for (const decision of p.result.nodes) {
90326
+ const sent = sentById.get(decision.canonicalId);
90327
+ const owner = owningStore(decision.canonicalId);
90328
+ if (!sent || !owner || blocked.has(sent.id)) continue;
90329
+ const attrs = acceptedInstanceReceipt(owner.n, sent, decision, destinationKey, owner.s === store);
90330
+ if (attrs) owner.s.updateNode(sent.id, { attrs });
90331
+ }
90286
90332
  noteFlushProgress(p.accepted, p.nodeIds.length, `instances ${p.chunkIndex}/${p.totalChunks}`);
90287
90333
  }
90288
90334
  });
@@ -90292,9 +90338,6 @@ async function startMultiDaemon(opts = {}) {
90292
90338
  );
90293
90339
  }
90294
90340
  uploaded += res.accepted;
90295
- const cloudIdByLocal = new Map(
90296
- res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
90297
- );
90298
90341
  const rejected = /* @__PURE__ */ new Map();
90299
90342
  for (const rn of res.result.nodes) {
90300
90343
  if (rn.decision === "rejected") rejected.set(rn.canonicalId, rn.reason ?? "no reason given");
@@ -90317,13 +90360,6 @@ async function startMultiDaemon(opts = {}) {
90317
90360
  `[sync\u2192cloud] [${projectName}] instances: ${rejected.size} node(s) REJECTED by the door \u2014 left pending for the next flush: ` + sample.join(" | ")
90318
90361
  );
90319
90362
  }
90320
- const owningStore = (id) => {
90321
- const w = store.getNode(id);
90322
- if (w) return { s: store, n: w };
90323
- const sh = sharedStore.getNode(id);
90324
- if (sh) return { s: sharedStore, n: sh };
90325
- return null;
90326
- };
90327
90363
  let blockedRepeat = 0;
90328
90364
  let rejectedRepeat = 0;
90329
90365
  const nowHeld = [];
@@ -90354,32 +90390,6 @@ async function startMultiDaemon(opts = {}) {
90354
90390
  `[sync\u2192cloud] [${projectName}] instances: HOLDING ${nowHeld.length} node(s) \u2014 refused identically ${SHIP_TERMINAL_REFUSALS}\xD7 on unchanged text; not re-sent until the text changes: ` + nowHeld.map(({ id, reason }) => `${id} "${owningStore(id)?.n.description.slice(0, 60) ?? ""}": ${reason}`).join(" | ")
90355
90391
  );
90356
90392
  }
90357
- await stampBatched(instances.nodes, (n) => {
90358
- const owner = owningStore(n.id);
90359
- if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) return;
90360
- if (blocked.has(n.id)) return;
90361
- if (!cloudIdByLocal.has(n.id)) return;
90362
- if (rejected.has(n.id)) return;
90363
- const cloudNodeId = cloudIdByLocal.get(n.id);
90364
- const {
90365
- shipRefusedSinceSeq: _clearedSeq,
90366
- shipRefusedCount: _clearedCount,
90367
- shipRefusedReason: _clearedReason,
90368
- shipRefusedFingerprint: _clearedFp,
90369
- ...carried
90370
- } = instanceReceipt(owner.n, destinationKey);
90371
- owner.s.updateNode(n.id, {
90372
- attrs: updateInstanceReceipt(owner.n, destinationKey, {
90373
- ...carried,
90374
- shipRefusedSinceSeq: void 0,
90375
- shipRefusedCount: void 0,
90376
- shipRefusedReason: void 0,
90377
- shipRefusedFingerprint: void 0,
90378
- contributedAtSeq: instanceReceiptSequence(n),
90379
- cloudNodeId
90380
- }, owner.s === store)
90381
- });
90382
- });
90383
90393
  await stampBatched(Object.entries(instances.anchorDigests), ([localId, dg]) => {
90384
90394
  const owner = owningStore(localId);
90385
90395
  if (!owner) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.17-dev.3433",
3
+ "version": "2.0.17-dev.3447",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {