@inerrata-corporation/errata 2.0.2-dev.156 → 2.0.2-dev.161
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 +116 -49
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -25916,6 +25916,33 @@ function federationHint(status) {
|
|
|
25916
25916
|
return void 0;
|
|
25917
25917
|
}
|
|
25918
25918
|
}
|
|
25919
|
+
function hasCloudNodeShape(id) {
|
|
25920
|
+
return CANONICAL_KNOWLEDGE_ID.test(id) || UUID_ID.test(id) || id.startsWith("pkg:");
|
|
25921
|
+
}
|
|
25922
|
+
async function collectiveDrilldown(cloud, seedId, limit) {
|
|
25923
|
+
try {
|
|
25924
|
+
const res = await cloud.search({ stack: [], domains: [], kinds: [], seed: [seedId], limit });
|
|
25925
|
+
if (res.nodes.length === 0) return null;
|
|
25926
|
+
return {
|
|
25927
|
+
seed: seedId,
|
|
25928
|
+
nodes: res.nodes.map((n) => ({
|
|
25929
|
+
id: n.id,
|
|
25930
|
+
label: n.label,
|
|
25931
|
+
name: n.description,
|
|
25932
|
+
score: Number((n.extractionConfidence ?? 0.5).toFixed(4)),
|
|
25933
|
+
hops: 1,
|
|
25934
|
+
provenance: "collective"
|
|
25935
|
+
})),
|
|
25936
|
+
edges: res.edges.map((e) => ({ from: e.from, to: e.to, type: e.type }))
|
|
25937
|
+
};
|
|
25938
|
+
} catch (err2) {
|
|
25939
|
+
console.error(
|
|
25940
|
+
"[errata] collectiveDrilldown: cloud fallback failed \u2014",
|
|
25941
|
+
err2 instanceof Error ? err2.message : err2
|
|
25942
|
+
);
|
|
25943
|
+
return null;
|
|
25944
|
+
}
|
|
25945
|
+
}
|
|
25919
25946
|
function formatDualNodes(merged) {
|
|
25920
25947
|
return merged.nodes.map((n) => ({
|
|
25921
25948
|
id: n.id,
|
|
@@ -25935,7 +25962,7 @@ function formatDualNodes(merged) {
|
|
|
25935
25962
|
} : {}
|
|
25936
25963
|
}));
|
|
25937
25964
|
}
|
|
25938
|
-
var BRIDGE_LABELS;
|
|
25965
|
+
var BRIDGE_LABELS, CANONICAL_KNOWLEDGE_ID, UUID_ID;
|
|
25939
25966
|
var init_dual_augment = __esm({
|
|
25940
25967
|
"src/dual-augment.ts"() {
|
|
25941
25968
|
"use strict";
|
|
@@ -25943,6 +25970,8 @@ var init_dual_augment = __esm({
|
|
|
25943
25970
|
init_generalize_graph();
|
|
25944
25971
|
init_dual_burst();
|
|
25945
25972
|
BRIDGE_LABELS = new Set(SEMANTIC_NODE_LABELS);
|
|
25973
|
+
CANONICAL_KNOWLEDGE_ID = /^[a-z][a-z0-9]*_[0-9a-f]{8,}$/;
|
|
25974
|
+
UUID_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
25946
25975
|
}
|
|
25947
25976
|
});
|
|
25948
25977
|
|
|
@@ -36858,6 +36887,12 @@ function cosine3(a, b) {
|
|
|
36858
36887
|
for (let i2 = 0; i2 < a.length; i2++) dot += a[i2] * b[i2];
|
|
36859
36888
|
return dot;
|
|
36860
36889
|
}
|
|
36890
|
+
async function collectiveSeedFallback(args2, ctx, defaultLimit) {
|
|
36891
|
+
const seedId = typeof args2["nodeId"] === "string" ? args2["nodeId"] : null;
|
|
36892
|
+
if (!seedId || !ctx.cloud || !hasCloudNodeShape(seedId)) return null;
|
|
36893
|
+
const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? defaultLimit)));
|
|
36894
|
+
return collectiveDrilldown(ctx.cloud, seedId, limit);
|
|
36895
|
+
}
|
|
36861
36896
|
function resolveSymbol2(store, args2) {
|
|
36862
36897
|
const id = args2["nodeId"];
|
|
36863
36898
|
if (typeof id === "string" && store.getNode(id)) return id;
|
|
@@ -37208,7 +37243,7 @@ var init_mcp = __esm({
|
|
|
37208
37243
|
},
|
|
37209
37244
|
{
|
|
37210
37245
|
name: "errata.neighbors",
|
|
37211
|
-
description: "Return direct in/out edges of a node. Pass either a nodeId or a qname (e.g. ClassName.method) \u2014 resolved like the other nav verbs. Use after errata.search or errata.locate to walk the graph.",
|
|
37246
|
+
description: "Return direct in/out edges of a node. Pass either a nodeId or a qname (e.g. ClassName.method) \u2014 resolved like the other nav verbs. Use after errata.search or errata.locate to walk the graph. A cloud id from search's collective blend (e.g. dprob_\u2026) that isn't in the local graph falls back to its collective neighborhood, tagged provenance:collective.",
|
|
37212
37247
|
inputSchema: {
|
|
37213
37248
|
type: "object",
|
|
37214
37249
|
properties: {
|
|
@@ -37217,9 +37252,27 @@ var init_mcp = __esm({
|
|
|
37217
37252
|
limit: { type: "number", description: "Max edges per direction (default 30)" }
|
|
37218
37253
|
}
|
|
37219
37254
|
},
|
|
37220
|
-
handler: (args2, store) => {
|
|
37255
|
+
handler: async (args2, store, ctx) => {
|
|
37221
37256
|
const id = resolveSymbol2(store, args2);
|
|
37222
|
-
if (!id)
|
|
37257
|
+
if (!id) {
|
|
37258
|
+
const cn = await collectiveSeedFallback(args2, ctx, 30);
|
|
37259
|
+
if (cn) {
|
|
37260
|
+
return {
|
|
37261
|
+
found: true,
|
|
37262
|
+
node: { id: cn.seed, provenance: "collective" },
|
|
37263
|
+
collectiveReachable: true,
|
|
37264
|
+
collectiveStatus: "cloud-seed",
|
|
37265
|
+
// Seed-touching edge types aren't on the wire (the server's seed
|
|
37266
|
+
// burst excludes the seed itself, and edges to nodes outside the
|
|
37267
|
+
// result set are dropped), so the collective fallback reports the
|
|
37268
|
+
// 1-hop neighborhood + its internal topology instead of the local
|
|
37269
|
+
// contract's typed out/in lists.
|
|
37270
|
+
nearby: cn.nodes,
|
|
37271
|
+
edges: cn.edges
|
|
37272
|
+
};
|
|
37273
|
+
}
|
|
37274
|
+
return unresolved(args2);
|
|
37275
|
+
}
|
|
37223
37276
|
const limit = Math.max(1, Math.min(200, Number(args2["limit"] ?? 30)));
|
|
37224
37277
|
const node2 = store.getNode(id);
|
|
37225
37278
|
if (!node2) return { found: false, reason: "not-found" };
|
|
@@ -37266,32 +37319,17 @@ var init_mcp = __esm({
|
|
|
37266
37319
|
handler: async (args2, store, ctx) => {
|
|
37267
37320
|
const id = resolveSymbol2(store, args2);
|
|
37268
37321
|
if (!id) {
|
|
37269
|
-
const
|
|
37270
|
-
if (
|
|
37271
|
-
|
|
37272
|
-
|
|
37273
|
-
|
|
37274
|
-
|
|
37275
|
-
|
|
37276
|
-
|
|
37277
|
-
|
|
37278
|
-
|
|
37279
|
-
|
|
37280
|
-
seed: seedId,
|
|
37281
|
-
seedProvenance: "collective",
|
|
37282
|
-
collectiveReachable: true,
|
|
37283
|
-
collectiveStatus: "cloud-seed",
|
|
37284
|
-
count: res.nodes.length,
|
|
37285
|
-
results: res.nodes.map((n) => ({
|
|
37286
|
-
id: n.id,
|
|
37287
|
-
label: n.label,
|
|
37288
|
-
name: n.description,
|
|
37289
|
-
score: Number((n.extractionConfidence ?? 0.5).toFixed(4)),
|
|
37290
|
-
hops: 1,
|
|
37291
|
-
provenance: "collective"
|
|
37292
|
-
}))
|
|
37293
|
-
};
|
|
37294
|
-
}
|
|
37322
|
+
const cn = await collectiveSeedFallback(args2, ctx, 20);
|
|
37323
|
+
if (cn) {
|
|
37324
|
+
return {
|
|
37325
|
+
seed: cn.seed,
|
|
37326
|
+
seedProvenance: "collective",
|
|
37327
|
+
collectiveReachable: true,
|
|
37328
|
+
collectiveStatus: "cloud-seed",
|
|
37329
|
+
count: cn.nodes.length,
|
|
37330
|
+
results: cn.nodes,
|
|
37331
|
+
edges: cn.edges
|
|
37332
|
+
};
|
|
37295
37333
|
}
|
|
37296
37334
|
return unresolved(args2);
|
|
37297
37335
|
}
|
|
@@ -37448,7 +37486,7 @@ var init_mcp = __esm({
|
|
|
37448
37486
|
},
|
|
37449
37487
|
{
|
|
37450
37488
|
name: "errata.why",
|
|
37451
|
-
description: "Causal/resolution neighborhood along the causal edge families (CAUSED_BY, MANIFESTS_AS, FIXED_BY, SOLVED_BY, \u2026), walked in both directions. For a Problem this surfaces its root causes AND solutions; for a Solution, the problems it resolves. Merges the machine-wide shared store's triage layer (cause chains from inline `<-` diagnoses land there, keyed by the same content-derived problem id). Ranked by accumulated conductance. Pass nodeId or qname. Returns {seedId, nodes:[{id,label,description,hops,edgeType,relevance}]}.",
|
|
37489
|
+
description: "Causal/resolution neighborhood along the causal edge families (CAUSED_BY, MANIFESTS_AS, FIXED_BY, SOLVED_BY, \u2026), walked in both directions. For a Problem this surfaces its root causes AND solutions; for a Solution, the problems it resolves. Merges the machine-wide shared store's triage layer (cause chains from inline `<-` diagnoses land there, keyed by the same content-derived problem id). Ranked by accumulated conductance. Pass nodeId or qname. Returns {seedId, nodes:[{id,label,description,hops,edgeType,relevance}]}. A cloud id from search's collective blend (e.g. dprob_\u2026) that isn't in the local graph falls back to its collective causal neighborhood, tagged provenance:collective.",
|
|
37452
37490
|
inputSchema: {
|
|
37453
37491
|
type: "object",
|
|
37454
37492
|
properties: {
|
|
@@ -37458,9 +37496,30 @@ var init_mcp = __esm({
|
|
|
37458
37496
|
limit: { type: "number", description: "Default 30" }
|
|
37459
37497
|
}
|
|
37460
37498
|
},
|
|
37461
|
-
handler: (args2, store) => {
|
|
37499
|
+
handler: async (args2, store, ctx) => {
|
|
37462
37500
|
const id = resolveSymbol2(store, args2);
|
|
37463
|
-
if (!id)
|
|
37501
|
+
if (!id) {
|
|
37502
|
+
const cn = await collectiveSeedFallback(args2, ctx, 30);
|
|
37503
|
+
if (cn) {
|
|
37504
|
+
return {
|
|
37505
|
+
found: true,
|
|
37506
|
+
seedId: cn.seed,
|
|
37507
|
+
seedProvenance: "collective",
|
|
37508
|
+
collectiveReachable: true,
|
|
37509
|
+
collectiveStatus: "cloud-seed",
|
|
37510
|
+
nodes: cn.nodes.map((n) => ({
|
|
37511
|
+
id: n.id,
|
|
37512
|
+
label: n.label,
|
|
37513
|
+
description: n.name,
|
|
37514
|
+
hops: n.hops,
|
|
37515
|
+
relevance: n.score,
|
|
37516
|
+
provenance: n.provenance
|
|
37517
|
+
})),
|
|
37518
|
+
edges: cn.edges
|
|
37519
|
+
};
|
|
37520
|
+
}
|
|
37521
|
+
return unresolved(args2);
|
|
37522
|
+
}
|
|
37464
37523
|
const maxHops = Math.max(1, Math.min(8, Number(args2["maxHops"] ?? 4)));
|
|
37465
37524
|
const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? 30)));
|
|
37466
37525
|
const local = causalChain(store, { seedId: id, direction: "both", maxHops, limit });
|
|
@@ -50758,14 +50817,16 @@ function generalizePrincipleForSync(principle, level = 2) {
|
|
|
50758
50817
|
delete node2.logicalId;
|
|
50759
50818
|
return node2;
|
|
50760
50819
|
}
|
|
50761
|
-
function buildPrincipleIngest(sharedStore, daemonVersion, ignorePatterns = [], level = 2) {
|
|
50820
|
+
function buildPrincipleIngest(sharedStore, daemonVersion, ignorePatterns = [], level = 2, opts = {}) {
|
|
50821
|
+
const lang = opts.primaryLanguage?.trim().toLowerCase();
|
|
50822
|
+
const claim = lang ? { anchorVisibility: "public", anchor: `lang:${lang}` } : {};
|
|
50762
50823
|
const selected = sharedStore.findNodesByLabel("Claim").filter((n) => isSyncablePrinciple(n, ignorePatterns));
|
|
50763
50824
|
for (const n of selected) {
|
|
50764
50825
|
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) !== ABSTRACTION_LEVEL.PRINCIPLE || n.attrs["provisional"] !== false) {
|
|
50765
50826
|
throw new Error(`buildPrincipleIngest: refusing to sync non-canonical-principle ${n.id} \u2014 C7 invariant violated`);
|
|
50766
50827
|
}
|
|
50767
50828
|
}
|
|
50768
|
-
const nodes = selected.map((n) => generalizePrincipleForSync(n, level));
|
|
50829
|
+
const nodes = selected.map((n) => ({ ...generalizePrincipleForSync(n, level), ...claim }));
|
|
50769
50830
|
if (nodes.length === 0) return null;
|
|
50770
50831
|
const base = {
|
|
50771
50832
|
daemonVersion,
|
|
@@ -51936,7 +51997,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
51936
51997
|
}
|
|
51937
51998
|
|
|
51938
51999
|
// src/engine.ts
|
|
51939
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52000
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.161" : "2.0.0-alpha.0";
|
|
51940
52001
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
51941
52002
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
51942
52003
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -54374,6 +54435,18 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54374
54435
|
startLoopLagMonitor();
|
|
54375
54436
|
let baseUrl = "";
|
|
54376
54437
|
const records = [];
|
|
54438
|
+
const machineDominantLanguage = () => {
|
|
54439
|
+
const langCounts = /* @__PURE__ */ new Map();
|
|
54440
|
+
for (const r of records) {
|
|
54441
|
+
for (const l of r.engine.profile.languages ?? []) {
|
|
54442
|
+
const k = String(l).trim().toLowerCase();
|
|
54443
|
+
if (k) langCounts.set(k, (langCounts.get(k) ?? 0) + 1);
|
|
54444
|
+
}
|
|
54445
|
+
}
|
|
54446
|
+
return [...langCounts.entries()].sort(
|
|
54447
|
+
(a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)
|
|
54448
|
+
)[0]?.[0];
|
|
54449
|
+
};
|
|
54377
54450
|
const updatePoller = opts.updateCheck ? startUpdatePoller({
|
|
54378
54451
|
channel: loadConfig().updateChannel,
|
|
54379
54452
|
onChange: (pending) => {
|
|
@@ -54936,7 +55009,10 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54936
55009
|
async syncPrinciplesPublic() {
|
|
54937
55010
|
if (!loadConfig().consent.sync) return { uploaded: 0, skipped: "consent-off" };
|
|
54938
55011
|
const ignore = loadClaimIgnorePatterns(globalDir());
|
|
54939
|
-
const
|
|
55012
|
+
const primaryLanguage = machineDominantLanguage();
|
|
55013
|
+
const payload = buildPrincipleIngest(sharedStore, DAEMON_VERSION, ignore, 2, {
|
|
55014
|
+
...primaryLanguage ? { primaryLanguage } : {}
|
|
55015
|
+
});
|
|
54940
55016
|
if (!payload) return { uploaded: 0 };
|
|
54941
55017
|
const res = await cloudNow().ingest(payload);
|
|
54942
55018
|
return { uploaded: res.accepted };
|
|
@@ -54944,16 +55020,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54944
55020
|
async syncTriagePublic() {
|
|
54945
55021
|
if (!loadConfig().consent.sync) return { uploaded: 0, skipped: "consent-off" };
|
|
54946
55022
|
const ignore = loadClaimIgnorePatterns(globalDir());
|
|
54947
|
-
const
|
|
54948
|
-
for (const r of records) {
|
|
54949
|
-
for (const l of r.engine.profile.languages ?? []) {
|
|
54950
|
-
const k = String(l).trim().toLowerCase();
|
|
54951
|
-
if (k) langCounts.set(k, (langCounts.get(k) ?? 0) + 1);
|
|
54952
|
-
}
|
|
54953
|
-
}
|
|
54954
|
-
const primaryLanguage = [...langCounts.entries()].sort(
|
|
54955
|
-
(a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)
|
|
54956
|
-
)[0]?.[0];
|
|
55023
|
+
const primaryLanguage = machineDominantLanguage();
|
|
54957
55024
|
const payload = buildTriageIngest(sharedStore, DAEMON_VERSION, ignore, 2, {
|
|
54958
55025
|
...primaryLanguage ? { primaryLanguage } : {}
|
|
54959
55026
|
});
|
|
@@ -57373,8 +57440,8 @@ async function cmdSimilar(args2) {
|
|
|
57373
57440
|
const limitIdx = args2.indexOf("--limit");
|
|
57374
57441
|
const limit = limitIdx >= 0 && args2[limitIdx + 1] ? Number(args2[limitIdx + 1]) : 5;
|
|
57375
57442
|
const { runTool: runTool2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
57376
|
-
await withStore((store) => {
|
|
57377
|
-
const r = runTool2("errata.similar", { nodeId: seed, qname: seed, limit }, store);
|
|
57443
|
+
await withStore(async (store) => {
|
|
57444
|
+
const r = await runTool2("errata.similar", { nodeId: seed, qname: seed, limit }, store);
|
|
57378
57445
|
if (!r.found) {
|
|
57379
57446
|
console.log("seed not found");
|
|
57380
57447
|
return;
|