@inerrata-corporation/errata 2.0.8-dev.2916 → 2.0.8-dev.2932

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.
@@ -18216,6 +18216,15 @@ function generalize(text, opts = {}) {
18216
18216
  // src/instance-ingest.ts
18217
18217
  init_src();
18218
18218
 
18219
+ // src/instance-receipts.ts
18220
+ function receiptMap(attrs) {
18221
+ const value = attrs["instanceReceipts"];
18222
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
18223
+ }
18224
+ function instanceReceipt(n, destination) {
18225
+ return destination ? receiptMap(n.attrs)[destination] ?? {} : n.attrs;
18226
+ }
18227
+
18219
18228
  // src/contribution-ready.ts
18220
18229
  function cosine2(a, b) {
18221
18230
  if (a.length === 0 || a.length !== b.length) return 0;
@@ -19085,8 +19094,8 @@ function stripCodebaseScope(scope) {
19085
19094
  delete s["codebase"];
19086
19095
  return s;
19087
19096
  }
19088
- function contributedWireId(n) {
19089
- const cloudId = n.attrs["cloudNodeId"];
19097
+ function contributedWireId(n, destinationKey) {
19098
+ const cloudId = instanceReceipt(n, destinationKey)["cloudNodeId"];
19090
19099
  return isMembraneSaltedId(cloudId) ? cloudId : n.id;
19091
19100
  }
19092
19101
  var WIRE_CANONICAL_ID_MIN = 6;
@@ -19230,10 +19239,26 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19230
19239
  fileRefsSubstituted: 0,
19231
19240
  fileRefLexiconMisses: 0
19232
19241
  };
19242
+ const sharedCauses = /* @__PURE__ */ new Map();
19243
+ const causalQueue = store.findNodesByLabel("Problem").filter(
19244
+ (n) => n.attrs["source"] !== "cloud" && n.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE && !ignored(n.description)
19245
+ ).map((n) => n.id);
19246
+ const causalSeen = new Set(causalQueue);
19247
+ for (let i = 0; i < causalQueue.length; i++) {
19248
+ const id = causalQueue[i];
19249
+ for (const e of [...store.outEdges(id, ["CAUSED_BY"]), ...opts.sharedStore?.outEdges(id, ["CAUSED_BY"]) ?? []]) {
19250
+ if (causalSeen.has(e.to)) continue;
19251
+ causalSeen.add(e.to);
19252
+ const cause = nodeOf(e.to);
19253
+ if (!cause || cause.label !== "RootCause" || cause.attrs["source"] === "cloud" || ignored(cause.description)) continue;
19254
+ sharedCauses.set(cause.id, cause);
19255
+ causalQueue.push(cause.id);
19256
+ }
19257
+ }
19233
19258
  for (const label of INSTANCE_LABELS) {
19234
19259
  const ref = [];
19235
19260
  includedByLabel.set(label, ref);
19236
- const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...opts.sharedStore.findNodesByLabel(label)] : store.findNodesByLabel(label);
19261
+ const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...sharedCauses.values()] : store.findNodesByLabel(label);
19237
19262
  for (const n of population) {
19238
19263
  if (seen.has(n.id)) continue;
19239
19264
  if (walked.has(n.id)) continue;
@@ -19251,18 +19276,18 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19251
19276
  composition.ignored++;
19252
19277
  continue;
19253
19278
  }
19254
- const contributedAtSeq = n.attrs["contributedAtSeq"];
19279
+ const contributedAtSeq = instanceReceipt(n, opts.destinationKey)["contributedAtSeq"];
19255
19280
  if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
19256
19281
  composition.watermarked++;
19257
19282
  anchorSources.add(n.id);
19258
- semanticEndpoints.set(n.id, contributedWireId(n));
19283
+ semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
19259
19284
  continue;
19260
19285
  }
19261
19286
  if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
19262
19287
  composition.autoMint++;
19263
19288
  continue;
19264
19289
  }
19265
- if (isTerminallyRefused(n)) {
19290
+ if (isTerminallyRefused({ ...n, attrs: instanceReceipt(n, opts.destinationKey) })) {
19266
19291
  composition.terminalRefused++;
19267
19292
  continue;
19268
19293
  }
@@ -19321,9 +19346,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19321
19346
  }
