@inerrata-corporation/errata 2.0.1-dev.99 → 2.0.2-dev.73

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.
@@ -15307,7 +15307,12 @@ var init_wire = __esm({
15307
15307
  * knows which packages are private. The door does NOT trust a `public` claim
15308
15308
  * blindly (it re-confirms on the spine); absent ⇒ unknown ⇒ fail-closed to
15309
15309
  * org-private. Accepted-but-ignored until ORG_MEMBRANE_ENABLED flips. */
15310
- anchorVisibility: external_exports.enum(["public", "private"]).optional()
15310
+ anchorVisibility: external_exports.enum(["public", "private"]).optional(),
15311
+ /** The spine-resolvable anchor id backing a `public` tag (OM-anchor-tag): a
15312
+ * Package purl or `languageCanonicalId`. The door validates THIS on the
15313
+ * public spine (falling back to `canonicalId` when absent — context stubs
15314
+ * are self-anchored). Never trusted without spine confirmation. */
15315
+ anchor: external_exports.string().min(1).max(300).optional()
15311
15316
  });
15312
15317
  RouteContextCountWireSchema = external_exports.object({
15313
15318
  confirmed: external_exports.number().int().min(0),
package/errata.mjs CHANGED
@@ -938,6 +938,12 @@ function packageCanonicalId(p) {
938
938
  const name2 = eco === "npm" ? p.name.toLowerCase() : p.name;
939
939
  return `pkg:${eco}/${name2}${p.version ? `@${p.version}` : ""}`;
940
940
  }
941
+ function versionlessPurl(purl) {
942
+ if (!purl.startsWith("pkg:")) return null;
943
+ const lastSlash = purl.lastIndexOf("/");
944
+ const lastAt = purl.lastIndexOf("@");
945
+ return lastAt > lastSlash ? purl.slice(0, lastAt) : purl;
946
+ }
941
947
  function parsePackageRef(ref) {
942
948
  let rest2 = ref.trim();
943
949
  if (rest2.startsWith("pkg:")) {
@@ -15602,7 +15608,12 @@ var init_wire = __esm({
15602
15608
  * knows which packages are private. The door does NOT trust a `public` claim
15603
15609
  * blindly (it re-confirms on the spine); absent ⇒ unknown ⇒ fail-closed to
15604
15610
  * org-private. Accepted-but-ignored until ORG_MEMBRANE_ENABLED flips. */
15605
- anchorVisibility: external_exports.enum(["public", "private"]).optional()
15611
+ anchorVisibility: external_exports.enum(["public", "private"]).optional(),
15612
+ /** The spine-resolvable anchor id backing a `public` tag (OM-anchor-tag): a
15613
+ * Package purl or `languageCanonicalId`. The door validates THIS on the
15614
+ * public spine (falling back to `canonicalId` when absent — context stubs
15615
+ * are self-anchored). Never trusted without spine confirmation. */
15616
+ anchor: external_exports.string().min(1).max(300).optional()
15606
15617
  });
15607
15618
  RouteContextCountWireSchema = external_exports.object({
15608
15619
  confirmed: external_exports.number().int().min(0),
@@ -15993,6 +16004,7 @@ __export(src_exports, {
15993
16004
  toCloudAttrs: () => toCloudAttrs,
15994
16005
  toolCanonicalId: () => toolCanonicalId,
15995
16006
  validateCastaliaPayload: () => validateCastaliaPayload,
16007
+ versionlessPurl: () => versionlessPurl,
15996
16008
  vetSidecarSummaries: () => vetSidecarSummaries
15997
16009
  });
15998
16010
  var init_src = __esm({
@@ -21530,7 +21542,12 @@ function toWirePayload(batch, runId) {
21530
21542
  // attrs travel; node-level bookkeeping (embedding, momentum counters,
21531
21543
  // bi-temporal fields) is local-stratum and never crosses.
21532
21544
  attrs: n.attrs ?? {},
21533
- extractionSource: n.extractionSource
21545
+ extractionSource: n.extractionSource,
21546
+ // Org-membrane anchor tag (OM-anchor-tag): the batch builders set these
21547
+ // on wire-bound projections only; the door re-validates the claim on the
21548
+ // public spine, so lifting them is routing input, not a grant.
21549
+ ...n.anchorVisibility ? { anchorVisibility: n.anchorVisibility } : {},
21550
+ ...n.anchor ? { anchor: n.anchor } : {}
21534
21551
  }));
21535
21552
  const edges = batch.edges.filter((e) => !droppedNodeIds.has(e.from) && !droppedNodeIds.has(e.to)).map((e) => {
21536
21553
  const perContext = wirePerContext(e.attrs?.["perContext"]);
@@ -21851,8 +21868,14 @@ var init_client = __esm({
21851
21868
  * the per-decision response into flush accounting.
21852
21869
  *
21853
21870
  * The v1 door caps a payload at `MAX_NODES_PER_PAYLOAD` / `MAX_EDGES_PER_PAYLOAD`
21854
- * (413 over). A batch above the cap is split and drained across calls under ONE
21855
- * runId: every NODE chunk first (edges empty), then EDGE chunks (nodes empty).
21871
+ * (413 over). A batch above the cap is split and drained across calls, every
21872
+ * NODE chunk first (edges empty), then EDGE chunks (nodes empty). Each chunk
21873
+ * gets its OWN runId: the door's durable idempotency claim is keyed on
21874
+ * (agent, org, runId) with the payload digest, so reusing one runId across
21875
+ * different chunk payloads 409s "runId was already used with a different
21876
+ * payload" on the second chunk — exactly how the first real >25-node drain
21877
+ * died (2026-07-22). The runId never grouped anything server-side; it exists
21878
+ * for duplicate-POST protection, which is per-request by nature.
21856
21879
  * Recognition resolves an edge's endpoints against nodes already ingested this
21857
21880
  * drain (endpoint-label validation is deferred to the service when an endpoint
21858
21881
  * isn't in-payload), so the split never orphans an edge. Sub-results concat into
@@ -21865,6 +21888,7 @@ var init_client = __esm({
21865
21888
  }
21866
21889
  const merged = { runId, nodes: [], edges: [] };
21867
21890
  let pendingEdges = [...batch.edges];
21891
+ const echoedCloudId = /* @__PURE__ */ new Map();
21868
21892
  for (const nodeChunk of chunkArray(batch.nodes, INGEST_NODE_CHUNK)) {
21869
21893
  const ids = new Set(nodeChunk.map((n) => n.id));
21870
21894
  const inChunk = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, MAX_EDGES_PER_PAYLOAD);
@@ -21872,15 +21896,23 @@ var init_client = __esm({
21872
21896
  const shipped = new Set(inChunk);
21873
21897
  pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
21874
21898
  }
21875
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, runId));
21899
+ const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, randomUUID()));
21876
21900
  merged.nodes.push(...r.nodes);
21877
21901
  merged.edges.push(...r.edges);
21902
+ for (const rn of r.nodes) {
21903
+ if (rn.nodeId && rn.nodeId !== rn.canonicalId) echoedCloudId.set(rn.canonicalId, rn.nodeId);
21904
+ }
21878
21905
  if (r.patternReconciliation) {
21879
21906
  merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
21880
21907
  }
21881
21908
  }
21882
21909
  for (const edgeChunk of chunkArray(pendingEdges, MAX_EDGES_PER_PAYLOAD)) {
21883
- const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: edgeChunk }, runId));
21910
+ const rewritten = edgeChunk.map((e) => ({
21911
+ ...e,
21912
+ from: echoedCloudId.get(e.from) ?? e.from,
21913
+ to: echoedCloudId.get(e.to) ?? e.to
21914
+ }));
21915
+ const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: rewritten }, randomUUID()));
21884
21916
  merged.edges.push(...r.edges);
21885
21917
  }
21886
21918
  return { ...summarizeIngestResult(merged), result: merged };
@@ -51649,7 +51681,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51649
51681
  }
51650
51682
 
51651
51683
  // src/engine.ts
51652
- var DAEMON_VERSION = true ? "2.0.1-dev.99" : "2.0.0-alpha.0";
51684
+ var DAEMON_VERSION = true ? "2.0.2-dev.73" : "2.0.0-alpha.0";
51653
51685
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
51654
51686
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
51655
51687
  var GIT_OP_MUTE_MS = 4e3;
@@ -53238,13 +53270,21 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
53238
53270
  // Package ids are already the purl (= the cross-stratum canonicalId).
53239
53271
  id: label === "Language" ? languageCanonicalId(String(n.attrs["name"] ?? "").trim() || n.description) : n.id,
53240
53272
  embedding: [],
53273
+ // No `version` attr on the wire: the purl already encodes the resolved
53274
+ // version, and the door's temporal guard rejects ANY `attrs.version` as
53275
+ // bi-temporal bookkeeping (ingest-temporal-guard.ts) — shipping it 422s
53276
+ // the whole batch. `resolved` still travels (range-vs-lockfile signal).
53241
53277
  attrs: label === "Package" ? {
53242
53278
  purl: n.attrs["purl"],
53243
53279
  name: n.attrs["name"],
53244
- version: n.attrs["version"],
53245
53280
  ecosystem: n.attrs["ecosystem"],
53246
53281
  resolved: n.attrs["resolved"]
53247
- } : { name: n.attrs["name"] }
53282
+ } : { name: n.attrs["name"] },
53283
+ // OM-anchor-tag: context stubs are self-anchored — the wire id IS the
53284
+ // spine key (purl / languageCanonicalId). The door re-confirms on the
53285
+ // public spine; a private-registry or workspace package never confirms
53286
+ // and fails closed to org, exactly as an untagged one would.
53287
+ anchorVisibility: "public"
53248
53288
  });
