@inerrata-corporation/errata 2.0.2-dev.282 → 2.0.2-dev.288
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 +218 -105
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -21474,15 +21474,24 @@ function dropLowestUnit(s) {
|
|
|
21474
21474
|
case "skills":
|
|
21475
21475
|
if (s.skills.length) return s.skills.pop(), true;
|
|
21476
21476
|
break;
|
|
21477
|
+
case "motifsOverFloor":
|
|
21478
|
+
if (s.motifs.length > MOTIF_FLOOR) return s.motifs.pop(), true;
|
|
21479
|
+
break;
|
|
21477
21480
|
case "motifs":
|
|
21478
21481
|
if (s.motifs.length) return s.motifs.pop(), true;
|
|
21479
21482
|
break;
|
|
21480
21483
|
case "workingFile":
|
|
21481
21484
|
if (s.workingFile) return delete s.workingFile, true;
|
|
21482
21485
|
break;
|
|
21486
|
+
case "remoteOverFloor":
|
|
21487
|
+
if (s.remote && s.remote.length > REMOTE_FLOOR) return s.remote.pop(), true;
|
|
21488
|
+
break;
|
|
21483
21489
|
case "remote":
|
|
21484
21490
|
if (s.remote && s.remote.length) return s.remote.pop(), true;
|
|
21485
21491
|
break;
|
|
21492
|
+
case "recentProblemsOverFloor":
|
|
21493
|
+
if (s.recentProblems.length > PROBLEM_FLOOR) return s.recentProblems.pop(), true;
|
|
21494
|
+
break;
|
|
21486
21495
|
case "recentResolved":
|
|
21487
21496
|
if (s.recentResolved.length) return s.recentResolved.pop(), true;
|
|
21488
21497
|
break;
|
|
@@ -21541,7 +21550,7 @@ _${dropped} lower-priority item${dropped === 1 ? "" : "s"} omitted to fit the pa
|
|
|
21541
21550
|
}
|
|
21542
21551
|
return { body: body2, snapshot, dropped };
|
|
21543
21552
|
}
|
|
21544
|
-
var RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, EVICTION_ORDER, DEFAULT_AGENT_CONTEXT_BUDGET;
|
|
21553
|
+
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;
|
|
21545
21554
|
var init_render = __esm({
|
|
21546
21555
|
"../../packages/context-writer/src/render.ts"() {
|
|
21547
21556
|
"use strict";
|
|
@@ -21556,9 +21565,19 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21556
21565
|
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.";
|
|
21557
21566
|
EVICTION_ORDER = [
|
|
21558
21567
|
"skills",
|
|
21559
|
-
|
|
21568
|
+
// Collective floors (EE-evidence-live): motifs/remote trim to a FLOOR here and
|
|
21569
|
+
// fully drain only near the very end. The unfloored order zeroed them on every
|
|
21570
|
+
// render (~44 units dropped per block, live 8-01), which starved §5.4 at the
|
|
21571
|
+
// source: every witness channel (corroborate/refute) fires only on a prior the
|
|
21572
|
+
// agent was SHOWN, the self-gate correctly refuses same-session cites, so a
|
|
21573
|
+
// surface showing ONLY the session's own problems produces zero evidence by
|
|
21574
|
+
// construction — corroborationCount was 0 across all 1,785 cloud nodes while
|
|
21575
|
+
// the transport, parser and gate all worked. Same shape as the needsRevisit
|
|
21576
|
+
// inversion below: the budget optimized one objective and silently killed
|
|
21577
|
+
// another channel's entire input.
|
|
21578
|
+
"motifsOverFloor",
|
|
21560
21579
|
"workingFile",
|
|
21561
|
-
"
|
|
21580
|
+
"remoteOverFloor",
|
|
21562
21581
|
// Resolved priors are jumping-off points, not live defects — under a tight
|
|
21563
21582
|
// budget they drop before anything open/actionable.
|
|
21564
21583
|
"recentResolved",
|
|
@@ -21575,8 +21594,17 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21575
21594
|
// about something ALREADY closed; a live prior is the substrate every link verb
|
|
21576
21595
|
// needs. Problems outrank it now.
|
|
21577
21596
|
"needsRevisit",
|
|
21597
|
+
// Problems trim to a floor before the collective floors give way: a starved
|
|
21598
|
+
// budget keeps a few of BOTH (own problems to act on, cross-session priors to
|
|
21599
|
+
// witness against) rather than all of one and none of the other.
|
|
21600
|
+
"recentProblemsOverFloor",
|
|
21601
|
+
"motifs",
|
|
21602
|
+
"remote",
|
|
21578
21603
|
"recentProblems"
|
|
21579
21604
|
];
|
|
21605
|
+
MOTIF_FLOOR = 2;
|
|
21606
|
+
REMOTE_FLOOR = 3;
|
|
21607
|
+
PROBLEM_FLOOR = 4;
|
|
21580
21608
|
DEFAULT_AGENT_CONTEXT_BUDGET = 9e3;
|
|
21581
21609
|
}
|
|
21582
21610
|
});
|
|
@@ -47137,6 +47165,69 @@ var init_webui = __esm({
|
|
|
47137
47165
|
}
|
|
47138
47166
|
});
|
|
47139
47167
|
|
|
47168
|
+
// src/witness-ledger.ts
|
|
47169
|
+
var witness_ledger_exports = {};
|
|
47170
|
+
__export(witness_ledger_exports, {
|
|
47171
|
+
appendWitnessLedger: () => appendWitnessLedger,
|
|
47172
|
+
readWitnessLedger: () => readWitnessLedger,
|
|
47173
|
+
summarizeWitnessLedger: () => summarizeWitnessLedger,
|
|
47174
|
+
witnessLedgerPath: () => witnessLedgerPath
|
|
47175
|
+
});
|
|
47176
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync20, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "node:fs";
|
|
47177
|
+
import { join as join25 } from "node:path";
|
|
47178
|
+
function witnessLedgerPath(configDir) {
|
|
47179
|
+
return join25(configDir, "witness-ledger.jsonl");
|
|
47180
|
+
}
|
|
47181
|
+
function appendWitnessLedger(configDir, entry) {
|
|
47182
|
+
const path2 = witnessLedgerPath(configDir);
|
|
47183
|
+
try {
|
|
47184
|
+
appendFileSync2(path2, JSON.stringify(entry) + "\n");
|
|
47185
|
+
const lines = readFileSync20(path2, "utf8").split("\n").filter(Boolean);
|
|
47186
|
+
if (lines.length > LEDGER_MAX_LINES) {
|
|
47187
|
+
writeFileSync17(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
|
|
47188
|
+
}
|
|
47189
|
+
} catch {
|
|
47190
|
+
}
|
|
47191
|
+
}
|
|
47192
|
+
function readWitnessLedger(configDir) {
|
|
47193
|
+
const path2 = witnessLedgerPath(configDir);
|
|
47194
|
+
if (!existsSync20(path2)) return [];
|
|
47195
|
+
try {
|
|
47196
|
+
return readFileSync20(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
|
|
47197
|
+
} catch {
|
|
47198
|
+
return [];
|
|
47199
|
+
}
|
|
47200
|
+
}
|
|
47201
|
+
function summarizeWitnessLedger(configDir, nowMs) {
|
|
47202
|
+
const entries = readWitnessLedger(configDir);
|
|
47203
|
+
if (entries.length === 0) return [];
|
|
47204
|
+
const byChannel = /* @__PURE__ */ new Map();
|
|
47205
|
+
for (const e of entries) {
|
|
47206
|
+
const c = byChannel.get(e.channel) ?? { recorded: 0, selfSkipped: 0, selfGated: 0, unmatched: 0, lastTs: 0 };
|
|
47207
|
+
c.recorded += e.recorded ?? 0;
|
|
47208
|
+
c.selfSkipped += e.clientSelfSkipped ?? 0;
|
|
47209
|
+
c.selfGated += e.selfGated ?? 0;
|
|
47210
|
+
c.unmatched += e.unmatched ?? 0;
|
|
47211
|
+
c.lastTs = Math.max(c.lastTs, e.ts);
|
|
47212
|
+
byChannel.set(e.channel, c);
|
|
47213
|
+
}
|
|
47214
|
+
const out2 = [];
|
|
47215
|
+
for (const [channel, c] of byChannel) {
|
|
47216
|
+
const ageH = Math.round((nowMs - c.lastTs) / 36e5);
|
|
47217
|
+
out2.push(
|
|
47218
|
+
`${channel}: recorded ${c.recorded} \xB7 self-gated ${c.selfSkipped + c.selfGated} \xB7 unmatched ${c.unmatched} \xB7 last activity ${ageH}h ago`
|
|
47219
|
+
);
|
|
47220
|
+
}
|
|
47221
|
+
return out2;
|
|
47222
|
+
}
|
|
47223
|
+
var LEDGER_MAX_LINES;
|
|
47224
|
+
var init_witness_ledger = __esm({
|
|
47225
|
+
"src/witness-ledger.ts"() {
|
|
47226
|
+
"use strict";
|
|
47227
|
+
LEDGER_MAX_LINES = 500;
|
|
47228
|
+
}
|
|
47229
|
+
});
|
|
47230
|
+
|
|
47140
47231
|
// src/report-render.ts
|
|
47141
47232
|
var report_render_exports = {};
|
|
47142
47233
|
__export(report_render_exports, {
|
|
@@ -47528,12 +47619,12 @@ var init_report_render = __esm({
|
|
|
47528
47619
|
|
|
47529
47620
|
// src/cli.ts
|
|
47530
47621
|
init_src5();
|
|
47531
|
-
import { closeSync as closeSync2, existsSync as
|
|
47532
|
-
import { join as
|
|
47622
|
+
import { closeSync as closeSync2, existsSync as existsSync27, openSync as openSync2, readFileSync as readFileSync26, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
|
|
47623
|
+
import { join as join30 } from "node:path";
|
|
47533
47624
|
import { spawn as spawn3 } from "node:child_process";
|
|
47534
47625
|
|
|
47535
47626
|
// src/daemon.ts
|
|
47536
|
-
import { existsSync as
|
|
47627
|
+
import { existsSync as existsSync22, writeFileSync as writeFileSync19 } from "node:fs";
|
|
47537
47628
|
|
|
47538
47629
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
47539
47630
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -48113,8 +48204,8 @@ init_config();
|
|
|
48113
48204
|
|
|
48114
48205
|
// src/engine.ts
|
|
48115
48206
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
48116
|
-
import { existsSync as
|
|
48117
|
-
import { join as
|
|
48207
|
+
import { existsSync as existsSync21, statSync as statSync5, appendFileSync as appendFileSync3, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "node:fs";
|
|
48208
|
+
import { join as join26, relative as relative6, sep as sep4 } from "node:path";
|
|
48118
48209
|
|
|
48119
48210
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
48120
48211
|
import { stat as statcb } from "fs";
|
|
@@ -52560,6 +52651,9 @@ function retireWitnesses(queue, channel, settledKeys) {
|
|
|
52560
52651
|
return queue.filter((w) => !(w.channel === channel && settledKeys.has(w.witnessKey)));
|
|
52561
52652
|
}
|
|
52562
52653
|
|
|
52654
|
+
// src/engine.ts
|
|
52655
|
+
init_witness_ledger();
|
|
52656
|
+
|
|
52563
52657
|
// src/causal.ts
|
|
52564
52658
|
var SUPPRESSORS = [
|
|
52565
52659
|
{ kind: "ts-nocheck", re: /@ts-nocheck\b/g },
|
|
@@ -52812,7 +52906,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52812
52906
|
}
|
|
52813
52907
|
|
|
52814
52908
|
// src/engine.ts
|
|
52815
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52909
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.288" : "2.0.0-alpha.0";
|
|
52816
52910
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52817
52911
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52818
52912
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -52822,17 +52916,17 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
52822
52916
|
function appendIdentityAudit(path2, record2, line) {
|
|
52823
52917
|
if (!record2.accepted && record2.score <= 0) return;
|
|
52824
52918
|
try {
|
|
52825
|
-
if (
|
|
52919
|
+
if (existsSync21(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
52826
52920
|
renameSync3(path2, `${path2}.1`);
|
|
52827
52921
|
}
|
|
52828
|
-
|
|
52922
|
+
appendFileSync3(path2, line);
|
|
52829
52923
|
} catch {
|
|
52830
52924
|
}
|
|
52831
52925
|
}
|
|
52832
52926
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
52833
52927
|
function loadTurnCursors(path2) {
|
|
52834
52928
|
try {
|
|
52835
|
-
const raw2 = JSON.parse(
|
|
52929
|
+
const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
|
|
52836
52930
|
return new Map(
|
|
52837
52931
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
52838
52932
|
);
|
|
@@ -52842,7 +52936,7 @@ function loadTurnCursors(path2) {
|
|
|
52842
52936
|
}
|
|
52843
52937
|
function loadTurnOffsets(path2) {
|
|
52844
52938
|
try {
|
|
52845
|
-
const raw2 = JSON.parse(
|
|
52939
|
+
const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
|
|
52846
52940
|
const out2 = /* @__PURE__ */ new Map();
|
|
52847
52941
|
for (const [k, v] of Object.entries(raw2)) {
|
|
52848
52942
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -52858,7 +52952,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
52858
52952
|
const merged = {};
|
|
52859
52953
|
for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
|
|
52860
52954
|
for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
|
|
52861
|
-
|
|
52955
|
+
writeFileSync18(path2, JSON.stringify(merged), "utf8");
|
|
52862
52956
|
} catch {
|
|
52863
52957
|
}
|
|
52864
52958
|
}
|
|
@@ -52880,7 +52974,7 @@ function gitSourceWatchTargets(root) {
|
|
|
52880
52974
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
52881
52975
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
52882
52976
|
);
|
|
52883
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
52977
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join26(root, d) + sep4));
|
|
52884
52978
|
} catch {
|
|
52885
52979
|
}
|
|
52886
52980
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -52892,19 +52986,19 @@ function gitSourceWatchTargets(root) {
|
|
|
52892
52986
|
if (!f.startsWith(prefix)) continue;
|
|
52893
52987
|
const rest2 = f.slice(prefix.length);
|
|
52894
52988
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
52895
|
-
else targets.add(
|
|
52989
|
+
else targets.add(join26(root, f));
|
|
52896
52990
|
}
|
|
52897
52991
|
for (const c of children) {
|
|
52898
|
-
if (IGNORED_PATH.test(
|
|
52992
|
+
if (IGNORED_PATH.test(join26(root, c) + sep4)) continue;
|
|
52899
52993
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
52900
|
-
else targets.add(
|
|
52994
|
+
else targets.add(join26(root, c));
|
|
52901
52995
|
}
|
|
52902
52996
|
};
|
|
52903
52997
|
addUnder("");
|
|
52904
52998
|
if (targets.size > 0) return [...targets];
|
|
52905
52999
|
} catch {
|
|
52906
53000
|
}
|
|
52907
|
-
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(
|
|
53001
|
+
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join26(root, String(e.name)) + sep4)).map((e) => join26(root, String(e.name)));
|
|
52908
53002
|
}
|
|
52909
53003
|
function createWorkspaceEngine(opts) {
|
|
52910
53004
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -53062,7 +53156,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53062
53156
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
53063
53157
|
let episodeId2;
|
|
53064
53158
|
if (srcPaths.length > 0) {
|
|
53065
|
-
const abs = srcPaths.map((p) =>
|
|
53159
|
+
const abs = srcPaths.map((p) => join26(opts.workspaceRoot, p));
|
|
53066
53160
|
try {
|
|
53067
53161
|
const r = await runReindexPass(
|
|
53068
53162
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -53098,8 +53192,8 @@ function createWorkspaceEngine(opts) {
|
|
|
53098
53192
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
53099
53193
|
);
|
|
53100
53194
|
};
|
|
53101
|
-
const gitDir =
|
|
53102
|
-
if (
|
|
53195
|
+
const gitDir = join26(opts.workspaceRoot, ".git");
|
|
53196
|
+
if (existsSync21(gitDir)) {
|
|
53103
53197
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
53104
53198
|
void handleGitEvent(ev).catch((err2) => {
|
|
53105
53199
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -53169,10 +53263,10 @@ function createWorkspaceEngine(opts) {
|
|
|
53169
53263
|
});
|
|
53170
53264
|
doneRender?.();
|
|
53171
53265
|
writeContextFile(opts.workspaceRoot, body2);
|
|
53172
|
-
const target =
|
|
53266
|
+
const target = join26(opts.workspaceRoot, "AGENTS.md");
|
|
53173
53267
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
53174
53268
|
if (elicit) {
|
|
53175
|
-
writePrimingHandles(
|
|
53269
|
+
writePrimingHandles(join26(paths.configDir, "priming-handles.json"), [
|
|
53176
53270
|
...snapshot.recentProblems.map((r) => r.node),
|
|
53177
53271
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
53178
53272
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -53202,7 +53296,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53202
53296
|
remoteInFlight = true;
|
|
53203
53297
|
lastRemoteAt = now;
|
|
53204
53298
|
try {
|
|
53205
|
-
const norm = (xs) => (xs ?? []).map((t) => t.trim().toLowerCase().replace(/[@\s].*$/, "")).filter(Boolean);
|
|
53299
|
+
const norm = (xs) => (xs ?? []).map((t) => t.trim().toLowerCase().replace(/(?!^)[@\s].*$/, "")).filter(Boolean);
|
|
53206
53300
|
const seed = store.findNodesByLabel("Problem").sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 6).map((p) => p.id);
|
|
53207
53301
|
const q = {
|
|
53208
53302
|
stack: norm(profile.stack),
|
|
@@ -53388,7 +53482,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53388
53482
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
53389
53483
|
});
|
|
53390
53484
|
};
|
|
53391
|
-
const turnCursorPath =
|
|
53485
|
+
const turnCursorPath = join26(paths.configDir, "turn-cursors.json");
|
|
53392
53486
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
53393
53487
|
const turnOffset = loadTurnOffsets(turnCursorPath);
|
|
53394
53488
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
@@ -53412,7 +53506,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53412
53506
|
const t = Date.now();
|
|
53413
53507
|
let processedTurns = 0;
|
|
53414
53508
|
const elicit = isEdgeElicitationEnabled();
|
|
53415
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
53509
|
+
const handleMap = elicit ? readPrimingHandles(join26(paths.configDir, "priming-handles.json")) : {};
|
|
53416
53510
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
53417
53511
|
const toRel = (abs) => {
|
|
53418
53512
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -53803,6 +53897,15 @@ function createWorkspaceEngine(opts) {
|
|
|
53803
53897
|
console.log(
|
|
53804
53898
|
`[errata] ${channel}: ${formatDisposition({ recorded, unmatched, duplicate, selfGated })}` + (queued.length > 0 ? ` (incl. ${queued.length} replayed)` : "")
|
|
53805
53899
|
);
|
|
53900
|
+
appendWitnessLedger(paths.configDir, {
|
|
53901
|
+
ts: Date.now(),
|
|
53902
|
+
channel,
|
|
53903
|
+
recorded,
|
|
53904
|
+
unmatched,
|
|
53905
|
+
duplicate,
|
|
53906
|
+
selfGated,
|
|
53907
|
+
parked: pendingFor(witnessQueue, channel).length
|
|
53908
|
+
});
|
|
53806
53909
|
};
|
|
53807
53910
|
if (typeof cloud.reportContradictions === "function") {
|
|
53808
53911
|
await sendWitnesses(
|
|
@@ -53819,7 +53922,10 @@ function createWorkspaceEngine(opts) {
|
|
|
53819
53922
|
if (typeof cloud.reportCorroborations === "function") {
|
|
53820
53923
|
const emit = plan.corroborations.filter((c) => !mintedHere(c.nodeId));
|
|
53821
53924
|
const skipped = plan.corroborations.length - emit.length;
|
|
53822
|
-
if (skipped > 0)
|
|
53925
|
+
if (skipped > 0) {
|
|
53926
|
+
console.log(`[errata] corroborate: ${skipped} skipped (this session authored the node)`);
|
|
53927
|
+
appendWitnessLedger(paths.configDir, { ts: Date.now(), channel: "corroborate", clientSelfSkipped: skipped });
|
|
53928
|
+
}
|
|
53823
53929
|
await sendWitnesses(
|
|
53824
53930
|
"corroborate",
|
|
53825
53931
|
emit,
|
|
@@ -54021,7 +54127,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54021
54127
|
try {
|
|
54022
54128
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
54023
54129
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
54024
|
-
writePrimingHandles(
|
|
54130
|
+
writePrimingHandles(join26(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
54025
54131
|
} catch (err2) {
|
|
54026
54132
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
54027
54133
|
}
|
|
@@ -54208,7 +54314,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54208
54314
|
console.log(
|
|
54209
54315
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
54210
54316
|
);
|
|
54211
|
-
const pending =
|
|
54317
|
+
const pending = existsSync21(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
54212
54318
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
54213
54319
|
}
|
|
54214
54320
|
try {
|
|
@@ -54295,7 +54401,7 @@ async function startDaemon(opts) {
|
|
|
54295
54401
|
reviewUrl: () => webUiUrl + "/review"
|
|
54296
54402
|
});
|
|
54297
54403
|
const writeLockFile = (url2) => {
|
|
54298
|
-
|
|
54404
|
+
writeFileSync19(
|
|
54299
54405
|
engine.paths.daemonLock,
|
|
54300
54406
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
54301
54407
|
"utf8"
|
|
@@ -54338,7 +54444,7 @@ async function startDaemon(opts) {
|
|
|
54338
54444
|
);
|
|
54339
54445
|
await engine.stop();
|
|
54340
54446
|
try {
|
|
54341
|
-
if (
|
|
54447
|
+
if (existsSync22(engine.paths.daemonLock)) {
|
|
54342
54448
|
}
|
|
54343
54449
|
} catch {
|
|
54344
54450
|
}
|
|
@@ -54355,16 +54461,16 @@ async function listenServer(fetchFn, port) {
|
|
|
54355
54461
|
|
|
54356
54462
|
// src/registry.ts
|
|
54357
54463
|
init_paths();
|
|
54358
|
-
import { existsSync as
|
|
54359
|
-
import { join as
|
|
54464
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync20 } from "node:fs";
|
|
54465
|
+
import { join as join27 } from "node:path";
|
|
54360
54466
|
function registryPath() {
|
|
54361
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
54467
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join27(globalDir(), "workspaces.json");
|
|
54362
54468
|
}
|
|
54363
54469
|
function read() {
|
|
54364
54470
|
const p = registryPath();
|
|
54365
|
-
if (!
|
|
54471
|
+
if (!existsSync23(p)) return { version: 1, workspaces: {} };
|
|
54366
54472
|
try {
|
|
54367
|
-
const parsed = JSON.parse(
|
|
54473
|
+
const parsed = JSON.parse(readFileSync22(p, "utf8"));
|
|
54368
54474
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
54369
54475
|
} catch {
|
|
54370
54476
|
return { version: 1, workspaces: {} };
|
|
@@ -54372,7 +54478,7 @@ function read() {
|
|
|
54372
54478
|
}
|
|
54373
54479
|
function write(reg) {
|
|
54374
54480
|
ensureDir(globalDir());
|
|
54375
|
-
|
|
54481
|
+
writeFileSync20(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
54376
54482
|
}
|
|
54377
54483
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
54378
54484
|
const reg = read();
|
|
@@ -54389,7 +54495,7 @@ function pruneMissingWorkspaces() {
|
|
|
54389
54495
|
const reg = read();
|
|
54390
54496
|
const removed = [];
|
|
54391
54497
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
54392
|
-
if (!
|
|
54498
|
+
if (!existsSync23(entry.path)) {
|
|
54393
54499
|
removed.push(entry);
|
|
54394
54500
|
delete reg.workspaces[id];
|
|
54395
54501
|
}
|
|
@@ -54398,13 +54504,13 @@ function pruneMissingWorkspaces() {
|
|
|
54398
54504
|
return removed;
|
|
54399
54505
|
}
|
|
54400
54506
|
function workspaceStatus(entry) {
|
|
54401
|
-
const missing = !
|
|
54507
|
+
const missing = !existsSync23(entry.path);
|
|
54402
54508
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
54403
54509
|
let running = false;
|
|
54404
54510
|
let webUiUrl = null;
|
|
54405
|
-
if (
|
|
54511
|
+
if (existsSync23(lockPath)) {
|
|
54406
54512
|
try {
|
|
54407
|
-
const lock = JSON.parse(
|
|
54513
|
+
const lock = JSON.parse(readFileSync22(lockPath, "utf8"));
|
|
54408
54514
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
54409
54515
|
running = true;
|
|
54410
54516
|
webUiUrl = lock.webUiUrl;
|
|
@@ -54432,7 +54538,7 @@ function pidAlive(pid) {
|
|
|
54432
54538
|
// src/multi.ts
|
|
54433
54539
|
init_dist();
|
|
54434
54540
|
init_src4();
|
|
54435
|
-
import { readFileSync as
|
|
54541
|
+
import { readFileSync as readFileSync25, unlinkSync as unlinkSync3, writeFileSync as writeFileSync21 } from "node:fs";
|
|
54436
54542
|
|
|
54437
54543
|
// src/principle-sync.ts
|
|
54438
54544
|
init_src4();
|
|
@@ -54460,8 +54566,8 @@ init_reconcile();
|
|
|
54460
54566
|
|
|
54461
54567
|
// src/lockfile-auto.ts
|
|
54462
54568
|
init_src();
|
|
54463
|
-
import { existsSync as
|
|
54464
|
-
import { join as
|
|
54569
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
|
|
54570
|
+
import { join as join28 } from "node:path";
|
|
54465
54571
|
|
|
54466
54572
|
// src/package-index.ts
|
|
54467
54573
|
init_src();
|
|
@@ -54610,11 +54716,11 @@ function runLockfilePass(opts) {
|
|
|
54610
54716
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
54611
54717
|
];
|
|
54612
54718
|
for (const c of candidates) {
|
|
54613
|
-
const p =
|
|
54614
|
-
if (!
|
|
54719
|
+
const p = join28(opts.root, c.file);
|
|
54720
|
+
if (!existsSync24(p)) continue;
|
|
54615
54721
|
let sbom;
|
|
54616
54722
|
try {
|
|
54617
|
-
sbom = c.parse(
|
|
54723
|
+
sbom = c.parse(readFileSync23(p, "utf8"));
|
|
54618
54724
|
} catch {
|
|
54619
54725
|
continue;
|
|
54620
54726
|
}
|
|
@@ -55062,7 +55168,7 @@ var ConsolidateWorker = class {
|
|
|
55062
55168
|
init_paths();
|
|
55063
55169
|
|
|
55064
55170
|
// src/lock.ts
|
|
55065
|
-
import { existsSync as
|
|
55171
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
|
|
55066
55172
|
function isProcessAlive(pid) {
|
|
55067
55173
|
if (!pid || pid <= 0) return false;
|
|
55068
55174
|
try {
|
|
@@ -55073,9 +55179,9 @@ function isProcessAlive(pid) {
|
|
|
55073
55179
|
}
|
|
55074
55180
|
}
|
|
55075
55181
|
function readDaemonLock(lockPath) {
|
|
55076
|
-
if (!
|
|
55182
|
+
if (!existsSync25(lockPath)) return null;
|
|
55077
55183
|
try {
|
|
55078
|
-
const lock = JSON.parse(
|
|
55184
|
+
const lock = JSON.parse(readFileSync24(lockPath, "utf8"));
|
|
55079
55185
|
return typeof lock.pid === "number" ? lock : null;
|
|
55080
55186
|
} catch {
|
|
55081
55187
|
return null;
|
|
@@ -55354,12 +55460,12 @@ async function reanchorProject(opts) {
|
|
|
55354
55460
|
}
|
|
55355
55461
|
|
|
55356
55462
|
// src/adopt.ts
|
|
55357
|
-
import { existsSync as
|
|
55358
|
-
import { dirname as dirname10, join as
|
|
55463
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
55464
|
+
import { dirname as dirname10, join as join29 } from "node:path";
|
|
55359
55465
|
function findGitRoot(absPath) {
|
|
55360
55466
|
let dir = absPath;
|
|
55361
55467
|
for (let depth = 0; depth < 64; depth++) {
|
|
55362
|
-
if (
|
|
55468
|
+
if (existsSync26(join29(dir, ".git"))) return dir;
|
|
55363
55469
|
const parent = dirname10(dir);
|
|
55364
55470
|
if (parent === dir) return null;
|
|
55365
55471
|
dir = parent;
|
|
@@ -55608,7 +55714,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55608
55714
|
void ambientLinkAll();
|
|
55609
55715
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
55610
55716
|
try {
|
|
55611
|
-
|
|
55717
|
+
writeFileSync21(
|
|
55612
55718
|
rec.engine.paths.daemonLock,
|
|
55613
55719
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
55614
55720
|
"utf8"
|
|
@@ -55797,7 +55903,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55797
55903
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
55798
55904
|
try {
|
|
55799
55905
|
ensureDir(globalDir());
|
|
55800
|
-
|
|
55906
|
+
writeFileSync21(
|
|
55801
55907
|
lockPath,
|
|
55802
55908
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
55803
55909
|
"utf8"
|
|
@@ -55806,7 +55912,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55806
55912
|
}
|
|
55807
55913
|
for (const r of records) {
|
|
55808
55914
|
try {
|
|
55809
|
-
|
|
55915
|
+
writeFileSync21(
|
|
55810
55916
|
r.engine.paths.daemonLock,
|
|
55811
55917
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
55812
55918
|
"utf8"
|
|
@@ -56304,7 +56410,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56304
56410
|
},
|
|
56305
56411
|
async stop() {
|
|
56306
56412
|
try {
|
|
56307
|
-
const cur =
|
|
56413
|
+
const cur = readFileSync25(lockPath, "utf8");
|
|
56308
56414
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
56309
56415
|
} catch {
|
|
56310
56416
|
}
|
|
@@ -57321,21 +57427,21 @@ async function cmdInit() {
|
|
|
57321
57427
|
if (!skipHooks) {
|
|
57322
57428
|
console.log("");
|
|
57323
57429
|
console.log("installing harness hooks...");
|
|
57324
|
-
const { existsSync:
|
|
57325
|
-
const { join:
|
|
57430
|
+
const { existsSync: existsSync28 } = await import("node:fs");
|
|
57431
|
+
const { join: join31 } = await import("node:path");
|
|
57326
57432
|
try {
|
|
57327
57433
|
await installClaudeHooks(port);
|
|
57328
57434
|
} catch (err2) {
|
|
57329
57435
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57330
57436
|
}
|
|
57331
|
-
if (
|
|
57437
|
+
if (existsSync28(join31(ROOT, ".cursor"))) {
|
|
57332
57438
|
try {
|
|
57333
57439
|
await installCursorMcpConfig();
|
|
57334
57440
|
} catch (err2) {
|
|
57335
57441
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57336
57442
|
}
|
|
57337
57443
|
}
|
|
57338
|
-
if (
|
|
57444
|
+
if (existsSync28(join31(ROOT, ".codex"))) {
|
|
57339
57445
|
try {
|
|
57340
57446
|
await installCodexHooks(port);
|
|
57341
57447
|
} catch (err2) {
|
|
@@ -57492,9 +57598,9 @@ async function cmdStatus() {
|
|
|
57492
57598
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
57493
57599
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
57494
57600
|
}
|
|
57495
|
-
console.log(` graph db: ${
|
|
57496
|
-
console.log(` event log: ${
|
|
57497
|
-
if (
|
|
57601
|
+
console.log(` graph db: ${existsSync27(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
57602
|
+
console.log(` event log: ${existsSync27(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
57603
|
+
if (existsSync27(paths.castalia)) {
|
|
57498
57604
|
try {
|
|
57499
57605
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
57500
57606
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -57526,6 +57632,13 @@ async function cmdStatus() {
|
|
|
57526
57632
|
} catch {
|
|
57527
57633
|
}
|
|
57528
57634
|
}
|
|
57635
|
+
try {
|
|
57636
|
+
const { summarizeWitnessLedger: summarizeWitnessLedger2 } = await Promise.resolve().then(() => (init_witness_ledger(), witness_ledger_exports));
|
|
57637
|
+
const lines = summarizeWitnessLedger2(paths.configDir, Date.now());
|
|
57638
|
+
if (lines.length === 0) console.log(" evidence: no witness activity ledgered yet (corroborate/contradict have never fired here)");
|
|
57639
|
+
else for (const l of lines) console.log(` evidence: ${l}`);
|
|
57640
|
+
} catch {
|
|
57641
|
+
}
|
|
57529
57642
|
const lockPath = globalDaemonLock();
|
|
57530
57643
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
57531
57644
|
console.log(
|
|
@@ -58168,11 +58281,11 @@ function cmdInstallationProfile(args2) {
|
|
|
58168
58281
|
}
|
|
58169
58282
|
async function cmdReview() {
|
|
58170
58283
|
const paths = workspacePaths(ROOT);
|
|
58171
|
-
if (!
|
|
58284
|
+
if (!existsSync27(paths.reviewQueue)) {
|
|
58172
58285
|
console.log("(review queue empty)");
|
|
58173
58286
|
return;
|
|
58174
58287
|
}
|
|
58175
|
-
const queue = JSON.parse(
|
|
58288
|
+
const queue = JSON.parse(readFileSync26(paths.reviewQueue, "utf8"));
|
|
58176
58289
|
if (queue.length === 0) {
|
|
58177
58290
|
console.log("(review queue empty)");
|
|
58178
58291
|
return;
|
|
@@ -58843,7 +58956,7 @@ async function gatherRepo(store, ws) {
|
|
|
58843
58956
|
};
|
|
58844
58957
|
}
|
|
58845
58958
|
async function gatherReportData(generatedAt) {
|
|
58846
|
-
const { existsSync:
|
|
58959
|
+
const { existsSync: existsSync28 } = await import("node:fs");
|
|
58847
58960
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
58848
58961
|
const cfg = loadConfig();
|
|
58849
58962
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -58851,7 +58964,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58851
58964
|
for (const ws of listWorkspaces()) {
|
|
58852
58965
|
if (ws.missing) continue;
|
|
58853
58966
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
58854
|
-
if (!
|
|
58967
|
+
if (!existsSync28(dbPath)) continue;
|
|
58855
58968
|
let store = null;
|
|
58856
58969
|
try {
|
|
58857
58970
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -58882,7 +58995,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58882
58995
|
};
|
|
58883
58996
|
}
|
|
58884
58997
|
async function cmdReport(args2) {
|
|
58885
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
58998
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync22 } = await import("node:fs");
|
|
58886
58999
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
58887
59000
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
58888
59001
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -58895,8 +59008,8 @@ async function cmdReport(args2) {
|
|
|
58895
59008
|
const outDir = workspacePaths(ROOT).configDir;
|
|
58896
59009
|
mkdirSync8(outDir, { recursive: true });
|
|
58897
59010
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
58898
|
-
for (const f of files)
|
|
58899
|
-
const indexPath =
|
|
59011
|
+
for (const f of files) writeFileSync22(join30(outDir, f.name), f.html, "utf8");
|
|
59012
|
+
const indexPath = join30(outDir, "report.html");
|
|
58900
59013
|
console.log(`report \u2192 ${indexPath}`);
|
|
58901
59014
|
console.log(
|
|
58902
59015
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -59014,15 +59127,15 @@ function hookRelayCommand(port, path2) {
|
|
|
59014
59127
|
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
59015
59128
|
}
|
|
59016
59129
|
async function installClaudeHooks(port) {
|
|
59017
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
59018
|
-
const { join:
|
|
59019
|
-
const dir =
|
|
59020
|
-
if (!
|
|
59021
|
-
const file2 =
|
|
59130
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
|
|
59131
|
+
const { join: join31 } = await import("node:path");
|
|
59132
|
+
const dir = join31(ROOT, ".claude");
|
|
59133
|
+
if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
|
|
59134
|
+
const file2 = join31(dir, "settings.json");
|
|
59022
59135
|
let settings = {};
|
|
59023
|
-
if (
|
|
59136
|
+
if (existsSync28(file2)) {
|
|
59024
59137
|
try {
|
|
59025
|
-
settings = JSON.parse(
|
|
59138
|
+
settings = JSON.parse(readFileSync27(file2, "utf8"));
|
|
59026
59139
|
} catch {
|
|
59027
59140
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
59028
59141
|
process.exit(2);
|
|
@@ -59068,10 +59181,10 @@ async function installClaudeHooks(port) {
|
|
|
59068
59181
|
dropErrata(list);
|
|
59069
59182
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
59070
59183
|
}
|
|
59071
|
-
|
|
59184
|
+
writeFileSync22(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
59072
59185
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
59073
59186
|
await installClaudeMcpConfig();
|
|
59074
|
-
const claudeMd =
|
|
59187
|
+
const claudeMd = join31(ROOT, "CLAUDE.md");
|
|
59075
59188
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
59076
59189
|
if (recall.kind === "collision") {
|
|
59077
59190
|
console.warn(
|
|
@@ -59083,15 +59196,15 @@ async function installClaudeHooks(port) {
|
|
|
59083
59196
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
59084
59197
|
}
|
|
59085
59198
|
async function installClaudeMcpConfig() {
|
|
59086
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
59087
|
-
const { join:
|
|
59088
|
-
const file2 =
|
|
59199
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
|
|
59200
|
+
const { join: join31, dirname: dirname11 } = await import("node:path");
|
|
59201
|
+
const file2 = join31(ROOT, ".mcp.json");
|
|
59089
59202
|
const dir = dirname11(file2);
|
|
59090
|
-
if (!
|
|
59203
|
+
if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
|
|
59091
59204
|
let cfg = {};
|
|
59092
|
-
if (
|
|
59205
|
+
if (existsSync28(file2)) {
|
|
59093
59206
|
try {
|
|
59094
|
-
cfg = JSON.parse(
|
|
59207
|
+
cfg = JSON.parse(readFileSync27(file2, "utf8"));
|
|
59095
59208
|
} catch {
|
|
59096
59209
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
59097
59210
|
process.exit(2);
|
|
@@ -59099,21 +59212,21 @@ async function installClaudeMcpConfig() {
|
|
|
59099
59212
|
}
|
|
59100
59213
|
cfg.mcpServers ??= {};
|
|
59101
59214
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
59102
|
-
|
|
59215
|
+
writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
59103
59216
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
59104
59217
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
59105
59218
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
59106
59219
|
}
|
|
59107
59220
|
async function installCursorMcpConfig() {
|
|
59108
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
59109
|
-
const { join:
|
|
59110
|
-
const dir =
|
|
59111
|
-
if (!
|
|
59112
|
-
const file2 =
|
|
59221
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
|
|
59222
|
+
const { join: join31 } = await import("node:path");
|
|
59223
|
+
const dir = join31(ROOT, ".cursor");
|
|
59224
|
+
if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
|
|
59225
|
+
const file2 = join31(dir, "mcp.json");
|
|
59113
59226
|
let cfg = {};
|
|
59114
|
-
if (
|
|
59227
|
+
if (existsSync28(file2)) {
|
|
59115
59228
|
try {
|
|
59116
|
-
cfg = JSON.parse(
|
|
59229
|
+
cfg = JSON.parse(readFileSync27(file2, "utf8"));
|
|
59117
59230
|
} catch {
|
|
59118
59231
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
59119
59232
|
process.exit(2);
|
|
@@ -59121,7 +59234,7 @@ async function installCursorMcpConfig() {
|
|
|
59121
59234
|
}
|
|
59122
59235
|
cfg.mcpServers ??= {};
|
|
59123
59236
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
59124
|
-
|
|
59237
|
+
writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
59125
59238
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
59126
59239
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
59127
59240
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -59129,16 +59242,16 @@ async function installCursorMcpConfig() {
|
|
|
59129
59242
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
59130
59243
|
}
|
|
59131
59244
|
async function installCodexHooks(port) {
|
|
59132
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
59133
|
-
const { join:
|
|
59134
|
-
const dir =
|
|
59135
|
-
if (!
|
|
59136
|
-
const file2 =
|
|
59245
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
|
|
59246
|
+
const { join: join31 } = await import("node:path");
|
|
59247
|
+
const dir = join31(ROOT, ".codex");
|
|
59248
|
+
if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
|
|
59249
|
+
const file2 = join31(dir, "config.toml");
|
|
59137
59250
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
59138
59251
|
const END = `# <<< errata hooks`;
|
|
59139
59252
|
let existing = "";
|
|
59140
|
-
if (
|
|
59141
|
-
existing =
|
|
59253
|
+
if (existsSync28(file2)) {
|
|
59254
|
+
existing = readFileSync27(file2, "utf8");
|
|
59142
59255
|
const beginIdx = existing.indexOf(BEGIN);
|
|
59143
59256
|
const endIdx = existing.indexOf(END);
|
|
59144
59257
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -59167,7 +59280,7 @@ ${END}
|
|
|
59167
59280
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
59168
59281
|
|
|
59169
59282
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
59170
|
-
|
|
59283
|
+
writeFileSync22(file2, final, "utf8");
|
|
59171
59284
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
59172
59285
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
59173
59286
|
console.log("");
|
|
@@ -59481,7 +59594,7 @@ async function cmdDash(args2) {
|
|
|
59481
59594
|
await yieldToLoop2();
|
|
59482
59595
|
try {
|
|
59483
59596
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
59484
|
-
const res = bleedRules(
|
|
59597
|
+
const res = bleedRules(join30(r.root, ".claude", "rules"), items);
|
|
59485
59598
|
if (res.written || res.pruned) {
|
|
59486
59599
|
console.log(
|
|
59487
59600
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|