19322
19347
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
19323
19348
  const sourceNode = nodeOf(sourceId);
19324
- if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
19349
+ if ((sourceNode && instanceReceipt(sourceNode, opts.destinationKey)["anchorsContributedDigest"]) === dg) continue;
19325
19350
  anchorDigests[sourceId] = dg;
19326
- const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode);
19351
+ const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode, opts.destinationKey);
19327
19352
  for (const { e, t, wireId } of targets) {
19328
19353
  const reject = unshippableReason(wireId, t.label);
19329
19354
  if (reject) {
@@ -19352,7 +19377,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19352
19377
  for (const sourceId of anchorSources) {
19353
19378
  const source = nodeOf(sourceId);
19354
19379
  if (!source) continue;
19355
- const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
19380
+ const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source, opts.destinationKey);
19356
19381
  const planned = [];
19357
19382
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
19358
19383
  const target = nodeOf(e.to);
@@ -19387,7 +19412,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19387
19412
  const dg = digest(
19388
19413
  planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
19389
19414
  );
19390
- if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
19415
+ if (instanceReceipt(source, opts.destinationKey)["projectAnchorsContributedDigest"] === dg) continue;
19391
19416
  projectAnchorDigests[sourceId] = dg;
19392
19417
  for (const { e, target, symId, wireAttrs } of planned) {
19393
19418
  if (!contextSeen.has(symId)) {
@@ -19433,7 +19458,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19433
19458
  if (outs.length === 0) continue;
19434
19459
  const dg = digest(outs.map(({ e, wireTo }) => `${e.type}>${wireTo}`).sort());
19435
19460
  const owner = nodeOf(sourceId);
19436
- const digestSkip = owner?.attrs["semanticEdgesContributedDigest"] === dg;
19461
+ const digestSkip = (owner && instanceReceipt(owner, opts.destinationKey)["semanticEdgesContributedDigest"]) === dg;
19437
19462
  if (!digestSkip) semanticEdgeDigests[sourceId] = dg;
19438
19463
  for (const { e, wireTo } of outs) {
19439
19464
  if (digestSkip && !shippedById.has(e.to)) continue;
@@ -19490,7 +19515,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19490
19515
  for (const wn of nodes) {
19491
19516
  if (wn.label !== "RootCause" && wn.label !== "Solution") continue;
19492
19517
  const src = nodeOf(wn.id);
19493
- if (typeof src?.attrs["contributedAtSeq"] === "number") continue;
19518
+ if (src && typeof instanceReceipt(src, opts.destinationKey)["contributedAtSeq"] === "number") continue;
19494
19519
  if (bindingEndpoints.has(wn.id)) continue;
19495
19520
  heldOrphans.add(wn.id);
19496
19521
  }
@@ -19568,6 +19593,7 @@ function buildDrainInstances(store, sharedStore, input) {
19568
19593
  ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {},
19569
19594
  workspaceRoot: input.workspaceRoot,
19570
19595
  sharedStore,
19596
+ destinationKey: input.destinationKey,
19571
19597
  onComposition: (c) => {
19572
19598
  composition = c;
19573
19599
  },
package/errata.mjs CHANGED
@@ -29506,6 +29506,18 @@ function resolveWorkspaceIdentity(cfg, entry, env2 = process.env) {
29506
29506
  function identityKey(id) {
29507
29507
  return id.profileName ?? "@default";
29508
29508
  }
29509
+ function publicWorkspaceIdentity(identity) {
29510
+ return {
29511
+ profileName: identity.profileName,
29512
+ rule: identity.rule,
29513
+ invalid: identity.invalid,
29514
+ reason: identity.reason,
29515
+ profile: identity.profile ? {
29516
+ installationId: identity.profile.installationId,
29517
+ cloudUrl: identity.profile.cloudUrl
29518
+ } : null
29519
+ };
29520
+ }
29509
29521
  function blockedCloudClient(reason) {
29510
29522
  return new Proxy(
29511
29523
  {},
@@ -80267,7 +80279,7 @@ function createWatchBreaker(deps) {
80267
80279
  }
80268
80280
 
80269
80281
  // src/engine.ts
80270
- var DAEMON_VERSION = true ? "2.0.8-dev.2916" : "2.0.0-alpha.0";
80282
+ var DAEMON_VERSION = true ? "2.0.8-dev.2932" : "2.0.0-alpha.0";
80271
80283
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
80272
80284
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
80273
80285
  var GIT_OP_MUTE_MS = 4e3;
@@ -82713,6 +82725,40 @@ async function listenServer(fetchFn, port) {
82713
82725
  init_registry();
82714
82726
  init_identity2();
82715
82727
 
82728
+ // src/instance-receipts.ts
82729
+ import { createHash as createHash16 } from "node:crypto";
82730
+ var FIELDS = ["contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
82731
+ function instanceDestinationKey(input) {
82732
+ return createHash16("sha256").update(JSON.stringify([
82733
+ input.workspace,
82734
+ input.cloudUrl.replace(/\/+$/, ""),
82735
+ input.installationId ?? input.profileName ?? "default",
82736
+ input.projectId ?? null,
82737
+ input.writeTarget?.visibility ?? null,
82738
+ input.writeTarget?.org_id ?? null,
82739
+ input.writeTarget?.team_id ?? null
82740
+ ])).digest("hex");
82741
+ }
82742
+ function receiptMap(attrs) {
82743
+ const value = attrs["instanceReceipts"];
82744
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
82745
+ }
82746
+ function instanceReceipt(n, destination) {
82747
+ return destination ? receiptMap(n.attrs)[destination] ?? {} : n.attrs;
82748
+ }
82749
+ function updateInstanceReceipt(n, destination, patch, mirrorLegacy) {
82750
+ const receipt = { ...instanceReceipt(n, destination), ...patch };
82751
+ const attrs = { ...n.attrs, instanceReceipts: { ...receiptMap(n.attrs), [destination]: receipt } };
82752
+ if (mirrorLegacy) for (const field of FIELDS) {
82753
+ if (field in receipt) attrs[field] = receipt[field];
82754
+ else delete attrs[field];
82755
+ }
82756
+ return attrs;
82757
+ }
82758
+ function instanceReceiptSequence(n) {
82759
+ return Math.max(n.lastReinforcedAtSeq ?? 0, n.createdAtSeq ?? 0);
82760
+ }
82761
+
82716
82762
  // src/multi.ts
82717
82763
  init_dist();
82718
82764
  init_src5();
@@ -83117,8 +83163,8 @@ function compositionCounters(c) {
83117
83163
  ...Object.fromEntries(buckets.map((b) => [`sidecarDrop_${b}`, sidecarDropReasons[b] ?? 0]))
83118
83164
  };
83119
83165
  }
83120
- function contributedWireId(n) {
83121
- const cloudId = n.attrs["cloudNodeId"];
83166
+ function contributedWireId(n, destinationKey) {
83167
+ const cloudId = instanceReceipt(n, destinationKey)["cloudNodeId"];
83122
83168
  return isMembraneSaltedId(cloudId) ? cloudId : n.id;
83123
83169
  }
83124
83170
  var WIRE_CANONICAL_ID_MIN = 6;
@@ -83262,10 +83308,26 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83262
83308
  fileRefsSubstituted: 0,
83263
83309
  fileRefLexiconMisses: 0
83264
83310
  };
83311
+ const sharedCauses = /* @__PURE__ */ new Map();
83312
+ const causalQueue = store.findNodesByLabel("Problem").filter(
83313
+ (n) => n.attrs["source"] !== "cloud" && n.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE && !ignored(n.description)
83314
+ ).map((n) => n.id);
83315
+ const causalSeen = new Set(causalQueue);
83316
+ for (let i2 = 0; i2 < causalQueue.length; i2++) {
83317
+ const id = causalQueue[i2];
83318
+ for (const e of [...store.outEdges(id, ["CAUSED_BY"]), ...opts.sharedStore?.outEdges(id, ["CAUSED_BY"]) ?? []]) {
83319
+ if (causalSeen.has(e.to)) continue;
83320
+ causalSeen.add(e.to);
83321
+ const cause = nodeOf(e.to);
83322
+ if (!cause || cause.label !== "RootCause" || cause.attrs["source"] === "cloud" || ignored(cause.description)) continue;
83323
+ sharedCauses.set(cause.id, cause);
83324
+ causalQueue.push(cause.id);
83325
+ }
83326
+ }
83265
83327
  for (const label of INSTANCE_LABELS) {
83266
83328
  const ref = [];
83267
83329
  includedByLabel.set(label, ref);
83268
- const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...opts.sharedStore.findNodesByLabel(label)] : store.findNodesByLabel(label);
83330
+ const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...sharedCauses.values()] : store.findNodesByLabel(label);
83269
83331
  for (const n of population) {
83270
83332
  if (seen.has(n.id)) continue;
83271
83333
  if (walked.has(n.id)) continue;
@@ -83283,18 +83345,18 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83283
83345
  composition.ignored++;
83284
83346
  continue;
83285
83347
  }
83286
- const contributedAtSeq = n.attrs["contributedAtSeq"];
83348
+ const contributedAtSeq = instanceReceipt(n, opts.destinationKey)["contributedAtSeq"];
83287
83349
  if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
83288
83350
  composition.watermarked++;
83289
83351
  anchorSources.add(n.id);
83290
- semanticEndpoints.set(n.id, contributedWireId(n));
83352
+ semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
83291
83353
  continue;
83292
83354
  }
83293
83355
  if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
83294
83356
  composition.autoMint++;
83295
83357
  continue;
83296
83358
  }
83297
- if (isTerminallyRefused(n)) {
83359
+ if (isTerminallyRefused({ ...n, attrs: instanceReceipt(n, opts.destinationKey) })) {
83298
83360
  composition.terminalRefused++;
83299
83361
  continue;
83300
83362
  }
@@ -83353,9 +83415,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83353
83415
  }
83354
83416
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
83355
83417
  const sourceNode = nodeOf(sourceId);
83356
- if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
83418
+ if ((sourceNode && instanceReceipt(sourceNode, opts.destinationKey)["anchorsContributedDigest"]) === dg) continue;
83357
83419
  anchorDigests[sourceId] = dg;
83358
- const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode);
83420
+ const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode, opts.destinationKey);
83359
83421
  for (const { e, t, wireId } of targets) {
83360
83422
  const reject = unshippableReason(wireId, t.label);
83361
83423
  if (reject) {
@@ -83384,7 +83446,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83384
83446
  for (const sourceId of anchorSources) {
83385
83447
  const source = nodeOf(sourceId);
83386
83448
  if (!source) continue;
83387
- const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
83449
+ const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source, opts.destinationKey);
83388
83450
  const planned = [];
83389
83451
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
83390
83452
  const target = nodeOf(e.to);
@@ -83419,7 +83481,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83419
83481
  const dg = digest(
83420
83482
  planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
83421
83483
  );
83422
- if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
83484
+ if (instanceReceipt(source, opts.destinationKey)["projectAnchorsContributedDigest"] === dg) continue;
83423
83485
  projectAnchorDigests[sourceId] = dg;
83424
83486
  for (const { e, target, symId, wireAttrs } of planned) {
83425
83487
  if (!contextSeen.has(symId)) {
@@ -83465,7 +83527,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83465
83527
  if (outs.length === 0) continue;
83466
83528
  const dg = digest(outs.map(({ e, wireTo }) => `${e.type}>${wireTo}`).sort());
83467
83529
  const owner = nodeOf(sourceId);
83468
- const digestSkip = owner?.attrs["semanticEdgesContributedDigest"] === dg;
83530
+ const digestSkip = (owner && instanceReceipt(owner, opts.destinationKey)["semanticEdgesContributedDigest"]) === dg;
83469
83531
  if (!digestSkip) semanticEdgeDigests[sourceId] = dg;
83470
83532
  for (const { e, wireTo } of outs) {
83471
83533
  if (digestSkip && !shippedById.has(e.to)) continue;
@@ -83522,7 +83584,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83522
83584
  for (const wn of nodes) {
83523
83585
  if (wn.label !== "RootCause" && wn.label !== "Solution") continue;
83524
83586
  const src = nodeOf(wn.id);
83525
- if (typeof src?.attrs["contributedAtSeq"] === "number") continue;
83587
+ if (src && typeof instanceReceipt(src, opts.destinationKey)["contributedAtSeq"] === "number") continue;
83526
83588
  if (bindingEndpoints.has(wn.id)) continue;
83527
83589
  heldOrphans.add(wn.id);
83528
83590
  }
@@ -83676,6 +83738,7 @@ function buildDrainInstances(store, sharedStore, input) {
83676
83738
  ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {},
83677
83739
  workspaceRoot: input.workspaceRoot,
83678
83740
  sharedStore,
83741
+ destinationKey: input.destinationKey,
83679
83742
  onComposition: (c) => {
83680
83743
  composition = c;
83681
83744
  },
@@ -85343,7 +85406,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
85343
85406
 
85344
85407
  // src/link-flow.ts
85345
85408
  init_cloud_auth();
85346
- import { createHash as createHash16 } from "node:crypto";
85409
+ import { createHash as createHash17 } from "node:crypto";
85347
85410
  import { execFileSync as execFileSync5 } from "node:child_process";
85348
85411
  import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
85349
85412
  import { join as join38 } from "node:path";
@@ -85637,7 +85700,7 @@ async function loginOAuthLoopback(opts) {
85637
85700
 
85638
85701
  // src/link-flow.ts
85639
85702
  function remoteFingerprint(locator) {
85640
- return createHash16("sha256").update(locator).digest("hex");
85703
+ return createHash17("sha256").update(locator).digest("hex");
85641
85704
  }
85642
85705
  function isDecision(value) {
85643
85706
  if (!value || typeof value !== "object") return false;
@@ -86944,11 +87007,17 @@ async function startMultiDaemon(opts = {}) {
86944
87007
  const ANCHOR_PULL_INTERVAL_MS = 10 * 60 * 1e3;
86945
87008
  const anchorPullAll = async () => {
86946
87009
  const c = loadConfig();
86947
- if (!hasCloudCredential(c)) return;
86948
- const client = cloudNow();
87010
+ if (registryCorrupt()) return;
86949
87011
  for (const r of records) {
86950
87012
  const projectId = r.engine.profile.projectId;
86951
87013
  if (!projectId || !effectiveConsent(c, r.engine.profile).sync) continue;
87014
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87015
+ if (identity.invalid) {
87016
+ noteIdentityBlock(r.id, r.entry.name, identity);
87017
+ continue;
87018
+ }
87019
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87020
+ const client = cloudForIdentity(identity);
86952
87021
  try {
86953
87022
  const { salt } = await resolveProjectSymbolSalt(client, projectId);
86954
87023
  await pullProjectAnchors(r, client, salt);
@@ -86962,11 +87031,17 @@ async function startMultiDaemon(opts = {}) {
86962
87031
  }, ANCHOR_PULL_INTERVAL_MS);
86963
87032
  const ambientLinkAll = async () => {
86964
87033
  const c = loadConfig();
86965
- if (!hasCloudCredential(c)) return;
86966
- const client = cloudNow();
87034
+ if (registryCorrupt()) return;
86967
87035
  for (const r of records) {
86968
87036
  const working = loadProfile(r.root) ?? r.engine.profile;
86969
87037
  if (!effectiveConsent(c, working).sync) continue;
87038
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87039
+ if (identity.invalid) {
87040
+ noteIdentityBlock(r.id, r.entry.name, identity);
87041
+ continue;
87042
+ }
87043
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87044
+ const client = cloudForIdentity(identity);
86970
87045
  const out2 = await ensureProjectLink(r.root, working, client);
86971
87046
  if (working !== r.engine.profile) adoptLinkFields(r.engine.profile, working);
86972
87047
  if (out2.linked) {
@@ -87354,6 +87429,7 @@ async function startMultiDaemon(opts = {}) {
87354
87429
  }
87355
87430
  const ignore2 = loadClaimIgnorePatterns(globalDir());
87356
87431
  const clientPool = /* @__PURE__ */ new Map();
87432
+ const receiptContexts = /* @__PURE__ */ new Map();
87357
87433
  const poolFor = (identity) => {
87358
87434
  const k = identityKey(identity);
87359
87435
  let c = clientPool.get(k);
@@ -87496,7 +87572,26 @@ async function startMultiDaemon(opts = {}) {
87496
87572
  return res.accepted;
87497
87573
  });
87498
87574
  }
87575
+ const receiptProfile = recordIdentity.profile ?? (cfg2.activeInstallationProfile ? cfg2.installationProfiles[cfg2.activeInstallationProfile] : void 0);
87576
+ let receiptContext = receiptContexts.get(identityKey(recordIdentity));
87577
+ if (!receiptContext) {
87578
+ try {
87579
+ receiptContext = await client.context();
87580
+ receiptContexts.set(identityKey(recordIdentity), receiptContext);
87581
+ } catch (err2) {
87582
+ errors.push(`[${projectName}] instance destination unresolved: ${err2 instanceof Error ? err2.message : String(err2)}`);
87583
+ continue;
87584
+ }
87585
+ }
87586
+ const destinationKey = instanceDestinationKey({
87587
+ workspace: r.id,
87588
+ cloudUrl: opts.cloudUrl ?? receiptProfile?.cloudUrl ?? cfg2.cloudUrl,
87589
+ installationId: receiptContext.context.installation_id ?? receiptContext.identity.credential_id,
87590
+ projectId: project?.projectId,
87591
+ writeTarget: project ? null : receiptContext.context.default_write_target
87592
+ });
87499
87593
  const built = await buildInstanceBatch(r, {
87594
+ destinationKey,
87500
87595
  profile: r.engine.profile,
87501
87596
  daemonVersion: DAEMON_VERSION,
87502
87597
  ignorePatterns: [...ignore2],
@@ -87541,7 +87636,6 @@ async function startMultiDaemon(opts = {}) {
87541
87636
  );
87542
87637
  }
87543
87638
  uploaded += res.accepted;
87544
- const seq = store.currentIngestSeq();
87545
87639
  const cloudIdByLocal = new Map(
87546
87640
  res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
87547
87641
  );
@@ -87550,6 +87644,7 @@ async function startMultiDaemon(opts = {}) {
87550
87644
  if (rn.decision === "rejected") rejected.set(rn.canonicalId, rn.reason ?? "no reason given");
87551
87645
  }
87552
87646
  const rejectedEdges = res.result.edges.filter((re) => re.decision === "rejected");
87647
+ const edgeReceiptsComplete = rejectedEdges.length === 0 && res.result.edges.length === instances.edges.length;
87553
87648
  if (rejectedEdges.length > 0) {
87554
87649
  const byReason = /* @__PURE__ */ new Map();
87555
87650
  for (const re of rejectedEdges) {
@@ -87580,17 +87675,17 @@ async function startMultiDaemon(opts = {}) {
87580
87675
  const owner = owningStore(id);
87581
87676
  if (!owner) return;
87582
87677
  const fp = refusalFingerprint(reason, owner.n.description);
87583
- const same = owner.n.attrs["shipRefusedFingerprint"] === fp;
87584
- const count = same ? Number(owner.n.attrs["shipRefusedCount"] ?? 0) + 1 : 1;
87585
- if (owner.n.attrs["shipRefusedSinceSeq"] !== void 0) repeat();
87678
+ const same = instanceReceipt(owner.n, destinationKey)["shipRefusedFingerprint"] === fp;
87679
+ const count = same ? Number(instanceReceipt(owner.n, destinationKey)["shipRefusedCount"] ?? 0) + 1 : 1;
87680
+ if (instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0) repeat();
87586
87681
  owner.s.updateNode(id, {
87587
- attrs: {
87588
- ...owner.n.attrs,
87589
- ...same && owner.n.attrs["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: seq },
87682
+ attrs: updateInstanceReceipt(owner.n, destinationKey, {
87683
+ ...instanceReceipt(owner.n, destinationKey),
87684
+ ...same && instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: owner.s.currentIngestSeq() },
87590
87685
  shipRefusedCount: count,
87591
87686
  shipRefusedReason: reason,
87592
87687
  shipRefusedFingerprint: fp
87593
- }
87688
+ }, owner.s === store)
87594
87689
  });
87595
87690
  if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
87596
87691
  nowHeld.push({ id, reason });
@@ -87607,6 +87702,7 @@ async function startMultiDaemon(opts = {}) {
87607
87702
  const owner = owningStore(n.id);
87608
87703
  if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) return;
87609
87704
  if (blocked.has(n.id)) return;
87705
+ if (!cloudIdByLocal.has(n.id)) return;
87610
87706
  if (rejected.has(n.id)) return;
87611
87707
  const cloudNodeId = cloudIdByLocal.get(n.id);
87612
87708
  const {
@@ -87615,37 +87711,41 @@ async function startMultiDaemon(opts = {}) {
87615
87711
  shipRefusedReason: _clearedReason,
87616
87712
  shipRefusedFingerprint: _clearedFp,
87617
87713
  ...carried
87618
- } = owner.n.attrs;
87714
+ } = instanceReceipt(owner.n, destinationKey);
87619
87715
  owner.s.updateNode(n.id, {
87620
- attrs: {
87716
+ attrs: updateInstanceReceipt(owner.n, destinationKey, {
87621
87717
  ...carried,
87622
- contributedAtSeq: seq,
87623
- ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
87624
- }
87718
+ shipRefusedSinceSeq: void 0,
87719
+ shipRefusedCount: void 0,
87720
+ shipRefusedReason: void 0,
87721
+ shipRefusedFingerprint: void 0,
87722
+ contributedAtSeq: instanceReceiptSequence(n),
87723
+ cloudNodeId
87724
+ }, owner.s === store)
87625
87725
  });
87626
87726
  });
87627
87727
  await stampBatched(Object.entries(instances.anchorDigests), ([localId, dg]) => {
87628
87728
  const owner = owningStore(localId);
87629
87729
  if (!owner) return;
87630
- if (rejected.has(localId) || blocked.has(localId)) return;
87730
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87631
87731
  owner.s.updateNode(localId, {
87632
- attrs: { ...owner.n.attrs, anchorsContributedDigest: dg }
87732
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { anchorsContributedDigest: dg }, owner.s === store)
87633
87733
  });
87634
87734
  });
87635
87735
  await stampBatched(Object.entries(instances.projectAnchorDigests), ([localId, dg]) => {
87636
87736
  const owner = owningStore(localId);
87637
87737
  if (!owner) return;
87638
- if (rejected.has(localId) || blocked.has(localId)) return;
87738
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87639
87739
  owner.s.updateNode(localId, {
87640
- attrs: { ...owner.n.attrs, projectAnchorsContributedDigest: dg }
87740
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { projectAnchorsContributedDigest: dg }, owner.s === store)
87641
87741
  });
87642
87742
  });
87643
87743
  await stampBatched(Object.entries(instances.semanticEdgeDigests), ([localId, dg]) => {
87644
87744
  const owner = owningStore(localId);
87645
87745
  if (!owner) return;
87646
- if (rejected.has(localId) || blocked.has(localId)) return;
87746
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87647
87747
  owner.s.updateNode(localId, {
87648
- attrs: { ...owner.n.attrs, semanticEdgesContributedDigest: dg }
87748
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { semanticEdgesContributedDigest: dg }, owner.s === store)
87649
87749
  });
87650
87750
  });
87651
87751
  appendPassLedger(r.engine.paths.configDir, "ship", Date.now() - shipStartedAt, {
@@ -89539,7 +89639,7 @@ async function cmdWhoami(args2) {
89539
89639
  `note: daemon capture and the MCP server resolve identically; a process with ERRATA_CONFIG_PATH set resolves by rule 1 regardless of binding.`
89540
89640
  ];
89541
89641
  if (args2.includes("--json")) {
89542
- console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...identity }, null, 2));
89642
+ console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...publicWorkspaceIdentity(identity) }, null, 2));
89543
89643
  } else {
89544
89644
  for (const l of lines) console.log(l);
89545
89645
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.8-dev.2916",
3
+ "version": "2.0.8-dev.2932",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {