@inerrata-corporation/errata 2.0.17-dev.3469 → 2.0.17-dev.3483

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.
@@ -18584,13 +18584,18 @@ var INSTANCE_ANCHOR_EDGE_TYPES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONC
18584
18584
  function instanceCloudWithdrawal(n, destination, getMeta) {
18585
18585
  const id = n.attrs["source"] === "cloud" ? n.attrs["cloudNodeId"] ?? n.id : instanceReceipt(n, destination)["cloudNodeId"];
18586
18586
  if (typeof id !== "string") return false;
18587
+ const receipt = instanceReceipt(n, destination);
18588
+ const held = receipt["cloudWithdrawn"] === true;
18587
18589
  const raw = getMeta(`history-correction:${id}`);
18588
- if (!raw) return false;
18590
+ if (!raw) return held;
18589
18591
  try {
18590
18592
  const correction = JSON.parse(raw);
18591
- return correction.nodeId === id && correction.action === "quarantine" && correction.sourceSupport !== "supported";
18592
- } catch {
18593
+ if (correction.nodeId !== id) return held;
18594
+ if (correction.action === "quarantine" && correction.sourceSupport !== "supported") return true;
18595
+ if (held && (correction.seq ?? 0) <= Number(receipt["withdrawnAtCorrectionSeq"] ?? 0)) return true;
18593
18596
  return false;
18597
+ } catch {
18598
+ return held;
18594
18599
  }
18595
18600
  }
