@inerrata-corporation/errata 2.0.23-dev.4863 → 2.0.23-dev.4881
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
CHANGED
|
@@ -18892,10 +18892,10 @@ function wmCalibrationCells(store) {
|
|
|
18892
18892
|
}
|
|
18893
18893
|
})();
|
|
18894
18894
|
for (const n of rows) {
|
|
18895
|
-
const
|
|
18895
|
+
const live4 = n.validTo === null;
|
|
18896
18896
|
const prev = newest.get(n.logicalId);
|
|
18897
|
-
if (prev && (prev.live || !
|
|
18898
|
-
newest.set(n.logicalId, { version: n.version, live:
|
|
18897
|
+
if (prev && (prev.live || !live4 && prev.version >= n.version)) continue;
|
|
18898
|
+
newest.set(n.logicalId, { version: n.version, live: live4, attrs: n.attrs });
|
|
18899
18899
|
}
|
|
18900
18900
|
for (const { attrs } of newest.values()) {
|
|
18901
18901
|
const shown = num(attrs["shownCount"]);
|
|
@@ -22560,7 +22560,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
22560
22560
|
return out2;
|
|
22561
22561
|
}
|
|
22562
22562
|
liveNodeIds(ids) {
|
|
22563
|
-
const
|
|
22563
|
+
const live4 = /* @__PURE__ */ new Set();
|
|
22564
22564
|
const CHUNK2 = 900;
|
|
22565
22565
|
for (let i2 = 0; i2 < ids.length; i2 += CHUNK2) {
|
|
22566
22566
|
const slice = ids.slice(i2, i2 + CHUNK2);
|
|
@@ -22568,9 +22568,9 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
22568
22568
|
const rows = this.db.prepare(
|
|
22569
22569
|
`SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
|
|
22570
22570
|
).all(...slice);
|
|
22571
|
-
for (const r of rows)
|
|
22571
|
+
for (const r of rows) live4.add(r.id);
|
|
22572
22572
|
}
|
|
22573
|
-
return
|
|
22573
|
+
return live4;
|
|
22574
22574
|
}
|
|
22575
22575
|
/**
|
|
22576
22576
|
* Live edges WITH their endpoint labels and ids, resolved in ONE join.
|
|
@@ -22639,9 +22639,9 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
22639
22639
|
// the indexer calls freezeNode inside its own store.transaction(). So this
|
|
22640
22640
|
// method does NOT open a transaction — callers needing atomicity wrap it.
|
|
22641
22641
|
freezeNode(liveId, t) {
|
|
22642
|
-
const
|
|
22643
|
-
if (!
|
|
22644
|
-
const version3 =
|
|
22642
|
+
const live4 = this.getNode(liveId);
|
|
22643
|
+
if (!live4) return null;
|
|
22644
|
+
const version3 = live4.version ?? 1;
|
|
22645
22645
|
const frozenId = `${liveId}@v${version3}`;
|
|
22646
22646
|
if (this.getNode(frozenId)) {
|
|
22647
22647
|
this.stmts.advanceLive.run({ live_id: liveId, t });
|
|
@@ -22791,11 +22791,11 @@ function walk(store, opts) {
|
|
|
22791
22791
|
}
|
|
22792
22792
|
}
|
|
22793
22793
|
best.delete(seed.id);
|
|
22794
|
-
const
|
|
22794
|
+
const ranked2 = [];
|
|
22795
22795
|
for (const [id, r] of best) {
|
|
22796
22796
|
const node2 = store.getNode(id);
|
|
22797
22797
|
if (!node2) continue;
|
|
22798
|
-
|
|
22798
|
+
ranked2.push({
|
|
22799
22799
|
id,
|
|
22800
22800
|
label: node2.label,
|
|
22801
22801
|
description: node2.description,
|
|
@@ -22805,11 +22805,11 @@ function walk(store, opts) {
|
|
|
22805
22805
|
// product of conductances along best path
|
|
22806
22806
|
});
|
|
22807
22807
|
}
|
|
22808
|
-
|
|
22808
|
+
ranked2.sort(
|
|
22809
22809
|
(a, b) => b.relevance - a.relevance || a.hops - b.hops
|
|
22810
22810
|
);
|
|
22811
|
-
const truncated =
|
|
22812
|
-
return { seedId: seed.id, nodes:
|
|
22811
|
+
const truncated = ranked2.length > limit;
|
|
22812
|
+
return { seedId: seed.id, nodes: ranked2.slice(0, limit), truncated };
|
|
22813
22813
|
}
|
|
22814
22814
|
function findPath(store, opts) {
|
|
22815
22815
|
const maxHops = opts.maxHops ?? 6;
|
|
@@ -24914,8 +24914,8 @@ function anchorNodeToDiff(store, nodeId, expectLabel, changedPaths, workspaceId2
|
|
|
24914
24914
|
}
|
|
24915
24915
|
function solutionForProblem(store, problemId) {
|
|
24916
24916
|
const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
|
|
24917
|
-
const
|
|
24918
|
-
const pick2 = (
|
|
24917
|
+
const live4 = sols.filter((s) => s.validTo == null && !isAutoMinted(s));
|
|
24918
|
+
const pick2 = (live4.length > 0 ? live4 : sols).reduce(
|
|
24919
24919
|
(best, s) => !best || s.createdAt > best.createdAt ? s : best,
|
|
24920
24920
|
null
|
|
24921
24921
|
);
|
|
@@ -25663,13 +25663,13 @@ function recallableCorpus(store) {
|
|
|
25663
25663
|
let cache2 = bagCache.get(store);
|
|
25664
25664
|
if (!cache2) bagCache.set(store, cache2 = /* @__PURE__ */ new Map());
|
|
25665
25665
|
const docs = [];
|
|
25666
|
-
const
|
|
25666
|
+
const live4 = /* @__PURE__ */ new Set();
|
|
25667
25667
|
for (const row of store.selectNodes({ labels: RECALLABLE, attrs: RECALL_FILTER_KEYS })) {
|
|
25668
25668
|
if (row.attrs["mergedInto"] !== void 0) continue;
|
|
25669
25669
|
if (row.label === "Problem" && row.attrs["resolvedAt"] != null && !isConstraintProblem(row)) {
|
|
25670
25670
|
continue;
|
|
25671
25671
|
}
|
|
25672
|
-
|
|
25672
|
+
live4.add(row.id);
|
|
25673
25673
|
let entry = cache2.get(row.id);
|
|
25674
25674
|
if (!entry || entry.description !== row.description) {
|
|
25675
25675
|
entry = { description: row.description, bag: retrievalTokens(row.description) };
|
|
@@ -25678,7 +25678,7 @@ function recallableCorpus(store) {
|
|
|
25678
25678
|
if (entry.bag.length === 0) continue;
|
|
25679
25679
|
docs.push({ id: row.id, descLength: row.description.length, bag: entry.bag });
|
|
25680
25680
|
}
|
|
25681
|
-
for (const id of cache2.keys()) if (!
|
|
25681
|
+
for (const id of cache2.keys()) if (!live4.has(id)) cache2.delete(id);
|
|
25682
25682
|
return docs;
|
|
25683
25683
|
}
|
|
25684
25684
|
var FIELD_LINE, RECALLABLE, MIN_INTENT_TOKENS, DEFAULT_MIN_COVERAGE, RECALL_FILTER_KEYS, bagCache;
|
|
@@ -27057,7 +27057,7 @@ function communitySeeds(store, opts = {}) {
|
|
|
27057
27057
|
byCommunity.set(cid, l);
|
|
27058
27058
|
}
|
|
27059
27059
|
if (byCommunity.size === 0) return [];
|
|
27060
|
-
const
|
|
27060
|
+
const ranked2 = [...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);
|
|
27061
27061
|
const seeds = [];
|
|
27062
27062
|
const seen = /* @__PURE__ */ new Set();
|
|
27063
27063
|
const push = (id) => {
|
|
@@ -27065,7 +27065,7 @@ function communitySeeds(store, opts = {}) {
|
|
|
27065
27065
|
seen.add(id);
|
|
27066
27066
|
seeds.push(id);
|
|
27067
27067
|
};
|
|
27068
|
-
for (const { mem } of
|
|
27068
|
+
for (const { mem } of ranked2) {
|
|
27069
27069
|
const ordered = [...mem].sort(
|
|
27070
27070
|
(a, b) => a.pulled === b.pulled ? b.ts - a.ts : a.pulled ? -1 : 1
|
|
27071
27071
|
);
|
|
@@ -31325,12 +31325,12 @@ function hasCloudCredential(cfg) {
|
|
|
31325
31325
|
}
|
|
31326
31326
|
function persistProfileTokens(profileName, t) {
|
|
31327
31327
|
const current = loadConfig();
|
|
31328
|
-
const
|
|
31329
|
-
if (!
|
|
31328
|
+
const live4 = current.installationProfiles[profileName];
|
|
31329
|
+
if (!live4) return;
|
|
31330
31330
|
current.installationProfiles = {
|
|
31331
31331
|
...current.installationProfiles,
|
|
31332
31332
|
[profileName]: {
|
|
31333
|
-
...
|
|
31333
|
+
...live4,
|
|
31334
31334
|
accessToken: t.accessToken,
|
|
31335
31335
|
...t.refreshToken ? { refreshToken: t.refreshToken } : {}
|
|
31336
31336
|
}
|
|
@@ -34221,11 +34221,11 @@ function bindCanonicalNeighbors(store, opts) {
|
|
|
34221
34221
|
store.outEdges(p.id, ["MATCHES", "INSTANCE_OF", "RELATES_TO"]).map((e) => e.to)
|
|
34222
34222
|
);
|
|
34223
34223
|
if (existing.size >= k) continue;
|
|
34224
|
-
const
|
|
34224
|
+
const ranked2 = pool.filter(
|
|
34225
34225
|
(c) => c.id !== p.id && !existing.has(c.id) && c.embedding.length === p.embedding.length && (c.attrs["embeddingVersion"] ?? "") === (p.attrs["embeddingVersion"] ?? "")
|
|
34226
34226
|
).map((c) => ({ c, s: cosine(p.embedding, c.embedding) })).filter((x) => x.s >= CANONICAL_BIND_MIN && x.s < NEMORI_DEDUP_COSINE).sort((a, b) => b.s - a.s);
|
|
34227
34227
|
const picked = [];
|
|
34228
|
-
for (const cand of
|
|
34228
|
+
for (const cand of ranked2) {
|
|
34229
34229
|
if (picked.length + existing.size >= k) break;
|
|
34230
34230
|
if (picked.some((q) => cosine(q.c.embedding, cand.c.embedding) >= NEMORI_DEDUP_COSINE)) continue;
|
|
34231
34231
|
picked.push(cand);
|
|
@@ -35882,14 +35882,14 @@ function localBurst(store, seedId, opts = {}) {
|
|
|
35882
35882
|
}).filter((r) => !gated || r.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
35883
35883
|
}
|
|
35884
35884
|
function burstFromSeeds(store, seeds, opts = {}) {
|
|
35885
|
-
const
|
|
35886
|
-
if (
|
|
35887
|
-
const { act, hopOf, viaOf } = spreadActivation(store,
|
|
35885
|
+
const live4 = seeds.filter((s) => s.weight > 0);
|
|
35886
|
+
if (live4.length === 0) return [];
|
|
35887
|
+
const { act, hopOf, viaOf } = spreadActivation(store, live4, {
|
|
35888
35888
|
maxHops: opts.maxHops ?? 3,
|
|
35889
35889
|
nodeCap: opts.nodeCap ?? 300,
|
|
35890
35890
|
accumulate: true
|
|
35891
35891
|
});
|
|
35892
|
-
const seedIds = new Set(
|
|
35892
|
+
const seedIds = new Set(live4.map((s) => s.id));
|
|
35893
35893
|
const labelOf = store.nodeLabels([...act.keys()]);
|
|
35894
35894
|
const pool = (keep) => [...act.entries()].filter(([id]) => keep(labelOf.get(id) ?? "")).sort((x, y) => y[1] - x[1]).slice(0, BURST_SCORED_CANDIDATES);
|
|
35895
35895
|
const isKnowledge = (label) => typeRelevance(label) >= KNOWLEDGE_TYPE_RELEVANCE;
|
|
@@ -36583,10 +36583,10 @@ function createSessionRegistry(opts = {}) {
|
|
|
36583
36583
|
originSessions: () => [...origins.keys()],
|
|
36584
36584
|
isOwn: (sessionId, viewer) => sessionId === viewer || parentOf.get(sessionId) === viewer,
|
|
36585
36585
|
version(nowMs) {
|
|
36586
|
-
let
|
|
36587
|
-
for (const id of lastSeen.keys()) if (ownLive(id, nowMs))
|
|
36588
|
-
if (
|
|
36589
|
-
lastLiveCount =
|
|
36586
|
+
let live4 = 0;
|
|
36587
|
+
for (const id of lastSeen.keys()) if (ownLive(id, nowMs)) live4++;
|
|
36588
|
+
if (live4 !== lastLiveCount) {
|
|
36589
|
+
lastLiveCount = live4;
|
|
36590
36590
|
ver++;
|
|
36591
36591
|
}
|
|
36592
36592
|
return ver;
|
|
@@ -38083,7 +38083,7 @@ function lazySymbolLexicon(store) {
|
|
|
38083
38083
|
const members = /* @__PURE__ */ new Map();
|
|
38084
38084
|
const docs = /* @__PURE__ */ new Map();
|
|
38085
38085
|
const entries = /* @__PURE__ */ new Map();
|
|
38086
|
-
const
|
|
38086
|
+
const member2 = (name2) => {
|
|
38087
38087
|
if (!members.has(name2)) {
|
|
38088
38088
|
const hit = isDistinctiveIdentifier(name2) ? store.firstLiveByNameOrQname(labels, name2) : null;
|
|
38089
38089
|
members.set(name2, hit ? { kind: kindOf.get(hit.label), description: hit.description, qname: hit.qname } : null);
|
|
@@ -38104,13 +38104,13 @@ function lazySymbolLexicon(store) {
|
|
|
38104
38104
|
}
|
|
38105
38105
|
return docs.get(name2);
|
|
38106
38106
|
};
|
|
38107
|
-
const isKnown = (tok) =>
|
|
38107
|
+
const isKnown = (tok) => member2(tok) !== null;
|
|
38108
38108
|
let anySymbol;
|
|
38109
38109
|
return {
|
|
38110
38110
|
has: isKnown,
|
|
38111
38111
|
get(name2) {
|
|
38112
38112
|
if (!entries.has(name2)) {
|
|
38113
|
-
const m =
|
|
38113
|
+
const m = member2(name2);
|
|
38114
38114
|
let entry = null;
|
|
38115
38115
|
if (m) {
|
|
38116
38116
|
entry = { kind: m.kind };
|
|
@@ -39129,17 +39129,17 @@ async function rankHits(store, query, hits, opts = {}) {
|
|
|
39129
39129
|
if (p != null && p !== i2 && best[p] > best[i2]) best[i2] = best[p];
|
|
39130
39130
|
});
|
|
39131
39131
|
}
|
|
39132
|
-
const
|
|
39132
|
+
const ranked2 = hits.map((h, i2) => {
|
|
39133
39133
|
const r = rankKnowledge({ ...inputs[i2], ...best[i2] > own[i2] ? { inherited: best[i2] } : {} }, weights);
|
|
39134
39134
|
return { hit: h, i: i2, r };
|
|
39135
39135
|
});
|
|
39136
|
-
|
|
39137
|
-
return
|
|
39136
|
+
ranked2.sort((a, b) => b.r.score - a.r.score || a.i - b.i);
|
|
39137
|
+
return ranked2.map(({ hit, r }) => ({ ...hit, score: r.score, rank: r.components }));
|
|
39138
39138
|
}
|
|
39139
|
-
function interleaveLanes(
|
|
39140
|
-
const lanes = [
|
|
39139
|
+
function interleaveLanes(ranked2, isKnowledge, limit) {
|
|
39140
|
+
const lanes = [ranked2.filter((r) => isKnowledge(r.label)), ranked2.filter((r) => !isKnowledge(r.label))];
|
|
39141
39141
|
const out2 = [];
|
|
39142
|
-
for (let i2 = 0; out2.length < limit && i2 <
|
|
39142
|
+
for (let i2 = 0; out2.length < limit && i2 < ranked2.length; i2++) {
|
|
39143
39143
|
const round2 = lanes.flatMap((lane) => lane[i2] ? [lane[i2]] : []).sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
39144
39144
|
for (const hit of round2) if (out2.length < limit) out2.push(hit);
|
|
39145
39145
|
}
|
|
@@ -39153,12 +39153,12 @@ async function rankDualNodes(store, query, nodes, cloudEvidence2) {
|
|
|
39153
39153
|
const parent = n.via?.parentId;
|
|
39154
39154
|
return parent ? { ...n, parentId: parent } : n;
|
|
39155
39155
|
});
|
|
39156
|
-
const
|
|
39157
|
-
return
|
|
39156
|
+
const ranked2 = await rankHits(store, query, withParents, cloudEvidence2 ? { cloudEvidence: cloudEvidence2 } : {});
|
|
39157
|
+
return ranked2.map(({ rank, score: score2, ...n }) => ({ ...n, score: score2, why: rankWhy(rank) }));
|
|
39158
39158
|
}
|
|
39159
39159
|
async function rankSimilarLocal(store, seedText, hits) {
|
|
39160
|
-
const
|
|
39161
|
-
return
|
|
39160
|
+
const ranked2 = await rankHits(store, seedQuery(seedText), hits.map((h) => ({ ...h, hops: 0 })));
|
|
39161
|
+
return ranked2.map(({ rank, score: score2, hops: _hops, ...h }) => ({ ...h, score: score2, why: rankWhy(rank) }));
|
|
39162
39162
|
}
|
|
39163
39163
|
function withCite(records, isKnowledge) {
|
|
39164
39164
|
return records.map((r) => isKnowledge(String(r["label"])) ? { ...r, cite: String(r["id"]) } : r);
|
|
@@ -39180,6 +39180,104 @@ var init_one_search = __esm({
|
|
|
39180
39180
|
}
|
|
39181
39181
|
});
|
|
39182
39182
|
|
|
39183
|
+
// src/chain-complete.ts
|
|
39184
|
+
function fixesOf(store, problemId, causes) {
|
|
39185
|
+
const own = store.outEdges(problemId, [...FIX_EDGES]).map((e) => e.to).filter((id) => live2(store, id));
|
|
39186
|
+
if (own.length > 0) return own.map((id) => ({ id }));
|
|
39187
|
+
const borrowed = /* @__PURE__ */ new Map();
|
|
39188
|
+
for (const c of causes) {
|
|
39189
|
+
for (const e of store.inEdges(c, ["CAUSED_BY"])) {
|
|
39190
|
+
if (e.from === problemId || live2(store, e.from)?.label !== "Problem") continue;
|
|
39191
|
+
for (const f of store.outEdges(e.from, [...FIX_EDGES])) if (!borrowed.has(f.to) && live2(store, f.to)) borrowed.set(f.to, e.from);
|
|
39192
|
+
}
|
|
39193
|
+
}
|
|
39194
|
+
return [...borrowed].map(([id, via]) => ({ id, via }));
|
|
39195
|
+
}
|
|
39196
|
+
async function ranked(store, about, ids) {
|
|
39197
|
+
const hits = ids.flatMap(({ id, via }) => {
|
|
39198
|
+
const n = live2(store, id);
|
|
39199
|
+
return n ? [{ id, label: n.label, name: n.description, hops: 0, ...via ? { via } : {} }] : [];
|
|
39200
|
+
});
|
|
39201
|
+
const order = hits.length > 1 ? await rankHits(store, about, hits) : hits;
|
|
39202
|
+
return order.flatMap((h) => member(store, h.id, h.via) ?? []);
|
|
39203
|
+
}
|
|
39204
|
+
async function chainOf(store, problemId) {
|
|
39205
|
+
const p = live2(store, problemId);
|
|
39206
|
+
if (!p || p.label !== "Problem") return void 0;
|
|
39207
|
+
const causes = store.outEdges(problemId, ["CAUSED_BY"]).map((e) => e.to).filter((id) => live2(store, id)?.label === "RootCause");
|
|
39208
|
+
const [cause] = await ranked(store, p.description, causes.map((id) => ({ id })));
|
|
39209
|
+
const fixIds = fixesOf(store, problemId, causes);
|
|
39210
|
+
const [fix, ...rest2] = await ranked(store, [p.description, cause?.text ?? ""].join(" "), fixIds);
|
|
39211
|
+
if (!cause && !fix) return void 0;
|
|
39212
|
+
const alsoFixes = rest2.slice(0, ALSO_FIXES);
|
|
39213
|
+
return {
|
|
39214
|
+
...cause ? { cause } : {},
|
|
39215
|
+
...fix ? { fix, fixes: fixIds.length } : {},
|
|
39216
|
+
...alsoFixes.length > 0 ? { alsoFixes } : {}
|
|
39217
|
+
};
|
|
39218
|
+
}
|
|
39219
|
+
function statementOf(description) {
|
|
39220
|
+
const s = description?.replace(/\s+@\s+\S+\s*$/, "").trim().toLowerCase();
|
|
39221
|
+
return s ? s : void 0;
|
|
39222
|
+
}
|
|
39223
|
+
function searchChainsEnabled(env2 = process.env) {
|
|
39224
|
+
return !/^(0|off|false|no)$/i.test((env2["ERRATA_SEARCH_CHAINS"] ?? "").trim());
|
|
39225
|
+
}
|
|
39226
|
+
async function completeChains(store, hits) {
|
|
39227
|
+
if (!searchChainsEnabled()) return [...hits];
|
|
39228
|
+
const idOf = (h) => String(h.id ?? "");
|
|
39229
|
+
const isProblem = (h) => h.label === "Problem";
|
|
39230
|
+
const chains = /* @__PURE__ */ new Map();
|
|
39231
|
+
for (const h of hits) {
|
|
39232
|
+
if (!isProblem(h)) continue;
|
|
39233
|
+
const c = await chainOf(store, idOf(h));
|
|
39234
|
+
if (c) chains.set(idOf(h), c);
|
|
39235
|
+
}
|
|
39236
|
+
const out2 = [];
|
|
39237
|
+
const shownAt = /* @__PURE__ */ new Map();
|
|
39238
|
+
const statementAt = /* @__PURE__ */ new Map();
|
|
39239
|
+
const carried = /* @__PURE__ */ new Set();
|
|
39240
|
+
for (const h of hits) {
|
|
39241
|
+
const id = idOf(h);
|
|
39242
|
+
if (carried.has(id)) continue;
|
|
39243
|
+
const chain2 = chains.get(id);
|
|
39244
|
+
const owner = chain2?.fix?.via;
|
|
39245
|
+
const statement = isProblem(h) ? statementOf(live2(store, id)?.description) : void 0;
|
|
39246
|
+
let into = owner && shownAt.has(owner) ? shownAt.get(owner) : out2.findIndex((o) => o.chain?.fix?.via === id);
|
|
39247
|
+
if (into < 0 && statement && statementAt.has(statement)) into = statementAt.get(statement);
|
|
39248
|
+
if (into >= 0) {
|
|
39249
|
+
const at = out2[into];
|
|
39250
|
+
const adopt = !at.chain?.fix && chain2?.fix ? { chain: { ...chain2, ...at.chain?.cause ? { cause: at.chain.cause } : {} } } : {};
|
|
39251
|
+
out2[into] = { ...at, ...adopt, alsoReportedAs: [...at.alsoReportedAs ?? [], id] };
|
|
39252
|
+
for (const m of membersOf(chain2)) carried.add(m.id);
|
|
39253
|
+
continue;
|
|
39254
|
+
}
|
|
39255
|
+
if (statement) statementAt.set(statement, out2.length);
|
|
39256
|
+
shownAt.set(id, out2.length);
|
|
39257
|
+
out2.push(chain2 ? { ...h, chain: chain2 } : h);
|
|
39258
|
+
for (const m of membersOf(chain2)) carried.add(m.id);
|
|
39259
|
+
}
|
|
39260
|
+
return out2;
|
|
39261
|
+
}
|
|
39262
|
+
var FIX_EDGES, live2, member, ALSO_FIXES, membersOf;
|
|
39263
|
+
var init_chain_complete = __esm({
|
|
39264
|
+
"src/chain-complete.ts"() {
|
|
39265
|
+
"use strict";
|
|
39266
|
+
init_one_search();
|
|
39267
|
+
FIX_EDGES = ["SOLVED_BY", "FIXED_BY"];
|
|
39268
|
+
live2 = (store, id) => {
|
|
39269
|
+
const n = store.getNode(id);
|
|
39270
|
+
return n && n.validTo == null ? n : null;
|
|
39271
|
+
};
|
|
39272
|
+
member = (store, id, via) => {
|
|
39273
|
+
const n = live2(store, id);
|
|
39274
|
+
return n ? { id, text: n.description, ...via ? { via } : {} } : void 0;
|
|
39275
|
+
};
|
|
39276
|
+
ALSO_FIXES = 2;
|
|
39277
|
+
membersOf = (c) => c ? [c.cause, c.fix, ...c.alsoFixes ?? []].filter((m) => m != null) : [];
|
|
39278
|
+
}
|
|
39279
|
+
});
|
|
39280
|
+
|
|
39183
39281
|
// src/daemon-generalize-client.ts
|
|
39184
39282
|
function daemonLoopbackUrl(lockPath = globalDaemonLock()) {
|
|
39185
39283
|
const url2 = readDaemonLock(lockPath)?.webUiUrl;
|
|
@@ -39938,12 +40036,12 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
39938
40036
|
if (changedIds.length > 0) {
|
|
39939
40037
|
store.transaction(() => {
|
|
39940
40038
|
for (const nid of changedIds) {
|
|
39941
|
-
const
|
|
39942
|
-
if (!
|
|
39943
|
-
const history = store.nodeHistory(
|
|
40039
|
+
const live4 = store.getNode(nid);
|
|
40040
|
+
if (!live4) continue;
|
|
40041
|
+
const history = store.nodeHistory(live4.logicalId ?? nid);
|
|
39944
40042
|
const birth = history[0];
|
|
39945
40043
|
if (!birth || birth.id === nid) continue;
|
|
39946
|
-
const currentSim =
|
|
40044
|
+
const currentSim = live4.attrs["bodySimhash"];
|
|
39947
40045
|
const birthSim = birth.attrs["bodySimhash"];
|
|
39948
40046
|
if (!hasForkedDrift(currentSim, birthSim)) continue;
|
|
39949
40047
|
const forkId = edgeId(nid, "FORKED_FROM", birth.id);
|
|
@@ -48169,12 +48267,12 @@ function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
|
|
|
48169
48267
|
if (listed === null) return { reaped: 0, symbolsClosed: 0, skipped: "no-git-listing" };
|
|
48170
48268
|
if (listed.length === 0) return { reaped: 0, symbolsClosed: 0, skipped: "empty-listing" };
|
|
48171
48269
|
const onDisk = new Set(listed);
|
|
48172
|
-
const
|
|
48173
|
-
const orphans =
|
|
48270
|
+
const live4 = store.selectNodes({ labels: ["File"], attrs: ["workspaceId", "relPath"] }).filter((f) => f.attrs["workspaceId"] === workspaceId2);
|
|
48271
|
+
const orphans = live4.filter((f) => {
|
|
48174
48272
|
const rel = f.attrs["relPath"];
|
|
48175
48273
|
return typeof rel === "string" && !onDisk.has(rel);
|
|
48176
48274
|
});
|
|
48177
|
-
const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE,
|
|
48275
|
+
const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE, live4.length * ORPHAN_REAP_MAX_FRACTION);
|
|
48178
48276
|
if (orphans.length > allowance) {
|
|
48179
48277
|
return {
|
|
48180
48278
|
reaped: 0,
|
|
@@ -48559,17 +48657,17 @@ function searchEntries(query, matches) {
|
|
|
48559
48657
|
for (const { m, w } of code) put(m, w);
|
|
48560
48658
|
return [...seeds.values()].filter((sd) => sd.weight > 0);
|
|
48561
48659
|
}
|
|
48562
|
-
function withoutSymbolInternals(store,
|
|
48563
|
-
const ids = new Set(
|
|
48660
|
+
function withoutSymbolInternals(store, ranked2) {
|
|
48661
|
+
const ids = new Set(ranked2.map((r) => r.id));
|
|
48564
48662
|
const internal = /* @__PURE__ */ new Set();
|
|
48565
|
-
for (const r of
|
|
48663
|
+
for (const r of ranked2) {
|
|
48566
48664
|
for (const e of store.inEdges(r.id, ["DEFINES"])) {
|
|
48567
48665
|
if (!ids.has(e.from)) continue;
|
|
48568
48666
|
const parent = store.getNode(e.from);
|
|
48569
48667
|
if (parent && SYMBOL_PARENT_LABELS.has(parent.label)) internal.add(r.id);
|
|
48570
48668
|
}
|
|
48571
48669
|
}
|
|
48572
|
-
return internal.size > 0 ?
|
|
48670
|
+
return internal.size > 0 ? ranked2.filter((r) => !internal.has(r.id)) : ranked2;
|
|
48573
48671
|
}
|
|
48574
48672
|
function searchWalkEnabled(env2 = process.env) {
|
|
48575
48673
|
return !/^(0|off|false|no)$/i.test((env2["ERRATA_SEARCH_WALK"] ?? "").trim());
|
|
@@ -48584,11 +48682,11 @@ function searchGraphWalk(store, query, limit) {
|
|
|
48584
48682
|
burstFromSeeds(store, searchEntries(query, matches), { limit: limit * 4, typeRelevanceForSeeds: false })
|
|
48585
48683
|
);
|
|
48586
48684
|
const lanes = [walked.filter((r) => KNOWLEDGE_LABELS.has(r.node.label)), walked.filter((r) => !KNOWLEDGE_LABELS.has(r.node.label))];
|
|
48587
|
-
const
|
|
48588
|
-
for (let i2 = 0;
|
|
48589
|
-
for (const lane of lanes) if (lane[i2] &&
|
|
48685
|
+
const ranked2 = [];
|
|
48686
|
+
for (let i2 = 0; ranked2.length < limit && i2 < walked.length; i2++) {
|
|
48687
|
+
for (const lane of lanes) if (lane[i2] && ranked2.length < limit) ranked2.push(lane[i2]);
|
|
48590
48688
|
}
|
|
48591
|
-
return
|
|
48689
|
+
return ranked2.map((r) => {
|
|
48592
48690
|
const m = byId.get(r.id);
|
|
48593
48691
|
if (m) return { ...toSearchHit(m.node, m.via, m.rg), score: r.score, matched: true };
|
|
48594
48692
|
const rg = hitState(store, r.node);
|
|
@@ -48954,6 +49052,7 @@ var init_mcp = __esm({
|
|
|
48954
49052
|
init_identity2();
|
|
48955
49053
|
init_registry();
|
|
48956
49054
|
init_dual_augment();
|
|
49055
|
+
init_chain_complete();
|
|
48957
49056
|
init_one_search();
|
|
48958
49057
|
init_dual_burst();
|
|
48959
49058
|
init_twin_index();
|
|
@@ -49068,7 +49167,7 @@ var init_mcp = __esm({
|
|
|
49068
49167
|
limit
|
|
49069
49168
|
});
|
|
49070
49169
|
if (dual.status === "merged") {
|
|
49071
|
-
const
|
|
49170
|
+
const ranked2 = await rankHits(
|
|
49072
49171
|
store,
|
|
49073
49172
|
query,
|
|
49074
49173
|
dual.merged.nodes.map((n) => ({
|
|
@@ -49080,17 +49179,12 @@ var init_mcp = __esm({
|
|
|
49080
49179
|
})),
|
|
49081
49180
|
{ cloudEvidence: dual.cloudEvidence }
|
|
49082
49181
|
);
|
|
49083
|
-
const chosen = interleaveLanes(
|
|
49182
|
+
const chosen = interleaveLanes(ranked2, isKnowledge, limit);
|
|
49084
49183
|
const why = new Map(chosen.map((n) => [n.id, rankWhy(n.rank)]));
|
|
49085
49184
|
const formatted = formatDualNodes({ ...dual.merged, nodes: chosen.map(({ rank: _rank, viaText: _via, ...n }) => n) });
|
|
49086
|
-
|
|
49087
|
-
|
|
49088
|
-
|
|
49089
|
-
collectiveStatus: "merged",
|
|
49090
|
-
count: formatted.length,
|
|
49091
|
-
corroborated: dual.merged.corroboratedCount,
|
|
49092
|
-
collective: dual.merged.collectiveCount,
|
|
49093
|
-
results: withLinks(
|
|
49185
|
+
const results = withLinks(
|
|
49186
|
+
store,
|
|
49187
|
+
await completeChains(
|
|
49094
49188
|
store,
|
|
49095
49189
|
withCite(
|
|
49096
49190
|
formatted.map((r) => ({
|
|
@@ -49101,9 +49195,18 @@ var init_mcp = __esm({
|
|
|
49101
49195
|
isKnowledge
|
|
49102
49196
|
)
|
|
49103
49197
|
)
|
|
49198
|
+
);
|
|
49199
|
+
return {
|
|
49200
|
+
query,
|
|
49201
|
+
collectiveReachable: true,
|
|
49202
|
+
collectiveStatus: "merged",
|
|
49203
|
+
count: results.length,
|
|
49204
|
+
corroborated: dual.merged.corroboratedCount,
|
|
49205
|
+
collective: dual.merged.collectiveCount,
|
|
49206
|
+
results
|
|
49104
49207
|
};
|
|
49105
49208
|
}
|
|
49106
|
-
const local = withLinks(store, await rankLocal());
|
|
49209
|
+
const local = withLinks(store, await completeChains(store, await rankLocal()));
|
|
49107
49210
|
return {
|
|
49108
49211
|
query,
|
|
49109
49212
|
collectiveReachable: dual.status === "empty",
|
|
@@ -49113,7 +49216,7 @@ var init_mcp = __esm({
|
|
|
49113
49216
|
results: local
|
|
49114
49217
|
};
|
|
49115
49218
|
}
|
|
49116
|
-
return withLinks(store, await rankLocal());
|
|
49219
|
+
return withLinks(store, await completeChains(store, await rankLocal()));
|
|
49117
49220
|
}
|
|
49118
49221
|
},
|
|
49119
49222
|
{
|
|
@@ -49263,7 +49366,7 @@ var init_mcp = __esm({
|
|
|
49263
49366
|
if (seedForBurst && seedForBurst.embedding.length === 0) {
|
|
49264
49367
|
await ensureNodeEmbedded(store, id);
|
|
49265
49368
|
}
|
|
49266
|
-
const
|
|
49369
|
+
const ranked2 = localBurst(store, id, {
|
|
49267
49370
|
// Hold an embeddingless candidate's neutral semantic under the dual-burst
|
|
49268
49371
|
// cloud cap so unknown local code can't outrank the capped collective (see
|
|
49269
49372
|
// DUAL_BURST_SEMANTIC_NEUTRAL). No-op for local-only bursts.
|
|
@@ -49271,7 +49374,7 @@ var init_mcp = __esm({
|
|
|
49271
49374
|
...args2["maxHops"] != null ? { maxHops: Number(args2["maxHops"]) } : {},
|
|
49272
49375
|
...args2["limit"] != null ? { limit: Number(args2["limit"]) } : {}
|
|
49273
49376
|
});
|
|
49274
|
-
const localHits =
|
|
49377
|
+
const localHits = ranked2.map((r) => ({
|
|
49275
49378
|
id: r.id,
|
|
49276
49379
|
node: { label: r.node.label, description: r.node.description },
|
|
49277
49380
|
score: r.score,
|
|
@@ -49504,8 +49607,8 @@ var init_mcp = __esm({
|
|
|
49504
49607
|
if (!ex || node2.hops < ex.hops) merged.set(node2.id, node2);
|
|
49505
49608
|
}
|
|
49506
49609
|
}
|
|
49507
|
-
const
|
|
49508
|
-
return { found: true, seedId: id, nodes:
|
|
49610
|
+
const ranked2 = [...merged.values()].sort((a, b) => b.relevance - a.relevance);
|
|
49611
|
+
return { found: true, seedId: id, nodes: ranked2.slice(0, limit), truncated: ranked2.length > limit };
|
|
49509
49612
|
}
|
|
49510
49613
|
},
|
|
49511
49614
|
{
|
|
@@ -49766,8 +49869,8 @@ var init_mcp = __esm({
|
|
|
49766
49869
|
};
|
|
49767
49870
|
}
|
|
49768
49871
|
const fanIn = store.inDegreeByType([...CODE_REACH_EDGES]);
|
|
49769
|
-
const
|
|
49770
|
-
return { kind: "fan-in", items:
|
|
49872
|
+
const ranked2 = store.selectNodes({ labels: CODE }).map((n) => ({ id: n.id, label: n.label, name: n.description, fanIn: fanIn.get(n.id) ?? 0 })).sort((a, b) => b.fanIn - a.fanIn).slice(0, limit);
|
|
49873
|
+
return { kind: "fan-in", items: ranked2 };
|
|
49771
49874
|
}
|
|
49772
49875
|
},
|
|
49773
49876
|
{
|
|
@@ -50290,8 +50393,8 @@ function formatBurstMd(r, opts) {
|
|
|
50290
50393
|
lines.push("legend: \u25A3 local \xB7 \u25CC collective \xB7 \u2713 corroborated");
|
|
50291
50394
|
lines.push("");
|
|
50292
50395
|
lines.push(`## neighborhood (${r.results.length})`);
|
|
50293
|
-
const
|
|
50294
|
-
for (const n of
|
|
50396
|
+
const ranked2 = [...r.results].sort((a, b) => b.score - a.score);
|
|
50397
|
+
for (const n of ranked2) {
|
|
50295
50398
|
const usage = n.usageCount != null ? ` \xB7 ${n.usageCount} proj` : "";
|
|
50296
50399
|
const rel = n.rel ? ` \xB7 ${n.rel}` : "";
|
|
50297
50400
|
lines.push(
|
|
@@ -58292,8 +58395,8 @@ function fileRecall(store, relPath) {
|
|
|
58292
58395
|
const priors = priorsForFile(store, relPath);
|
|
58293
58396
|
if (!priors) return null;
|
|
58294
58397
|
const pool = [...priors.openProblems, ...priors.constraints, ...priors.related];
|
|
58295
|
-
const
|
|
58296
|
-
const rank = new Map(
|
|
58398
|
+
const ranked2 = rankByRelevance(store, priors.file.id, pool.map((n) => n.id));
|
|
58399
|
+
const rank = new Map(ranked2.map((r, i2) => [r.id, i2]));
|
|
58297
58400
|
const byRank = (a, b) => (rank.get(a.id) ?? 0) - (rank.get(b.id) ?? 0);
|
|
58298
58401
|
priors.openProblems.sort(byRank);
|
|
58299
58402
|
priors.constraints.sort(byRank);
|
|
@@ -58329,8 +58432,8 @@ ${lines.join("\n")}
|
|
|
58329
58432
|
function editVerdict(store, relPath) {
|
|
58330
58433
|
const priors = priorsForFile(store, relPath);
|
|
58331
58434
|
if (!priors || priors.openProblems.length === 0) return null;
|
|
58332
|
-
const
|
|
58333
|
-
const rank = new Map(
|
|
58435
|
+
const ranked2 = rankByRelevance(store, priors.file.id, priors.openProblems.map((n) => n.id));
|
|
58436
|
+
const rank = new Map(ranked2.map((r, i2) => [r.id, i2]));
|
|
58334
58437
|
const asked = [...priors.openProblems].sort((a, b) => (rank.get(a.id) ?? 0) - (rank.get(b.id) ?? 0)).slice(0, 3);
|
|
58335
58438
|
const lines = asked.map(
|
|
58336
58439
|
(p) => closableByCaller(p) ? recallLine(p, `fixed: ${TAG_EXAMPLE.fix(p.id)} \xB7 not a real problem: retract it (block below) \xB7 still open: say nothing`) : recallLine(p, `another membrane's \u2014 not yours to close: ${TAG_EXAMPLE.confirm(p.id)} it held \xB7 ${TAG_EXAMPLE.refute(p.id)}`)
|
|
@@ -78129,11 +78232,11 @@ function isLive2(verb) {
|
|
|
78129
78232
|
function nextHtml(n, opts) {
|
|
78130
78233
|
if (!n) return "";
|
|
78131
78234
|
const cmd2 = `errata ${n.verb}${n.arg ? " " + n.arg : ""}`;
|
|
78132
|
-
const
|
|
78133
|
-
if (!
|
|
78235
|
+
const live4 = isLive2(n.verb);
|
|
78236
|
+
if (!live4 && !opts.includeFutureVerbs) return "";
|
|
78134
78237
|
const hint = n.hint ? ` \u2014 ${esc3(n.hint)}` : "";
|
|
78135
|
-
const cls =
|
|
78136
|
-
const tag =
|
|
78238
|
+
const cls = live4 ? "next" : "next soon";
|
|
78239
|
+
const tag = live4 ? `<code>${esc3(cmd2)}</code>` : `<span class="vsoon">${esc3(cmd2)} \xB7 soon</span>`;
|
|
78137
78240
|
return `<div class="${cls}">next: ${tag}${hint}</div>`;
|
|
78138
78241
|
}
|
|
78139
78242
|
function shell(title, body2) {
|
|
@@ -78498,7 +78601,7 @@ var init_report_render = __esm({
|
|
|
78498
78601
|
|
|
78499
78602
|
// src/cli.ts
|
|
78500
78603
|
init_src6();
|
|
78501
|
-
import { closeSync as closeSync3, existsSync as existsSync41, openSync as openSync3, readFileSync as readFileSync49, renameSync as renameSync10, statSync as statSync17 } from "node:fs";
|
|
78604
|
+
import { closeSync as closeSync3, existsSync as existsSync41, openSync as openSync3, readFileSync as readFileSync49, renameSync as renameSync10, statSync as statSync17, writeFileSync as writeFileSync34 } from "node:fs";
|
|
78502
78605
|
import { join as join57, resolve as pathResolve2 } from "node:path";
|
|
78503
78606
|
import { spawn as spawn5 } from "node:child_process";
|
|
78504
78607
|
|
|
@@ -81442,8 +81545,8 @@ function createSubagentState() {
|
|
|
81442
81545
|
for (const [id, a] of agents) if (nowMs - a.lastSeenMs > SUBAGENT_IDLE_TTL_MS) agents.delete(id);
|
|
81443
81546
|
while (agents.size > MAX_AGENTS) agents.delete(agents.keys().next().value);
|
|
81444
81547
|
for (const [sid, list] of pending) {
|
|
81445
|
-
const
|
|
81446
|
-
if (
|
|
81548
|
+
const live4 = list.filter((s) => nowMs - s.atMs <= SPAWN_CLAIM_TTL_MS);
|
|
81549
|
+
if (live4.length) pending.set(sid, live4);
|
|
81447
81550
|
else pending.delete(sid);
|
|
81448
81551
|
}
|
|
81449
81552
|
};
|
|
@@ -81525,12 +81628,12 @@ function walkIntent(store, intent, opts) {
|
|
|
81525
81628
|
if (out2.length >= opts.limit) return out2;
|
|
81526
81629
|
const shown = new Set(out2.map((h) => h.node.id));
|
|
81527
81630
|
const seedIds = new Set(entries.map((h) => h.node.id));
|
|
81528
|
-
const
|
|
81631
|
+
const ranked2 = burstFromSeeds(
|
|
81529
81632
|
store,
|
|
81530
81633
|
entries.map((h) => ({ id: h.node.id, label: h.node.label, weight: h.coverage * h.coverage })),
|
|
81531
81634
|
{ limit: opts.limit * 10, typeRelevanceForSeeds: false }
|
|
81532
81635
|
);
|
|
81533
|
-
for (const r of
|
|
81636
|
+
for (const r of ranked2) {
|
|
81534
81637
|
if (out2.length >= opts.limit) break;
|
|
81535
81638
|
if (shown.has(r.id) || seedIds.has(r.id)) continue;
|
|
81536
81639
|
const n = r.node;
|
|
@@ -84008,19 +84111,19 @@ import { appendFileSync as appendFileSync2, existsSync as existsSync23, readFile
|
|
|
84008
84111
|
import { join as join27 } from "node:path";
|
|
84009
84112
|
|
|
84010
84113
|
// src/isolate-census.ts
|
|
84011
|
-
var
|
|
84114
|
+
var live3 = 0;
|
|
84012
84115
|
var spawnedTotal = 0;
|
|
84013
84116
|
var peak = 0;
|
|
84014
84117
|
function noteIsolateSpawned() {
|
|
84015
|
-
|
|
84118
|
+
live3 += 1;
|
|
84016
84119
|
spawnedTotal += 1;
|
|
84017
|
-
if (
|
|
84120
|
+
if (live3 > peak) peak = live3;
|
|
84018
84121
|
}
|
|
84019
84122
|
function noteIsolateExited() {
|
|
84020
|
-
if (
|
|
84123
|
+
if (live3 > 0) live3 -= 1;
|
|
84021
84124
|
}
|
|
84022
84125
|
function isolateCensus() {
|
|
84023
|
-
return { live:
|
|
84126
|
+
return { live: live3, spawnedTotal, peak };
|
|
84024
84127
|
}
|
|
84025
84128
|
|
|
84026
84129
|
// src/io-reads.ts
|
|
@@ -84245,8 +84348,8 @@ function recordEpisode(store, workspaceId2, t, delta, causal) {
|
|
|
84245
84348
|
minted++;
|
|
84246
84349
|
}
|
|
84247
84350
|
if (s.change === "changed") {
|
|
84248
|
-
const
|
|
84249
|
-
const prev = (
|
|
84351
|
+
const live4 = store.getNode(s.nodeId);
|
|
84352
|
+
const prev = (live4?.version ?? 2) - 1;
|
|
84250
84353
|
const frozenId = `${s.nodeId}@v${prev}`;
|
|
84251
84354
|
if (store.getNode(frozenId)) {
|
|
84252
84355
|
store.mergeEdge(producedEdge(id, frozenId, t));
|
|
@@ -87399,7 +87502,7 @@ var INTENT_TTL_MS = 15 * 60 * 1e3;
|
|
|
87399
87502
|
function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
87400
87503
|
const bySession = /* @__PURE__ */ new Map();
|
|
87401
87504
|
let recent4 = null;
|
|
87402
|
-
const
|
|
87505
|
+
const live4 = (s, nowMs) => s !== void 0 && nowMs - s.atMs < ttlMs;
|
|
87403
87506
|
return {
|
|
87404
87507
|
set(sessionId, text, nowMs) {
|
|
87405
87508
|
const trimmed = text.trim();
|
|
@@ -87413,7 +87516,7 @@ function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
|
87413
87516
|
},
|
|
87414
87517
|
get(sessionId, nowMs) {
|
|
87415
87518
|
const s = bySession.get(sessionId);
|
|
87416
|
-
return
|
|
87519
|
+
return live4(s, nowMs) ? s.text : void 0;
|
|
87417
87520
|
},
|
|
87418
87521
|
mostRecent(nowMs) {
|
|
87419
87522
|
if (!recent4) return void 0;
|
|
@@ -87515,17 +87618,17 @@ function saveWitnessQueue(path3, queue) {
|
|
|
87515
87618
|
}
|
|
87516
87619
|
function pruneWitnessQueueWithDispositions(queue, now) {
|
|
87517
87620
|
const dropped = { expiredTtl: 0, exhaustedAttempts: 0, cappedOverflow: 0 };
|
|
87518
|
-
const
|
|
87621
|
+
const live4 = [];
|
|
87519
87622
|
for (const w of queue) {
|
|
87520
87623
|
if (now - w.ts >= WITNESS_TTL_MS) dropped.expiredTtl++;
|
|
87521
87624
|
else if (w.attempts >= WITNESS_MAX_ATTEMPTS) dropped.exhaustedAttempts++;
|
|
87522
|
-
else
|
|
87625
|
+
else live4.push(w);
|
|
87523
87626
|
}
|
|
87524
|
-
if (
|
|
87525
|
-
dropped.cappedOverflow =
|
|
87526
|
-
return { queue:
|
|
87627
|
+
if (live4.length > WITNESS_QUEUE_CAP) {
|
|
87628
|
+
dropped.cappedOverflow = live4.length - WITNESS_QUEUE_CAP;
|
|
87629
|
+
return { queue: live4.slice(live4.length - WITNESS_QUEUE_CAP), dropped };
|
|
87527
87630
|
}
|
|
87528
|
-
return { queue:
|
|
87631
|
+
return { queue: live4, dropped };
|
|
87529
87632
|
}
|
|
87530
87633
|
function enqueueWitnessesWithDispositions(queue, fresh, now) {
|
|
87531
87634
|
const byKey = new Map(queue.map((w) => [`${w.channel}:${w.witnessKey}`, w]));
|
|
@@ -88218,7 +88321,7 @@ function createWatchBreaker(deps) {
|
|
|
88218
88321
|
}
|
|
88219
88322
|
|
|
88220
88323
|
// src/engine.ts
|
|
88221
|
-
var DAEMON_VERSION = true ? "2.0.23-dev.
|
|
88324
|
+
var DAEMON_VERSION = true ? "2.0.23-dev.4881" : "2.0.0-alpha.0";
|
|
88222
88325
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
88223
88326
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
88224
88327
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -91601,16 +91704,16 @@ function settleEdgeOutcomes(queue, sent, verdicts, now) {
|
|
|
91601
91704
|
if (prior?.state === "parked") counts.edgesReparked++;
|
|
91602
91705
|
else counts.edgesParked++;
|
|
91603
91706
|
}
|
|
91604
|
-
const
|
|
91707
|
+
const live4 = [];
|
|
91605
91708
|
for (const e of byKey.values()) {
|
|
91606
91709
|
if (e.state === "parked" && now - e.ts >= EDGE_PARK_TTL_MS) {
|
|
91607
91710
|
counts.edgesDroppedExpired++;
|
|
91608
91711
|
continue;
|
|
91609
91712
|
}
|
|
91610
91713
|
if (e.state === "dropped" && now - (e.droppedAt ?? e.ts) >= tombstoneTtl(e)) continue;
|
|
91611
|
-
|
|
91714
|
+
live4.push(e);
|
|
91612
91715
|
}
|
|
91613
|
-
let next =
|
|
91716
|
+
let next = live4;
|
|
91614
91717
|
if (next.length > EDGE_PARK_CAP) {
|
|
91615
91718
|
const over = next.length - EDGE_PARK_CAP;
|
|
91616
91719
|
const order = [...next].sort((a, b) => (a.state === b.state ? 0 : a.state === "dropped" ? -1 : 1) || a.ts - b.ts);
|
|
@@ -91860,8 +91963,8 @@ function mintPackageGraph(store, sbom, workspaceId2, ts) {
|
|
|
91860
91963
|
for (const to of d.dependsOn) {
|
|
91861
91964
|
if (!minted.has(to)) continue;
|
|
91862
91965
|
const id = `edge_${digest({ from: d.ref, type: "DEPENDS_ON", to })}`.slice(0, 24);
|
|
91863
|
-
const
|
|
91864
|
-
if (
|
|
91966
|
+
const live4 = store.getEdge(id);
|
|
91967
|
+
if (live4 && (live4.validTo ?? null) === null) {
|
|
91865
91968
|
edges++;
|
|
91866
91969
|
continue;
|
|
91867
91970
|
}
|
|
@@ -92794,8 +92897,8 @@ function cloudWireId(n) {
|
|
|
92794
92897
|
function buildCausalEdgeBackfill(store, profile, daemonVersion) {
|
|
92795
92898
|
const edges = [];
|
|
92796
92899
|
const seenEdge = /* @__PURE__ */ new Set();
|
|
92797
|
-
const
|
|
92798
|
-
const byId = new Map(
|
|
92900
|
+
const live4 = store.selectNodes({ labels: CAUSAL_LABELS, attrs: WIRE_ATTRS });
|
|
92901
|
+
const byId = new Map(live4.map((n) => [n.id, n]));
|
|
92799
92902
|
const wireIds = /* @__PURE__ */ new Map();
|
|
92800
92903
|
const wireIdOf = (id) => {
|
|
92801
92904
|
if (wireIds.has(id)) return wireIds.get(id);
|
|
@@ -92803,7 +92906,7 @@ function buildCausalEdgeBackfill(store, profile, daemonVersion) {
|
|
|
92803
92906
|
wireIds.set(id, w);
|
|
92804
92907
|
return w;
|
|
92805
92908
|
};
|
|
92806
|
-
for (const n of
|
|
92909
|
+
for (const n of live4) {
|
|
92807
92910
|
for (const e of store.outEdges(n.id, [...CAUSAL_EDGES2])) {
|
|
92808
92911
|
if (seenEdge.has(e.id)) continue;
|
|
92809
92912
|
seenEdge.add(e.id);
|
|
@@ -93296,15 +93399,20 @@ async function runInstalledHookRefresh() {
|
|
|
93296
93399
|
child.on("close", (code) => resolve11(code === 0 ? output.trim() : ""));
|
|
93297
93400
|
});
|
|
93298
93401
|
if (!isAbsolute6(root)) return 1;
|
|
93299
|
-
|
|
93300
|
-
|
|
93301
|
-
|
|
93302
|
-
|
|
93303
|
-
|
|
93402
|
+
let worst = 0;
|
|
93403
|
+
for (const harness of ["codex", "claude"]) {
|
|
93404
|
+
const code = await new Promise((resolve11) => {
|
|
93405
|
+
const child = spawn2(process.execPath, [join42(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", harness, "--refresh-existing"], {
|
|
93406
|
+
windowsHide: true,
|
|
93407
|
+
stdio: "inherit",
|
|
93408
|
+
timeout: 3e4
|
|
93409
|
+
});
|
|
93410
|
+
child.on("error", () => resolve11(1));
|
|
93411
|
+
child.on("close", (exit) => resolve11(exit ?? 1));
|
|
93304
93412
|
});
|
|
93305
|
-
|
|
93306
|
-
|
|
93307
|
-
|
|
93413
|
+
worst = Math.max(worst, code);
|
|
93414
|
+
}
|
|
93415
|
+
return worst;
|
|
93308
93416
|
}
|
|
93309
93417
|
|
|
93310
93418
|
// src/multi.ts
|
|
@@ -93474,9 +93582,9 @@ function saveCausalEdgeQueue(path3, queue) {
|
|
|
93474
93582
|
}
|
|
93475
93583
|
}
|
|
93476
93584
|
function pruneCausalEdgeQueue(queue, now) {
|
|
93477
|
-
const
|
|
93478
|
-
if (
|
|
93479
|
-
return [...
|
|
93585
|
+
const live4 = queue.filter((p) => now - p.ts < CAUSAL_EDGE_TTL_MS);
|
|
93586
|
+
if (live4.length <= CAUSAL_EDGE_QUEUE_CAP) return live4;
|
|
93587
|
+
return [...live4].sort((a, b) => a.ts - b.ts).slice(live4.length - CAUSAL_EDGE_QUEUE_CAP);
|
|
93480
93588
|
}
|
|
93481
93589
|
|
|
93482
93590
|
// src/project-reanchor.ts
|
|
@@ -94731,7 +94839,7 @@ function narrativeSources(unit, group) {
|
|
|
94731
94839
|
if (!group || group.length === 0) return [{ commitSha: unit.sha, text: message(unit).trim() }].filter((s) => s.text.length > 0);
|
|
94732
94840
|
const members = group.filter((g) => g.groupSha === (unit.groupSha ?? unit.sha)).sort((a, b) => a.subIndex - b.subIndex);
|
|
94733
94841
|
const source = members.length > 0 ? members : [...group].sort((a, b) => a.subIndex - b.subIndex);
|
|
94734
|
-
return source.map((
|
|
94842
|
+
return source.map((member2) => ({ commitSha: member2.sha, text: message(member2).trim() })).filter((s) => s.text.length > 0);
|
|
94735
94843
|
}
|
|
94736
94844
|
|
|
94737
94845
|
// src/git-batch.ts
|
|
@@ -96408,8 +96516,8 @@ function misfiledTarget(roots, home) {
|
|
|
96408
96516
|
if (roots.includes(home)) return null;
|
|
96409
96517
|
const tally = /* @__PURE__ */ new Map();
|
|
96410
96518
|
for (const r of roots) tally.set(r, (tally.get(r) ?? 0) + 1);
|
|
96411
|
-
const
|
|
96412
|
-
const [top, next] =
|
|
96519
|
+
const ranked2 = [...tally].sort((a, b) => b[1] - a[1]);
|
|
96520
|
+
const [top, next] = ranked2;
|
|
96413
96521
|
if (!top || top[1] < FOCUS_QUORUM || next && next[1] === top[1]) return null;
|
|
96414
96522
|
return top[0];
|
|
96415
96523
|
}
|
|
@@ -99560,6 +99668,50 @@ function installedHookPort(settingsText) {
|
|
|
99560
99668
|
}
|
|
99561
99669
|
return null;
|
|
99562
99670
|
}
|
|
99671
|
+
var ERRATA_HOOK_TAG = "# errata-managed";
|
|
99672
|
+
function claudeErrataHookGroups(port) {
|
|
99673
|
+
const matcher = "Read|Edit|Write|Grep|Glob|NotebookEdit|Bash";
|
|
99674
|
+
const postMatcher = `${matcher}|ToolSearch|mcp__errata__.*`;
|
|
99675
|
+
const preMatcher = `${matcher}|Agent|Task`;
|
|
99676
|
+
const command = (cmd2) => [{ type: "command", command: `${cmd2} ${ERRATA_HOOK_TAG}` }];
|
|
99677
|
+
const toolHook = command(hookRelayCommand(port, "/api/hook"));
|
|
99678
|
+
const turn = command(hookCurlCommand(port, "/api/turn"));
|
|
99679
|
+
const inject = command(hookRelayCommand(port, "/api/context-inject"));
|
|
99680
|
+
return {
|
|
99681
|
+
PreToolUse: { matcher: preMatcher, hooks: toolHook },
|
|
99682
|
+
PostToolUse: { matcher: postMatcher, hooks: toolHook },
|
|
99683
|
+
PostToolUseFailure: { matcher: postMatcher, hooks: toolHook },
|
|
99684
|
+
Stop: { hooks: turn },
|
|
99685
|
+
SubagentStop: { hooks: turn },
|
|
99686
|
+
// The assistant's prose delivered LIVE by the harness: the transcript jsonl
|
|
99687
|
+
// drops mid-turn assistant text (anthropics/claude-code#21751), so this is the
|
|
99688
|
+
// reliable channel for inline tags and /api/turn is the backfill.
|
|
99689
|
+
MessageDisplay: { hooks: command(hookCurlCommand(port, "/api/message")) },
|
|
99690
|
+
// The gated end-of-session roll-up (P3).
|
|
99691
|
+
SessionEnd: { hooks: command(hookCurlCommand(port, "/api/session-end")) },
|
|
99692
|
+
SessionStart: { hooks: inject },
|
|
99693
|
+
UserPromptSubmit: { hooks: inject },
|
|
99694
|
+
SubagentStart: { hooks: inject }
|
|
99695
|
+
};
|
|
99696
|
+
}
|
|
99697
|
+
function applyClaudeErrataHooks(settings, port) {
|
|
99698
|
+
settings.hooks ??= {};
|
|
99699
|
+
for (const [event, group] of Object.entries(claudeErrataHookGroups(port))) {
|
|
99700
|
+
const list = settings.hooks[event] ??= [];
|
|
99701
|
+
for (let i2 = list.length - 1; i2 >= 0; i2--) {
|
|
99702
|
+
if (list[i2].hooks?.some((h) => typeof h.command === "string" && h.command.includes(ERRATA_HOOK_TAG))) list.splice(i2, 1);
|
|
99703
|
+
}
|
|
99704
|
+
list.push(group);
|
|
99705
|
+
}
|
|
99706
|
+
}
|
|
99707
|
+
function refreshClaudeHookSettings(text) {
|
|
99708
|
+
const port = installedHookPort(text);
|
|
99709
|
+
if (port === null) return null;
|
|
99710
|
+
const settings = JSON.parse(text);
|
|
99711
|
+
applyClaudeErrataHooks(settings, port);
|
|
99712
|
+
const next = JSON.stringify(settings, null, 2) + "\n";
|
|
99713
|
+
return next === text.replace(/\r\n/g, "\n") ? null : next;
|
|
99714
|
+
}
|
|
99563
99715
|
|
|
99564
99716
|
// src/codex-hook-relay.ts
|
|
99565
99717
|
var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
|
|
@@ -101496,6 +101648,7 @@ async function cmdNotifyTest() {
|
|
|
101496
101648
|
}
|
|
101497
101649
|
async function cmdStart() {
|
|
101498
101650
|
refreshExistingCodexHooks();
|
|
101651
|
+
refreshExistingClaudeHooks();
|
|
101499
101652
|
if (!loadProfile(ROOT)) {
|
|
101500
101653
|
const cfg = loadConfig();
|
|
101501
101654
|
const locator = detectRepoLocator(ROOT);
|
|
@@ -101973,7 +102126,7 @@ async function cmdUpdate(args2) {
|
|
|
101973
102126
|
const code = await runNpmInstall(channel);
|
|
101974
102127
|
if (code === 0) {
|
|
101975
102128
|
if (await runInstalledHookRefresh() !== 0) {
|
|
101976
|
-
console.warn("[!] Package updated, but some
|
|
102129
|
+
console.warn("[!] Package updated, but some existing hooks could not be refreshed. Run `errata install-hooks codex --refresh-existing` and `errata install-hooks claude --refresh-existing`; daemon startup also retries.");
|
|
101977
102130
|
}
|
|
101978
102131
|
console.log(`
|
|
101979
102132
|
[OK] updated to ${status.latest}. Restart the daemon to run it:`);
|
|
@@ -103265,9 +103418,9 @@ async function gatherRepo(store, ws) {
|
|
|
103265
103418
|
}
|
|
103266
103419
|
let hotspots;
|
|
103267
103420
|
if (byFile.size > 0) {
|
|
103268
|
-
const
|
|
103269
|
-
const maxC =
|
|
103270
|
-
hotspots =
|
|
103421
|
+
const ranked2 = [...byFile].sort((a, b) => b[1] - a[1]).slice(0, 6);
|
|
103422
|
+
const maxC = ranked2[0]?.[1] ?? 1;
|
|
103423
|
+
hotspots = ranked2.map(([file2, c]) => ({
|
|
103271
103424
|
file: file2.split(/[\\/]/).pop() ?? file2,
|
|
103272
103425
|
problemCount: c,
|
|
103273
103426
|
weight: c / maxC,
|
|
@@ -103356,7 +103509,7 @@ async function gatherReportData(generatedAt) {
|
|
|
103356
103509
|
};
|
|
103357
103510
|
}
|
|
103358
103511
|
async function cmdReport(args2) {
|
|
103359
|
-
const { mkdirSync: mkdirSync13, writeFileSync:
|
|
103512
|
+
const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync35 } = await import("node:fs");
|
|
103360
103513
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
103361
103514
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
103362
103515
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -103369,7 +103522,7 @@ async function cmdReport(args2) {
|
|
|
103369
103522
|
const outDir = workspacePaths(ROOT).configDir;
|
|
103370
103523
|
mkdirSync13(outDir, { recursive: true });
|
|
103371
103524
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
103372
|
-
for (const f of files)
|
|
103525
|
+
for (const f of files) writeFileSync35(join57(outDir, f.name), f.html, "utf8");
|
|
103373
103526
|
const indexPath = join57(outDir, "report.html");
|
|
103374
103527
|
console.log(`report \u2192 ${indexPath}`);
|
|
103375
103528
|
console.log(
|
|
@@ -103470,6 +103623,10 @@ async function cmdInstallHooks(args2) {
|
|
|
103470
103623
|
const port = resolveHookPort(portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : void 0);
|
|
103471
103624
|
switch (harness) {
|
|
103472
103625
|
case "claude":
|
|
103626
|
+
if (args2.includes("--refresh-existing")) {
|
|
103627
|
+
if (!refreshExistingClaudeHooks()) process.exitCode = 1;
|
|
103628
|
+
return;
|
|
103629
|
+
}
|
|
103473
103630
|
await installClaudeHooks(port);
|
|
103474
103631
|
return;
|
|
103475
103632
|
case "cursor":
|
|
@@ -103495,7 +103652,7 @@ async function cmdInstallHooks(args2) {
|
|
|
103495
103652
|
}
|
|
103496
103653
|
}
|
|
103497
103654
|
async function installOpencodePlugin(port) {
|
|
103498
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync:
|
|
103655
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync: writeFileSync35 } = await import("node:fs");
|
|
103499
103656
|
const { join: join58 } = await import("node:path");
|
|
103500
103657
|
const dir = join58(ROOT, ".opencode", "plugin");
|
|
103501
103658
|
if (!existsSync42(dir)) mkdirSync13(dir, { recursive: true });
|
|
@@ -103507,7 +103664,7 @@ async function installOpencodePlugin(port) {
|
|
|
103507
103664
|
process.exit(2);
|
|
103508
103665
|
}
|
|
103509
103666
|
}
|
|
103510
|
-
|
|
103667
|
+
writeFileSync35(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
103511
103668
|
const cfgFile = join58(ROOT, "opencode.json");
|
|
103512
103669
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
103513
103670
|
if (existsSync42(cfgFile)) {
|
|
@@ -103523,7 +103680,7 @@ async function installOpencodePlugin(port) {
|
|
|
103523
103680
|
if (!hadErrata) {
|
|
103524
103681
|
const inv = errataMcpInvocation();
|
|
103525
103682
|
cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
|
|
103526
|
-
|
|
103683
|
+
writeFileSync35(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
103527
103684
|
}
|
|
103528
103685
|
console.log(`installed OpenCode plugin \u2192 ${file2}`);
|
|
103529
103686
|
if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
|
|
@@ -103537,7 +103694,6 @@ async function installOpencodePlugin(port) {
|
|
|
103537
103694
|
console.log(` Cloud tools (search/contribute) are the MCP entry in opencode.json:`);
|
|
103538
103695
|
console.log(` { "mcp": { "inerrata": { "type": "remote", "url": "${mcpUrlFor(loadConfig().cloudUrl)}", "headers": { "Authorization": "Bearer <errk_\u2026>" } } } }`);
|
|
103539
103696
|
}
|
|
103540
|
-
var ERRATA_TAG = "# errata-managed";
|
|
103541
103697
|
function errataMcpInvocation() {
|
|
103542
103698
|
const { cmd: cmd2, args: args2 } = selfArgv("mcp");
|
|
103543
103699
|
return { command: cmd2, args: args2 };
|
|
@@ -103558,7 +103714,7 @@ function installClaudeMods() {
|
|
|
103558
103714
|
}
|
|
103559
103715
|
}
|
|
103560
103716
|
async function installClaudeHooks(port) {
|
|
103561
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync:
|
|
103717
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync: writeFileSync35 } = await import("node:fs");
|
|
103562
103718
|
const { join: join58 } = await import("node:path");
|
|
103563
103719
|
const dir = join58(ROOT, ".claude");
|
|
103564
103720
|
if (!existsSync42(dir)) mkdirSync13(dir, { recursive: true });
|
|
@@ -103572,50 +103728,9 @@ async function installClaudeHooks(port) {
|
|
|
103572
103728
|
process.exit(2);
|
|
103573
103729
|
}
|
|
103574
103730
|
}
|
|
103575
|
-
|
|
103576
|
-
const postMatcher = `${matcher}|ToolSearch|mcp__errata__.*`;
|
|
103577
|
-
const preMatcher = `${matcher}|Agent|Task`;
|
|
103578
|
-
const preCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
|
|
103579
|
-
const postCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
|
|
103580
|
-
settings.hooks ??= {};
|
|
103581
|
-
const dropErrata = (list) => {
|
|
103582
|
-
for (let i2 = list.length - 1; i2 >= 0; i2--) {
|
|
103583
|
-
if (list[i2].hooks.some((h) => h.command.includes(ERRATA_TAG))) list.splice(i2, 1);
|
|
103584
|
-
}
|
|
103585
|
-
};
|
|
103586
|
-
for (const [event, command, eventMatcher] of [
|
|
103587
|
-
["PreToolUse", preCmd, preMatcher],
|
|
103588
|
-
["PostToolUse", postCmd, postMatcher],
|
|
103589
|
-
["PostToolUseFailure", postCmd, postMatcher]
|
|
103590
|
-
]) {
|
|
103591
|
-
const list = settings.hooks[event] ??= [];
|
|
103592
|
-
dropErrata(list);
|
|
103593
|
-
list.push({ matcher: eventMatcher, hooks: [{ type: "command", command }] });
|
|
103594
|
-
}
|
|
103595
|
-
const turnCmd = `${hookCurlCommand(port, "/api/turn")} ${ERRATA_TAG}`;
|
|
103596
|
-
for (const event of ["Stop", "SubagentStop"]) {
|
|
103597
|
-
const list = settings.hooks[event] ??= [];
|
|
103598
|
-
dropErrata(list);
|
|
103599
|
-
list.push({ hooks: [{ type: "command", command: turnCmd }] });
|
|
103600
|
-
}
|
|
103601
|
-
const msgCmd = `${hookCurlCommand(port, "/api/message")} ${ERRATA_TAG}`;
|
|
103602
|
-
{
|
|
103603
|
-
const list = settings.hooks["MessageDisplay"] ??= [];
|
|
103604
|
-
dropErrata(list);
|
|
103605
|
-
list.push({ hooks: [{ type: "command", command: msgCmd }] });
|
|
103606
|
-
}
|
|
103607
|
-
const endCmd = `${hookCurlCommand(port, "/api/session-end")} ${ERRATA_TAG}`;
|
|
103608
|
-
const endList = settings.hooks["SessionEnd"] ??= [];
|
|
103609
|
-
dropErrata(endList);
|
|
103610
|
-
endList.push({ hooks: [{ type: "command", command: endCmd }] });
|
|
103611
|
-
const injectCmd = `${hookRelayCommand(port, "/api/context-inject")} ${ERRATA_TAG}`;
|
|
103612
|
-
for (const event of ["SessionStart", "UserPromptSubmit", "SubagentStart"]) {
|
|
103613
|
-
const list = settings.hooks[event] ??= [];
|
|
103614
|
-
dropErrata(list);
|
|
103615
|
-
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
103616
|
-
}
|
|
103731
|
+
applyClaudeErrataHooks(settings, port);
|
|
103617
103732
|
removeProjectStatusLine(settings);
|
|
103618
|
-
|
|
103733
|
+
writeFileSync35(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
103619
103734
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
103620
103735
|
console.log(` ${ensureStatusLine(port)}`);
|
|
103621
103736
|
console.log(` ${installClaudeMods().line}`);
|
|
@@ -103632,7 +103747,7 @@ async function installClaudeHooks(port) {
|
|
|
103632
103747
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
103633
103748
|
}
|
|
103634
103749
|
async function installClaudeMcpConfig() {
|
|
103635
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync:
|
|
103750
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync: writeFileSync35 } = await import("node:fs");
|
|
103636
103751
|
const { join: join58, dirname: dirname22 } = await import("node:path");
|
|
103637
103752
|
const file2 = join58(ROOT, ".mcp.json");
|
|
103638
103753
|
const dir = dirname22(file2);
|
|
@@ -103648,13 +103763,13 @@ async function installClaudeMcpConfig() {
|
|
|
103648
103763
|
}
|
|
103649
103764
|
cfg.mcpServers ??= {};
|
|
103650
103765
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
103651
|
-
|
|
103766
|
+
writeFileSync35(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
103652
103767
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
103653
103768
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
103654
103769
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
103655
103770
|
}
|
|
103656
103771
|
async function installCursorMcpConfig() {
|
|
103657
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync:
|
|
103772
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync42, readFileSync: readFileSync50, writeFileSync: writeFileSync35 } = await import("node:fs");
|
|
103658
103773
|
const { join: join58 } = await import("node:path");
|
|
103659
103774
|
const dir = join58(ROOT, ".cursor");
|
|
103660
103775
|
if (!existsSync42(dir)) mkdirSync13(dir, { recursive: true });
|
|
@@ -103670,7 +103785,7 @@ async function installCursorMcpConfig() {
|
|
|
103670
103785
|
}
|
|
103671
103786
|
cfg.mcpServers ??= {};
|
|
103672
103787
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
103673
|
-
|
|
103788
|
+
writeFileSync35(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
103674
103789
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
103675
103790
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
103676
103791
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -103725,6 +103840,24 @@ function refreshExistingCodexHooks() {
|
|
|
103725
103840
|
}
|
|
103726
103841
|
return ok;
|
|
103727
103842
|
}
|
|
103843
|
+
function refreshExistingClaudeHooks() {
|
|
103844
|
+
let ok = true;
|
|
103845
|
+
const roots = [...listWorkspaceEntries().map((entry) => entry.path), process.cwd()];
|
|
103846
|
+
for (const root of codexHookRoots(roots)) {
|
|
103847
|
+
const file2 = join57(root, ".claude", "settings.json");
|
|
103848
|
+
try {
|
|
103849
|
+
if (!existsSync41(file2) || isReplayCheckout(root)) continue;
|
|
103850
|
+
const next = refreshClaudeHookSettings(readFileSync49(file2, "utf8"));
|
|
103851
|
+
if (next === null) continue;
|
|
103852
|
+
writeFileSync34(file2, next, "utf8");
|
|
103853
|
+
console.log(`updated existing Claude Code hooks \u2192 ${file2}`);
|
|
103854
|
+
} catch (error48) {
|
|
103855
|
+
ok = false;
|
|
103856
|
+
console.warn(`Claude Code hook refresh needs attention in ${root}: ${error48 instanceof Error ? error48.message : error48}`);
|
|
103857
|
+
}
|
|
103858
|
+
}
|
|
103859
|
+
return ok;
|
|
103860
|
+
}
|
|
103728
103861
|
async function refreshLinkedCodexHooks(args2) {
|
|
103729
103862
|
if (args2.includes("--skip-hooks") || !hasCodexConfig(ROOT)) return;
|
|
103730
103863
|
try {
|
|
@@ -103893,6 +104026,7 @@ async function cmdDash(args2) {
|
|
|
103893
104026
|
process.title = "errata-daemon";
|
|
103894
104027
|
installLogTimestamps();
|
|
103895
104028
|
refreshExistingCodexHooks();
|
|
104029
|
+
refreshExistingClaudeHooks();
|
|
103896
104030
|
const portIdx = args2.indexOf("--port");
|
|
103897
104031
|
const port = portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : 7891;
|
|
103898
104032
|
const reindexOnStart = !args2.includes("--no-reindex");
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
d3a9c0cdb6333538569766d24e122085d18c71a8c767f1b9edd5d73491450f77 .codex-plugin/plugin.json
|
|
2
2
|
a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
|
|
3
3
|
fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
|
|
4
4
|
73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js
|