@inerrata-corporation/errata 2.0.9 → 2.0.11

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.
@@ -15351,7 +15351,7 @@ function anchorLabelAttrs(attrs) {
15351
15351
  ...typeof line === "number" && Number.isInteger(line) && line >= 1 && line <= 1e7 ? { labelLine: line } : {}
15352
15352
  };
15353
15353
  }
15354
- var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15354
+ var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, TRIAGE_DISCRIMINATOR_MAX_LENGTH, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15355
15355
  var init_wire = __esm({
15356
15356
  "../../packages/shared/src/wire.ts"() {
15357
15357
  "use strict";
@@ -15470,6 +15470,7 @@ var init_wire = __esm({
15470
15470
  FILE_ANCHOR_QNAME = "";
15471
15471
  ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
15472
15472
  ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
15473
+ TRIAGE_DISCRIMINATOR_MAX_LENGTH = 2e3;
15473
15474
  CastaliaIngestEdgeSchema = external_exports.object({
15474
15475
  fromCanonicalId: external_exports.string().min(6).max(160),
15475
15476
  toCanonicalId: external_exports.string().min(6).max(160),
@@ -15480,6 +15481,8 @@ var init_wire = __esm({
15480
15481
  /** Triage route per-context counts (T3 induction). Carried as structured data
15481
15482
  * here; stored JSON-encoded on the Neo4j rel (`perContextJson`). */
15482
15483
  perContext: external_exports.record(external_exports.string(), RouteContextCountWireSchema).optional(),
15484
+ /** Scrubbed diagnostic check for a triage route, re-scanned at the cloud door. */
15485
+ discriminator: external_exports.string().trim().min(1).max(TRIAGE_DISCRIMINATOR_MAX_LENGTH).optional(),
15483
15486
  /** PJ-anchor-version: WHICH version of a symbol an `ANCHORED_AT` was
15484
15487
  * witnessed against. Both opaque — the observing checkout's HEAD sha and
15485
15488
  * the indexer's 16-hex sha256 of the symbol body. Neither is reversible
@@ -18216,6 +18219,15 @@ function generalize(text, opts = {}) {
18216
18219
  // src/instance-ingest.ts
18217
18220
  init_src();
18218
18221
 
18222
+ // src/instance-receipts.ts
18223
+ function receiptMap(attrs) {
18224
+ const value = attrs["instanceReceipts"];
18225
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
18226
+ }
18227
+ function instanceReceipt(n, destination) {
18228
+ return destination ? receiptMap(n.attrs)[destination] ?? {} : n.attrs;
18229
+ }
18230
+
18219
18231
  // src/contribution-ready.ts
18220
18232
  function cosine2(a, b) {
18221
18233
  if (a.length === 0 || a.length !== b.length) return 0;
@@ -19085,8 +19097,8 @@ function stripCodebaseScope(scope) {
19085
19097
  delete s["codebase"];
19086
19098
  return s;
19087
19099
  }
19088
- function contributedWireId(n) {
19089
- const cloudId = n.attrs["cloudNodeId"];
19100
+ function contributedWireId(n, destinationKey) {
19101
+ const cloudId = instanceReceipt(n, destinationKey)["cloudNodeId"];
19090
19102
  return isMembraneSaltedId(cloudId) ? cloudId : n.id;
19091
19103
  }
19092
19104
  var WIRE_CANONICAL_ID_MIN = 6;
@@ -19230,10 +19242,26 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19230
19242
  fileRefsSubstituted: 0,
19231
19243
  fileRefLexiconMisses: 0
19232
19244
  };
19245
+ const sharedCauses = /* @__PURE__ */ new Map();
19246
+ const causalQueue = store.findNodesByLabel("Problem").filter(
19247
+ (n) => n.attrs["source"] !== "cloud" && n.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE && !ignored(n.description)
19248
+ ).map((n) => n.id);
19249
+ const causalSeen = new Set(causalQueue);
19250
+ for (let i = 0; i < causalQueue.length; i++) {
19251
+ const id = causalQueue[i];
19252
+ for (const e of [...store.outEdges(id, ["CAUSED_BY"]), ...opts.sharedStore?.outEdges(id, ["CAUSED_BY"]) ?? []]) {
19253
+ if (causalSeen.has(e.to)) continue;
19254
+ causalSeen.add(e.to);
19255
+ const cause = nodeOf(e.to);
19256
+ if (!cause || cause.label !== "RootCause" || cause.attrs["source"] === "cloud" || ignored(cause.description)) continue;
19257
+ sharedCauses.set(cause.id, cause);
19258
+ causalQueue.push(cause.id);
19259
+ }
19260
+ }
19233
19261
  for (const label of INSTANCE_LABELS) {
19234
19262
  const ref = [];
19235
19263
  includedByLabel.set(label, ref);
19236
- const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...opts.sharedStore.findNodesByLabel(label)] : store.findNodesByLabel(label);
19264
+ const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...sharedCauses.values()] : store.findNodesByLabel(label);
19237
19265
  for (const n of population) {
19238
19266
  if (seen.has(n.id)) continue;
19239
19267
  if (walked.has(n.id)) continue;
@@ -19251,18 +19279,18 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19251
19279
  composition.ignored++;
19252
19280
  continue;
19253
19281
  }
19254
- const contributedAtSeq = n.attrs["contributedAtSeq"];
19282
+ const contributedAtSeq = instanceReceipt(n, opts.destinationKey)["contributedAtSeq"];
19255
19283
  if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
19256
19284
  composition.watermarked++;
19257
19285
  anchorSources.add(n.id);
19258
- semanticEndpoints.set(n.id, contributedWireId(n));
19286
+ semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
19259
19287
  continue;
19260
19288
  }
19261
19289
  if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
19262
19290
  composition.autoMint++;
19263
19291
  continue;
19264
19292
  }
19265
- if (isTerminallyRefused(n)) {
19293
+ if (isTerminallyRefused({ ...n, attrs: instanceReceipt(n, opts.destinationKey) })) {
19266
19294
  composition.terminalRefused++;
19267
19295
  continue;
19268
19296
  }
@@ -19321,9 +19349,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19321
19349
  }
19322
19350
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
19323
19351
  const sourceNode = nodeOf(sourceId);
19324
- if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
19352
+ if ((sourceNode && instanceReceipt(sourceNode, opts.destinationKey)["anchorsContributedDigest"]) === dg) continue;
19325
19353
  anchorDigests[sourceId] = dg;
19326
- const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode);
19354
+ const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode, opts.destinationKey);
19327
19355
  for (const { e, t, wireId } of targets) {
19328
19356
  const reject = unshippableReason(wireId, t.label);
19329
19357
  if (reject) {
@@ -19352,7 +19380,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19352
19380
  for (const sourceId of anchorSources) {
19353
19381
  const source = nodeOf(sourceId);
19354
19382
  if (!source) continue;
19355
- const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
19383
+ const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source, opts.destinationKey);
19356
19384
  const planned = [];
19357
19385
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
19358
19386
  const target = nodeOf(e.to);
@@ -19387,7 +19415,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19387
19415
  const dg = digest(
19388
19416
  planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
19389
19417
  );
19390
- if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
19418
+ if (instanceReceipt(source, opts.destinationKey)["projectAnchorsContributedDigest"] === dg) continue;
19391
19419
  projectAnchorDigests[sourceId] = dg;
19392
19420
  for (const { e, target, symId, wireAttrs } of planned) {
19393
19421
  if (!contextSeen.has(symId)) {
@@ -19433,7 +19461,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19433
19461
  if (outs.length === 0) continue;
19434
19462
  const dg = digest(outs.map(({ e, wireTo }) => `${e.type}>${wireTo}`).sort());
19435
19463
  const owner = nodeOf(sourceId);
19436
- const digestSkip = owner?.attrs["semanticEdgesContributedDigest"] === dg;
19464
+ const digestSkip = (owner && instanceReceipt(owner, opts.destinationKey)["semanticEdgesContributedDigest"]) === dg;
19437
19465
  if (!digestSkip) semanticEdgeDigests[sourceId] = dg;
19438
19466
  for (const { e, wireTo } of outs) {
19439
19467
  if (digestSkip && !shippedById.has(e.to)) continue;
@@ -19490,7 +19518,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19490
19518
  for (const wn of nodes) {
19491
19519
  if (wn.label !== "RootCause" && wn.label !== "Solution") continue;
19492
19520
  const src = nodeOf(wn.id);
19493
- if (typeof src?.attrs["contributedAtSeq"] === "number") continue;
19521
+ if (src && typeof instanceReceipt(src, opts.destinationKey)["contributedAtSeq"] === "number") continue;
19494
19522
  if (bindingEndpoints.has(wn.id)) continue;
19495
19523
  heldOrphans.add(wn.id);
19496
19524
  }
@@ -19568,6 +19596,7 @@ function buildDrainInstances(store, sharedStore, input) {
19568
19596
  ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {},
19569
19597
  workspaceRoot: input.workspaceRoot,
19570
19598
  sharedStore,
19599
+ destinationKey: input.destinationKey,
19571
19600
  onComposition: (c) => {
19572
19601
  composition = c;
19573
19602
  },
package/errata.mjs CHANGED
@@ -15732,6 +15732,13 @@ function isSeedProvenance(source) {
15732
15732
  function isAnchorLabelKind(kind) {
15733
15733
  return typeof kind === "string" && ANCHOR_LABEL_KINDS.includes(kind);
15734
15734
  }
15735
+ function triageDiscriminatorAttrs(type, attrs) {
15736
+ if (!["CONFIRMS", "INDICATES", "ROUTES_TO"].includes(type)) return {};
15737
+ const value = attrs?.["discriminator"];
15738
+ if (typeof value !== "string") return {};
15739
+ const test = value.trim();
15740
+ return test && test.length <= TRIAGE_DISCRIMINATOR_MAX_LENGTH && !(test.startsWith("<") && test.endsWith(">")) ? { discriminator: test } : {};
15741
+ }
15735
15742
  function anchorVersionAttrs(attrs) {
15736
15743
  if (!attrs) return {};
15737
15744
  const commit = attrs["observedAtCommit"];
@@ -15792,7 +15799,7 @@ function summarizeIngestResult(r) {
15792
15799
  ...r.patternReconciliation ? { patternReconciliation: r.patternReconciliation } : {}
15793
15800
  };
15794
15801
  }
15795
- var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, QUARANTINE_EXTRACTION_SOURCE_PREFIX, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, ANCHOR_LABEL_KEYS, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15802
+ var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, QUARANTINE_EXTRACTION_SOURCE_PREFIX, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, ANCHOR_LABEL_KEYS, TRIAGE_DISCRIMINATOR_MAX_LENGTH, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15796
15803
  var init_wire = __esm({
15797
15804
  "../../packages/shared/src/wire.ts"() {
15798
15805
  "use strict";
@@ -15915,6 +15922,7 @@ var init_wire = __esm({
15915
15922
  ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
15916
15923
  ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
15917
15924
  ANCHOR_LABEL_KEYS = ["labelRelPath", "labelQname", "labelKind", "labelLine"];
15925
+ TRIAGE_DISCRIMINATOR_MAX_LENGTH = 2e3;
15918
15926
  CastaliaIngestEdgeSchema = external_exports.object({
15919
15927
  fromCanonicalId: external_exports.string().min(6).max(160),
15920
15928
  toCanonicalId: external_exports.string().min(6).max(160),
@@ -15925,6 +15933,8 @@ var init_wire = __esm({
15925
15933
  /** Triage route per-context counts (T3 induction). Carried as structured data
15926
15934
  * here; stored JSON-encoded on the Neo4j rel (`perContextJson`). */
15927
15935
  perContext: external_exports.record(external_exports.string(), RouteContextCountWireSchema).optional(),
15936
+ /** Scrubbed diagnostic check for a triage route, re-scanned at the cloud door. */
15937
+ discriminator: external_exports.string().trim().min(1).max(TRIAGE_DISCRIMINATOR_MAX_LENGTH).optional(),
15928
15938
  /** PJ-anchor-version: WHICH version of a symbol an `ANCHORED_AT` was
15929
15939
  * witnessed against. Both opaque — the observing checkout's HEAD sha and
15930
15940
  * the indexer's 16-hex sha256 of the symbol body. Neither is reversible
@@ -16827,6 +16837,7 @@ __export(src_exports, {
16827
16837
  TAXONOMY_EDGES: () => TAXONOMY_EDGES,
16828
16838
  TOOL_KINDS: () => TOOL_KINDS,
16829
16839
  TRANSFER_EDGES: () => TRANSFER_EDGES,
16840
+ TRIAGE_DISCRIMINATOR_MAX_LENGTH: () => TRIAGE_DISCRIMINATOR_MAX_LENGTH,
16830
16841
  TRIAGE_EDGES: () => TRIAGE_EDGES,
16831
16842
  TRUTH_KIND: () => TRUTH_KIND,
16832
16843
  UnregisteredGraphEventError: () => UnregisteredGraphEventError,
@@ -16910,6 +16921,7 @@ __export(src_exports, {
16910
16921
  summaryRejectionReason: () => summaryRejectionReason,
16911
16922
  toCloudAttrs: () => toCloudAttrs,
16912
16923
  toolCanonicalId: () => toolCanonicalId,
16924
+ triageDiscriminatorAttrs: () => triageDiscriminatorAttrs,
16913
16925
  unregisteredGraphEventKeys: () => unregisteredGraphEventKeys,
16914
16926
  validateCastaliaPayload: () => validateCastaliaPayload,
16915
16927
  versionlessPurl: () => versionlessPurl,
@@ -22620,7 +22632,8 @@ function pendingDiscriminators(l2, opts = {}) {
22620
22632
  const perContext = e.attrs["perContext"] ?? {};
22621
22633
  const global2 = perContext[TRIAGE_GLOBAL_BUCKET] ?? {};
22622
22634
  const observations = Number(global2.confirmed ?? 0);
22623
- const sources = new Set(global2.contributors ?? []).size;
22635
+ const inferred = new Set(global2.inferredContributors ?? []);
22636
+ const sources = new Set((global2.contributors ?? []).filter((id) => !inferred.has(id))).size;
22624
22637
  if (sources < minSources || observations < minObservations) continue;
22625
22638
  out2.push({ route: e.id, presenting: triage.description, cause: "", sources, observations, causeId: e.to });
22626
22639
  }
@@ -22638,7 +22651,7 @@ function markDiscriminatorAsked(l2, routeIds, ts) {
22638
22651
  }
22639
22652
  }
22640
22653
  function promoteRouteWithDiscriminator(l2, routeId, discriminator, ts, source) {
22641
- const test = discriminator.trim();
22654
+ const test = triageDiscriminatorAttrs("CONFIRMS", { discriminator }).discriminator;
22642
22655
  if (!test) return false;
22643
22656
  if (isUnfilledPlaceholder(test)) return false;
22644
22657
  const existing = l2.getEdge(routeId);
@@ -22740,9 +22753,12 @@ function parseTriageFences(text) {
22740
22753
  return out2;
22741
22754
  }
22742
22755
  function harvestTriageFences(l2, text, opts) {
22756
+ const seen = [...text.matchAll(/```errata-triage[^\n]*\n([\s\S]*?)```/g)].length;
22743
22757
  let recorded = 0;
22744
22758
  let promoted = 0;
22745
22759
  for (const f of parseTriageFences(text)) {
22760
+ if ([f.presenting, f.cause, f.test, f.fix, f.route].some((value) => value && isUnfilledPlaceholder(value))) continue;
22761
+ if (f.test && !triageDiscriminatorAttrs("CONFIRMS", { discriminator: f.test }).discriminator) continue;
22746
22762
  if (f.route && f.test) {
22747
22763
  if (promoteRouteWithDiscriminator(l2, f.route.trim(), f.test, opts.ts, opts.contributor)) promoted++;
22748
22764
  continue;
@@ -22778,7 +22794,7 @@ function harvestTriageFences(l2, text, opts) {
22778
22794
  }
22779
22795
  recorded++;
22780
22796
  }
22781
- return { recorded, promoted };
22797
+ return { seen, recorded, promoted, rejected: seen - recorded - promoted };
22782
22798
  }
22783
22799
  var COOCCUR_BONUS, routeEdgeId, ROUTE_EDGE_TYPES, routeTypeFor, isRouterRoute, INDUCTED_MARK, DRIFT_VALUES;
22784
22800
  var init_triage2 = __esm({
@@ -24396,7 +24412,7 @@ function renderSnapshot(s) {
24396
24412
  lines.push("");
24397
24413
  lines.push("### \u270D\uFE0F CAPTURE PROTOCOL \u2014 tags are the record");
24398
24414
  lines.push(
24399
- "errata records ONLY inline tags: `[!one line]` for every problem you state, `(fix:[id])` when your edit fixed a shown problem, and to JUDGE a prior shown below \u2014 `(confirm:[id])` if it held, `(refute:[id] why)` if it's wrong or didn't hold. Untagged prose is silently lost \u2014 tag as you write (no fences), we filter downstream."
24415
+ "For problems and fixes, errata records inline tags: `[!one line]` for every problem you state, `(fix:[id])` when your edit fixed a shown problem, and to JUDGE a prior shown below \u2014 `(confirm:[id])` if it held, `(refute:[id] why)` if it's wrong or didn't hold. Untagged prose is silently lost \u2014 tag as you write. Requested errata-* answer blocks keep their fences; put them in your turn-final reply."
24400
24416
  );
24401
24417
  lines.push("");
24402
24418
  lines.push(SEARCH_IMPERATIVE_HEADER);
@@ -24682,7 +24698,7 @@ function renderSnapshot(s) {
24682
24698
  for (const item of reviewItems) {
24683
24699
  if (item.kind === "discriminator") {
24684
24700
  lines.push(
24685
- `- **A recurring diagnosis is one cheap check from promoting** \u2014 "${item.presenting}" usually turns out to be: ${item.cause}. If (and only if) you KNOW a cheap ante-hoc check that confirms it, answer in your reply:`
24701
+ `- **A recurring diagnosis is one cheap check from promoting** \u2014 "${item.presenting}" usually turns out to be: ${item.cause}. If (and only if) you KNOW a cheap ante-hoc check that confirms it, fill this fenced block in your turn-final reply:`
24686
24702
  );
24687
24703
  lines.push(" ```errata-triage");
24688
24704
  lines.push(` route: ${item.route}`);
@@ -24690,7 +24706,7 @@ function renderSnapshot(s) {
24690
24706
  lines.push(" ```");
24691
24707
  } else {
24692
24708
  lines.push(
24693
- `- **Name the principle this cluster of your beliefs generalizes** \u2014 it ships to the collective only once named, and the prose must cover ALL members in one sentence:`
24709
+ `- **Name the principle this cluster of your beliefs generalizes** \u2014 it ships to the collective only once named. Cover ALL members in one sentence; fill this fenced block in your turn-final reply:`
24694
24710
  );
24695
24711
  for (const m of item.members) lines.push(` - ${m.description}`);
24696
24712
  lines.push(" ```errata-abstraction");
@@ -25196,6 +25212,7 @@ function toWirePayload(batch, runId) {
25196
25212
  attrs: {
25197
25213
  ...typeof e.confidence === "number" ? { confidence: clamp012(e.confidence) } : {},
25198
25214
  ...perContext ? { perContext } : {},
25215
+ ...triageDiscriminatorAttrs(e.type, e.attrs),
25199
25216
  // PJ-anchor-version: the two opaque version stamps ride on anchors only.
25200
25217
  ...e.type === "ANCHORED_AT" ? anchorVersionAttrs(e.attrs) : {},
25201
25218
  // PJ-anchor-labels: readable labels ride only when the producer set the
@@ -25802,6 +25819,7 @@ var init_client = __esm({
25802
25819
  if (q.seed?.length) qs.set("seed", q.seed.join(","));
25803
25820
  if (q.q) qs.set("q", q.q);
25804
25821
  if (q.channel) qs.set("channel", q.channel);
25822
+ if (q.includeTriage) qs.set("includeTriage", "true");
25805
25823
  const publicCtx = process.env["ERRATA_PRIMING_PUBLIC_CONTEXT"];
25806
25824
  const usePublicCtx = Boolean(publicCtx && publicCtx !== "0" && q.channel === "priming");
25807
25825
  const UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -29016,7 +29034,7 @@ function buildAgentInstruction(opts = {}) {
29016
29034
  const signals = opts.signals ?? ["prior", "problem", "domain", "fix", "constraint", "triage", "attempt", "link"];
29017
29035
  const ref = opts.referent ?? "its-handle";
29018
29036
  const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "domain" ? TAG_EXAMPLE.domain() : s === "link" ? TAG_EXAMPLE.pattern() : s === "verdict" ? TAG_EXAMPLE.confirm(ref) : TAG_EXAMPLE[s](ref);
29019
- const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. Tags are the ONLY signal recorded \u2014 anything you state but don't tag is silently lost. Weave each tag inline in your prose as you state it (no fences or backticks, no extra calls); tag everything, we filter downstream:`;
29037
+ const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. Untagged prose is silently lost. Put each tag inline in prose (no fences or backticks). Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply. Tag everything, we filter downstream:`;
29020
29038
  const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 RESTATE every tag in your turn-final message; the final message is what reliably survives \u2014 EXCEPT one already shown above with an id: that is captured, so cite `[its-handle]` rather than retyping it (drift mints a duplicate).";
29021
29039
  return [
29022
29040
  head2,
@@ -29506,6 +29524,18 @@ function resolveWorkspaceIdentity(cfg, entry, env2 = process.env) {
29506
29524
  function identityKey(id) {
29507
29525
  return id.profileName ?? "@default";
29508
29526
  }
29527
+ function publicWorkspaceIdentity(identity) {
29528
+ return {
29529
+ profileName: identity.profileName,
29530
+ rule: identity.rule,
29531
+ invalid: identity.invalid,
29532
+ reason: identity.reason,
29533
+ profile: identity.profile ? {
29534
+ installationId: identity.profile.installationId,
29535
+ cloudUrl: identity.profile.cloudUrl
29536
+ } : null
29537
+ };
29538
+ }
29509
29539
  function blockedCloudClient(reason) {
29510
29540
  return new Proxy(
29511
29541
  {},
@@ -41888,7 +41918,7 @@ function takeDiscriminatorNudge(path2) {
41888
41918
  return [
41889
41919
  `\u26A1 errata \u2014 a known wrong-door is one field from ranking: "${top.presenting.slice(0, 90)}"`,
41890
41920
  ` usually turns out to be: ${top.cause.slice(0, 90)} (seen ${top.observations}x)`,
41891
- " Know a CHEAP check that confirms it? Answer in-flow \u2014 it promotes the route so the",
41921
+ " Know a CHEAP check that confirms it? Fill this fenced block in your turn-final reply so the",
41892
41922
  " next agent gets it first. Only if you actually know one: a guessed test ranks first",
41893
41923
  " and misroutes everyone after you.",
41894
41924
  " ```errata-triage",
@@ -43405,7 +43435,7 @@ var init_mcp = __esm({
43405
43435
  pending,
43406
43436
  ...pending.length > 0 ? {
43407
43437
  howToAnswer: [
43408
- "For each route you know a cheap test for, emit an errata-triage fence",
43438
+ "For each route you know a cheap test for, emit an errata-triage fence in your turn-final reply",
43409
43439
  "carrying its `route` id and the `test` \u2014 no presenting/cause needed, the",
43410
43440
  "route id identifies both endpoints. Attaching a test does NOT count as",
43411
43441
  "another sighting, so it cannot inflate the route's evidence.",
@@ -74132,18 +74162,21 @@ function readTailWithLosses(path2, maxBytes) {
74132
74162
  try {
74133
74163
  fd = openSync(path2, "r");
74134
74164
  } catch {
74135
- return { text: "", bytesUnreachable: 0, ioFailed: true };
74165
+ return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
74136
74166
  }
74137
74167
  try {
74138
74168
  const size = fstatSync(fd).size;
74139
74169
  const start2 = Math.max(0, size - maxBytes);
74140
74170
  const len = size - start2;
74141
- if (len <= 0) return { text: "", bytesUnreachable: 0, ioFailed: false };
74171
+ if (len <= 0) return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: false };
74142
74172
  const buf = Buffer.allocUnsafe(len);
74143
74173
  readSync(fd, buf, 0, len, start2);
74144
- return { text: buf.toString("utf8"), bytesUnreachable: start2, ioFailed: false };
74174
+ const text = buf.toString("utf8");
74175
+ const firstNewline = buf.indexOf(10);
74176
+ const parseStartByte = firstNewline < 0 ? start2 : start2 + firstNewline + 1 - Buffer.byteLength(buf.subarray(0, firstNewline + 1).toString("utf8"));
74177
+ return { text, bytesUnreachable: start2, parseStartByte, ioFailed: false };
74145
74178
  } catch {
74146
- return { text: "", bytesUnreachable: 0, ioFailed: true };
74179
+ return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
74147
74180
  } finally {
74148
74181
  closeSync(fd);
74149
74182
  }
@@ -74207,7 +74240,7 @@ function isUserTurnBoundary(obj) {
74207
74240
  }
74208
74241
  function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, maxBytes = 2e6) {
74209
74242
  const tail = readTailWithLosses(transcriptPath, maxBytes);
74210
- const parsed = parseAssistantTurns(tail.text, includeThinking, false);
74243
+ const parsed = parseAssistantTurns(tail.text, includeThinking, false, tail.parseStartByte);
74211
74244
  return {
74212
74245
  turns: parsed.turns,
74213
74246
  losses: {
@@ -74219,7 +74252,8 @@ function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, ma
74219
74252
  }
74220
74253
  function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true, maxBytes) {
74221
74254
  const { text, nextOffset, more, ioFailed } = readFrom(transcriptPath, fromByte, maxBytes);
74222
- const parsed = parseAssistantTurns(text, includeThinking, fromByte > 0);
74255
+ const startByte = fromByte > 0 && fromByte <= nextOffset ? fromByte : 0;
74256
+ const parsed = parseAssistantTurns(text, includeThinking, fromByte > 0, startByte);
74223
74257
  return {
74224
74258
  turns: parsed.turns,
74225
74259
  nextOffset,
@@ -74255,10 +74289,10 @@ function detectHostHarness(raw2) {
74255
74289
  }
74256
74290
  return "claude_code";
74257
74291
  }
74258
- function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false) {
74292
+ function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false, startByte = 0) {
74259
74293
  if (!raw2) return { turns: [], parseFailures: 0 };
74260
74294
  const harness = detectHostHarness(raw2);
74261
- if (harness === "codex") return parseCodexAssistantTurns(raw2, skipFirstLineParseFailure);
74295
+ if (harness === "codex") return parseCodexAssistantTurns(raw2, skipFirstLineParseFailure, startByte);
74262
74296
  if (harness === "gemini") return parseGeminiAssistantTurns(raw2, skipFirstLineParseFailure);
74263
74297
  if (harness === "opencode") return parseOpencodeAssistantTurns(raw2, skipFirstLineParseFailure);
74264
74298
  return parseClaudeAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure);
@@ -74349,13 +74383,16 @@ function parseGeminiAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74349
74383
  const turns = [...byId.entries()].sort((a, b) => a[1].order - b[1].order).map(([uuid3, v]) => ({ uuid: uuid3, text: v.text, hostHarness: "gemini" }));
74350
74384
  return { turns, parseFailures };
74351
74385
  }
74352
- function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74386
+ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false, startByte = 0) {
74353
74387
  const turns = [];
74354
- const lines = raw2.split(/\r?\n/);
74388
+ const lines = raw2.split("\n");
74355
74389
  let parseFailures = 0;
74390
+ let nextByte = startByte;
74356
74391
  for (let i2 = 0; i2 < lines.length; i2++) {
74357
74392
  const line = lines[i2];
74358
- if (!line) continue;
74393
+ const lineByte = nextByte;
74394
+ nextByte += Buffer.byteLength(line ?? "", "utf8") + 1;
74395
+ if (!line?.trim()) continue;
74359
74396
  let obj;
74360
74397
  try {
74361
74398
  obj = JSON.parse(line);
@@ -74374,7 +74411,9 @@ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74374
74411
  }
74375
74412
  if (parts2.length === 0) continue;
74376
74413
  turns.push({
74377
- uuid: typeof payload["id"] === "string" ? payload["id"] : `codex-${i2}`,
74414
+ // Slice-local line numbers repeat on every Stop. Position distinguishes
74415
+ // identical messages; the digest distinguishes a replaced row at that position.
74416
+ uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${createHash14("sha256").update(line.trimEnd()).digest("hex")}`,
74378
74417
  text: parts2.join("\n\n"),
74379
74418
  hostHarness: "codex"
74380
74419
  });
@@ -74551,6 +74590,7 @@ function readCodexRolloutCwd(path2) {
74551
74590
  }
74552
74591
  }
74553
74592
  }
74593
+ var codexRolloutActivity = /* @__PURE__ */ new Map();
74554
74594
  function codexRolloutsForCwd(cwd, opts = {}) {
74555
74595
  const sinceMs = opts.sinceMs ?? 0;
74556
74596
  const limit = opts.limit ?? 25;
@@ -74558,7 +74598,14 @@ function codexRolloutsForCwd(cwd, opts = {}) {
74558
74598
  const owner = checkoutRootOf(cwd);
74559
74599
  const owners = /* @__PURE__ */ new Map();
74560
74600
  for (const root of codexSessionRoots(opts.env, opts.home)) {
74561
- if (!existsSync16(root)) continue;
74601
+ if (!existsSync16(root)) {
74602
+ codexRolloutActivity.delete(root);
74603
+ continue;
74604
+ }
74605
+ const activity = codexRolloutActivity.get(root) ?? /* @__PURE__ */ new Map();
74606
+ codexRolloutActivity.set(root, activity);
74607
+ const observed = /* @__PURE__ */ new Set();
74608
+ const scannedAt = Date.now();
74562
74609
  const stack = [{ dir: root, depth: 0 }];
74563
74610
  while (stack.length > 0) {
74564
74611
  const { dir, depth } = stack.pop();
@@ -74582,7 +74629,15 @@ function codexRolloutsForCwd(cwd, opts = {}) {
74582
74629
  }
74583
74630
  if (depth < 3) continue;
74584
74631
  if (!name2.startsWith("rollout-") || !name2.endsWith(".jsonl")) continue;
74585
- if (st.mtimeMs < sinceMs) continue;
74632
+ observed.add(full);
74633
+ const previous = activity.get(full);
74634
+ const activityAtMs = Math.max(
74635
+ st.mtimeMs,
74636
+ previous?.activeAt ?? 0,
74637
+ previous && previous.size !== st.size ? scannedAt : 0
74638
+ );
74639
+ activity.set(full, { size: st.size, activeAt: activityAtMs });
74640
+ if (activityAtMs < sinceMs) continue;
74586
74641
  const sessionCwd = readCodexRolloutCwd(full);
74587
74642
  if (sessionCwd === null) continue;
74588
74643
  let sessionOwner = owners.get(sessionCwd);
@@ -74591,11 +74646,12 @@ function codexRolloutsForCwd(cwd, opts = {}) {
74591
74646
  owners.set(sessionCwd, sessionOwner);
74592
74647
  }
74593
74648
  if (sessionOwner !== owner) continue;
74594
- out2.push({ path: full, sessionId: `codex:${basename5(name2, ".jsonl")}`, mtimeMs: st.mtimeMs });
74649
+ out2.push({ path: full, sessionId: `codex:${basename5(name2, ".jsonl")}`, mtimeMs: st.mtimeMs, activityAtMs });
74595
74650
  }
74596
74651
  }
74652
+ for (const path2 of activity.keys()) if (!observed.has(path2)) activity.delete(path2);
74597
74653
  }
74598
- out2.sort((a, b) => b.mtimeMs - a.mtimeMs);
74654
+ out2.sort((a, b) => (b.activityAtMs ?? b.mtimeMs) - (a.activityAtMs ?? a.mtimeMs));
74599
74655
  return out2.slice(0, limit);
74600
74656
  }
74601
74657
  function geminiSessionRoots(env2 = process.env, home = homedir4()) {
@@ -76946,21 +77002,31 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
76946
77002
  stack: profile.stack,
76947
77003
  domains: profile.domains,
76948
77004
  kinds: ["Problem"],
77005
+ includeTriage: true,
76949
77006
  limit
76950
77007
  });
76951
77008
  const byId = new Map(res.nodes.map((n) => [n.id, n]));
76952
77009
  const now = Date.now();
76953
77010
  let merged = 0;
77011
+ const landedTriages = /* @__PURE__ */ new Set();
76954
77012
  const landNode = (id) => {
76955
- if (shared.getNode(id)) return true;
77013
+ const existing = shared.getNode(id);
76956
77014
  const n = byId.get(id);
77015
+ if (existing) {
77016
+ if (n && existing.attrs["source"] === "cloud") {
77017
+ shared.updateNode(id, { attrs: { ...existing.attrs, ...n.attrs, source: "cloud" }, lastUpdatedAt: now });
77018
+ }
77019
+ return true;
77020
+ }
76957
77021
  if (!n) return false;
76958
77022
  shared.mergeNode({ ...n, extractionSource: "bko-inferred", embedding: [], attrs: { ...n.attrs, source: "cloud" } });
76959
77023
  return true;
76960
77024
  };
76961
77025
  for (const edge2 of res.edges) {
76962
77026
  if (edge2.type !== "CONFIRMS" && edge2.type !== "ROUTES_TO") continue;
77027
+ if (!triageDiscriminatorAttrs(edge2.type, edge2.attrs).discriminator) continue;
76963
77028
  if (!landNode(edge2.from) || !landNode(edge2.to)) continue;
77029
+ landedTriages.add(edge2.from);
76964
77030
  const cloudAttrs = { ...edge2.attrs, source: "cloud", provisional: false };
76965
77031
  const existing = shared.getEdge(edge2.id);
76966
77032
  if (existing && existing.type === "CONFIRMS") {
@@ -76971,6 +77037,11 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
76971
77037
  }
76972
77038
  merged++;
76973
77039
  }
77040
+ for (const edge2 of res.edges) {
77041
+ if (edge2.type !== "TRIAGED_BY" || !landedTriages.has(edge2.to)) continue;
77042
+ if (!landNode(edge2.from)) continue;
77043
+ shared.mergeEdge({ ...edge2, attrs: { ...edge2.attrs, source: "cloud" } });
77044
+ }
76974
77045
  return merged;
76975
77046
  }
76976
77047
 
@@ -80267,7 +80338,7 @@ function createWatchBreaker(deps) {
80267
80338
  }
80268
80339
 
80269
80340
  // src/engine.ts
80270
- var DAEMON_VERSION = true ? "2.0.9" : "2.0.0-alpha.0";
80341
+ var DAEMON_VERSION = true ? "2.0.11" : "2.0.0-alpha.0";
80271
80342
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
80272
80343
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
80273
80344
  var GIT_OP_MUTE_MS = 4e3;
@@ -81153,6 +81224,9 @@ function createWorkspaceEngine(opts) {
81153
81224
  let resolved = 0;
81154
81225
  let abstracted = 0;
81155
81226
  let triaged = 0;
81227
+ let triageFencesSeen = 0;
81228
+ let triagePromoted = 0;
81229
+ let triageFencesRejected = 0;
81156
81230
  let priorEdges = 0;
81157
81231
  let exposureShown = 0;
81158
81232
  let exposureEvicted = 0;
@@ -81216,11 +81290,16 @@ function createWorkspaceEngine(opts) {
81216
81290
  console.warn("[errata] abstraction harvest failed:", err2);
81217
81291
  }
81218
81292
  try {
81219
- triaged += harvestTriageFences(opts.sharedStore, turn.text, {
81293
+ const triage = harvestTriageFences(opts.sharedStore, turn.text, {
81220
81294
  context: { stack: profile.stack, domain: profile.domains[0] },
81221
81295
  contributor: sessionId,
81222
81296
  ts: t
81223
- }).recorded;
81297
+ });
81298
+ triaged += triage.recorded;
81299
+ triageFencesSeen += triage.seen;
81300
+ triagePromoted += triage.promoted;
81301
+ triageFencesRejected += triage.rejected;
81302
+ if (triage.recorded > 0 || triage.promoted > 0) contextDirty = true;
81224
81303
  } catch (err2) {
81225
81304
  console.warn("[errata] triage harvest failed:", err2);
81226
81305
  }
@@ -81896,8 +81975,8 @@ function createWorkspaceEngine(opts) {
81896
81975
  if (abstracted > 0) {
81897
81976
  console.log(`[errata] abstraction: ${abstracted} principle(s) distilled from the conversation`);
81898
81977
  }
81899
- if (triaged > 0) {
81900
- console.log(`[errata] triage: ${triaged} wrong-door(s) captured from the conversation`);
81978
+ if (triaged > 0 || triagePromoted > 0 || triageFencesRejected > 0) {
81979
+ console.log(`[errata] triage: ${triaged} diagnosis(es), ${triagePromoted} route promotion(s), ${triageFencesRejected} rejected fence(s)`);
81901
81980
  }
81902
81981
  if (processedTurns > 0) {
81903
81982
  appendPassLedger(paths.configDir, "capture", Date.now() - t, {
@@ -81912,6 +81991,9 @@ function createWorkspaceEngine(opts) {
81912
81991
  tagsRestated,
81913
81992
  resolved,
81914
81993
  triaged,
81994
+ triageFencesSeen,
81995
+ triagePromoted,
81996
+ triageFencesRejected,
81915
81997
  priorEdges,
81916
81998
  corroboratedEdges,
81917
81999
  // RG-mark: refute witnesses stamped onto local nodes (the local half of
@@ -82114,6 +82196,7 @@ function createWorkspaceEngine(opts) {
82114
82196
  for (const ref of refs) {
82115
82197
  await yieldToLoop();
82116
82198
  await harvestSession(ref.sessionId, ref.path);
82199
+ lastActivityTs = Math.max(lastActivityTs, ref.activityAtMs ?? ref.mtimeMs);
82117
82200
  }
82118
82201
  } catch {
82119
82202
  }
@@ -82713,6 +82796,40 @@ async function listenServer(fetchFn, port) {
82713
82796
  init_registry();
82714
82797
  init_identity2();
82715
82798
 
82799
+ // src/instance-receipts.ts
82800
+ import { createHash as createHash16 } from "node:crypto";
82801
+ var FIELDS = ["contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
82802
+ function instanceDestinationKey(input) {
82803
+ return createHash16("sha256").update(JSON.stringify([
82804
+ input.workspace,
82805
+ input.cloudUrl.replace(/\/+$/, ""),
82806
+ input.installationId ?? input.profileName ?? "default",
82807
+ input.projectId ?? null,
82808
+ input.writeTarget?.visibility ?? null,
82809
+ input.writeTarget?.org_id ?? null,
82810
+ input.writeTarget?.team_id ?? null
82811
+ ])).digest("hex");
82812
+ }
82813
+ function receiptMap(attrs) {
82814
+ const value = attrs["instanceReceipts"];
82815
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
82816
+ }
82817
+ function instanceReceipt(n, destination) {
82818
+ return destination ? receiptMap(n.attrs)[destination] ?? {} : n.attrs;
82819
+ }
82820
+ function updateInstanceReceipt(n, destination, patch, mirrorLegacy) {
82821
+ const receipt = { ...instanceReceipt(n, destination), ...patch };
82822
+ const attrs = { ...n.attrs, instanceReceipts: { ...receiptMap(n.attrs), [destination]: receipt } };
82823
+ if (mirrorLegacy) for (const field of FIELDS) {
82824
+ if (field in receipt) attrs[field] = receipt[field];
82825
+ else delete attrs[field];
82826
+ }
82827
+ return attrs;
82828
+ }
82829
+ function instanceReceiptSequence(n) {
82830
+ return Math.max(n.lastReinforcedAtSeq ?? 0, n.createdAtSeq ?? 0);
82831
+ }
82832
+
82716
82833
  // src/multi.ts
82717
82834
  init_dist();
82718
82835
  init_src5();
@@ -83117,8 +83234,8 @@ function compositionCounters(c) {
83117
83234
  ...Object.fromEntries(buckets.map((b) => [`sidecarDrop_${b}`, sidecarDropReasons[b] ?? 0]))
83118
83235
  };
83119
83236
  }
83120
- function contributedWireId(n) {
83121
- const cloudId = n.attrs["cloudNodeId"];
83237
+ function contributedWireId(n, destinationKey) {
83238
+ const cloudId = instanceReceipt(n, destinationKey)["cloudNodeId"];
83122
83239
  return isMembraneSaltedId(cloudId) ? cloudId : n.id;
83123
83240
  }
83124
83241
  var WIRE_CANONICAL_ID_MIN = 6;
@@ -83262,10 +83379,26 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83262
83379
  fileRefsSubstituted: 0,
83263
83380
  fileRefLexiconMisses: 0
83264
83381
  };
83382
+ const sharedCauses = /* @__PURE__ */ new Map();
83383
+ const causalQueue = store.findNodesByLabel("Problem").filter(
83384
+ (n) => n.attrs["source"] !== "cloud" && n.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE && !ignored(n.description)
83385
+ ).map((n) => n.id);
83386
+ const causalSeen = new Set(causalQueue);
83387
+ for (let i2 = 0; i2 < causalQueue.length; i2++) {
83388
+ const id = causalQueue[i2];
83389
+ for (const e of [...store.outEdges(id, ["CAUSED_BY"]), ...opts.sharedStore?.outEdges(id, ["CAUSED_BY"]) ?? []]) {
83390
+ if (causalSeen.has(e.to)) continue;
83391
+ causalSeen.add(e.to);
83392
+ const cause = nodeOf(e.to);
83393
+ if (!cause || cause.label !== "RootCause" || cause.attrs["source"] === "cloud" || ignored(cause.description)) continue;
83394
+ sharedCauses.set(cause.id, cause);
83395
+ causalQueue.push(cause.id);
83396
+ }
83397
+ }
83265
83398
  for (const label of INSTANCE_LABELS) {
83266
83399
  const ref = [];
83267
83400
  includedByLabel.set(label, ref);
83268
- const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...opts.sharedStore.findNodesByLabel(label)] : store.findNodesByLabel(label);
83401
+ const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...sharedCauses.values()] : store.findNodesByLabel(label);
83269
83402
  for (const n of population) {
83270
83403
  if (seen.has(n.id)) continue;
83271
83404
  if (walked.has(n.id)) continue;
@@ -83283,18 +83416,18 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83283
83416
  composition.ignored++;
83284
83417
  continue;
83285
83418
  }
83286
- const contributedAtSeq = n.attrs["contributedAtSeq"];
83419
+ const contributedAtSeq = instanceReceipt(n, opts.destinationKey)["contributedAtSeq"];
83287
83420
  if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
83288
83421
  composition.watermarked++;
83289
83422
  anchorSources.add(n.id);
83290
- semanticEndpoints.set(n.id, contributedWireId(n));
83423
+ semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
83291
83424
  continue;
83292
83425
  }
83293
83426
  if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
83294
83427
  composition.autoMint++;
83295
83428
  continue;
83296
83429
  }
83297
- if (isTerminallyRefused(n)) {
83430
+ if (isTerminallyRefused({ ...n, attrs: instanceReceipt(n, opts.destinationKey) })) {
83298
83431
  composition.terminalRefused++;
83299
83432
  continue;
83300
83433
  }
@@ -83353,9 +83486,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83353
83486
  }
83354
83487
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
83355
83488
  const sourceNode = nodeOf(sourceId);
83356
- if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
83489
+ if ((sourceNode && instanceReceipt(sourceNode, opts.destinationKey)["anchorsContributedDigest"]) === dg) continue;
83357
83490
  anchorDigests[sourceId] = dg;
83358
- const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode);
83491
+ const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode, opts.destinationKey);
83359
83492
  for (const { e, t, wireId } of targets) {
83360
83493
  const reject = unshippableReason(wireId, t.label);
83361
83494
  if (reject) {
@@ -83384,7 +83517,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83384
83517
  for (const sourceId of anchorSources) {
83385
83518
  const source = nodeOf(sourceId);
83386
83519
  if (!source) continue;
83387
- const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
83520
+ const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source, opts.destinationKey);
83388
83521
  const planned = [];
83389
83522
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
83390
83523
  const target = nodeOf(e.to);
@@ -83419,7 +83552,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83419
83552
  const dg = digest(
83420
83553
  planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
83421
83554
  );
83422
- if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
83555
+ if (instanceReceipt(source, opts.destinationKey)["projectAnchorsContributedDigest"] === dg) continue;
83423
83556
  projectAnchorDigests[sourceId] = dg;
83424
83557
  for (const { e, target, symId, wireAttrs } of planned) {
83425
83558
  if (!contextSeen.has(symId)) {
@@ -83465,7 +83598,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83465
83598
  if (outs.length === 0) continue;
83466
83599
  const dg = digest(outs.map(({ e, wireTo }) => `${e.type}>${wireTo}`).sort());
83467
83600
  const owner = nodeOf(sourceId);
83468
- const digestSkip = owner?.attrs["semanticEdgesContributedDigest"] === dg;
83601
+ const digestSkip = (owner && instanceReceipt(owner, opts.destinationKey)["semanticEdgesContributedDigest"]) === dg;
83469
83602
  if (!digestSkip) semanticEdgeDigests[sourceId] = dg;
83470
83603
  for (const { e, wireTo } of outs) {
83471
83604
  if (digestSkip && !shippedById.has(e.to)) continue;
@@ -83522,7 +83655,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
83522
83655
  for (const wn of nodes) {
83523
83656
  if (wn.label !== "RootCause" && wn.label !== "Solution") continue;
83524
83657
  const src = nodeOf(wn.id);
83525
- if (typeof src?.attrs["contributedAtSeq"] === "number") continue;
83658
+ if (src && typeof instanceReceipt(src, opts.destinationKey)["contributedAtSeq"] === "number") continue;
83526
83659
  if (bindingEndpoints.has(wn.id)) continue;
83527
83660
  heldOrphans.add(wn.id);
83528
83661
  }
@@ -83676,6 +83809,7 @@ function buildDrainInstances(store, sharedStore, input) {
83676
83809
  ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {},
83677
83810
  workspaceRoot: input.workspaceRoot,
83678
83811
  sharedStore,
83812
+ destinationKey: input.destinationKey,
83679
83813
  onComposition: (c) => {
83680
83814
  composition = c;
83681
83815
  },
@@ -85343,7 +85477,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
85343
85477
 
85344
85478
  // src/link-flow.ts
85345
85479
  init_cloud_auth();
85346
- import { createHash as createHash16 } from "node:crypto";
85480
+ import { createHash as createHash17 } from "node:crypto";
85347
85481
  import { execFileSync as execFileSync5 } from "node:child_process";
85348
85482
  import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
85349
85483
  import { join as join38 } from "node:path";
@@ -85637,7 +85771,7 @@ async function loginOAuthLoopback(opts) {
85637
85771
 
85638
85772
  // src/link-flow.ts
85639
85773
  function remoteFingerprint(locator) {
85640
- return createHash16("sha256").update(locator).digest("hex");
85774
+ return createHash17("sha256").update(locator).digest("hex");
85641
85775
  }
85642
85776
  function isDecision(value) {
85643
85777
  if (!value || typeof value !== "object") return false;
@@ -86944,11 +87078,17 @@ async function startMultiDaemon(opts = {}) {
86944
87078
  const ANCHOR_PULL_INTERVAL_MS = 10 * 60 * 1e3;
86945
87079
  const anchorPullAll = async () => {
86946
87080
  const c = loadConfig();
86947
- if (!hasCloudCredential(c)) return;
86948
- const client = cloudNow();
87081
+ if (registryCorrupt()) return;
86949
87082
  for (const r of records) {
86950
87083
  const projectId = r.engine.profile.projectId;
86951
87084
  if (!projectId || !effectiveConsent(c, r.engine.profile).sync) continue;
87085
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87086
+ if (identity.invalid) {
87087
+ noteIdentityBlock(r.id, r.entry.name, identity);
87088
+ continue;
87089
+ }
87090
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87091
+ const client = cloudForIdentity(identity);
86952
87092
  try {
86953
87093
  const { salt } = await resolveProjectSymbolSalt(client, projectId);
86954
87094
  await pullProjectAnchors(r, client, salt);
@@ -86962,11 +87102,17 @@ async function startMultiDaemon(opts = {}) {
86962
87102
  }, ANCHOR_PULL_INTERVAL_MS);
86963
87103
  const ambientLinkAll = async () => {
86964
87104
  const c = loadConfig();
86965
- if (!hasCloudCredential(c)) return;
86966
- const client = cloudNow();
87105
+ if (registryCorrupt()) return;
86967
87106
  for (const r of records) {
86968
87107
  const working = loadProfile(r.root) ?? r.engine.profile;
86969
87108
  if (!effectiveConsent(c, working).sync) continue;
87109
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87110
+ if (identity.invalid) {
87111
+ noteIdentityBlock(r.id, r.entry.name, identity);
87112
+ continue;
87113
+ }
87114
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87115
+ const client = cloudForIdentity(identity);
86970
87116
  const out2 = await ensureProjectLink(r.root, working, client);
86971
87117
  if (working !== r.engine.profile) adoptLinkFields(r.engine.profile, working);
86972
87118
  if (out2.linked) {
@@ -87354,6 +87500,7 @@ async function startMultiDaemon(opts = {}) {
87354
87500
  }
87355
87501
  const ignore2 = loadClaimIgnorePatterns(globalDir());
87356
87502
  const clientPool = /* @__PURE__ */ new Map();
87503
+ const receiptContexts = /* @__PURE__ */ new Map();
87357
87504
  const poolFor = (identity) => {
87358
87505
  const k = identityKey(identity);
87359
87506
  let c = clientPool.get(k);
@@ -87496,7 +87643,26 @@ async function startMultiDaemon(opts = {}) {
87496
87643
  return res.accepted;
87497
87644
  });
87498
87645
  }
87646
+ const receiptProfile = recordIdentity.profile ?? (cfg2.activeInstallationProfile ? cfg2.installationProfiles[cfg2.activeInstallationProfile] : void 0);
87647
+ let receiptContext = receiptContexts.get(identityKey(recordIdentity));
87648
+ if (!receiptContext) {
87649
+ try {
87650
+ receiptContext = await client.context();
87651
+ receiptContexts.set(identityKey(recordIdentity), receiptContext);
87652
+ } catch (err2) {
87653
+ errors.push(`[${projectName}] instance destination unresolved: ${err2 instanceof Error ? err2.message : String(err2)}`);
87654
+ continue;
87655
+ }
87656
+ }
87657
+ const destinationKey = instanceDestinationKey({
87658
+ workspace: r.id,
87659
+ cloudUrl: opts.cloudUrl ?? receiptProfile?.cloudUrl ?? cfg2.cloudUrl,
87660
+ installationId: receiptContext.context.installation_id ?? receiptContext.identity.credential_id,
87661
+ projectId: project?.projectId,
87662
+ writeTarget: project ? null : receiptContext.context.default_write_target
87663
+ });
87499
87664
  const built = await buildInstanceBatch(r, {
87665
+ destinationKey,
87500
87666
  profile: r.engine.profile,
87501
87667
  daemonVersion: DAEMON_VERSION,
87502
87668
  ignorePatterns: [...ignore2],
@@ -87541,7 +87707,6 @@ async function startMultiDaemon(opts = {}) {
87541
87707
  );
87542
87708
  }
87543
87709
  uploaded += res.accepted;
87544
- const seq = store.currentIngestSeq();
87545
87710
  const cloudIdByLocal = new Map(
87546
87711
  res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
87547
87712
  );
@@ -87550,6 +87715,7 @@ async function startMultiDaemon(opts = {}) {
87550
87715
  if (rn.decision === "rejected") rejected.set(rn.canonicalId, rn.reason ?? "no reason given");
87551
87716
  }
87552
87717
  const rejectedEdges = res.result.edges.filter((re) => re.decision === "rejected");
87718
+ const edgeReceiptsComplete = rejectedEdges.length === 0 && res.result.edges.length === instances.edges.length;
87553
87719
  if (rejectedEdges.length > 0) {
87554
87720
  const byReason = /* @__PURE__ */ new Map();
87555
87721
  for (const re of rejectedEdges) {
@@ -87580,17 +87746,17 @@ async function startMultiDaemon(opts = {}) {
87580
87746
  const owner = owningStore(id);
87581
87747
  if (!owner) return;
87582
87748
  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();
87749
+ const same = instanceReceipt(owner.n, destinationKey)["shipRefusedFingerprint"] === fp;
87750
+ const count = same ? Number(instanceReceipt(owner.n, destinationKey)["shipRefusedCount"] ?? 0) + 1 : 1;
87751
+ if (instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0) repeat();
87586
87752
  owner.s.updateNode(id, {
87587
- attrs: {
87588
- ...owner.n.attrs,
87589
- ...same && owner.n.attrs["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: seq },
87753
+ attrs: updateInstanceReceipt(owner.n, destinationKey, {
87754
+ ...instanceReceipt(owner.n, destinationKey),
87755
+ ...same && instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: owner.s.currentIngestSeq() },
87590
87756
  shipRefusedCount: count,
87591
87757
  shipRefusedReason: reason,
87592
87758
  shipRefusedFingerprint: fp
87593
- }
87759
+ }, owner.s === store)
87594
87760
  });
87595
87761
  if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
87596
87762
  nowHeld.push({ id, reason });
@@ -87607,6 +87773,7 @@ async function startMultiDaemon(opts = {}) {
87607
87773
  const owner = owningStore(n.id);
87608
87774
  if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) return;
87609
87775
  if (blocked.has(n.id)) return;
87776
+ if (!cloudIdByLocal.has(n.id)) return;
87610
87777
  if (rejected.has(n.id)) return;
87611
87778
  const cloudNodeId = cloudIdByLocal.get(n.id);
87612
87779
  const {
@@ -87615,37 +87782,41 @@ async function startMultiDaemon(opts = {}) {
87615
87782
  shipRefusedReason: _clearedReason,
87616
87783
  shipRefusedFingerprint: _clearedFp,
87617
87784
  ...carried
87618
- } = owner.n.attrs;
87785
+ } = instanceReceipt(owner.n, destinationKey);
87619
87786
  owner.s.updateNode(n.id, {
87620
- attrs: {
87787
+ attrs: updateInstanceReceipt(owner.n, destinationKey, {
87621
87788
  ...carried,
87622
- contributedAtSeq: seq,
87623
- ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
87624
- }
87789
+ shipRefusedSinceSeq: void 0,
87790
+ shipRefusedCount: void 0,
87791
+ shipRefusedReason: void 0,
87792
+ shipRefusedFingerprint: void 0,
87793
+ contributedAtSeq: instanceReceiptSequence(n),
87794
+ cloudNodeId
87795
+ }, owner.s === store)
87625
87796
  });
87626
87797
  });
87627
87798
  await stampBatched(Object.entries(instances.anchorDigests), ([localId, dg]) => {
87628
87799
  const owner = owningStore(localId);
87629
87800
  if (!owner) return;
87630
- if (rejected.has(localId) || blocked.has(localId)) return;
87801
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87631
87802
  owner.s.updateNode(localId, {
87632
- attrs: { ...owner.n.attrs, anchorsContributedDigest: dg }
87803
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { anchorsContributedDigest: dg }, owner.s === store)
87633
87804
  });
87634
87805
  });
87635
87806
  await stampBatched(Object.entries(instances.projectAnchorDigests), ([localId, dg]) => {
87636
87807
  const owner = owningStore(localId);
87637
87808
  if (!owner) return;
87638
- if (rejected.has(localId) || blocked.has(localId)) return;
87809
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87639
87810
  owner.s.updateNode(localId, {
87640
- attrs: { ...owner.n.attrs, projectAnchorsContributedDigest: dg }
87811
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { projectAnchorsContributedDigest: dg }, owner.s === store)
87641
87812
  });
87642
87813
  });
87643
87814
  await stampBatched(Object.entries(instances.semanticEdgeDigests), ([localId, dg]) => {
87644
87815
  const owner = owningStore(localId);
87645
87816
  if (!owner) return;
87646
- if (rejected.has(localId) || blocked.has(localId)) return;
87817
+ if (!edgeReceiptsComplete || !instanceReceipt(owner.n, destinationKey)["cloudNodeId"] || rejected.has(localId) || blocked.has(localId)) return;
87647
87818
  owner.s.updateNode(localId, {
87648
- attrs: { ...owner.n.attrs, semanticEdgesContributedDigest: dg }
87819
+ attrs: updateInstanceReceipt(owner.n, destinationKey, { semanticEdgesContributedDigest: dg }, owner.s === store)
87649
87820
  });
87650
87821
  });
87651
87822
  appendPassLedger(r.engine.paths.configDir, "ship", Date.now() - shipStartedAt, {
@@ -88385,7 +88556,7 @@ function buildCodexHooksToml(port, options) {
88385
88556
  if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid hook port");
88386
88557
  const command = quote(options.nodePath) + " " + quote(options.relayPath) + " " + port;
88387
88558
  const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop"].map(
88388
- (event) => "[[hooks." + event + "]]\n" + (["UserPromptSubmit", "Stop"].includes(event) ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\ntimeout = 10\nadditionalContextLimit = 5000\n"
88559
+ (event) => "[[hooks." + event + "]]\n" + (["UserPromptSubmit", "Stop"].includes(event) ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\ntimeout = 10\n" + (event === "Stop" ? "" : "additionalContextLimit = 5000\n")
88389
88560
  );
88390
88561
  return CODEX_HOOKS_BEGIN + "\n" + handlers.join("\n") + CODEX_HOOKS_END + "\n";
88391
88562
  }
@@ -89539,7 +89710,7 @@ async function cmdWhoami(args2) {
89539
89710
  `note: daemon capture and the MCP server resolve identically; a process with ERRATA_CONFIG_PATH set resolves by rule 1 regardless of binding.`
89540
89711
  ];
89541
89712
  if (args2.includes("--json")) {
89542
- console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...identity }, null, 2));
89713
+ console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...publicWorkspaceIdentity(identity) }, null, 2));
89543
89714
  } else {
89544
89715
  for (const l of lines) console.log(l);
89545
89716
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -15140,7 +15140,7 @@ var init_symbol_intent = __esm({
15140
15140
  });
15141
15141
 
15142
15142
  // ../../packages/shared/src/wire.ts
15143
- var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15143
+ var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, TRIAGE_DISCRIMINATOR_MAX_LENGTH, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15144
15144
  var init_wire = __esm({
15145
15145
  "../../packages/shared/src/wire.ts"() {
15146
15146
  "use strict";
@@ -15258,6 +15258,7 @@ var init_wire = __esm({
15258
15258
  ANCHOR_LABEL_KINDS = [...ANCHOR_SYMBOL_KINDS, "File"];
15259
15259
  ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
15260
15260
  ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
15261
+ TRIAGE_DISCRIMINATOR_MAX_LENGTH = 2e3;
15261
15262
  CastaliaIngestEdgeSchema = external_exports.object({
15262
15263
  fromCanonicalId: external_exports.string().min(6).max(160),
15263
15264
  toCanonicalId: external_exports.string().min(6).max(160),
@@ -15268,6 +15269,8 @@ var init_wire = __esm({
15268
15269
  /** Triage route per-context counts (T3 induction). Carried as structured data
15269
15270
  * here; stored JSON-encoded on the Neo4j rel (`perContextJson`). */
15270
15271
  perContext: external_exports.record(external_exports.string(), RouteContextCountWireSchema).optional(),
15272
+ /** Scrubbed diagnostic check for a triage route, re-scanned at the cloud door. */
15273
+ discriminator: external_exports.string().trim().min(1).max(TRIAGE_DISCRIMINATOR_MAX_LENGTH).optional(),
15271
15274
  /** PJ-anchor-version: WHICH version of a symbol an `ANCHORED_AT` was
15272
15275
  * witnessed against. Both opaque — the observing checkout's HEAD sha and
15273
15276
  * the indexer's 16-hex sha256 of the symbol body. Neither is reversible