18596
18601
  function receiptMap(attrs) {
@@ -19727,6 +19732,13 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19727
19732
  const anchorEdges = [];
19728
19733
  const contextNodes = [];
19729
19734
  const contextSeen = /* @__PURE__ */ new Set();
19735
+ const contextNodeSources = {};
19736
+ const endpointSources = {};
19737
+ const trackEndpoint = (wireId, localId) => {
19738
+ const sources = endpointSources[wireId] ??= [];
19739
+ if (!sources.includes(localId)) sources.push(localId);
19740
+ };
19741
+ for (const [localId, wireId] of semanticEndpoints) trackEndpoint(wireId, localId);
19730
19742
  const anchorDigests = {};
19731
19743
  for (const sourceId of anchorSources) {
19732
19744
  const targets = [];
@@ -19743,13 +19755,16 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19743
19755
  if (e.type === "CONCERNS" && t.label !== "Component") continue;
19744
19756
  if ((t.label === "Package" || t.label === "Component") && opts.includePackages !== true) continue;
19745
19757
  if (ignored(t.description) || ignored(String(t.attrs["name"] ?? ""))) continue;
19746
- targets.push({ e, t, wireId: wireContextId(t) });
19758
+ const receipt = instanceReceipt(t, opts.destinationKey);
19759
+ const wireId = typeof receipt["contributedAtSeq"] === "number" && typeof receipt["cloudNodeId"] === "string" ? receipt["cloudNodeId"] : wireContextId(t);
19760
+ targets.push({ e, t, wireId });
19761
+ trackEndpoint(wireId, t.id);
19747
19762
  }
19748
19763
  if (targets.length === 0) continue;
19749
19764
  const shipped = shippedById.get(sourceId);
19750
19765
  if (shipped && !shipped.attrs["privateFinding"]) {
19751
19766
  const anchors = (label) => targets.filter((x) => x.t.label === label).map(
19752
- (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
19767
+ (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${wireContextId(x.t)}` : wireContextId(x.t)
19753
19768
  ).filter((a) => a != null).sort();
19754
19769
  const anchor = anchors("Package")[0] ?? anchors("Component")[0] ?? anchors("Language")[0];
19755
19770
  if (anchor) {
@@ -19769,8 +19784,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19769
19784
  continue;
19770
19785
  }
19771
19786
  anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
19772
- if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
19787
+ if (t.attrs["source"] === "cloud" || contextSeen.has(wireId) || typeof instanceReceipt(t, opts.destinationKey)["contributedAtSeq"] === "number") continue;
19773
19788
  contextSeen.add(wireId);
19789
+ contextNodeSources[wireId] = t.id;
19774
19790
  contextNodes.push(shareableContext(t, wireId));
19775
19791
  }
19776
19792
  }
@@ -19974,7 +19990,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19974
19990
  ...symbolSummaries ? { symbolSummaries } : {}
19975
19991
  };
19976
19992
  opts.onComposition?.(composition);
19977
- return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
19993
+ return { ...base, payloadDigest: digest(base), contextNodeSources, endpointSources, anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
19978
19994
  }
19979
19995
 
19980
19996
  // src/drain-build.ts
package/errata.mjs CHANGED
@@ -82234,7 +82234,7 @@ function createWatchBreaker(deps) {
82234
82234
  }
82235
82235
 
82236
82236
  // src/engine.ts
82237
- var DAEMON_VERSION = true ? "2.0.17-dev.3469" : "2.0.0-alpha.0";
82237
+ var DAEMON_VERSION = true ? "2.0.17-dev.3483" : "2.0.0-alpha.0";
82238
82238
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
82239
82239
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
82240
82240
  var GIT_OP_MUTE_MS = 4e3;
@@ -85150,16 +85150,21 @@ function instanceEdgeReceipts(sent, received, cloudIds) {
85150
85150
  function instanceCloudWithdrawal(n, destination, getMeta) {
85151
85151
  const id = n.attrs["source"] === "cloud" ? n.attrs["cloudNodeId"] ?? n.id : instanceReceipt(n, destination)["cloudNodeId"];
85152
85152
  if (typeof id !== "string") return false;
85153
+ const receipt = instanceReceipt(n, destination);
85154
+ const held = receipt["cloudWithdrawn"] === true;
85153
85155
  const raw2 = getMeta(`history-correction:${id}`);
85154
- if (!raw2) return false;
85156
+ if (!raw2) return held;
85155
85157
  try {
85156
85158
  const correction = JSON.parse(raw2);
85157
- return correction.nodeId === id && correction.action === "quarantine" && correction.sourceSupport !== "supported";
85158
- } catch {
85159
+ if (correction.nodeId !== id) return held;
85160
+ if (correction.action === "quarantine" && correction.sourceSupport !== "supported") return true;
85161
+ if (held && (correction.seq ?? 0) <= Number(receipt["withdrawnAtCorrectionSeq"] ?? 0)) return true;
85159
85162
  return false;
85163
+ } catch {
85164
+ return held;
85160
85165
  }
85161
85166
  }
85162
- var FIELDS = ["contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
85167
+ var FIELDS = ["cloudWithdrawn", "withdrawnAtCorrectionSeq", "contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
85163
85168
  function instanceDestinationKey(input) {
85164
85169
  return createHash18("sha256").update(JSON.stringify([
85165
85170
  input.workspace,
@@ -85191,16 +85196,59 @@ function instanceReceiptSequence(n) {
85191
85196
  return Math.max(n.lastReinforcedAtSeq ?? 0, n.createdAtSeq ?? 0);
85192
85197
  }
85193
85198
  function acceptedInstanceReceipt(current, sent, decision, destination, mirrorLegacy) {
85194
- if (!["Problem", "Vulnerability", "Solution", "RootCause"].includes(current.label) || !["created", "reinforced"].includes(decision.decision) || !decision.nodeId) return null;
85199
+ if (!["Problem", "Vulnerability", "Solution", "RootCause", "Language", "Package", "Domain", "Component"].includes(current.label) || !["created", "reinforced"].includes(decision.decision) || !decision.nodeId) return null;
85195
85200
  return updateInstanceReceipt(current, destination, {
85196
85201
  contributedAtSeq: instanceReceiptSequence(sent),
85197
85202
  cloudNodeId: decision.nodeId,
85203
+ cloudWithdrawn: void 0,
85204
+ withdrawnAtCorrectionSeq: void 0,
85198
85205
  shipRefusedSinceSeq: void 0,
85199
85206
  shipRefusedCount: void 0,
85200
85207
  shipRefusedReason: void 0,
85201
85208
  shipRefusedFingerprint: void 0
85202
85209
  }, mirrorLegacy);
85203
85210
  }
85211
+ function withdrawnInstanceReceipt(current, destination, decision, getMeta, mirrorLegacy) {
85212
+ if (decision.decision !== "rejected" || !decision.nodeId || !decision.reason?.startsWith("cloud node withdrawn")) return null;
85213
+ let seq = 0;
85214
+ try {
85215
+ seq = Number(JSON.parse(getMeta(`history-correction:${decision.nodeId}`) ?? "{}").seq ?? 0);
85216
+ } catch {
85217
+ }
85218
+ return updateInstanceReceipt(current, destination, {
85219
+ cloudNodeId: decision.nodeId,
85220
+ cloudWithdrawn: true,
85221
+ withdrawnAtCorrectionSeq: seq,
85222
+ contributedAtSeq: void 0,
85223
+ anchorsContributedDigest: void 0,
85224
+ projectAnchorsContributedDigest: void 0,
85225
+ semanticEdgesContributedDigest: void 0
85226
+ }, mirrorLegacy);
85227
+ }
85228
+ function invalidInstanceEndpointIds(edges) {
85229
+ const ids = /* @__PURE__ */ new Set();
85230
+ for (const edge2 of edges) {
85231
+ if (edge2.decision !== "rejected") continue;
85232
+ if (edge2.reason === "edge endpoints are outside the authorized write scope") {
85233
+ ids.add(edge2.from);
85234
+ ids.add(edge2.to);
85235
+ } else {
85236
+ const missing = /^unresolved endpoint '([^']+)'/.exec(edge2.reason ?? "");
85237
+ if (missing) ids.add(missing[1]);
85238
+ }
85239
+ }
85240
+ return ids;
85241
+ }
85242
+ function invalidateInstanceReceipt(current, destination, failedId, mirrorLegacy) {
85243
+ if (instanceReceipt(current, destination)["cloudNodeId"] !== failedId) return null;
85244
+ return updateInstanceReceipt(current, destination, {
85245
+ cloudNodeId: void 0,
85246
+ contributedAtSeq: void 0,
85247
+ anchorsContributedDigest: void 0,
85248
+ projectAnchorsContributedDigest: void 0,
85249
+ semanticEdgesContributedDigest: void 0
85250
+ }, mirrorLegacy);
85251
+ }
85204
85252
 
85205
85253
  // src/multi.ts
85206
85254
  init_dist();
@@ -85853,6 +85901,13 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
85853
85901
  const anchorEdges = [];
85854
85902
  const contextNodes = [];
85855
85903
  const contextSeen = /* @__PURE__ */ new Set();
85904
+ const contextNodeSources = {};
85905
+ const endpointSources = {};
85906
+ const trackEndpoint = (wireId, localId) => {
85907
+ const sources = endpointSources[wireId] ??= [];
85908
+ if (!sources.includes(localId)) sources.push(localId);
85909
+ };
85910
+ for (const [localId, wireId] of semanticEndpoints) trackEndpoint(wireId, localId);
85856
85911
  const anchorDigests = {};
85857
85912
  for (const sourceId of anchorSources) {
85858
85913
  const targets = [];
@@ -85869,13 +85924,16 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
85869
85924
  if (e.type === "CONCERNS" && t.label !== "Component") continue;
85870
85925
  if ((t.label === "Package" || t.label === "Component") && opts.includePackages !== true) continue;
85871
85926
  if (ignored(t.description) || ignored(String(t.attrs["name"] ?? ""))) continue;
85872
- targets.push({ e, t, wireId: wireContextId(t) });
85927
+ const receipt = instanceReceipt(t, opts.destinationKey);
85928
+ const wireId = typeof receipt["contributedAtSeq"] === "number" && typeof receipt["cloudNodeId"] === "string" ? receipt["cloudNodeId"] : wireContextId(t);
85929
+ targets.push({ e, t, wireId });
85930
+ trackEndpoint(wireId, t.id);
85873
85931
  }
85874
85932
  if (targets.length === 0) continue;
85875
85933
  const shipped = shippedById.get(sourceId);
85876
85934
  if (shipped && !shipped.attrs["privateFinding"]) {
85877
85935
  const anchors = (label) => targets.filter((x) => x.t.label === label).map(
85878
- (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
85936
+ (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${wireContextId(x.t)}` : wireContextId(x.t)
85879
85937
  ).filter((a) => a != null).sort();
85880
85938
  const anchor = anchors("Package")[0] ?? anchors("Component")[0] ?? anchors("Language")[0];
85881
85939
  if (anchor) {
@@ -85895,8 +85953,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
85895
85953
  continue;
85896
85954
  }
85897
85955
  anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
85898
- if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
85956
+ if (t.attrs["source"] === "cloud" || contextSeen.has(wireId) || typeof instanceReceipt(t, opts.destinationKey)["contributedAtSeq"] === "number") continue;
85899
85957
  contextSeen.add(wireId);
85958
+ contextNodeSources[wireId] = t.id;
85900
85959
  contextNodes.push(shareableContext(t, wireId));
85901
85960
  }
85902
85961
  }
@@ -86100,7 +86159,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
86100
86159
  ...symbolSummaries ? { symbolSummaries } : {}
86101
86160
  };
86102
86161
  opts.onComposition?.(composition);
86103
- return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
86162
+ return { ...base, payloadDigest: digest(base), contextNodeSources, endpointSources, anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
86104
86163
  }
86105
86164
 
86106
86165
  // src/backfill-edges.ts
@@ -88109,6 +88168,12 @@ function historyConsents(profile) {
88109
88168
  contributeHistory: Boolean(c?.contributeHistory) && profile.syncConsent !== "disabled"
88110
88169
  };
88111
88170
  }
88171
+ var HISTORY_RETRY_INTERVAL_MS = 5 * 60 * 1e3;
88172
+ function historyRetryDue(profile, now, lastAttempt = 0) {
88173
+ if (!profile.projectId || !profile.projectHydratedAt || profile.historyStage?.state !== "paused" || !historyConsents(profile).mineHistory || profile.syncConsent === "disabled") return false;
88174
+ const pausedAt = Date.parse(profile.historyStage.updatedAt);
88175
+ return Number.isFinite(pausedAt) && now - Math.max(pausedAt, lastAttempt) >= HISTORY_RETRY_INTERVAL_MS;
88176
+ }
88112
88177
  function buildHistoryReport(profile) {
88113
88178
  const stage2 = profile.historyStage;
88114
88179
  return {
@@ -89869,11 +89934,17 @@ async function startMultiDaemon(opts = {}) {
89869
89934
  const anchorPull = setInterval(() => {
89870
89935
  void anchorPullAll();
89871
89936
  }, 6e4);
89872
- const ambientLinkAll = async () => {
89937
+ const historyRetryAttempts = /* @__PURE__ */ new Map();
89938
+ const ambientLinkAll = async (retryPausedOnly = false) => {
89873
89939
  const c = loadConfig();
89874
89940
  if (registryCorrupt()) return;
89875
89941
  for (const r of records) {
89942
+ if (stopping) return;
89876
89943
  const working = loadProfile(r.root) ?? r.engine.profile;
89944
+ if (retryPausedOnly) {
89945
+ if (historyInFlight.has(r.root) || !historyRetryDue(working, Date.now(), historyRetryAttempts.get(r.root))) continue;
89946
+ historyRetryAttempts.set(r.root, Date.now());
89947
+ }
89877
89948
  if (!effectiveConsent(c, working).sync) continue;
89878
89949
  const identity = identityFor(liveWorkspaceEntry(r.entry));
89879
89950
  if (identity.invalid) {
@@ -89937,8 +90008,9 @@ async function startMultiDaemon(opts = {}) {
89937
90008
  console.warn(`[errata] project reanchor failed for ${r.engine.profile.name}: ${re.detail}`);
89938
90009
  }
89939
90010
  await pullProjectAnchors(r, client, salt);
89940
- if (r.engine.profile.projectHydratedAt && !historyInFlight.has(r.root)) {
90011
+ if (!stopping && records.includes(r) && r.engine.profile.projectHydratedAt && !historyInFlight.has(r.root)) {
89941
90012
  historyInFlight.add(r.root);
90013
+ if (retryPausedOnly) console.log(`[errata] resuming paused history for ${r.engine.profile.name} from its acknowledged watermark`);
89942
90014
  const engine = r.engine;
89943
90015
  const root = r.root;
89944
90016
  const anchorIndex = {
@@ -89993,6 +90065,16 @@ async function startMultiDaemon(opts = {}) {
89993
90065
  };
89994
90066
  const historyInFlight = /* @__PURE__ */ new Set();
89995
90067
  void ambientLinkAll();
90068
+ let historyRetryRunning = false;
90069
+ const historyRetry = setInterval(() => {
90070
+ if (stopping || historyRetryRunning) return;
90071
+ historyRetryRunning = true;
90072
+ void ambientLinkAll(true).catch((err2) => {
90073
+ console.warn(`[errata] history retry pass failed: ${err2 instanceof Error ? err2.message : err2}`);
90074
+ }).finally(() => {
90075
+ historyRetryRunning = false;
90076
+ });
90077
+ }, 6e4);
89996
90078
  const packageAutoAll = async () => {
89997
90079
  const out2 = /* @__PURE__ */ new Map();
89998
90080
  for (const r of records) {
@@ -90479,10 +90561,11 @@ async function startMultiDaemon(opts = {}) {
90479
90561
  for (const id of p.blockedNodeIds ?? []) blocked.add(id);
90480
90562
  for (const decision of p.result.nodes) {
90481
90563
  const sent = sentById.get(decision.canonicalId);
90482
- const owner = owningStore(decision.canonicalId);
90564
+ const localId = instances.contextNodeSources[decision.canonicalId] ?? decision.canonicalId;
90565
+ const owner = owningStore(localId);
90483
90566
  if (!sent || !owner || blocked.has(sent.id)) continue;
90484
- const attrs = acceptedInstanceReceipt(owner.n, sent, decision, destinationKey, owner.s === store);
90485
- if (attrs) owner.s.updateNode(sent.id, { attrs });
90567
+ const attrs = acceptedInstanceReceipt(owner.n, sent, decision, destinationKey, owner.s === store) ?? withdrawnInstanceReceipt(owner.n, destinationKey, decision, (key) => store.getMeta?.(key) ?? sharedStore.getMeta?.(key), owner.s === store);
90568
+ if (attrs) owner.s.updateNode(localId, { attrs });
90486
90569
  }
90487
90570
  noteFlushProgress(p.accepted, p.nodeIds.length, `instances ${p.chunkIndex}/${p.totalChunks}`);
90488
90571
  }
@@ -90582,9 +90665,26 @@ async function startMultiDaemon(opts = {}) {
90582
90665
  attrs: updateInstanceReceipt(owner.n, destinationKey, { semanticEdgesContributedDigest: dg }, owner.s === store)
90583
90666
  });
90584
90667
  });
90668
+ let invalidatedReceipts = 0;
90669
+ for (const failedId of invalidInstanceEndpointIds(res.result.edges)) {
90670
+ const localIds = new Set(instances.endpointSources[failedId] ?? []);
90671
+ for (const [wireId, cloudId] of cloudIds) if (cloudId === failedId) {
90672
+ for (const id of instances.endpointSources[wireId] ?? [instances.contextNodeSources[wireId] ?? wireId]) localIds.add(id);
90673
+ }
90674
+ for (const localId of localIds) {
90675
+ const owner = owningStore(localId);
90676
+ if (!owner || instanceCloudWithdrawal(owner.n, destinationKey, (key) => store.getMeta?.(key) ?? sharedStore.getMeta?.(key))) continue;
90677
+ const attrs = invalidateInstanceReceipt(owner.n, destinationKey, failedId, owner.s === store);
90678
+ if (attrs) {
90679
+ owner.s.updateNode(localId, { attrs });
90680
+ invalidatedReceipts++;
90681
+ }
90682
+ }
90683
+ }
90585
90684
  appendPassLedger(r.engine.paths.configDir, "ship", Date.now() - shipStartedAt, {
90586
90685
  ...compositionCounters(instances.composition),
90587
90686
  accepted: res.accepted,
90687
+ invalidatedReceipts,
90588
90688
  rejected: rejected.size,
90589
90689
  blocked: blocked.size,
90590
90690
  // The half of the refusal count that is NOT news. `blocked` flat
@@ -90727,6 +90827,7 @@ async function startMultiDaemon(opts = {}) {
90727
90827
  clearInterval(idleSweep);
90728
90828
  clearInterval(codexWake);
90729
90829
  clearInterval(anchorPull);
90830
+ clearInterval(historyRetry);
90730
90831
  clearTimeout(codexWakeBoot);
90731
90832
  try {
90732
90833
  const cur = readFileSync36(lockPath, "utf8");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.17-dev.3469",
3
+ "version": "2.0.17-dev.3483",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {