@inerrata-corporation/errata 2.0.6-dev.2069 → 2.0.6-dev.2081

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 +71 -11
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -77056,7 +77056,7 @@ function createWatchBreaker(deps) {
77056
77056
  }
77057
77057
 
77058
77058
  // src/engine.ts
77059
- var DAEMON_VERSION = true ? "2.0.6-dev.2069" : "2.0.0-alpha.0";
77059
+ var DAEMON_VERSION = true ? "2.0.6-dev.2081" : "2.0.0-alpha.0";
77060
77060
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
77061
77061
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
77062
77062
  var GIT_OP_MUTE_MS = 4e3;
@@ -79783,6 +79783,13 @@ var SHIP_TERMINAL_REFUSALS = 3;
79783
79783
  function refusalFingerprint(reason, description) {
79784
79784
  return digest(`${reason}\0${description}`);
79785
79785
  }
79786
+ function isRetryableRefusal(reason) {
79787
+ return /\bretry\b/i.test(reason);
79788
+ }
79789
+ function isTerminallyRefused(n) {
79790
+ const reason = String(n.attrs["shipRefusedReason"] ?? "");
79791
+ return typeof n.attrs["shipRefusedCount"] === "number" && n.attrs["shipRefusedCount"] >= SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason) && n.attrs["shipRefusedFingerprint"] === refusalFingerprint(reason, n.description);
79792
+ }
79786
79793
  function unshippableReason(canonical, label) {
79787
79794
  void label;
79788
79795
  if (canonical.length < WIRE_CANONICAL_ID_MIN) {
@@ -79935,10 +79942,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
79935
79942
  composition.autoMint++;
79936
79943
  continue;
79937
79944
  }
79938
- if (typeof n.attrs["shipRefusedCount"] === "number" && n.attrs["shipRefusedCount"] >= SHIP_TERMINAL_REFUSALS && n.attrs["shipRefusedFingerprint"] === refusalFingerprint(
79939
- String(n.attrs["shipRefusedReason"] ?? ""),
79940
- n.description
79941
- )) {
79945
+ if (isTerminallyRefused(n)) {
79942
79946
  composition.terminalRefused++;
79943
79947
  continue;
79944
79948
  }
@@ -80022,12 +80026,14 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
80022
80026
  }
80023
80027
  }
80024
80028
  const project = opts.project;
80029
+ const projectAnchorDigests = {};
80025
80030
  if (project) {
80026
80031
  const now = Date.now();
80027
80032
  for (const sourceId of anchorSources) {
80028
80033
  const source = store.getNode(sourceId);
80029
80034
  if (!source) continue;
80030
80035
  const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
80036
+ const planned = [];
80031
80037
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
80032
80038
  const target = store.getNode(e.to);
80033
80039
  if (!target) continue;
@@ -80035,7 +80041,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
80035
80041
  const qname = target.attrs["qname"];
80036
80042
  if (typeof relPath !== "string" || typeof qname !== "string") continue;
80037
80043
  if (ignored(relPath) || ignored(qname)) continue;
80038
- const symId = projectSymbolId(project.salt, project.projectId, relPath, qname, target.label);
80044
+ planned.push({ e, target, symId: projectSymbolId(project.salt, project.projectId, relPath, qname, target.label) });
80045
+ }
80046
+ if (planned.length === 0) continue;
80047
+ const dg = digest(
80048
+ planned.map(({ e, symId }) => `ANCHORED_AT>${symId}>${JSON.stringify(anchorVersionAttrs(e.attrs))}`).sort()
80049
+ );
80050
+ if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
80051
+ projectAnchorDigests[sourceId] = dg;
80052
+ for (const { e, target, symId } of planned) {
80039
80053
  if (!contextSeen.has(symId)) {
80040
80054
  contextSeen.add(symId);
80041
80055
  contextNodes.push({
@@ -80142,6 +80156,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
80142
80156
  }
80143
80157
  const shippableNodes = heldOrphans.size === 0 ? nodes : nodes.filter((n) => !heldOrphans.has(n.id));
80144
80158
  const shippableEdges = heldOrphans.size === 0 ? edges : edges.filter((e) => !heldOrphans.has(e.from) && !heldOrphans.has(e.to));
80159
+ for (const id of heldOrphans) {
80160
+ delete anchorDigests[id];
80161
+ delete semanticEdgeDigests[id];
80162
+ delete projectAnchorDigests[id];
80163
+ }
80145
80164
  if (heldOrphans.size > 0) {
80146
80165
  console.warn(
80147
80166
  `[errata] held ${heldOrphans.size} causal-orphan node(s) \u2014 no shippable binding edge this drain (VS-orphan-gate)`
@@ -80171,7 +80190,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
80171
80190
  ...symbolSummaries ? { symbolSummaries } : {}
80172
80191
  };
80173
80192
  opts.onComposition?.(composition);
80174
- return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, composition };
80193
+ return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
80175
80194
  }
80176
80195
 
80177
80196
  // src/backfill-edges.ts
@@ -84325,7 +84344,8 @@ async function startMultiDaemon(opts = {}) {
84325
84344
  // Same shape as the drained row: a first/last trend reading must not
84326
84345
  // straddle rows where the counter is merely absent.
84327
84346
  blockedRepeat: 0,
84328
- rejectedRepeat: 0
84347
+ rejectedRepeat: 0,
84348
+ edgesRejected: 0
84329
84349
  });
84330
84350
  }
84331
84351
  if (instances) {
@@ -84353,6 +84373,17 @@ async function startMultiDaemon(opts = {}) {
84353
84373
  for (const rn of res.result.nodes) {
84354
84374
  if (rn.decision === "rejected") rejected.set(rn.canonicalId, rn.reason ?? "no reason given");
84355
84375
  }
84376
+ const rejectedEdges = res.result.edges.filter((re) => re.decision === "rejected");
84377
+ if (rejectedEdges.length > 0) {
84378
+ const byReason = /* @__PURE__ */ new Map();
84379
+ for (const re of rejectedEdges) {
84380
+ const why = `${re.type}: ${re.reason ?? "no reason given"}`;
84381
+ byReason.set(why, (byReason.get(why) ?? 0) + 1);
84382
+ }
84383
+ console.warn(
84384
+ `[sync\u2192cloud] [${projectName}] instances: ${rejectedEdges.length} edge(s) REJECTED by the door: ` + [...byReason.entries()].map(([why, n]) => `${n}\xD7 ${why}`).join(" | ")
84385
+ );
84386
+ }
84356
84387
  if (rejected.size > 0) {
84357
84388
  const sample = [...rejected.entries()].slice(0, 3).map(([id, why]) => `${store.getNode(id)?.description.slice(0, 60) ?? id}: ${why}`);
84358
84389
  console.warn(
@@ -84368,6 +84399,7 @@ async function startMultiDaemon(opts = {}) {
84368
84399
  };
84369
84400
  let blockedRepeat = 0;
84370
84401
  let rejectedRepeat = 0;
84402
+ const nowHeld = [];
84371
84403
  const noteRefused = (id, reason, repeat) => {
84372
84404
  const owner = owningStore(id);
84373
84405
  if (!owner) return;
@@ -84384,9 +84416,17 @@ async function startMultiDaemon(opts = {}) {
84384
84416
  shipRefusedFingerprint: fp
84385
84417
  }
84386
84418
  });
84419
+ if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
84420
+ nowHeld.push({ id, reason });
84421
+ }
84387
84422
  };
84388
84423
  for (const id of blocked) noteRefused(id, "blocked", () => blockedRepeat++);
84389
84424
  for (const [id, why] of rejected) noteRefused(id, why, () => rejectedRepeat++);
84425
+ if (nowHeld.length > 0) {
84426
+ console.warn(
84427
+ `[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(" | ")
84428
+ );
84429
+ }
84390
84430
  for (const n of instances.nodes) {
84391
84431
  const owner = owningStore(n.id);
84392
84432
  if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) continue;
@@ -84416,6 +84456,14 @@ async function startMultiDaemon(opts = {}) {
84416
84456
  attrs: { ...owner.n.attrs, anchorsContributedDigest: dg }
84417
84457
  });
84418
84458
  }
84459
+ for (const [localId, dg] of Object.entries(instances.projectAnchorDigests)) {
84460
+ const owner = owningStore(localId);
84461
+ if (!owner) continue;
84462
+ if (rejected.has(localId) || blocked.has(localId)) continue;
84463
+ owner.s.updateNode(localId, {
84464
+ attrs: { ...owner.n.attrs, projectAnchorsContributedDigest: dg }
84465
+ });
84466
+ }
84419
84467
  for (const [localId, dg] of Object.entries(instances.semanticEdgeDigests)) {
84420
84468
  const owner = owningStore(localId);
84421
84469
  if (!owner) continue;
@@ -84434,7 +84482,8 @@ async function startMultiDaemon(opts = {}) {
84434
84482
  // node; flat at 1 with `blockedRepeat` 0 is a different node
84435
84483
  // failing every pass. Same total, different bug.
84436
84484
  blockedRepeat,
84437
- rejectedRepeat
84485
+ rejectedRepeat,
84486
+ edgesRejected: rejectedEdges.length
84438
84487
  });
84439
84488
  return res.accepted;
84440
84489
  });
@@ -85771,15 +85820,26 @@ async function cmdStatus() {
85771
85820
  try {
85772
85821
  let pending = 0;
85773
85822
  let total = 0;
85823
+ let heldRefused = 0;
85824
+ let autoMint = 0;
85774
85825
  for (const label of ["Problem", "Solution", "RootCause"]) {
85775
85826
  for (const n of store.findNodesByLabel(label)) {
85776
85827
  if (n.attrs["source"] === "cloud") continue;
85777
85828
  total++;
85778
85829
  const c = n.attrs["contributedAtSeq"];
85779
- if (typeof c !== "number" || (n.lastReinforcedAtSeq ?? 0) > c) pending++;
85830
+ if (typeof c === "number" && (n.lastReinforcedAtSeq ?? 0) <= c) continue;
85831
+ if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) autoMint++;
85832
+ else if (isTerminallyRefused(n)) heldRefused++;
85833
+ else pending++;
85780
85834
  }
85781
85835
  }
85782
- console.log(` contribute: ${pending} pending of ${total} instance node(s)`);
85836
+ const held = [
85837
+ ...heldRefused > 0 ? [`${heldRefused} held after identical door refusals`] : [],
85838
+ ...autoMint > 0 ? [`${autoMint} auto-close marker(s) that never ship`] : []
85839
+ ];
85840
+ console.log(
85841
+ ` contribute: ${pending} pending of ${total} instance node(s)${held.length > 0 ? ` \xB7 ${held.join(" \xB7 ")}` : ""}`
85842
+ );
85783
85843
  const rejections = store.edgeRejections();
85784
85844
  if (rejections.length > 0) {
85785
85845
  const refused = rejections.reduce((n, r) => n + r.count, 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.6-dev.2069",
3
+ "version": "2.0.6-dev.2081",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {