@inerrata-corporation/errata 2.0.2-dev.361 → 2.0.2-dev.417
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/consolidate-worker.mjs +207 -207
- package/errata.mjs +695 -471
- package/package.json +1 -1
- package/pass-worker.mjs +3 -3
package/errata.mjs
CHANGED
|
@@ -19177,7 +19177,55 @@ function percolate(l1, l2, opts) {
|
|
|
19177
19177
|
result.touched = [...touched];
|
|
19178
19178
|
return result;
|
|
19179
19179
|
}
|
|
19180
|
-
|
|
19180
|
+
function migrateProjectAlias(l2, opts) {
|
|
19181
|
+
const { from, to } = opts;
|
|
19182
|
+
let nodesRewritten = 0;
|
|
19183
|
+
let edgesRewritten = 0;
|
|
19184
|
+
if (from === to) return { nodesRewritten, edgesRewritten };
|
|
19185
|
+
const rewrite = (seen) => {
|
|
19186
|
+
if (!seen.includes(from)) return null;
|
|
19187
|
+
const out2 = [];
|
|
19188
|
+
for (const p of seen.map((p2) => p2 === from ? to : p2)) if (!out2.includes(p)) out2.push(p);
|
|
19189
|
+
return out2;
|
|
19190
|
+
};
|
|
19191
|
+
const nodeUpdates = [];
|
|
19192
|
+
const edgeUpdates = [];
|
|
19193
|
+
const seenEdges = /* @__PURE__ */ new Set();
|
|
19194
|
+
for (const label of PROVENANCE_LABELS) {
|
|
19195
|
+
for (const n of l2.findNodesByLabel(label)) {
|
|
19196
|
+
const next = rewrite(observedProjects(n));
|
|
19197
|
+
if (next) nodeUpdates.push({ id: n.id, attrs: { ...n.attrs, observedInProjects: next } });
|
|
19198
|
+
for (const e of l2.outEdges(n.id, [...PERCOLATING_DRIFT_EDGES])) {
|
|
19199
|
+
if (seenEdges.has(e.id)) continue;
|
|
19200
|
+
seenEdges.add(e.id);
|
|
19201
|
+
const eSeen = Array.isArray(e.attrs["observedInProjects"]) ? e.attrs["observedInProjects"] : [];
|
|
19202
|
+
const eNext = rewrite(eSeen);
|
|
19203
|
+
if (eNext) edgeUpdates.push({ id: e.id, attrs: { ...e.attrs, observedInProjects: eNext } });
|
|
19204
|
+
}
|
|
19205
|
+
}
|
|
19206
|
+
}
|
|
19207
|
+
const CHUNK = 200;
|
|
19208
|
+
for (let i2 = 0; i2 < nodeUpdates.length; i2 += CHUNK) {
|
|
19209
|
+
const slice = nodeUpdates.slice(i2, i2 + CHUNK);
|
|
19210
|
+
l2.transaction(() => {
|
|
19211
|
+
for (const u of slice) {
|
|
19212
|
+
l2.updateNode(u.id, { attrs: u.attrs, lastUpdatedAt: opts.ts });
|
|
19213
|
+
nodesRewritten++;
|
|
19214
|
+
}
|
|
19215
|
+
});
|
|
19216
|
+
}
|
|
19217
|
+
for (let i2 = 0; i2 < edgeUpdates.length; i2 += CHUNK) {
|
|
19218
|
+
const slice = edgeUpdates.slice(i2, i2 + CHUNK);
|
|
19219
|
+
l2.transaction(() => {
|
|
19220
|
+
for (const u of slice) {
|
|
19221
|
+
l2.updateEdge(u.id, { attrs: u.attrs, lastSeenAt: opts.ts });
|
|
19222
|
+
edgesRewritten++;
|
|
19223
|
+
}
|
|
19224
|
+
});
|
|
19225
|
+
}
|
|
19226
|
+
return { nodesRewritten, edgesRewritten };
|
|
19227
|
+
}
|
|
19228
|
+
var PERCOLATING_LABELS, PERCOLATING_EDGES, PERCOLATING_DRIFT_EDGES, PROVENANCE_LABELS;
|
|
19181
19229
|
var init_percolate = __esm({
|
|
19182
19230
|
"../../packages/local-graph/src/percolate.ts"() {
|
|
19183
19231
|
"use strict";
|
|
@@ -19185,6 +19233,7 @@ var init_percolate = __esm({
|
|
|
19185
19233
|
PERCOLATING_LABELS = ["Claim", "Problem", "Solution"];
|
|
19186
19234
|
PERCOLATING_EDGES = ["CAUSED_BY", "SOLVED_BY", "CONTRADICTS"];
|
|
19187
19235
|
PERCOLATING_DRIFT_EDGES = ["CONTINUES", "REVEALED_BY", "SUPERSEDED_BY", "SPLIT_INTO"];
|
|
19236
|
+
PROVENANCE_LABELS = ["Claim", "Problem", "Solution", "Triage", "RootCause"];
|
|
19188
19237
|
}
|
|
19189
19238
|
});
|
|
19190
19239
|
|
|
@@ -19937,463 +19986,6 @@ var init_src3 = __esm({
|
|
|
19937
19986
|
}
|
|
19938
19987
|
});
|
|
19939
19988
|
|
|
19940
|
-
// ../../packages/local-graph/src/abstraction.ts
|
|
19941
|
-
function sharedScope(l2, memberIds) {
|
|
19942
|
-
const shared = (field) => {
|
|
19943
|
-
const vals = /* @__PURE__ */ new Set();
|
|
19944
|
-
for (const id of memberIds) {
|
|
19945
|
-
const s = l2.getNode(id)?.attrs["scope"] ?? {};
|
|
19946
|
-
if (typeof s[field] === "string") vals.add(s[field]);
|
|
19947
|
-
}
|
|
19948
|
-
return vals.size === 1 ? [...vals][0] : void 0;
|
|
19949
|
-
};
|
|
19950
|
-
const lang = shared("lang");
|
|
19951
|
-
const versionRange = shared("versionRange");
|
|
19952
|
-
return { ...lang ? { lang } : {}, ...versionRange ? { versionRange } : {} };
|
|
19953
|
-
}
|
|
19954
|
-
function buildCandidate(id, ts, members, contexts, originMachine, scope) {
|
|
19955
|
-
return {
|
|
19956
|
-
id,
|
|
19957
|
-
label: "Claim",
|
|
19958
|
-
description: "",
|
|
19959
|
-
// empty — the harness distills the prose in P3
|
|
19960
|
-
extractionConfidence: 0.4,
|
|
19961
|
-
extractionSource: "agent-observed",
|
|
19962
|
-
embedding: [],
|
|
19963
|
-
cumulativeSurprise: 0,
|
|
19964
|
-
peakSurprise: 0,
|
|
19965
|
-
cumulativeHits: 1,
|
|
19966
|
-
lastUpdatedAt: ts,
|
|
19967
|
-
createdAt: ts,
|
|
19968
|
-
memoryTier: "short-term",
|
|
19969
|
-
pageRank: 0,
|
|
19970
|
-
isLandmark: false,
|
|
19971
|
-
community: null,
|
|
19972
|
-
stability: "unstable",
|
|
19973
|
-
attrs: {
|
|
19974
|
-
abstractionLevel: ABSTRACTION_LEVEL.PRINCIPLE,
|
|
19975
|
-
kind: "abstraction-candidate",
|
|
19976
|
-
provisional: true,
|
|
19977
|
-
pendingDistillation: true,
|
|
19978
|
-
// membership is the unit of truth — the harness validates its fence against
|
|
19979
|
-
// this set (P3 / C3) and may only phrase, never alter, it.
|
|
19980
|
-
members,
|
|
19981
|
-
memberContexts: contexts,
|
|
19982
|
-
distinctContexts: contexts.length,
|
|
19983
|
-
// standard Claim envelope so it crystallizes/syncs unchanged once distilled
|
|
19984
|
-
truthKind: "contextual",
|
|
19985
|
-
// Derived from members (P1): a single-language cluster becomes a lang-scoped
|
|
19986
|
-
// principle; a cross-language one stays universal (`{}`).
|
|
19987
|
-
scope,
|
|
19988
|
-
groundedSupport: 0,
|
|
19989
|
-
sources: [],
|
|
19990
|
-
crystallized: "hypothesis",
|
|
19991
|
-
confidence: 0.4,
|
|
19992
|
-
...originMachine ? { originMachine } : {}
|
|
19993
|
-
}
|
|
19994
|
-
};
|
|
19995
|
-
}
|
|
19996
|
-
function mergeGeneralizes(store, principleId, memberId, ts) {
|
|
19997
|
-
store.mergeEdge({
|
|
19998
|
-
id: `edge_${digest({ from: principleId, type: "GENERALIZES", to: memberId })}`.slice(0, 24),
|
|
19999
|
-
from: principleId,
|
|
20000
|
-
to: memberId,
|
|
20001
|
-
type: "GENERALIZES",
|
|
20002
|
-
confidence: 0.4,
|
|
20003
|
-
extractionSource: "agent-observed",
|
|
20004
|
-
createdAt: ts,
|
|
20005
|
-
lastSeenAt: ts,
|
|
20006
|
-
navSuccesses: 0,
|
|
20007
|
-
navFailures: 0,
|
|
20008
|
-
attrs: { provisional: true }
|
|
20009
|
-
});
|
|
20010
|
-
}
|
|
20011
|
-
function induceAbstractions(l2, opts) {
|
|
20012
|
-
const K = opts.minClusterSize ?? DEFAULT_MIN_CLUSTER_SIZE;
|
|
20013
|
-
const minCtx = opts.minDistinctContexts ?? DEFAULT_MIN_DISTINCT_CONTEXTS;
|
|
20014
|
-
const report = {
|
|
20015
|
-
communities: 0,
|
|
20016
|
-
candidatesMinted: 0,
|
|
20017
|
-
candidatesExisting: 0,
|
|
20018
|
-
skippedSmall: 0,
|
|
20019
|
-
skippedSingleContext: 0,
|
|
20020
|
-
generalizesEdges: 0
|
|
20021
|
-
};
|
|
20022
|
-
const ids = /* @__PURE__ */ new Set();
|
|
20023
|
-
for (const label of PERCOLATING_LABELS) {
|
|
20024
|
-
for (const n of l2.findNodesByLabel(label)) {
|
|
20025
|
-
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
|
|
20026
|
-
continue;
|
|
20027
|
-
}
|
|
20028
|
-
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
20029
|
-
ids.add(n.id);
|
|
20030
|
-
}
|
|
20031
|
-
}
|
|
20032
|
-
if (ids.size === 0) return report;
|
|
20033
|
-
const adj = /* @__PURE__ */ new Map();
|
|
20034
|
-
const protect = [];
|
|
20035
|
-
const add = (a, b, w) => {
|
|
20036
|
-
const l = adj.get(a) ?? [];
|
|
20037
|
-
l.push({ to: b, weight: w });
|
|
20038
|
-
adj.set(a, l);
|
|
20039
|
-
};
|
|
20040
|
-
for (const id of ids) {
|
|
20041
|
-
for (const e of l2.outEdges(id, [...PERCOLATING_EDGES])) {
|
|
20042
|
-
if (!ids.has(e.to)) continue;
|
|
20043
|
-
const conf = e.confidence > 0 ? e.confidence : 0.5;
|
|
20044
|
-
const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
|
|
20045
|
-
add(id, e.to, w);
|
|
20046
|
-
add(e.to, id, w);
|
|
20047
|
-
if (isCausalProtected(e.type)) protect.push([id, e.to]);
|
|
20048
|
-
}
|
|
20049
|
-
}
|
|
20050
|
-
const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
|
|
20051
|
-
report.communities = comm.count;
|
|
20052
|
-
const members = /* @__PURE__ */ new Map();
|
|
20053
|
-
for (const [id, c] of comm.community) {
|
|
20054
|
-
const l = members.get(c) ?? [];
|
|
20055
|
-
l.push(id);
|
|
20056
|
-
members.set(c, l);
|
|
20057
|
-
}
|
|
20058
|
-
l2.transaction(() => {
|
|
20059
|
-
for (const mem of members.values()) {
|
|
20060
|
-
if (opts.touched && !mem.some((id) => opts.touched.has(id))) continue;
|
|
20061
|
-
if (mem.length < K) {
|
|
20062
|
-
report.skippedSmall++;
|
|
20063
|
-
continue;
|
|
20064
|
-
}
|
|
20065
|
-
if (mem.some((id) => l2.inEdges(id, ["GENERALIZES"]).length > 0)) {
|
|
20066
|
-
report.candidatesExisting++;
|
|
20067
|
-
continue;
|
|
20068
|
-
}
|
|
20069
|
-
const contexts = /* @__PURE__ */ new Set();
|
|
20070
|
-
for (const id of mem) {
|
|
20071
|
-
const n = l2.getNode(id);
|
|
20072
|
-
const obs = n?.attrs["observedInProjects"];
|
|
20073
|
-
if (Array.isArray(obs)) {
|
|
20074
|
-
for (const ws of obs) contexts.add(opts.contextOf(ws) ?? `project:${ws}`);
|
|
20075
|
-
}
|
|
20076
|
-
}
|
|
20077
|
-
if (contexts.size < minCtx) {
|
|
20078
|
-
report.skippedSingleContext++;
|
|
20079
|
-
continue;
|
|
20080
|
-
}
|
|
20081
|
-
const sorted = [...mem].sort();
|
|
20082
|
-
const principleId = `princ_${digest({ members: sorted })}`.slice(0, 56);
|
|
20083
|
-
l2.mergeNode(
|
|
20084
|
-
buildCandidate(principleId, opts.ts, sorted, [...contexts].sort(), opts.originMachine, sharedScope(l2, sorted))
|
|
20085
|
-
);
|
|
20086
|
-
for (const id of sorted) {
|
|
20087
|
-
mergeGeneralizes(l2, principleId, id, opts.ts);
|
|
20088
|
-
report.generalizesEdges++;
|
|
20089
|
-
}
|
|
20090
|
-
report.candidatesMinted++;
|
|
20091
|
-
}
|
|
20092
|
-
});
|
|
20093
|
-
return report;
|
|
20094
|
-
}
|
|
20095
|
-
function pendingAbstractions(l2) {
|
|
20096
|
-
const out2 = [];
|
|
20097
|
-
for (const n of l2.findNodesByLabel("Claim")) {
|
|
20098
|
-
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
|
|
20099
|
-
if (n.attrs["provisional"] !== true) continue;
|
|
20100
|
-
const memberIds = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
|
|
20101
|
-
const members = memberIds.map((id) => {
|
|
20102
|
-
const m = l2.getNode(id);
|
|
20103
|
-
return m ? { id: m.id, label: m.label, description: m.description } : { id, label: "?", description: "(member missing)" };
|
|
20104
|
-
});
|
|
20105
|
-
out2.push({
|
|
20106
|
-
candidate: n.id,
|
|
20107
|
-
distinctContexts: Number(n.attrs["distinctContexts"] ?? 0),
|
|
20108
|
-
members
|
|
20109
|
-
});
|
|
20110
|
-
}
|
|
20111
|
-
return out2;
|
|
20112
|
-
}
|
|
20113
|
-
function parseAbstractionFences(text) {
|
|
20114
|
-
const out2 = [];
|
|
20115
|
-
const block = /```errata-abstraction[^\n]*\n([\s\S]*?)```/g;
|
|
20116
|
-
let m;
|
|
20117
|
-
while ((m = block.exec(text)) !== null) {
|
|
20118
|
-
const fields = {};
|
|
20119
|
-
for (const line of m[1].split(/\r?\n/)) {
|
|
20120
|
-
const kv = /^\s*(candidate|principle|covers)\s*:\s*(.+?)\s*$/i.exec(line);
|
|
20121
|
-
if (kv) fields[kv[1].toLowerCase()] = kv[2].trim();
|
|
20122
|
-
}
|
|
20123
|
-
if (!fields["candidate"] || !fields["principle"] || !fields["covers"]) continue;
|
|
20124
|
-
const covers = fields["covers"].split(/[,\s]+/).map((s) => s.trim()).filter(Boolean);
|
|
20125
|
-
if (covers.length === 0) continue;
|
|
20126
|
-
out2.push({ candidate: fields["candidate"], principle: fields["principle"], covers });
|
|
20127
|
-
}
|
|
20128
|
-
return out2;
|
|
20129
|
-
}
|
|
20130
|
-
function applyAbstractionFence(l2, fence, ts) {
|
|
20131
|
-
const node2 = l2.getNode(fence.candidate);
|
|
20132
|
-
if (!node2 || node2.label !== "Claim" || Number(node2.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) {
|
|
20133
|
-
return { applied: false, principleId: fence.candidate, reason: "no such abstraction candidate" };
|
|
20134
|
-
}
|
|
20135
|
-
if (node2.attrs["provisional"] !== true) {
|
|
20136
|
-
return { applied: false, principleId: fence.candidate, reason: "candidate already distilled" };
|
|
20137
|
-
}
|
|
20138
|
-
const members = Array.isArray(node2.attrs["members"]) ? node2.attrs["members"] : [];
|
|
20139
|
-
const want = new Set(members);
|
|
20140
|
-
const got = new Set(fence.covers);
|
|
20141
|
-
const missing = members.filter((id) => !got.has(id));
|
|
20142
|
-
const invented = fence.covers.filter((id) => !want.has(id));
|
|
20143
|
-
if (missing.length > 0 || invented.length > 0) {
|
|
20144
|
-
return {
|
|
20145
|
-
applied: false,
|
|
20146
|
-
principleId: fence.candidate,
|
|
20147
|
-
reason: `coverage mismatch \u2014 ${missing.length} member(s) uncovered, ${invented.length} non-member(s) invented`
|
|
20148
|
-
};
|
|
20149
|
-
}
|
|
20150
|
-
const principle = fence.principle.trim();
|
|
20151
|
-
if (!principle) return { applied: false, principleId: fence.candidate, reason: "empty principle" };
|
|
20152
|
-
const { revisit: _r, revisitReason: _rr, revisitSinceTs: _rs, ...rest2 } = node2.attrs;
|
|
20153
|
-
void _r;
|
|
20154
|
-
void _rr;
|
|
20155
|
-
void _rs;
|
|
20156
|
-
l2.updateNode(fence.candidate, {
|
|
20157
|
-
description: principle,
|
|
20158
|
-
attrs: { ...rest2, provisional: false, pendingDistillation: false, distilledAt: ts },
|
|
20159
|
-
lastUpdatedAt: ts
|
|
20160
|
-
});
|
|
20161
|
-
return { applied: true, principleId: fence.candidate };
|
|
20162
|
-
}
|
|
20163
|
-
function revisitContradictedPrinciples(l2, ts) {
|
|
20164
|
-
const report = { flagged: 0 };
|
|
20165
|
-
l2.transaction(() => {
|
|
20166
|
-
for (const n of l2.findNodesByLabel("Claim")) {
|
|
20167
|
-
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
|
|
20168
|
-
if (n.attrs["revisit"] === true) continue;
|
|
20169
|
-
const members = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
|
|
20170
|
-
const memberSet = new Set(members);
|
|
20171
|
-
let reason = "";
|
|
20172
|
-
for (const id of members) {
|
|
20173
|
-
const m = l2.getNode(id);
|
|
20174
|
-
if (!m) {
|
|
20175
|
-
reason = `member ${id} was removed`;
|
|
20176
|
-
break;
|
|
20177
|
-
}
|
|
20178
|
-
if (m.attrs["revisit"] === true) {
|
|
20179
|
-
reason = `member "${m.description}" needs revisit`;
|
|
20180
|
-
break;
|
|
20181
|
-
}
|
|
20182
|
-
const contradictors = [
|
|
20183
|
-
...l2.outEdges(id, ["CONTRADICTS"]).map((e) => e.to),
|
|
20184
|
-
...l2.inEdges(id, ["CONTRADICTS"]).map((e) => e.from)
|
|
20185
|
-
];
|
|
20186
|
-
if (contradictors.some((other) => !memberSet.has(other))) {
|
|
20187
|
-
reason = `member "${m.description}" is now contradicted by external evidence`;
|
|
20188
|
-
break;
|
|
20189
|
-
}
|
|
20190
|
-
}
|
|
20191
|
-
if (!reason) continue;
|
|
20192
|
-
l2.updateNode(n.id, {
|
|
20193
|
-
attrs: {
|
|
20194
|
-
...n.attrs,
|
|
20195
|
-
revisit: true,
|
|
20196
|
-
revisitReason: reason,
|
|
20197
|
-
revisitSinceTs: ts,
|
|
20198
|
-
provisional: true,
|
|
20199
|
-
// re-queue for re-distillation (P3 re-name)
|
|
20200
|
-
pendingDistillation: true
|
|
20201
|
-
},
|
|
20202
|
-
lastUpdatedAt: ts
|
|
20203
|
-
});
|
|
20204
|
-
report.flagged++;
|
|
20205
|
-
}
|
|
20206
|
-
});
|
|
20207
|
-
return report;
|
|
20208
|
-
}
|
|
20209
|
-
function harvestAbstractionFences(l2, text, ts) {
|
|
20210
|
-
let applied = 0;
|
|
20211
|
-
let rejected = 0;
|
|
20212
|
-
for (const fence of parseAbstractionFences(text)) {
|
|
20213
|
-
if (applyAbstractionFence(l2, fence, ts).applied) applied++;
|
|
20214
|
-
else rejected++;
|
|
20215
|
-
}
|
|
20216
|
-
return { applied, rejected };
|
|
20217
|
-
}
|
|
20218
|
-
var DEFAULT_MIN_CLUSTER_SIZE, DEFAULT_MIN_DISTINCT_CONTEXTS;
|
|
20219
|
-
var init_abstraction = __esm({
|
|
20220
|
-
"../../packages/local-graph/src/abstraction.ts"() {
|
|
20221
|
-
"use strict";
|
|
20222
|
-
init_src();
|
|
20223
|
-
init_src2();
|
|
20224
|
-
init_src3();
|
|
20225
|
-
init_percolate();
|
|
20226
|
-
DEFAULT_MIN_CLUSTER_SIZE = 3;
|
|
20227
|
-
DEFAULT_MIN_DISTINCT_CONTEXTS = 2;
|
|
20228
|
-
}
|
|
20229
|
-
});
|
|
20230
|
-
|
|
20231
|
-
// ../../packages/local-graph/src/community.ts
|
|
20232
|
-
function detectLocalCommunities(store, opts = {}) {
|
|
20233
|
-
const minSize = opts.minCommunitySize ?? DEFAULT_MIN_COMMUNITY_SIZE;
|
|
20234
|
-
const report = { candidates: 0, communities: 0, joint: 0, assigned: 0 };
|
|
20235
|
-
const ids = /* @__PURE__ */ new Set();
|
|
20236
|
-
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20237
|
-
for (const n of store.findNodesByLabel(label)) {
|
|
20238
|
-
if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
20239
|
-
ids.add(n.id);
|
|
20240
|
-
}
|
|
20241
|
-
}
|
|
20242
|
-
report.candidates = ids.size;
|
|
20243
|
-
if (ids.size === 0) return report;
|
|
20244
|
-
const adj = /* @__PURE__ */ new Map();
|
|
20245
|
-
const protect = [];
|
|
20246
|
-
const add = (a, b, w) => {
|
|
20247
|
-
const l = adj.get(a) ?? [];
|
|
20248
|
-
l.push({ to: b, weight: w });
|
|
20249
|
-
adj.set(a, l);
|
|
20250
|
-
};
|
|
20251
|
-
for (const id of ids) {
|
|
20252
|
-
for (const e of store.outEdges(id, [...JOINT_COMMUNITY_EDGES])) {
|
|
20253
|
-
if (!ids.has(e.to)) continue;
|
|
20254
|
-
const conf = e.confidence > 0 ? e.confidence : 0.5;
|
|
20255
|
-
const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
|
|
20256
|
-
add(id, e.to, w);
|
|
20257
|
-
add(e.to, id, w);
|
|
20258
|
-
if (isCausalProtected(e.type)) protect.push([id, e.to]);
|
|
20259
|
-
}
|
|
20260
|
-
}
|
|
20261
|
-
const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
|
|
20262
|
-
const members = /* @__PURE__ */ new Map();
|
|
20263
|
-
for (const [id, c] of comm.community) {
|
|
20264
|
-
const l = members.get(c) ?? [];
|
|
20265
|
-
l.push(id);
|
|
20266
|
-
members.set(c, l);
|
|
20267
|
-
}
|
|
20268
|
-
store.transaction(() => {
|
|
20269
|
-
for (const [cid, mem] of members) {
|
|
20270
|
-
const qualifies = mem.length >= minSize;
|
|
20271
|
-
let hasLocal = false;
|
|
20272
|
-
let hasCloud = false;
|
|
20273
|
-
for (const id of mem) {
|
|
20274
|
-
const n = store.getNode(id);
|
|
20275
|
-
if (!n) continue;
|
|
20276
|
-
const pulled = n.attrs["source"] === "cloud";
|
|
20277
|
-
if (pulled) hasCloud = true;
|
|
20278
|
-
else hasLocal = true;
|
|
20279
|
-
const nextAttrs = { ...n.attrs };
|
|
20280
|
-
if (qualifies) nextAttrs["localCommunity"] = cid;
|
|
20281
|
-
else delete nextAttrs["localCommunity"];
|
|
20282
|
-
store.updateNode(id, { attrs: nextAttrs });
|
|
20283
|
-
if (!pulled) store.setCommunity(id, qualifies ? cid : null);
|
|
20284
|
-
}
|
|
20285
|
-
if (qualifies) {
|
|
20286
|
-
report.communities++;
|
|
20287
|
-
report.assigned += mem.length;
|
|
20288
|
-
if (hasLocal && hasCloud) report.joint++;
|
|
20289
|
-
}
|
|
20290
|
-
}
|
|
20291
|
-
});
|
|
20292
|
-
return report;
|
|
20293
|
-
}
|
|
20294
|
-
function communitySeeds(store, opts = {}) {
|
|
20295
|
-
const maxCommunities = opts.maxCommunities ?? 4;
|
|
20296
|
-
const maxSeeds = opts.maxSeeds ?? 32;
|
|
20297
|
-
const byCommunity = /* @__PURE__ */ new Map();
|
|
20298
|
-
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20299
|
-
for (const n of store.findNodesByLabel(label)) {
|
|
20300
|
-
const cid = n.attrs["localCommunity"];
|
|
20301
|
-
if (typeof cid !== "string") continue;
|
|
20302
|
-
const cloudId = n.attrs["cloudNodeId"];
|
|
20303
|
-
const l = byCommunity.get(cid) ?? [];
|
|
20304
|
-
l.push({
|
|
20305
|
-
id: n.id,
|
|
20306
|
-
pulled: n.attrs["source"] === "cloud",
|
|
20307
|
-
cloudId: typeof cloudId === "string" && cloudId !== n.id ? cloudId : null,
|
|
20308
|
-
ts: n.lastUpdatedAt
|
|
20309
|
-
});
|
|
20310
|
-
byCommunity.set(cid, l);
|
|
20311
|
-
}
|
|
20312
|
-
}
|
|
20313
|
-
if (byCommunity.size === 0) return [];
|
|
20314
|
-
const ranked = [...byCommunity.entries()].map(([cid, mem]) => ({ cid, mem, fresh: Math.max(...mem.map((m) => m.ts)) })).sort((a, b) => b.fresh - a.fresh).slice(0, maxCommunities);
|
|
20315
|
-
const seeds = [];
|
|
20316
|
-
const seen = /* @__PURE__ */ new Set();
|
|
20317
|
-
const push = (id) => {
|
|
20318
|
-
if (seeds.length >= maxSeeds || seen.has(id)) return;
|
|
20319
|
-
seen.add(id);
|
|
20320
|
-
seeds.push(id);
|
|
20321
|
-
};
|
|
20322
|
-
for (const { mem } of ranked) {
|
|
20323
|
-
const ordered = [...mem].sort(
|
|
20324
|
-
(a, b) => a.pulled === b.pulled ? b.ts - a.ts : a.pulled ? -1 : 1
|
|
20325
|
-
);
|
|
20326
|
-
for (const m of ordered) {
|
|
20327
|
-
push(m.id);
|
|
20328
|
-
if (m.cloudId) push(m.cloudId);
|
|
20329
|
-
}
|
|
20330
|
-
}
|
|
20331
|
-
return seeds;
|
|
20332
|
-
}
|
|
20333
|
-
function communityInductionRequests(store, opts = {}) {
|
|
20334
|
-
const maxCommunities = opts.maxCommunities ?? 2;
|
|
20335
|
-
const byCommunity = /* @__PURE__ */ new Map();
|
|
20336
|
-
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20337
|
-
for (const n of store.findNodesByLabel(label)) {
|
|
20338
|
-
const cid = n.attrs["localCommunity"];
|
|
20339
|
-
if (typeof cid !== "string") continue;
|
|
20340
|
-
const cloudId = n.attrs["cloudNodeId"];
|
|
20341
|
-
const l = byCommunity.get(cid) ?? [];
|
|
20342
|
-
l.push({
|
|
20343
|
-
id: n.id,
|
|
20344
|
-
pulled: n.attrs["source"] === "cloud",
|
|
20345
|
-
cloudId: typeof cloudId === "string" && cloudId !== n.id ? cloudId : null,
|
|
20346
|
-
ts: n.lastUpdatedAt,
|
|
20347
|
-
description: n.description
|
|
20348
|
-
});
|
|
20349
|
-
byCommunity.set(cid, l);
|
|
20350
|
-
}
|
|
20351
|
-
}
|
|
20352
|
-
if (byCommunity.size === 0) return [];
|
|
20353
|
-
return [...byCommunity.entries()].map(([cid, mem]) => ({ cid, mem, fresh: Math.max(...mem.map((m) => m.ts)) })).sort((a, b) => b.fresh - a.fresh).map(({ cid, mem }) => {
|
|
20354
|
-
const ids = /* @__PURE__ */ new Set();
|
|
20355
|
-
for (const m of mem) {
|
|
20356
|
-
ids.add(m.id);
|
|
20357
|
-
if (m.cloudId) ids.add(m.cloudId);
|
|
20358
|
-
}
|
|
20359
|
-
const freshestLocal = [...mem].filter((m) => !m.pulled).sort((a, b) => b.ts - a.ts)[0];
|
|
20360
|
-
return {
|
|
20361
|
-
communityId: cid,
|
|
20362
|
-
members: [...ids].slice(0, 64),
|
|
20363
|
-
context: (freshestLocal?.description ?? "recurring workspace problem cluster").slice(0, 200)
|
|
20364
|
-
};
|
|
20365
|
-
}).filter((r) => r.members.length >= MIN_INDUCTION_MEMBERS).slice(0, maxCommunities);
|
|
20366
|
-
}
|
|
20367
|
-
var JOINT_COMMUNITY_LABELS, JOINT_COMMUNITY_EDGES, DEFAULT_MIN_COMMUNITY_SIZE, MIN_INDUCTION_MEMBERS;
|
|
20368
|
-
var init_community2 = __esm({
|
|
20369
|
-
"../../packages/local-graph/src/community.ts"() {
|
|
20370
|
-
"use strict";
|
|
20371
|
-
init_src2();
|
|
20372
|
-
init_src3();
|
|
20373
|
-
JOINT_COMMUNITY_LABELS = [
|
|
20374
|
-
"Problem",
|
|
20375
|
-
"Solution",
|
|
20376
|
-
"RootCause",
|
|
20377
|
-
"Pattern"
|
|
20378
|
-
];
|
|
20379
|
-
JOINT_COMMUNITY_EDGES = [
|
|
20380
|
-
"CAUSED_BY",
|
|
20381
|
-
"SOLVED_BY",
|
|
20382
|
-
"FIXED_BY",
|
|
20383
|
-
"CONTRADICTS",
|
|
20384
|
-
"INSTANCE_OF",
|
|
20385
|
-
"MATCHES",
|
|
20386
|
-
"IMPLEMENTS",
|
|
20387
|
-
"TRIAGED_BY",
|
|
20388
|
-
"INDICATES",
|
|
20389
|
-
"CONFIRMS",
|
|
20390
|
-
"RELATES_TO"
|
|
20391
|
-
];
|
|
20392
|
-
DEFAULT_MIN_COMMUNITY_SIZE = 2;
|
|
20393
|
-
MIN_INDUCTION_MEMBERS = 3;
|
|
20394
|
-
}
|
|
20395
|
-
});
|
|
20396
|
-
|
|
20397
19989
|
// ../../packages/local-graph/src/triage.ts
|
|
20398
19990
|
function semNode(id, label, description, ts, attrs) {
|
|
20399
19991
|
return {
|
|
@@ -20431,6 +20023,10 @@ function semEdge(id, from, to, type, ts, attrs) {
|
|
|
20431
20023
|
attrs
|
|
20432
20024
|
};
|
|
20433
20025
|
}
|
|
20026
|
+
function isUnfilledPlaceholder(value) {
|
|
20027
|
+
const v = value.trim();
|
|
20028
|
+
return v.startsWith("<") && v.endsWith(">");
|
|
20029
|
+
}
|
|
20434
20030
|
function recordTriageObservation(l2, obs, ts) {
|
|
20435
20031
|
const statement = obs.presentingStatement.trim();
|
|
20436
20032
|
const presentingId = obs.presentingId?.trim() || identityId({ kind: "DesignProblem", statement });
|
|
@@ -20539,6 +20135,33 @@ function recordCauseChainLink(l2, link, ts, attrs = {}) {
|
|
|
20539
20135
|
});
|
|
20540
20136
|
return created;
|
|
20541
20137
|
}
|
|
20138
|
+
function mintWorkspaceCausalFact(ws, fact, ts) {
|
|
20139
|
+
if (fact.causeId === fact.presentingId) return false;
|
|
20140
|
+
const problem = ws.getNode(fact.presentingId);
|
|
20141
|
+
if (!problem || problem.label !== "Problem") return false;
|
|
20142
|
+
if (problem.attrs["source"] === "cloud") return false;
|
|
20143
|
+
const existingCause = ws.getNode(fact.causeId);
|
|
20144
|
+
if (existingCause && existingCause.label !== "RootCause") return false;
|
|
20145
|
+
const description = fact.causeDescription?.trim();
|
|
20146
|
+
if (!existingCause && !description) return false;
|
|
20147
|
+
let created = false;
|
|
20148
|
+
ws.transaction(() => {
|
|
20149
|
+
if (!ws.getNode(fact.causeId)) {
|
|
20150
|
+
ws.mergeNode(
|
|
20151
|
+
semNode(fact.causeId, "RootCause", description, ts, {
|
|
20152
|
+
scope: {},
|
|
20153
|
+
...fact.sessionId ? { sources: [fact.sessionId] } : {}
|
|
20154
|
+
})
|
|
20155
|
+
);
|
|
20156
|
+
}
|
|
20157
|
+
const edgeId2 = `edge_cb_${fact.presentingId}_${fact.causeId}`;
|
|
20158
|
+
if (!ws.getEdge(edgeId2)) {
|
|
20159
|
+
ws.mergeEdge(semEdge(edgeId2, fact.presentingId, fact.causeId, "CAUSED_BY", ts, { witnessed: true }));
|
|
20160
|
+
created = true;
|
|
20161
|
+
}
|
|
20162
|
+
});
|
|
20163
|
+
return created;
|
|
20164
|
+
}
|
|
20542
20165
|
function recordMisreadPrior(shared, problem, context, contributor, ts) {
|
|
20543
20166
|
if (problem.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE) return false;
|
|
20544
20167
|
if (Number(problem.attrs["corroborations"] ?? 0) < 1) return false;
|
|
@@ -20739,6 +20362,7 @@ function markDiscriminatorAsked(l2, routeIds, ts) {
|
|
|
20739
20362
|
function promoteRouteWithDiscriminator(l2, routeId, discriminator, ts, source) {
|
|
20740
20363
|
const test = discriminator.trim();
|
|
20741
20364
|
if (!test) return false;
|
|
20365
|
+
if (isUnfilledPlaceholder(test)) return false;
|
|
20742
20366
|
const existing = l2.getEdge(routeId);
|
|
20743
20367
|
if (!existing || !ROUTE_EDGE_TYPES.includes(existing.type)) return false;
|
|
20744
20368
|
const attrs = {
|
|
@@ -20896,6 +20520,467 @@ var init_triage2 = __esm({
|
|
|
20896
20520
|
}
|
|
20897
20521
|
});
|
|
20898
20522
|
|
|
20523
|
+
// ../../packages/local-graph/src/abstraction.ts
|
|
20524
|
+
function sharedScope(l2, memberIds) {
|
|
20525
|
+
const shared = (field) => {
|
|
20526
|
+
const vals = /* @__PURE__ */ new Set();
|
|
20527
|
+
for (const id of memberIds) {
|
|
20528
|
+
const s = l2.getNode(id)?.attrs["scope"] ?? {};
|
|
20529
|
+
if (typeof s[field] === "string") vals.add(s[field]);
|
|
20530
|
+
}
|
|
20531
|
+
return vals.size === 1 ? [...vals][0] : void 0;
|
|
20532
|
+
};
|
|
20533
|
+
const lang = shared("lang");
|
|
20534
|
+
const versionRange = shared("versionRange");
|
|
20535
|
+
return { ...lang ? { lang } : {}, ...versionRange ? { versionRange } : {} };
|
|
20536
|
+
}
|
|
20537
|
+
function buildCandidate(id, ts, members, contexts, originMachine, scope) {
|
|
20538
|
+
return {
|
|
20539
|
+
id,
|
|
20540
|
+
label: "Claim",
|
|
20541
|
+
description: "",
|
|
20542
|
+
// empty — the harness distills the prose in P3
|
|
20543
|
+
extractionConfidence: 0.4,
|
|
20544
|
+
extractionSource: "agent-observed",
|
|
20545
|
+
embedding: [],
|
|
20546
|
+
cumulativeSurprise: 0,
|
|
20547
|
+
peakSurprise: 0,
|
|
20548
|
+
cumulativeHits: 1,
|
|
20549
|
+
lastUpdatedAt: ts,
|
|
20550
|
+
createdAt: ts,
|
|
20551
|
+
memoryTier: "short-term",
|
|
20552
|
+
pageRank: 0,
|
|
20553
|
+
isLandmark: false,
|
|
20554
|
+
community: null,
|
|
20555
|
+
stability: "unstable",
|
|
20556
|
+
attrs: {
|
|
20557
|
+
abstractionLevel: ABSTRACTION_LEVEL.PRINCIPLE,
|
|
20558
|
+
kind: "abstraction-candidate",
|
|
20559
|
+
provisional: true,
|
|
20560
|
+
pendingDistillation: true,
|
|
20561
|
+
// membership is the unit of truth — the harness validates its fence against
|
|
20562
|
+
// this set (P3 / C3) and may only phrase, never alter, it.
|
|
20563
|
+
members,
|
|
20564
|
+
memberContexts: contexts,
|
|
20565
|
+
distinctContexts: contexts.length,
|
|
20566
|
+
// standard Claim envelope so it crystallizes/syncs unchanged once distilled
|
|
20567
|
+
truthKind: "contextual",
|
|
20568
|
+
// Derived from members (P1): a single-language cluster becomes a lang-scoped
|
|
20569
|
+
// principle; a cross-language one stays universal (`{}`).
|
|
20570
|
+
scope,
|
|
20571
|
+
groundedSupport: 0,
|
|
20572
|
+
sources: [],
|
|
20573
|
+
crystallized: "hypothesis",
|
|
20574
|
+
confidence: 0.4,
|
|
20575
|
+
...originMachine ? { originMachine } : {}
|
|
20576
|
+
}
|
|
20577
|
+
};
|
|
20578
|
+
}
|
|
20579
|
+
function mergeGeneralizes(store, principleId, memberId, ts) {
|
|
20580
|
+
store.mergeEdge({
|
|
20581
|
+
id: `edge_${digest({ from: principleId, type: "GENERALIZES", to: memberId })}`.slice(0, 24),
|
|
20582
|
+
from: principleId,
|
|
20583
|
+
to: memberId,
|
|
20584
|
+
type: "GENERALIZES",
|
|
20585
|
+
confidence: 0.4,
|
|
20586
|
+
extractionSource: "agent-observed",
|
|
20587
|
+
createdAt: ts,
|
|
20588
|
+
lastSeenAt: ts,
|
|
20589
|
+
navSuccesses: 0,
|
|
20590
|
+
navFailures: 0,
|
|
20591
|
+
attrs: { provisional: true }
|
|
20592
|
+
});
|
|
20593
|
+
}
|
|
20594
|
+
function induceAbstractions(l2, opts) {
|
|
20595
|
+
const K = opts.minClusterSize ?? DEFAULT_MIN_CLUSTER_SIZE;
|
|
20596
|
+
const minCtx = opts.minDistinctContexts ?? DEFAULT_MIN_DISTINCT_CONTEXTS;
|
|
20597
|
+
const report = {
|
|
20598
|
+
communities: 0,
|
|
20599
|
+
candidatesMinted: 0,
|
|
20600
|
+
candidatesExisting: 0,
|
|
20601
|
+
skippedSmall: 0,
|
|
20602
|
+
skippedSingleContext: 0,
|
|
20603
|
+
generalizesEdges: 0
|
|
20604
|
+
};
|
|
20605
|
+
const ids = /* @__PURE__ */ new Set();
|
|
20606
|
+
for (const label of PERCOLATING_LABELS) {
|
|
20607
|
+
for (const n of l2.findNodesByLabel(label)) {
|
|
20608
|
+
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
|
|
20609
|
+
continue;
|
|
20610
|
+
}
|
|
20611
|
+
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
20612
|
+
ids.add(n.id);
|
|
20613
|
+
}
|
|
20614
|
+
}
|
|
20615
|
+
if (ids.size === 0) return report;
|
|
20616
|
+
const adj = /* @__PURE__ */ new Map();
|
|
20617
|
+
const protect = [];
|
|
20618
|
+
const add = (a, b, w) => {
|
|
20619
|
+
const l = adj.get(a) ?? [];
|
|
20620
|
+
l.push({ to: b, weight: w });
|
|
20621
|
+
adj.set(a, l);
|
|
20622
|
+
};
|
|
20623
|
+
for (const id of ids) {
|
|
20624
|
+
for (const e of l2.outEdges(id, [...PERCOLATING_EDGES])) {
|
|
20625
|
+
if (!ids.has(e.to)) continue;
|
|
20626
|
+
const conf = e.confidence > 0 ? e.confidence : 0.5;
|
|
20627
|
+
const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
|
|
20628
|
+
add(id, e.to, w);
|
|
20629
|
+
add(e.to, id, w);
|
|
20630
|
+
if (isCausalProtected(e.type)) protect.push([id, e.to]);
|
|
20631
|
+
}
|
|
20632
|
+
}
|
|
20633
|
+
const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
|
|
20634
|
+
report.communities = comm.count;
|
|
20635
|
+
const members = /* @__PURE__ */ new Map();
|
|
20636
|
+
for (const [id, c] of comm.community) {
|
|
20637
|
+
const l = members.get(c) ?? [];
|
|
20638
|
+
l.push(id);
|
|
20639
|
+
members.set(c, l);
|
|
20640
|
+
}
|
|
20641
|
+
l2.transaction(() => {
|
|
20642
|
+
for (const mem of members.values()) {
|
|
20643
|
+
if (opts.touched && !mem.some((id) => opts.touched.has(id))) continue;
|
|
20644
|
+
if (mem.length < K) {
|
|
20645
|
+
report.skippedSmall++;
|
|
20646
|
+
continue;
|
|
20647
|
+
}
|
|
20648
|
+
if (mem.some((id) => l2.inEdges(id, ["GENERALIZES"]).length > 0)) {
|
|
20649
|
+
report.candidatesExisting++;
|
|
20650
|
+
continue;
|
|
20651
|
+
}
|
|
20652
|
+
const contexts = /* @__PURE__ */ new Set();
|
|
20653
|
+
for (const id of mem) {
|
|
20654
|
+
const n = l2.getNode(id);
|
|
20655
|
+
const obs = n?.attrs["observedInProjects"];
|
|
20656
|
+
if (Array.isArray(obs)) {
|
|
20657
|
+
for (const ws of obs) contexts.add(opts.contextOf(ws) ?? `project:${ws}`);
|
|
20658
|
+
}
|
|
20659
|
+
}
|
|
20660
|
+
if (contexts.size < minCtx) {
|
|
20661
|
+
report.skippedSingleContext++;
|
|
20662
|
+
continue;
|
|
20663
|
+
}
|
|
20664
|
+
const sorted = [...mem].sort();
|
|
20665
|
+
const principleId = `princ_${digest({ members: sorted })}`.slice(0, 56);
|
|
20666
|
+
l2.mergeNode(
|
|
20667
|
+
buildCandidate(principleId, opts.ts, sorted, [...contexts].sort(), opts.originMachine, sharedScope(l2, sorted))
|
|
20668
|
+
);
|
|
20669
|
+
for (const id of sorted) {
|
|
20670
|
+
mergeGeneralizes(l2, principleId, id, opts.ts);
|
|
20671
|
+
report.generalizesEdges++;
|
|
20672
|
+
}
|
|
20673
|
+
report.candidatesMinted++;
|
|
20674
|
+
}
|
|
20675
|
+
});
|
|
20676
|
+
return report;
|
|
20677
|
+
}
|
|
20678
|
+
function pendingAbstractions(l2) {
|
|
20679
|
+
const out2 = [];
|
|
20680
|
+
for (const n of l2.findNodesByLabel("Claim")) {
|
|
20681
|
+
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
|
|
20682
|
+
if (n.attrs["provisional"] !== true) continue;
|
|
20683
|
+
const memberIds = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
|
|
20684
|
+
const members = memberIds.map((id) => {
|
|
20685
|
+
const m = l2.getNode(id);
|
|
20686
|
+
return m ? { id: m.id, label: m.label, description: m.description } : { id, label: "?", description: "(member missing)" };
|
|
20687
|
+
});
|
|
20688
|
+
out2.push({
|
|
20689
|
+
candidate: n.id,
|
|
20690
|
+
distinctContexts: Number(n.attrs["distinctContexts"] ?? 0),
|
|
20691
|
+
members
|
|
20692
|
+
});
|
|
20693
|
+
}
|
|
20694
|
+
return out2;
|
|
20695
|
+
}
|
|
20696
|
+
function parseAbstractionFences(text) {
|
|
20697
|
+
const out2 = [];
|
|
20698
|
+
const block = /```errata-abstraction[^\n]*\n([\s\S]*?)```/g;
|
|
20699
|
+
let m;
|
|
20700
|
+
while ((m = block.exec(text)) !== null) {
|
|
20701
|
+
const fields = {};
|
|
20702
|
+
for (const line of m[1].split(/\r?\n/)) {
|
|
20703
|
+
const kv = /^\s*(candidate|principle|covers)\s*:\s*(.+?)\s*$/i.exec(line);
|
|
20704
|
+
if (kv) fields[kv[1].toLowerCase()] = kv[2].trim();
|
|
20705
|
+
}
|
|
20706
|
+
if (!fields["candidate"] || !fields["principle"] || !fields["covers"]) continue;
|
|
20707
|
+
const covers = fields["covers"].split(/[,\s]+/).map((s) => s.trim()).filter(Boolean);
|
|
20708
|
+
if (covers.length === 0) continue;
|
|
20709
|
+
out2.push({ candidate: fields["candidate"], principle: fields["principle"], covers });
|
|
20710
|
+
}
|
|
20711
|
+
return out2;
|
|
20712
|
+
}
|
|
20713
|
+
function applyAbstractionFence(l2, fence, ts) {
|
|
20714
|
+
const node2 = l2.getNode(fence.candidate);
|
|
20715
|
+
if (!node2 || node2.label !== "Claim" || Number(node2.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) {
|
|
20716
|
+
return { applied: false, principleId: fence.candidate, reason: "no such abstraction candidate" };
|
|
20717
|
+
}
|
|
20718
|
+
if (node2.attrs["provisional"] !== true) {
|
|
20719
|
+
return { applied: false, principleId: fence.candidate, reason: "candidate already distilled" };
|
|
20720
|
+
}
|
|
20721
|
+
const members = Array.isArray(node2.attrs["members"]) ? node2.attrs["members"] : [];
|
|
20722
|
+
const want = new Set(members);
|
|
20723
|
+
const got = new Set(fence.covers);
|
|
20724
|
+
const missing = members.filter((id) => !got.has(id));
|
|
20725
|
+
const invented = fence.covers.filter((id) => !want.has(id));
|
|
20726
|
+
if (missing.length > 0 || invented.length > 0) {
|
|
20727
|
+
return {
|
|
20728
|
+
applied: false,
|
|
20729
|
+
principleId: fence.candidate,
|
|
20730
|
+
reason: `coverage mismatch \u2014 ${missing.length} member(s) uncovered, ${invented.length} non-member(s) invented`
|
|
20731
|
+
};
|
|
20732
|
+
}
|
|
20733
|
+
const principle = fence.principle.trim();
|
|
20734
|
+
if (!principle) return { applied: false, principleId: fence.candidate, reason: "empty principle" };
|
|
20735
|
+
if (isUnfilledPlaceholder(principle)) {
|
|
20736
|
+
return { applied: false, principleId: fence.candidate, reason: "unfilled template placeholder" };
|
|
20737
|
+
}
|
|
20738
|
+
const { revisit: _r, revisitReason: _rr, revisitSinceTs: _rs, ...rest2 } = node2.attrs;
|
|
20739
|
+
void _r;
|
|
20740
|
+
void _rr;
|
|
20741
|
+
void _rs;
|
|
20742
|
+
l2.updateNode(fence.candidate, {
|
|
20743
|
+
description: principle,
|
|
20744
|
+
attrs: { ...rest2, provisional: false, pendingDistillation: false, distilledAt: ts },
|
|
20745
|
+
lastUpdatedAt: ts
|
|
20746
|
+
});
|
|
20747
|
+
return { applied: true, principleId: fence.candidate };
|
|
20748
|
+
}
|
|
20749
|
+
function revisitContradictedPrinciples(l2, ts) {
|
|
20750
|
+
const report = { flagged: 0 };
|
|
20751
|
+
l2.transaction(() => {
|
|
20752
|
+
for (const n of l2.findNodesByLabel("Claim")) {
|
|
20753
|
+
if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
|
|
20754
|
+
if (n.attrs["revisit"] === true) continue;
|
|
20755
|
+
const members = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
|
|
20756
|
+
const memberSet = new Set(members);
|
|
20757
|
+
let reason = "";
|
|
20758
|
+
for (const id of members) {
|
|
20759
|
+
const m = l2.getNode(id);
|
|
20760
|
+
if (!m) {
|
|
20761
|
+
reason = `member ${id} was removed`;
|
|
20762
|
+
break;
|
|
20763
|
+
}
|
|
20764
|
+
if (m.attrs["revisit"] === true) {
|
|
20765
|
+
reason = `member "${m.description}" needs revisit`;
|
|
20766
|
+
break;
|
|
20767
|
+
}
|
|
20768
|
+
const contradictors = [
|
|
20769
|
+
...l2.outEdges(id, ["CONTRADICTS"]).map((e) => e.to),
|
|
20770
|
+
...l2.inEdges(id, ["CONTRADICTS"]).map((e) => e.from)
|
|
20771
|
+
];
|
|
20772
|
+
if (contradictors.some((other) => !memberSet.has(other))) {
|
|
20773
|
+
reason = `member "${m.description}" is now contradicted by external evidence`;
|
|
20774
|
+
break;
|
|
20775
|
+
}
|
|
20776
|
+
}
|
|
20777
|
+
if (!reason) continue;
|
|
20778
|
+
l2.updateNode(n.id, {
|
|
20779
|
+
attrs: {
|
|
20780
|
+
...n.attrs,
|
|
20781
|
+
revisit: true,
|
|
20782
|
+
revisitReason: reason,
|
|
20783
|
+
revisitSinceTs: ts,
|
|
20784
|
+
provisional: true,
|
|
20785
|
+
// re-queue for re-distillation (P3 re-name)
|
|
20786
|
+
pendingDistillation: true
|
|
20787
|
+
},
|
|
20788
|
+
lastUpdatedAt: ts
|
|
20789
|
+
});
|
|
20790
|
+
report.flagged++;
|
|
20791
|
+
}
|
|
20792
|
+
});
|
|
20793
|
+
return report;
|
|
20794
|
+
}
|
|
20795
|
+
function harvestAbstractionFences(l2, text, ts) {
|
|
20796
|
+
let applied = 0;
|
|
20797
|
+
let rejected = 0;
|
|
20798
|
+
for (const fence of parseAbstractionFences(text)) {
|
|
20799
|
+
if (applyAbstractionFence(l2, fence, ts).applied) applied++;
|
|
20800
|
+
else rejected++;
|
|
20801
|
+
}
|
|
20802
|
+
return { applied, rejected };
|
|
20803
|
+
}
|
|
20804
|
+
var DEFAULT_MIN_CLUSTER_SIZE, DEFAULT_MIN_DISTINCT_CONTEXTS;
|
|
20805
|
+
var init_abstraction = __esm({
|
|
20806
|
+
"../../packages/local-graph/src/abstraction.ts"() {
|
|
20807
|
+
"use strict";
|
|
20808
|
+
init_src();
|
|
20809
|
+
init_src2();
|
|
20810
|
+
init_src3();
|
|
20811
|
+
init_percolate();
|
|
20812
|
+
init_triage2();
|
|
20813
|
+
DEFAULT_MIN_CLUSTER_SIZE = 3;
|
|
20814
|
+
DEFAULT_MIN_DISTINCT_CONTEXTS = 2;
|
|
20815
|
+
}
|
|
20816
|
+
});
|
|
20817
|
+
|
|
20818
|
+
// ../../packages/local-graph/src/community.ts
|
|
20819
|
+
function detectLocalCommunities(store, opts = {}) {
|
|
20820
|
+
const minSize = opts.minCommunitySize ?? DEFAULT_MIN_COMMUNITY_SIZE;
|
|
20821
|
+
const report = { candidates: 0, communities: 0, joint: 0, assigned: 0 };
|
|
20822
|
+
const ids = /* @__PURE__ */ new Set();
|
|
20823
|
+
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20824
|
+
for (const n of store.findNodesByLabel(label)) {
|
|
20825
|
+
if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
20826
|
+
ids.add(n.id);
|
|
20827
|
+
}
|
|
20828
|
+
}
|
|
20829
|
+
report.candidates = ids.size;
|
|
20830
|
+
if (ids.size === 0) return report;
|
|
20831
|
+
const adj = /* @__PURE__ */ new Map();
|
|
20832
|
+
const protect = [];
|
|
20833
|
+
const add = (a, b, w) => {
|
|
20834
|
+
const l = adj.get(a) ?? [];
|
|
20835
|
+
l.push({ to: b, weight: w });
|
|
20836
|
+
adj.set(a, l);
|
|
20837
|
+
};
|
|
20838
|
+
for (const id of ids) {
|
|
20839
|
+
for (const e of store.outEdges(id, [...JOINT_COMMUNITY_EDGES])) {
|
|
20840
|
+
if (!ids.has(e.to)) continue;
|
|
20841
|
+
const conf = e.confidence > 0 ? e.confidence : 0.5;
|
|
20842
|
+
const w = Math.max(EDGE_WEIGHT[e.type] ?? 1, 0.1) * conf;
|
|
20843
|
+
add(id, e.to, w);
|
|
20844
|
+
add(e.to, id, w);
|
|
20845
|
+
if (isCausalProtected(e.type)) protect.push([id, e.to]);
|
|
20846
|
+
}
|
|
20847
|
+
}
|
|
20848
|
+
const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
|
|
20849
|
+
const members = /* @__PURE__ */ new Map();
|
|
20850
|
+
for (const [id, c] of comm.community) {
|
|
20851
|
+
const l = members.get(c) ?? [];
|
|
20852
|
+
l.push(id);
|
|
20853
|
+
members.set(c, l);
|
|
20854
|
+
}
|
|
20855
|
+
store.transaction(() => {
|
|
20856
|
+
for (const [cid, mem] of members) {
|
|
20857
|
+
const qualifies = mem.length >= minSize;
|
|
20858
|
+
let hasLocal = false;
|
|
20859
|
+
let hasCloud = false;
|
|
20860
|
+
for (const id of mem) {
|
|
20861
|
+
const n = store.getNode(id);
|
|
20862
|
+
if (!n) continue;
|
|
20863
|
+
const pulled = n.attrs["source"] === "cloud";
|
|
20864
|
+
if (pulled) hasCloud = true;
|
|
20865
|
+
else hasLocal = true;
|
|
20866
|
+
const nextAttrs = { ...n.attrs };
|
|
20867
|
+
if (qualifies) nextAttrs["localCommunity"] = cid;
|
|
20868
|
+
else delete nextAttrs["localCommunity"];
|
|
20869
|
+
store.updateNode(id, { attrs: nextAttrs });
|
|
20870
|
+
if (!pulled) store.setCommunity(id, qualifies ? cid : null);
|
|
20871
|
+
}
|
|
20872
|
+
if (qualifies) {
|
|
20873
|
+
report.communities++;
|
|
20874
|
+
report.assigned += mem.length;
|
|
20875
|
+
if (hasLocal && hasCloud) report.joint++;
|
|
20876
|
+
}
|
|
20877
|
+
}
|
|
20878
|
+
});
|
|
20879
|
+
return report;
|
|
20880
|
+
}
|
|
20881
|
+
function communitySeeds(store, opts = {}) {
|
|
20882
|
+
const maxCommunities = opts.maxCommunities ?? 4;
|
|
20883
|
+
const maxSeeds = opts.maxSeeds ?? 32;
|
|
20884
|
+
const byCommunity = /* @__PURE__ */ new Map();
|
|
20885
|
+
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20886
|
+
for (const n of store.findNodesByLabel(label)) {
|
|
20887
|
+
const cid = n.attrs["localCommunity"];
|
|
20888
|
+
if (typeof cid !== "string") continue;
|
|
20889
|
+
const cloudId = n.attrs["cloudNodeId"];
|
|
20890
|
+
const l = byCommunity.get(cid) ?? [];
|
|
20891
|
+
l.push({
|
|
20892
|
+
id: n.id,
|
|
20893
|
+
pulled: n.attrs["source"] === "cloud",
|
|
20894
|
+
cloudId: typeof cloudId === "string" && cloudId !== n.id ? cloudId : null,
|
|
20895
|
+
ts: n.lastUpdatedAt
|
|
20896
|
+
});
|
|
20897
|
+
byCommunity.set(cid, l);
|
|
20898
|
+
}
|
|
20899
|
+
}
|
|
20900
|
+
if (byCommunity.size === 0) return [];
|
|
20901
|
+
const ranked = [...byCommunity.entries()].map(([cid, mem]) => ({ cid, mem, fresh: Math.max(...mem.map((m) => m.ts)) })).sort((a, b) => b.fresh - a.fresh).slice(0, maxCommunities);
|
|
20902
|
+
const seeds = [];
|
|
20903
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20904
|
+
const push = (id) => {
|
|
20905
|
+
if (seeds.length >= maxSeeds || seen.has(id)) return;
|
|
20906
|
+
seen.add(id);
|
|
20907
|
+
seeds.push(id);
|
|
20908
|
+
};
|
|
20909
|
+
for (const { mem } of ranked) {
|
|
20910
|
+
const ordered = [...mem].sort(
|
|
20911
|
+
(a, b) => a.pulled === b.pulled ? b.ts - a.ts : a.pulled ? -1 : 1
|
|
20912
|
+
);
|
|
20913
|
+
for (const m of ordered) {
|
|
20914
|
+
push(m.id);
|
|
20915
|
+
if (m.cloudId) push(m.cloudId);
|
|
20916
|
+
}
|
|
20917
|
+
}
|
|
20918
|
+
return seeds;
|
|
20919
|
+
}
|
|
20920
|
+
function communityInductionRequests(store, opts = {}) {
|
|
20921
|
+
const maxCommunities = opts.maxCommunities ?? 2;
|
|
20922
|
+
const byCommunity = /* @__PURE__ */ new Map();
|
|
20923
|
+
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
20924
|
+
for (const n of store.findNodesByLabel(label)) {
|
|
20925
|
+
const cid = n.attrs["localCommunity"];
|
|
20926
|
+
if (typeof cid !== "string") continue;
|
|
20927
|
+
const cloudId = n.attrs["cloudNodeId"];
|
|
20928
|
+
const l = byCommunity.get(cid) ?? [];
|
|
20929
|
+
l.push({
|
|
20930
|
+
id: n.id,
|
|
20931
|
+
pulled: n.attrs["source"] === "cloud",
|
|
20932
|
+
cloudId: typeof cloudId === "string" && cloudId !== n.id ? cloudId : null,
|
|
20933
|
+
ts: n.lastUpdatedAt,
|
|
20934
|
+
description: n.description
|
|
20935
|
+
});
|
|
20936
|
+
byCommunity.set(cid, l);
|
|
20937
|
+
}
|
|
20938
|
+
}
|
|
20939
|
+
if (byCommunity.size === 0) return [];
|
|
20940
|
+
return [...byCommunity.entries()].map(([cid, mem]) => ({ cid, mem, fresh: Math.max(...mem.map((m) => m.ts)) })).sort((a, b) => b.fresh - a.fresh).map(({ cid, mem }) => {
|
|
20941
|
+
const ids = /* @__PURE__ */ new Set();
|
|
20942
|
+
for (const m of mem) {
|
|
20943
|
+
ids.add(m.id);
|
|
20944
|
+
if (m.cloudId) ids.add(m.cloudId);
|
|
20945
|
+
}
|
|
20946
|
+
const freshestLocal = [...mem].filter((m) => !m.pulled).sort((a, b) => b.ts - a.ts)[0];
|
|
20947
|
+
return {
|
|
20948
|
+
communityId: cid,
|
|
20949
|
+
members: [...ids].slice(0, 64),
|
|
20950
|
+
context: (freshestLocal?.description ?? "recurring workspace problem cluster").slice(0, 200)
|
|
20951
|
+
};
|
|
20952
|
+
}).filter((r) => r.members.length >= MIN_INDUCTION_MEMBERS).slice(0, maxCommunities);
|
|
20953
|
+
}
|
|
20954
|
+
var JOINT_COMMUNITY_LABELS, JOINT_COMMUNITY_EDGES, DEFAULT_MIN_COMMUNITY_SIZE, MIN_INDUCTION_MEMBERS;
|
|
20955
|
+
var init_community2 = __esm({
|
|
20956
|
+
"../../packages/local-graph/src/community.ts"() {
|
|
20957
|
+
"use strict";
|
|
20958
|
+
init_src2();
|
|
20959
|
+
init_src3();
|
|
20960
|
+
JOINT_COMMUNITY_LABELS = [
|
|
20961
|
+
"Problem",
|
|
20962
|
+
"Solution",
|
|
20963
|
+
"RootCause",
|
|
20964
|
+
"Pattern"
|
|
20965
|
+
];
|
|
20966
|
+
JOINT_COMMUNITY_EDGES = [
|
|
20967
|
+
"CAUSED_BY",
|
|
20968
|
+
"SOLVED_BY",
|
|
20969
|
+
"FIXED_BY",
|
|
20970
|
+
"CONTRADICTS",
|
|
20971
|
+
"INSTANCE_OF",
|
|
20972
|
+
"MATCHES",
|
|
20973
|
+
"IMPLEMENTS",
|
|
20974
|
+
"TRIAGED_BY",
|
|
20975
|
+
"INDICATES",
|
|
20976
|
+
"CONFIRMS",
|
|
20977
|
+
"RELATES_TO"
|
|
20978
|
+
];
|
|
20979
|
+
DEFAULT_MIN_COMMUNITY_SIZE = 2;
|
|
20980
|
+
MIN_INDUCTION_MEMBERS = 3;
|
|
20981
|
+
}
|
|
20982
|
+
});
|
|
20983
|
+
|
|
20899
20984
|
// ../../packages/local-graph/src/problem-dedup.ts
|
|
20900
20985
|
function corroborations(n) {
|
|
20901
20986
|
return Number(n.attrs["corroborations"] ?? 0);
|
|
@@ -21243,6 +21328,7 @@ __export(src_exports2, {
|
|
|
21243
21328
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
21244
21329
|
isConstraintProblem: () => isConstraintProblem,
|
|
21245
21330
|
isPlaceholderStatement: () => isPlaceholderStatement,
|
|
21331
|
+
isUnfilledPlaceholder: () => isUnfilledPlaceholder,
|
|
21246
21332
|
linkProblemToLanguages: () => linkProblemToLanguages,
|
|
21247
21333
|
linkProblemToPackages: () => linkProblemToPackages,
|
|
21248
21334
|
linkProblemToSymbols: () => linkProblemToSymbols,
|
|
@@ -21256,10 +21342,12 @@ __export(src_exports2, {
|
|
|
21256
21342
|
matchSymbolsInText: () => matchSymbolsInText,
|
|
21257
21343
|
mergeCloudCounts: () => mergeCloudCounts,
|
|
21258
21344
|
mergeDuplicateProblems: () => mergeDuplicateProblems,
|
|
21345
|
+
migrateProjectAlias: () => migrateProjectAlias,
|
|
21259
21346
|
mintCitedPackageNode: () => mintCitedPackageNode,
|
|
21260
21347
|
mintComponentNode: () => mintComponentNode,
|
|
21261
21348
|
mintDomainNode: () => mintDomainNode,
|
|
21262
21349
|
mintPatternNode: () => mintPatternNode,
|
|
21350
|
+
mintWorkspaceCausalFact: () => mintWorkspaceCausalFact,
|
|
21263
21351
|
openGraphStore: () => openGraphStore,
|
|
21264
21352
|
osNodeId: () => osNodeId,
|
|
21265
21353
|
parseAbstractionFences: () => parseAbstractionFences,
|
|
@@ -21698,10 +21786,32 @@ function renderSnapshot(s) {
|
|
|
21698
21786
|
lines.push("");
|
|
21699
21787
|
}
|
|
21700
21788
|
lines.push("### Open review queue");
|
|
21701
|
-
|
|
21789
|
+
const reviewItems = s.reviewItems ?? [];
|
|
21790
|
+
if (s.reviewCount === 0 && reviewItems.length === 0) {
|
|
21702
21791
|
lines.push("- (none)");
|
|
21703
21792
|
} else {
|
|
21704
|
-
lines.push(`- ${s.reviewCount} items awaiting your review at ${s.reviewUiUrl}`);
|
|
21793
|
+
if (s.reviewCount > 0) lines.push(`- ${s.reviewCount} items awaiting your review at ${s.reviewUiUrl}`);
|
|
21794
|
+
for (const item of reviewItems) {
|
|
21795
|
+
if (item.kind === "discriminator") {
|
|
21796
|
+
lines.push(
|
|
21797
|
+
`- **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:`
|
|
21798
|
+
);
|
|
21799
|
+
lines.push(" ```errata-triage");
|
|
21800
|
+
lines.push(` route: ${item.route}`);
|
|
21801
|
+
lines.push(" test: <the cheap check>");
|
|
21802
|
+
lines.push(" ```");
|
|
21803
|
+
} else {
|
|
21804
|
+
lines.push(
|
|
21805
|
+
`- **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:`
|
|
21806
|
+
);
|
|
21807
|
+
for (const m of item.members) lines.push(` - ${m.description}`);
|
|
21808
|
+
lines.push(" ```errata-abstraction");
|
|
21809
|
+
lines.push(` candidate: ${item.candidate}`);
|
|
21810
|
+
lines.push(" principle: <one sentence covering all members>");
|
|
21811
|
+
lines.push(` covers: ${item.members.map((m) => m.id).join(", ")}`);
|
|
21812
|
+
lines.push(" ```");
|
|
21813
|
+
}
|
|
21814
|
+
}
|
|
21705
21815
|
}
|
|
21706
21816
|
return lines.join("\n");
|
|
21707
21817
|
}
|
|
@@ -21711,6 +21821,12 @@ function dropLowestUnit(s) {
|
|
|
21711
21821
|
case "skills":
|
|
21712
21822
|
if (s.skills.length) return s.skills.pop(), true;
|
|
21713
21823
|
break;
|
|
21824
|
+
case "reviewItemsOverFloor":
|
|
21825
|
+
if (s.reviewItems && s.reviewItems.length > REVIEW_ITEM_FLOOR) return s.reviewItems.pop(), true;
|
|
21826
|
+
break;
|
|
21827
|
+
case "reviewItems":
|
|
21828
|
+
if (s.reviewItems && s.reviewItems.length) return s.reviewItems.pop(), true;
|
|
21829
|
+
break;
|
|
21714
21830
|
case "motifsOverFloor":
|
|
21715
21831
|
if (s.motifs.length > MOTIF_FLOOR) return s.motifs.pop(), true;
|
|
21716
21832
|
break;
|
|
@@ -21765,6 +21881,7 @@ function assembleAgentContext(opts) {
|
|
|
21765
21881
|
});
|
|
21766
21882
|
if (opts.edgeElicitation) snapshot.edgeElicitation = opts.edgeElicitation;
|
|
21767
21883
|
if (opts.pendingUpdate) snapshot.pendingUpdate = opts.pendingUpdate;
|
|
21884
|
+
if (opts.reviewItems?.length) snapshot.reviewItems = [...opts.reviewItems];
|
|
21768
21885
|
if (opts.remote && opts.remote.length > 0) {
|
|
21769
21886
|
const seen = /* @__PURE__ */ new Set();
|
|
21770
21887
|
const remote = opts.remote.filter((n) => {
|
|
@@ -21787,7 +21904,7 @@ _${dropped} lower-priority item${dropped === 1 ? "" : "s"} omitted to fit the pa
|
|
|
21787
21904
|
}
|
|
21788
21905
|
return { body: body2, snapshot, dropped };
|
|
21789
21906
|
}
|
|
21790
|
-
var RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
|
|
21907
|
+
var RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
|
|
21791
21908
|
var init_render = __esm({
|
|
21792
21909
|
"../../packages/context-writer/src/render.ts"() {
|
|
21793
21910
|
"use strict";
|
|
@@ -21802,6 +21919,9 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21802
21919
|
SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted, top-of-head slice of a much larger graph. Any prior id below is a live burst seed: `errata.burst` it (or read `.errata/g/burst/<id>`) to pull its wider neighborhood \u2014 causes, fixes, siblings. When a prior is adjacent-but-not-quite, or none fit, that gap is exactly when to search deeper before solving cold: a stuck search is itself a signal that routes help to you.";
|
|
21803
21920
|
EVICTION_ORDER = [
|
|
21804
21921
|
"skills",
|
|
21922
|
+
// Review items beyond the floor drop immediately after skills — one naming
|
|
21923
|
+
// ask per render is the design (the caller rotates), extras are padding.
|
|
21924
|
+
"reviewItemsOverFloor",
|
|
21805
21925
|
// Collective floors (EE-evidence-live): motifs/remote trim to a FLOOR here and
|
|
21806
21926
|
// fully drain only near the very end. The unfloored order zeroed them on every
|
|
21807
21927
|
// render (~44 units dropped per block, live 8-01), which starved §5.4 at the
|
|
@@ -21837,11 +21957,22 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21837
21957
|
"recentProblemsOverFloor",
|
|
21838
21958
|
"motifs",
|
|
21839
21959
|
"remote",
|
|
21960
|
+
// The floored review item outlives even the terminal motif/remote stages ON
|
|
21961
|
+
// PURPOSE: the block's deficit reaches those stages on EVERY render (measured
|
|
21962
|
+
// — non-evictable instruction prose leaves ~2k discretionary, and live
|
|
21963
|
+
// renders land at exactly the problem floor with motifs/remote at zero), so
|
|
21964
|
+
// any earlier slot is structurally invisible — the same starvation that
|
|
21965
|
+
// killed the pull surfaces this band replaces. Cost: one compact ask ≈ one
|
|
21966
|
+
// remote prior. That trade is deliberate: the ask IS a witness elicitation
|
|
21967
|
+
// (a discriminator/principle is §5.4-grade evidence nothing else produces),
|
|
21968
|
+
// and it still yields to the agent's own live problems.
|
|
21969
|
+
"reviewItems",
|
|
21840
21970
|
"recentProblems"
|
|
21841
21971
|
];
|
|
21842
21972
|
MOTIF_FLOOR = 2;
|
|
21843
21973
|
REMOTE_FLOOR = 3;
|
|
21844
21974
|
PROBLEM_FLOOR = 4;
|
|
21975
|
+
REVIEW_ITEM_FLOOR = 1;
|
|
21845
21976
|
DEFAULT_AGENT_CONTEXT_BUDGET = 9e3;
|
|
21846
21977
|
}
|
|
21847
21978
|
});
|
|
@@ -26344,7 +26475,8 @@ function mergeDualBurst(local, cloud, opts = {}) {
|
|
|
26344
26475
|
provenance: corroborated ? "corroborated" : "local",
|
|
26345
26476
|
...twin?.usageCount != null ? { usageCount: twin.usageCount } : {},
|
|
26346
26477
|
...twin?.rel ? { rel: twin.rel } : {},
|
|
26347
|
-
why: l.components
|
|
26478
|
+
why: l.components,
|
|
26479
|
+
...l.via ? { via: l.via } : {}
|
|
26348
26480
|
});
|
|
26349
26481
|
}
|
|
26350
26482
|
let collectiveCount = 0;
|
|
@@ -26531,7 +26663,8 @@ function formatDualNodes(merged) {
|
|
|
26531
26663
|
centrality: Number(n.why.centrality.toFixed(3)),
|
|
26532
26664
|
trust: n.why.trust
|
|
26533
26665
|
}
|
|
26534
|
-
} : {}
|
|
26666
|
+
} : {},
|
|
26667
|
+
...n.via ? { via: n.via } : {}
|
|
26535
26668
|
}));
|
|
26536
26669
|
}
|
|
26537
26670
|
var BRIDGE_LABELS, CANONICAL_KNOWLEDGE_ID, UUID_ID;
|
|
@@ -28275,14 +28408,19 @@ function localBurst(store, seedId, opts = {}) {
|
|
|
28275
28408
|
const seed = store.getNode(seedId);
|
|
28276
28409
|
if (!seed) return [];
|
|
28277
28410
|
const hopOf = /* @__PURE__ */ new Map([[seedId, 0]]);
|
|
28411
|
+
const viaOf = /* @__PURE__ */ new Map();
|
|
28278
28412
|
let frontier = [seedId];
|
|
28279
28413
|
for (let h = 1; h <= maxHops && hopOf.size < nodeCap; h++) {
|
|
28280
28414
|
const next = [];
|
|
28281
28415
|
for (const id of frontier) {
|
|
28282
|
-
const neigh = [
|
|
28283
|
-
|
|
28416
|
+
const neigh = [
|
|
28417
|
+
...store.outEdges(id).map((e) => ({ nb: e.to, via: { edgeType: e.type, parentId: id, forward: true } })),
|
|
28418
|
+
...store.inEdges(id).map((e) => ({ nb: e.from, via: { edgeType: e.type, parentId: id, forward: false } }))
|
|
28419
|
+
];
|
|
28420
|
+
for (const { nb, via } of neigh) {
|
|
28284
28421
|
if (!hopOf.has(nb)) {
|
|
28285
28422
|
hopOf.set(nb, h);
|
|
28423
|
+
viaOf.set(nb, via);
|
|
28286
28424
|
next.push(nb);
|
|
28287
28425
|
if (hopOf.size >= nodeCap) break;
|
|
28288
28426
|
}
|
|
@@ -28304,7 +28442,8 @@ function localBurst(store, seedId, opts = {}) {
|
|
|
28304
28442
|
const now = store.currentIngestSeq();
|
|
28305
28443
|
return nodes.map(({ node: node2, hops }) => {
|
|
28306
28444
|
const r = scoreCandidate(node2, { ...ctxSeed, hops, decay: nodeFreshness(node2, now) }, weights);
|
|
28307
|
-
|
|
28445
|
+
const via = viaOf.get(node2.id);
|
|
28446
|
+
return { id: node2.id, score: r.score, components: r.components, node: node2, hops, ...via ? { via } : {} };
|
|
28308
28447
|
}).filter((r) => !gated || r.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
28309
28448
|
}
|
|
28310
28449
|
var init_relevance_rank = __esm({
|
|
@@ -38028,7 +38167,7 @@ var init_mcp = __esm({
|
|
|
38028
38167
|
},
|
|
38029
38168
|
{
|
|
38030
38169
|
name: "errata.burst",
|
|
38031
|
-
description: "Burst-grade local retrieval \u2014 the INTELLIGENT, seed-relative neighborhood (not a flat list). Given a SEED (`nodeId` or `qname`), expand its neighborhood and return the RELEVANT scored subset, ranked by burst-style relevance: semantic similarity to the seed \xD7 centrality \xD7 trust, hop-decayed; semantically-unrelated nodes are gated out. Prefer this over errata.neighbors when you want signal-ranked CONTEXT rather than raw edges. When the SEED is a package and the collective is reachable, results BLEND cross-project knowledge \u2014 each carries `provenance` (local | collective | corroborated) and `usageCount` (projects using it); `corroborated` means your graph and the collective agree (trust it most), `collective` is a cross-project prior to verify. Returns {seed, count, results:[{id,label,name,score,hops,provenance,usageCount?,why?}]}.",
|
|
38170
|
+
description: "Burst-grade local retrieval \u2014 the INTELLIGENT, seed-relative neighborhood (not a flat list). Given a SEED (`nodeId` or `qname`), expand its neighborhood and return the RELEVANT scored subset, ranked by burst-style relevance: semantic similarity to the seed \xD7 centrality \xD7 trust, hop-decayed; semantically-unrelated nodes are gated out. Prefer this over errata.neighbors when you want signal-ranked CONTEXT rather than raw edges. When the SEED is a package and the collective is reachable, results BLEND cross-project knowledge \u2014 each carries `provenance` (local | collective | corroborated) and `usageCount` (projects using it); `corroborated` means your graph and the collective agree (trust it most), `collective` is a cross-project prior to verify. Returns {seed, count, results:[{id,label,name,score,hops,provenance,usageCount?,why?,via?}]} \u2014 `via` is the TOPOLOGY: the edge that reached this result in the walk ({edgeType, parentId, forward}; forward: true \u21D2 parent \u2014edgeType\u2192 node), so you can tell 'FIXED_BY your seed' from 'two hops away via a shared package' and choose whether to dig down a causal chain or turn elsewhere.",
|
|
38032
38171
|
inputSchema: {
|
|
38033
38172
|
type: "object",
|
|
38034
38173
|
properties: {
|
|
@@ -38072,7 +38211,8 @@ var init_mcp = __esm({
|
|
|
38072
38211
|
node: { label: r.node.label, description: r.node.description },
|
|
38073
38212
|
score: r.score,
|
|
38074
38213
|
hops: r.hops ?? 0,
|
|
38075
|
-
components: r.components
|
|
38214
|
+
components: r.components,
|
|
38215
|
+
...r.via ? { via: r.via } : {}
|
|
38076
38216
|
}));
|
|
38077
38217
|
const seedNode = store.getNode(id);
|
|
38078
38218
|
let collectiveStatus = "local-only";
|
|
@@ -38118,7 +38258,8 @@ var init_mcp = __esm({
|
|
|
38118
38258
|
semantic: Number(r.components.semantic.toFixed(3)),
|
|
38119
38259
|
centrality: Number(r.components.centrality.toFixed(3)),
|
|
38120
38260
|
trust: r.components.trust
|
|
38121
|
-
}
|
|
38261
|
+
},
|
|
38262
|
+
...r.via ? { via: r.via } : {}
|
|
38122
38263
|
}))
|
|
38123
38264
|
};
|
|
38124
38265
|
}
|
|
@@ -52874,6 +53015,12 @@ function sessionOriginKey(sessionId) {
|
|
|
52874
53015
|
function refreshRepoLocator(root, profile) {
|
|
52875
53016
|
const detected = detectRepoLocator(root, profile.repoRemote);
|
|
52876
53017
|
if (!detected || detected === profile.repoLocator) return false;
|
|
53018
|
+
if (profile.repoLocator) {
|
|
53019
|
+
const aliases = new Set(profile.repoLocatorAliases ?? []);
|
|
53020
|
+
aliases.add(profile.repoLocator);
|
|
53021
|
+
aliases.delete(detected);
|
|
53022
|
+
profile.repoLocatorAliases = [...aliases];
|
|
53023
|
+
}
|
|
52877
53024
|
profile.repoLocator = detected;
|
|
52878
53025
|
saveProfile(root, profile);
|
|
52879
53026
|
return true;
|
|
@@ -53264,7 +53411,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
53264
53411
|
}
|
|
53265
53412
|
|
|
53266
53413
|
// src/engine.ts
|
|
53267
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
53414
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.417" : "2.0.0-alpha.0";
|
|
53268
53415
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
53269
53416
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
53270
53417
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -53600,6 +53747,27 @@ function createWorkspaceEngine(opts) {
|
|
|
53600
53747
|
}
|
|
53601
53748
|
}
|
|
53602
53749
|
};
|
|
53750
|
+
const clip = (s, n) => s.length > n ? `${s.slice(0, n - 1)}\u2026` : s;
|
|
53751
|
+
const pickReviewItems = () => {
|
|
53752
|
+
const shared = opts.sharedStore;
|
|
53753
|
+
if (!shared) return [];
|
|
53754
|
+
try {
|
|
53755
|
+
if ((/* @__PURE__ */ new Date()).getHours() % 2 === 0) {
|
|
53756
|
+
const small = pendingAbstractions(shared).filter((a) => a.members.length >= 2 && a.members.length <= 5).sort((a, b) => a.members.length - b.members.length)[0];
|
|
53757
|
+
if (small) {
|
|
53758
|
+
return [{
|
|
53759
|
+
kind: "abstraction",
|
|
53760
|
+
candidate: small.candidate,
|
|
53761
|
+
members: small.members.map((m) => ({ id: m.id, description: clip(m.description, 110) }))
|
|
53762
|
+
}];
|
|
53763
|
+
}
|
|
53764
|
+
}
|
|
53765
|
+
const [d] = pendingDiscriminators(shared, { limit: 1 });
|
|
53766
|
+
return d ? [{ kind: "discriminator", route: d.route, presenting: clip(d.presenting, 140), cause: clip(d.cause, 140) }] : [];
|
|
53767
|
+
} catch {
|
|
53768
|
+
return [];
|
|
53769
|
+
}
|
|
53770
|
+
};
|
|
53603
53771
|
const refreshContextOnce = async () => {
|
|
53604
53772
|
const elicit = isEdgeElicitationEnabled();
|
|
53605
53773
|
const snapOpts = {
|
|
@@ -53613,13 +53781,15 @@ function createWorkspaceEngine(opts) {
|
|
|
53613
53781
|
const prebuilt = passWorker ? await passWorker.snapshot(snapOpts).catch(() => null) : null;
|
|
53614
53782
|
const doneRender = prebuilt ? null : markPass(`context-render-inline:${profile.name}`);
|
|
53615
53783
|
const pendingUpdate = opts.pendingUpdate?.() ?? null;
|
|
53784
|
+
const reviewItems = pickReviewItems();
|
|
53616
53785
|
const { body: body2, snapshot } = assembleAgentContext({
|
|
53617
53786
|
store,
|
|
53618
53787
|
...snapOpts,
|
|
53619
53788
|
remote: remotePriors,
|
|
53620
53789
|
...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {},
|
|
53621
53790
|
...prebuilt ? { snapshot: prebuilt } : {},
|
|
53622
|
-
...pendingUpdate ? { pendingUpdate } : {}
|
|
53791
|
+
...pendingUpdate ? { pendingUpdate } : {},
|
|
53792
|
+
...reviewItems.length ? { reviewItems } : {}
|
|
53623
53793
|
});
|
|
53624
53794
|
doneRender?.();
|
|
53625
53795
|
writeContextFile(opts.workspaceRoot, body2);
|
|
@@ -54102,6 +54272,22 @@ function createWorkspaceEngine(opts) {
|
|
|
54102
54272
|
} catch (err2) {
|
|
54103
54273
|
console.warn("[errata] inline triage route failed:", err2);
|
|
54104
54274
|
}
|
|
54275
|
+
if (evidence !== "inferred") {
|
|
54276
|
+
try {
|
|
54277
|
+
mintWorkspaceCausalFact(
|
|
54278
|
+
store,
|
|
54279
|
+
{
|
|
54280
|
+
presentingId,
|
|
54281
|
+
causeId: tr.causeId,
|
|
54282
|
+
...tr.causeDescription ? { causeDescription: tr.causeDescription } : {},
|
|
54283
|
+
sessionId
|
|
54284
|
+
},
|
|
54285
|
+
t
|
|
54286
|
+
);
|
|
54287
|
+
} catch (err2) {
|
|
54288
|
+
console.warn("[errata] workspace causal-fact mirror failed:", err2);
|
|
54289
|
+
}
|
|
54290
|
+
}
|
|
54105
54291
|
}
|
|
54106
54292
|
}
|
|
54107
54293
|
if (opts.sharedStore) {
|
|
@@ -54115,6 +54301,13 @@ function createWorkspaceEngine(opts) {
|
|
|
54115
54301
|
}
|
|
54116
54302
|
}
|
|
54117
54303
|
}
|
|
54304
|
+
for (const link of plan.causalLinks) {
|
|
54305
|
+
try {
|
|
54306
|
+
recordCauseChainLink(store, link, t, { contributor: sessionId, sources: [sessionId] });
|
|
54307
|
+
} catch (err2) {
|
|
54308
|
+
console.warn("[errata] workspace causal chain mirror failed:", err2);
|
|
54309
|
+
}
|
|
54310
|
+
}
|
|
54118
54311
|
for (const at of plan.attempts) {
|
|
54119
54312
|
const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? designProblemId(at.boundStatement) : void 0);
|
|
54120
54313
|
const node2 = pid ? store.getNode(pid) : void 0;
|
|
@@ -56453,6 +56646,37 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56453
56646
|
async percolateAll() {
|
|
56454
56647
|
const ts = Date.now();
|
|
56455
56648
|
const out2 = /* @__PURE__ */ new Map();
|
|
56649
|
+
const repoBasename = (locator) => (locator.split("/").filter(Boolean).pop() ?? locator).toLowerCase();
|
|
56650
|
+
for (const r of records) {
|
|
56651
|
+
const profile = r.engine.profile;
|
|
56652
|
+
const aliases = profile.repoLocatorAliases ?? [];
|
|
56653
|
+
const locator = profile.repoLocator;
|
|
56654
|
+
if (!locator || aliases.length === 0) continue;
|
|
56655
|
+
try {
|
|
56656
|
+
for (const alias of aliases) {
|
|
56657
|
+
if (repoBasename(alias) !== repoBasename(locator)) {
|
|
56658
|
+
console.log(
|
|
56659
|
+
`[errata] project alias NOT auto-migrated for ${r.entry.name} (${alias} \u2192 ${locator}: repo name differs \u2014 a fork/repoint, not a rename). Run scripts/migrate-project-alias.ts if this really is the same repo.`
|
|
56660
|
+
);
|
|
56661
|
+
continue;
|
|
56662
|
+
}
|
|
56663
|
+
const m = migrateProjectAlias(sharedStore, { from: alias, to: locator, ts });
|
|
56664
|
+
if (m.nodesRewritten || m.edgesRewritten) {
|
|
56665
|
+
console.log(
|
|
56666
|
+
`[errata] project alias migrated for ${r.entry.name}: ${alias} \u2192 ${locator} (${m.nodesRewritten} nodes, ${m.edgesRewritten} edges)`
|
|
56667
|
+
);
|
|
56668
|
+
}
|
|
56669
|
+
}
|
|
56670
|
+
delete profile.repoLocatorAliases;
|
|
56671
|
+
const onDisk = loadProfile(r.root);
|
|
56672
|
+
if (onDisk) {
|
|
56673
|
+
delete onDisk.repoLocatorAliases;
|
|
56674
|
+
saveProfile(r.root, onDisk);
|
|
56675
|
+
}
|
|
56676
|
+
} catch (err2) {
|
|
56677
|
+
console.warn(`[errata] project-alias migration failed for ${r.entry.name} (kept for next pass): ${err2 instanceof Error ? err2.message : err2}`);
|
|
56678
|
+
}
|
|
56679
|
+
}
|
|
56456
56680
|
let inlineRecords = records;
|
|
56457
56681
|
if (consolidateWorker) {
|
|
56458
56682
|
const fileBacked = records.filter((r) => r.engine.paths.castalia !== ":memory:");
|