53249
53289
  seen.add(n.id);
53250
53290
  }
@@ -53356,13 +53396,20 @@ function wireContextId(n) {
53356
53396
  }
53357
53397
  function shareableContext(n, wireId) {
53358
53398
  const attrs = n.label === "Package" ? {
53399
+ // No `version` attr: the purl encodes it, and the door's temporal
53400
+ // guard 422s any `attrs.version` (mirrors buildContextIngest).
53359
53401
  purl: n.attrs["purl"],
53360
53402
  name: n.attrs["name"],
53361
- version: n.attrs["version"],
53362
53403
  ecosystem: n.attrs["ecosystem"],
53363
53404
  resolved: n.attrs["resolved"]
53364
53405
  } : n.label === "Domain" ? { name: n.description, canonicalId: n.attrs["canonicalId"] } : { name: n.attrs["name"] };
53365
- return { ...n, id: wireId, embedding: [], attrs };
53406
+ return {
53407
+ ...n,
53408
+ id: wireId,
53409
+ embedding: [],
53410
+ attrs,
53411
+ ...n.label === "Package" || n.label === "Language" ? { anchorVisibility: "public" } : {}
53412
+ };
53366
53413
  }
53367
53414
  function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
53368
53415
  const level = opts.level ?? 1;
@@ -53380,6 +53427,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53380
53427
  });
