@inerrata-corporation/errata 2.0.1-dev.99 → 2.0.2-dev.70
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.
- package/errata.mjs +146 -39
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -21851,8 +21851,14 @@ var init_client = __esm({
|
|
|
21851
21851
|
* the per-decision response into flush accounting.
|
|
21852
21852
|
*
|
|
21853
21853
|
* 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
|
|
21855
|
-
*
|
|
21854
|
+
* (413 over). A batch above the cap is split and drained across calls, every
|
|
21855
|
+
* NODE chunk first (edges empty), then EDGE chunks (nodes empty). Each chunk
|
|
21856
|
+
* gets its OWN runId: the door's durable idempotency claim is keyed on
|
|
21857
|
+
* (agent, org, runId) with the payload digest, so reusing one runId across
|
|
21858
|
+
* different chunk payloads 409s "runId was already used with a different
|
|
21859
|
+
* payload" on the second chunk — exactly how the first real >25-node drain
|
|
21860
|
+
* died (2026-07-22). The runId never grouped anything server-side; it exists
|
|
21861
|
+
* for duplicate-POST protection, which is per-request by nature.
|
|
21856
21862
|
* Recognition resolves an edge's endpoints against nodes already ingested this
|
|
21857
21863
|
* drain (endpoint-label validation is deferred to the service when an endpoint
|
|
21858
21864
|
* isn't in-payload), so the split never orphans an edge. Sub-results concat into
|
|
@@ -21865,6 +21871,7 @@ var init_client = __esm({
|
|
|
21865
21871
|
}
|
|
21866
21872
|
const merged = { runId, nodes: [], edges: [] };
|
|
21867
21873
|
let pendingEdges = [...batch.edges];
|
|
21874
|
+
const echoedCloudId = /* @__PURE__ */ new Map();
|
|
21868
21875
|
for (const nodeChunk of chunkArray(batch.nodes, INGEST_NODE_CHUNK)) {
|
|
21869
21876
|
const ids = new Set(nodeChunk.map((n) => n.id));
|
|
21870
21877
|
const inChunk = pendingEdges.filter((e) => ids.has(e.from) && ids.has(e.to)).slice(0, MAX_EDGES_PER_PAYLOAD);
|
|
@@ -21872,15 +21879,23 @@ var init_client = __esm({
|
|
|
21872
21879
|
const shipped = new Set(inChunk);
|
|
21873
21880
|
pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
|
|
21874
21881
|
}
|
|
21875
|
-
const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk },
|
|
21882
|
+
const r = await this.ingestWire(toWirePayload({ ...batch, nodes: nodeChunk, edges: inChunk }, randomUUID()));
|
|
21876
21883
|
merged.nodes.push(...r.nodes);
|
|
21877
21884
|
merged.edges.push(...r.edges);
|
|
21885
|
+
for (const rn of r.nodes) {
|
|
21886
|
+
if (rn.nodeId && rn.nodeId !== rn.canonicalId) echoedCloudId.set(rn.canonicalId, rn.nodeId);
|
|
21887
|
+
}
|
|
21878
21888
|
if (r.patternReconciliation) {
|
|
21879
21889
|
merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
|
|
21880
21890
|
}
|
|
21881
21891
|
}
|
|
21882
21892
|
for (const edgeChunk of chunkArray(pendingEdges, MAX_EDGES_PER_PAYLOAD)) {
|
|
21883
|
-
const
|
|
21893
|
+
const rewritten = edgeChunk.map((e) => ({
|
|
21894
|
+
...e,
|
|
21895
|
+
from: echoedCloudId.get(e.from) ?? e.from,
|
|
21896
|
+
to: echoedCloudId.get(e.to) ?? e.to
|
|
21897
|
+
}));
|
|
21898
|
+
const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: rewritten }, randomUUID()));
|
|
21884
21899
|
merged.edges.push(...r.edges);
|
|
21885
21900
|
}
|
|
21886
21901
|
return { ...summarizeIngestResult(merged), result: merged };
|
|
@@ -51649,7 +51664,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
51649
51664
|
}
|
|
51650
51665
|
|
|
51651
51666
|
// src/engine.ts
|
|
51652
|
-
var DAEMON_VERSION = true ? "2.0.
|
|
51667
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.70" : "2.0.0-alpha.0";
|
|
51653
51668
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
51654
51669
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
51655
51670
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -53238,10 +53253,13 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
53238
53253
|
// Package ids are already the purl (= the cross-stratum canonicalId).
|
|
53239
53254
|
id: label === "Language" ? languageCanonicalId(String(n.attrs["name"] ?? "").trim() || n.description) : n.id,
|
|
53240
53255
|
embedding: [],
|
|
53256
|
+
// No `version` attr on the wire: the purl already encodes the resolved
|
|
53257
|
+
// version, and the door's temporal guard rejects ANY `attrs.version` as
|
|
53258
|
+
// bi-temporal bookkeeping (ingest-temporal-guard.ts) — shipping it 422s
|
|
53259
|
+
// the whole batch. `resolved` still travels (range-vs-lockfile signal).
|
|
53241
53260
|
attrs: label === "Package" ? {
|
|
53242
53261
|
purl: n.attrs["purl"],
|
|
53243
53262
|
name: n.attrs["name"],
|
|
53244
|
-
version: n.attrs["version"],
|
|
53245
53263
|
ecosystem: n.attrs["ecosystem"],
|
|
53246
53264
|
resolved: n.attrs["resolved"]
|
|
53247
53265
|
} : { name: n.attrs["name"] }
|
|
@@ -53356,9 +53374,10 @@ function wireContextId(n) {
|
|
|
53356
53374
|
}
|
|
53357
53375
|
function shareableContext(n, wireId) {
|
|
53358
53376
|
const attrs = n.label === "Package" ? {
|
|
53377
|
+
// No `version` attr: the purl encodes it, and the door's temporal
|
|
53378
|
+
// guard 422s any `attrs.version` (mirrors buildContextIngest).
|
|
53359
53379
|
purl: n.attrs["purl"],
|
|
53360
53380
|
name: n.attrs["name"],
|
|
53361
|
-
version: n.attrs["version"],
|
|
53362
53381
|
ecosystem: n.attrs["ecosystem"],
|
|
53363
53382
|
resolved: n.attrs["resolved"]
|
|
53364
53383
|
} : n.label === "Domain" ? { name: n.description, canonicalId: n.attrs["canonicalId"] } : { name: n.attrs["name"] };
|
|
@@ -53425,10 +53444,13 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
53425
53444
|
}
|
|
53426
53445
|
if (targets.length === 0) continue;
|
|
53427
53446
|
const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
|
|
53428
|
-
|
|
53447
|
+
const sourceNode = store.getNode(sourceId);
|
|
53448
|
+
if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
|
|
53429
53449
|
anchorDigests[sourceId] = dg;
|
|
53450
|
+
const skippedCloudId = !seen.has(sourceId) ? sourceNode?.attrs["cloudNodeId"] : void 0;
|
|
53451
|
+
const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
|
|
53430
53452
|
for (const { e, t, wireId } of targets) {
|
|
53431
|
-
anchorEdges.push({ ...e, to: wireId, attrs: {} });
|
|
53453
|
+
anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
|
|
53432
53454
|
if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
|
|
53433
53455
|
contextSeen.add(wireId);
|
|
53434
53456
|
contextNodes.push(shareableContext(t, wireId));
|
|
@@ -53440,6 +53462,8 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
53440
53462
|
for (const sourceId of anchorSources) {
|
|
53441
53463
|
const source = store.getNode(sourceId);
|
|
53442
53464
|
if (!source) continue;
|
|
53465
|
+
const skippedCloudId = !seen.has(sourceId) ? source.attrs["cloudNodeId"] : void 0;
|
|
53466
|
+
const wireFrom = typeof skippedCloudId === "string" && skippedCloudId.length > 0 ? skippedCloudId : sourceId;
|
|
53443
53467
|
for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
|
|
53444
53468
|
const target = store.getNode(e.to);
|
|
53445
53469
|
if (!target) continue;
|
|
@@ -53474,7 +53498,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
53474
53498
|
stability: "unstable"
|
|
53475
53499
|
});
|
|
53476
53500
|
}
|
|
53477
|
-
anchorEdges.push({ ...e, to: symId, attrs: {} });
|
|
53501
|
+
anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: {} });
|
|
53478
53502
|
}
|
|
53479
53503
|
}
|
|
53480
53504
|
}
|
|
@@ -53522,6 +53546,46 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
53522
53546
|
return { ...base, payloadDigest: digest(base), anchorDigests };
|
|
53523
53547
|
}
|
|
53524
53548
|
|
|
53549
|
+
// src/backfill-edges.ts
|
|
53550
|
+
init_src();
|
|
53551
|
+
init_src2();
|
|
53552
|
+
var CAUSAL_LABELS = ["Problem", "Solution", "RootCause"];
|
|
53553
|
+
var CAUSAL_EDGES2 = ["SOLVED_BY", "CAUSED_BY", "FIXED_BY"];
|
|
53554
|
+
function cloudWireId(store, id) {
|
|
53555
|
+
const n = store.getNode(id);
|
|
53556
|
+
if (!n || !CAUSAL_LABELS.includes(n.label)) return null;
|
|
53557
|
+
if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) return null;
|
|
53558
|
+
const cloudNodeId = n.attrs["cloudNodeId"];
|
|
53559
|
+
if (typeof cloudNodeId === "string" && cloudNodeId.length > 0) return cloudNodeId;
|
|
53560
|
+
if (n.attrs["source"] === "cloud") return n.id;
|
|
53561
|
+
return typeof n.attrs["contributedAtSeq"] === "number" ? n.id : null;
|
|
53562
|
+
}
|
|
53563
|
+
function buildCausalEdgeBackfill(store, profile, daemonVersion) {
|
|
53564
|
+
const edges = [];
|
|
53565
|
+
const seenEdge = /* @__PURE__ */ new Set();
|
|
53566
|
+
for (const label of CAUSAL_LABELS) {
|
|
53567
|
+
for (const n of store.findNodesByLabel(label)) {
|
|
53568
|
+
for (const e of store.outEdges(n.id, [...CAUSAL_EDGES2])) {
|
|
53569
|
+
if (seenEdge.has(e.id)) continue;
|
|
53570
|
+
seenEdge.add(e.id);
|
|
53571
|
+
const from = cloudWireId(store, e.from);
|
|
53572
|
+
const to = cloudWireId(store, e.to);
|
|
53573
|
+
if (!from || !to) continue;
|
|
53574
|
+
edges.push({ ...e, from, to, attrs: {} });
|
|
53575
|
+
}
|
|
53576
|
+
}
|
|
53577
|
+
}
|
|
53578
|
+
if (edges.length === 0) return null;
|
|
53579
|
+
const base = {
|
|
53580
|
+
daemonVersion,
|
|
53581
|
+
profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
|
|
53582
|
+
originProject: profile.id,
|
|
53583
|
+
nodes: [],
|
|
53584
|
+
edges
|
|
53585
|
+
};
|
|
53586
|
+
return { ...base, payloadDigest: digest(base) };
|
|
53587
|
+
}
|
|
53588
|
+
|
|
53525
53589
|
// src/multi.ts
|
|
53526
53590
|
init_generalize_graph();
|
|
53527
53591
|
init_symbol_summaries();
|
|
@@ -54533,14 +54597,27 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54533
54597
|
const ignore = loadClaimIgnorePatterns(globalDir());
|
|
54534
54598
|
const client = cloudNow();
|
|
54535
54599
|
let uploaded = 0;
|
|
54600
|
+
const errors = [];
|
|
54601
|
+
const lane = async (name2, projectName, run3) => {
|
|
54602
|
+
try {
|
|
54603
|
+
await run3();
|
|
54604
|
+
} catch (err2) {
|
|
54605
|
+
const msg = `[${projectName}] ${name2}: ${err2 instanceof Error ? err2.message : String(err2)}`;
|
|
54606
|
+
errors.push(msg);
|
|
54607
|
+
console.error(`[sync\u2192cloud] ${msg}`);
|
|
54608
|
+
}
|
|
54609
|
+
};
|
|
54536
54610
|
for (const r of records) {
|
|
54537
54611
|
const store = r.engine.store;
|
|
54612
|
+
const projectName = r.engine.profile.name ?? r.engine.profile.id;
|
|
54538
54613
|
const context = buildContextIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
|
|
54539
54614
|
includePackages: cfg2.consent.contributePackages
|
|
54540
54615
|
});
|
|
54541
54616
|
if (context) {
|
|
54542
|
-
|
|
54543
|
-
|
|
54617
|
+
await lane("context", projectName, async () => {
|
|
54618
|
+
const res = await client.ingest(context);
|
|
54619
|
+
uploaded += res.accepted;
|
|
54620
|
+
});
|
|
54544
54621
|
}
|
|
54545
54622
|
let lexicon;
|
|
54546
54623
|
try {
|
|
@@ -54563,34 +54640,58 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54563
54640
|
});
|
|
54564
54641
|
if (instances) {
|
|
54565
54642
|
if (project) instances.projectId = project.projectId;
|
|
54566
|
-
|
|
54567
|
-
|
|
54568
|
-
|
|
54569
|
-
|
|
54570
|
-
|
|
54643
|
+
await lane("instances", projectName, async () => {
|
|
54644
|
+
const res = await client.ingest(instances);
|
|
54645
|
+
uploaded += res.accepted;
|
|
54646
|
+
const seq = store.currentIngestSeq();
|
|
54647
|
+
const cloudIdByLocal = new Map(
|
|
54648
|
+
res.result.nodes.filter((rn) => rn.nodeId).map((rn) => [rn.canonicalId, rn.nodeId])
|
|
54649
|
+
);
|
|
54650
|
+
for (const n of instances.nodes) {
|
|
54651
|
+
const local = store.getNode(n.id);
|
|
54652
|
+
if (!local || !["Problem", "Solution", "RootCause"].includes(local.label)) continue;
|
|
54653
|
+
const cloudNodeId = cloudIdByLocal.get(n.id);
|
|
54654
|
+
store.updateNode(n.id, {
|
|
54655
|
+
attrs: {
|
|
54656
|
+
...local.attrs,
|
|
54657
|
+
contributedAtSeq: seq,
|
|
54658
|
+
...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
|
|
54659
|
+
}
|
|
54660
|
+
});
|
|
54661
|
+
}
|
|
54662
|
+
for (const [localId, dg] of Object.entries(instances.anchorDigests)) {
|
|
54663
|
+
const local = store.getNode(localId);
|
|
54664
|
+
if (!local) continue;
|
|
54665
|
+
store.updateNode(localId, {
|
|
54666
|
+
attrs: { ...local.attrs, anchorsContributedDigest: dg }
|
|
54667
|
+
});
|
|
54668
|
+
}
|
|
54669
|
+
});
|
|
54670
|
+
}
|
|
54671
|
+
}
|
|
54672
|
+
return { uploaded, ...errors.length > 0 ? { errors } : {} };
|
|
54673
|
+
},
|
|
54674
|
+
async backfillCausalEdges() {
|
|
54675
|
+
if (!loadConfig().consent.sync) return { accepted: 0, rejected: 0, skipped: "consent-off" };
|
|
54676
|
+
const client = cloudNow();
|
|
54677
|
+
let accepted = 0;
|
|
54678
|
+
let rejected = 0;
|
|
54679
|
+
const errors = [];
|
|
54680
|
+
for (const r of records) {
|
|
54681
|
+
const payload = buildCausalEdgeBackfill(r.engine.store, r.engine.profile, DAEMON_VERSION);
|
|
54682
|
+
if (!payload) continue;
|
|
54683
|
+
try {
|
|
54684
|
+
const res = await client.ingest(payload);
|
|
54685
|
+
accepted += res.accepted;
|
|
54686
|
+
rejected += res.rejected;
|
|
54687
|
+
if (res.rejected > 0) errors.push(...res.violations.slice(0, 5));
|
|
54688
|
+
} catch (err2) {
|
|
54689
|
+
errors.push(
|
|
54690
|
+
`[${r.engine.profile.name ?? r.engine.profile.id}] backfill: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
54571
54691
|
);
|
|
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
54692
|
}
|
|
54592
54693
|
}
|
|
54593
|
-
return {
|
|
54694
|
+
return { accepted, rejected, ...errors.length > 0 ? { errors } : {} };
|
|
54594
54695
|
},
|
|
54595
54696
|
async pullTriagePublic() {
|
|
54596
54697
|
if (!loadConfig().consent.sync) return { merged: 0, skipped: "consent-off" };
|
|
@@ -54640,7 +54741,12 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54640
54741
|
}
|
|
54641
54742
|
const inst = await daemon.syncInstancesPublic();
|
|
54642
54743
|
const skills = await daemon.syncSkillsAll();
|
|
54643
|
-
return {
|
|
54744
|
+
return {
|
|
54745
|
+
uploaded: inst.uploaded,
|
|
54746
|
+
written: skills.written,
|
|
54747
|
+
pruned: skills.pruned,
|
|
54748
|
+
...inst.errors ? { errors: inst.errors } : {}
|
|
54749
|
+
};
|
|
54644
54750
|
} finally {
|
|
54645
54751
|
boundaryFlushing = false;
|
|
54646
54752
|
}
|
|
@@ -54671,7 +54777,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54671
54777
|
const principles = await daemon.syncPrinciplesPublic();
|
|
54672
54778
|
const triage = await daemon.syncTriagePublic();
|
|
54673
54779
|
const instances = await daemon.syncInstancesPublic();
|
|
54674
|
-
|
|
54780
|
+
const edgeBackfill = await daemon.backfillCausalEdges();
|
|
54781
|
+
return c.json({ principles, triage, instances, edgeBackfill });
|
|
54675
54782
|
} catch (err2) {
|
|
54676
54783
|
return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 500);
|
|
54677
54784
|
}
|