53381
53428
  const nodes = [];
53382
53429
  const seen = /* @__PURE__ */ new Set();
53430
+ const shippedById = /* @__PURE__ */ new Map();
53383
53431
  const anchorSources = /* @__PURE__ */ new Set();
53384
53432
  const includedByLabel = /* @__PURE__ */ new Map();
53385
53433
  for (const label of INSTANCE_LABELS) {
@@ -53397,7 +53445,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53397
53445
  }
53398
53446
  if (!noveltyAgainst(n, ref, noveltyOpts).ready) continue;
53399
53447
  ref.push(n);
53400
- nodes.push(shareable(n));
53448
+ const wireNode = shareable(n);
53449
+ nodes.push(wireNode);
53450
+ shippedById.set(n.id, wireNode);
53401
53451
  seen.add(n.id);
53402
53452
  anchorSources.add(n.id);
53403
53453
  }
@@ -53424,11 +53474,23 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53424
53474
  targets.push({ e, t, wireId: wireContextId(t) });
53425
53475
  }
53426
53476
  if (targets.length === 0) continue;
53477
+ const shipped = shippedById.get(sourceId);
53478
+ if (shipped) {
53479
+ const pick2 = (label) => targets.filter((x) => x.t.label === label).map((x) => x.wireId).sort()[0];
53480
+ const anchor = pick2("Package") ?? pick2("Language");
53481
+ if (anchor) {
53482
+ shipped.anchorVisibility = "public";
53483
+ shipped.anchor = anchor;
53484
+ }
53485
+ }
53427
53486
  const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
53428
- if (store.getNode(sourceId)?.attrs["anchorsContributedDigest"] === dg) continue;
53487
+ const sourceNode = store.getNode(sourceId);
53488
+ if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
53429
53489
  anchorDigests[sourceId] = dg;
53490
+ const skippedCloudId = !seen.has(sourceId) ? sourceNode?.attrs["cloudNodeId"] : void 0;
53491
+ const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
53430
53492
  for (const { e, t, wireId } of targets) {
53431
- anchorEdges.push({ ...e, to: wireId, attrs: {} });
53493
+ anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
53432
53494
  if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
53433
53495
  contextSeen.add(wireId);
53434
53496
  contextNodes.push(shareableContext(t, wireId));
@@ -53440,6 +53502,8 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53440
53502
  for (const sourceId of anchorSources) {
53441
53503
  const source = store.getNode(sourceId);
53442
53504
  if (!source) continue;
53505
+ const skippedCloudId = !seen.has(sourceId) ? source.attrs["cloudNodeId"] : void 0;
53506
+ const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
53443
53507
  for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
53444
53508
  const target = store.getNode(e.to);
53445
53509
  if (!target) continue;
@@ -53474,7 +53538,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53474
53538
  stability: "unstable"
53475
53539
  });
53476
53540
  }
53477
- anchorEdges.push({ ...e, to: symId, attrs: {} });
53541
+ anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: {} });
53478
53542
  }
53479
53543
  }
53480
53544
  }
@@ -53522,6 +53586,46 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53522
53586
  return { ...base, payloadDigest: digest(base), anchorDigests };
53523
53587
  }
53524
53588
 
53589
+ // src/backfill-edges.ts
53590
+ init_src();
53591
+ init_src2();
53592
+ var CAUSAL_LABELS = ["Problem", "Solution", "RootCause"];
53593
+ var CAUSAL_EDGES2 = ["SOLVED_BY", "CAUSED_BY", "FIXED_BY"];
53594
+ function cloudWireId(store, id) {
53595
+ const n = store.getNode(id);
53596
+ if (!n || !CAUSAL_LABELS.includes(n.label)) return null;
53597
+ if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) return null;
53598
+ const cloudNodeId = n.attrs["cloudNodeId"];
53599
+ if (typeof cloudNodeId === "string" && cloudNodeId.length > 0) return cloudNodeId;
53600
+ if (n.attrs["source"] === "cloud") return n.id;
53601
+ return typeof n.attrs["contributedAtSeq"] === "number" ? n.id : null;
53602
+ }
53603
+ function buildCausalEdgeBackfill(store, profile, daemonVersion) {
53604
+ const edges = [];
53605
+ const seenEdge = /* @__PURE__ */ new Set();
53606
+ for (const label of CAUSAL_LABELS) {
53607
+ for (const n of store.findNodesByLabel(label)) {
53608
+ for (const e of store.outEdges(n.id, [...CAUSAL_EDGES2])) {
53609
+ if (seenEdge.has(e.id)) continue;
53610
+ seenEdge.add(e.id);
53611
+ const from = cloudWireId(store, e.from);
53612
+ const to = cloudWireId(store, e.to);
53613
+ if (!from || !to) continue;
53614
+ edges.push({ ...e, from, to, attrs: {} });
53615
+ }
53616
+ }
53617
+ }
53618
+ if (edges.length === 0) return null;
53619
+ const base = {
53620
+ daemonVersion,
53621
+ profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
53622
+ originProject: profile.id,
53623
+ nodes: [],
53624
+ edges
53625
+ };
53626
+ return { ...base, payloadDigest: digest(base) };
53627
+ }
53628
+
53525
53629
  // src/multi.ts
53526
53630
  init_generalize_graph();
53527
53631
  init_symbol_summaries();
@@ -54533,14 +54637,27 @@ async function startMultiDaemon(opts = {}) {
54533
54637
  const ignore = loadClaimIgnorePatterns(globalDir());
54534
54638
  const client = cloudNow();
54535
54639
  let uploaded = 0;
54640
+ const errors = [];
54641
+ const lane = async (name2, projectName, run3) => {
54642
+ try {
54643
+ await run3();
54644
+ } catch (err2) {
54645
+ const msg = `[${projectName}] ${name2}: ${err2 instanceof Error ? err2.message : String(err2)}`;
54646
+ errors.push(msg);
54647
+ console.error(`[sync\u2192cloud] ${msg}`);
54648
+ }
54649
+ };
54536
54650
  for (const r of records) {
54537
54651
  const store = r.engine.store;
54652
+ const projectName = r.engine.profile.name ?? r.engine.profile.id;
54538
54653
  const context = buildContextIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
54539
54654
  includePackages: cfg2.consent.contributePackages
54540
54655
  });
54541
54656
  if (context) {
54542
- const res = await client.ingest(context);
54543
- uploaded += res.accepted;
54657
+ await lane("context", projectName, async () => {
54658
+ const res = await client.ingest(context);
54659
+ uploaded += res.accepted;
54660
+ });
54544
54661
  }
54545
54662
  let lexicon;
54546
54663
  try {
@@ -54563,34 +54680,58 @@ async function startMultiDaemon(opts = {}) {
54563
54680
  });
54564
54681
  if (instances) {
54565
54682
  if (project) instances.projectId = project.projectId;
54566
- const res = await client.ingest(instances);
54567
- uploaded += res.accepted;
54568
- const seq = store.currentIngestSeq();
54569
- const cloudIdByLocal = new Map(
54570
- res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
54683
+ await lane("instances", projectName, async () => {
54684
+ const res = await client.ingest(instances);
54685
+ uploaded += res.accepted;
54686
+ const seq = store.currentIngestSeq();
54687
+ const cloudIdByLocal = new Map(
54688
+ res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
54689
+ );
54690
+ for (const n of instances.nodes) {
54691
+ const local = store.getNode(n.id);
54692
+ if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
54693
+ const cloudNodeId = cloudIdByLocal.get(n.id);
54694
+ store.updateNode(n.id, {
54695
+ attrs: {
54696
+ ...local.attrs,
54697
+ contributedAtSeq: seq,
54698
+ ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
54699
+ }
54700
+ });
54701
+ }
54702
+ for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
54703
+ const local = store.getNode(localId);
54704
+ if (!local) continue;
54705
+ store.updateNode(localId, {
54706
+ attrs: { ...local.attrs, anchorsContributedDigest: dg }
54707
+ });
54708
+ }
54709
+ });
54710
+ }
54711
+ }
54712
+ return { uploaded, ...errors.length > 0 ? { errors } : {} };
54713
+ },
54714
+ async backfillCausalEdges() {
54715
+ if (!loadConfig().consent.sync) return { accepted: 0, rejected: 0, skipped: "consent-off" };
54716
+ const client = cloudNow();
54717
+ let accepted = 0;
54718
+ let rejected = 0;
54719
+ const errors = [];
54720
+ for (const r of records) {
54721
+ const payload = buildCausalEdgeBackfill(r.engine.store, r.engine.profile, DAEMON_VERSION);
54722
+ if (!payload) continue;
54723
+ try {
54724
+ const res = await client.ingest(payload);
54725
+ accepted += res.accepted;
54726
+ rejected += res.rejected;
54727
+ if (res.rejected > 0) errors.push(...res.violations.slice(0, 5));
54728
+ } catch (err2) {
54729
+ errors.push(
54730
+ `[${r.engine.profile.name ?? r.engine.profile.id}] backfill: ${err2 instanceof Error ? err2.message : String(err2)}`
54571
54731
  );
54572
- for (const n of instances.nodes) {
54573
- const local = store.getNode(n.id);
54574
- if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
54575
- const cloudNodeId = cloudIdByLocal.get(n.id);
54576
- store.updateNode(n.id, {
54577
- attrs: {
54578
- ...local.attrs,
54579
- contributedAtSeq: seq,
54580
- ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
54581
- }
54582
- });
54583
- }
54584
- for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
54585
- const local = store.getNode(localId);
54586
- if (!local) continue;
54587
- store.updateNode(localId, {
54588
- attrs: { ...local.attrs, anchorsContributedDigest: dg }
54589
- });
54590
- }
54591
54732
  }
54592
54733
  }
54593
- return { uploaded };
54734
+ return { accepted, rejected, ...errors.length > 0 ? { errors } : {} };
54594
54735
  },
54595
54736
  async pullTriagePublic() {
54596
54737
  if (!loadConfig().consent.sync) return { merged: 0, skipped: "consent-off" };
@@ -54640,7 +54781,12 @@ async function startMultiDaemon(opts = {}) {
54640
54781
  }
54641
54782
  const inst = await daemon.syncInstancesPublic();
54642
54783
  const skills = await daemon.syncSkillsAll();
54643
- return { uploaded: inst.uploaded, written: skills.written, pruned: skills.pruned };
54784
+ return {
54785
+ uploaded: inst.uploaded,
54786
+ written: skills.written,
54787
+ pruned: skills.pruned,
54788
+ ...inst.errors ? { errors: inst.errors } : {}
54789
+ };
54644
54790
  } finally {
54645
54791
  boundaryFlushing = false;
54646
54792
  }
@@ -54671,7 +54817,8 @@ async function startMultiDaemon(opts = {}) {
54671
54817
  const principles = await daemon.syncPrinciplesPublic();
54672
54818
  const triage = await daemon.syncTriagePublic();
54673
54819
  const instances = await daemon.syncInstancesPublic();
54674
- return c.json({ principles, triage, instances });
54820
+ const edgeBackfill = await daemon.backfillCausalEdges();
54821
+ return c.json({ principles, triage, instances, edgeBackfill });
54675
54822
  } catch (err2) {
54676
54823
  return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 500);
54677
54824
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.1-dev.99",
3
+ "version": "2.0.2-dev.73",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -15162,7 +15162,12 @@ var init_wire = __esm({
15162
15162
  * knows which packages are private. The door does NOT trust a `public` claim
15163
15163
  * blindly (it re-confirms on the spine); absent ⇒ unknown ⇒ fail-closed to
15164
15164
  * org-private. Accepted-but-ignored until ORG_MEMBRANE_ENABLED flips. */
15165
- anchorVisibility: external_exports.enum(["public", "private"]).optional()
15165
+ anchorVisibility: external_exports.enum(["public", "private"]).optional(),
15166
+ /** The spine-resolvable anchor id backing a `public` tag (OM-anchor-tag): a
15167
+ * Package purl or `languageCanonicalId`. The door validates THIS on the
15168
+ * public spine (falling back to `canonicalId` when absent — context stubs
15169
+ * are self-anchored). Never trusted without spine confirmation. */
15170
+ anchor: external_exports.string().min(1).max(300).optional()
15166
15171
  });
15167
15172
  RouteContextCountWireSchema = external_exports.object({
15168
15173
  confirmed: external_exports.number().int().min(0),