@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.
Files changed (2) hide show
  1. package/errata.mjs +218 -105
  2. 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
- "motifs",
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
- "remote",
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 existsSync26, openSync as openSync2, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
47532
- import { join as join29 } from "node:path";
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 existsSync21, writeFileSync as writeFileSync18 } from "node:fs";
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 existsSync20, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "node:fs";
48117
- import { join as join25, relative as relative6, sep as sep4 } from "node:path";
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.282" : "2.0.0-alpha.0";
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 (existsSync20(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
52919
+ if (existsSync21(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
52826
52920
  renameSync3(path2, `${path2}.1`);
52827
52921
  }
52828
- appendFileSync2(path2, line);
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(readFileSync20(path2, "utf8"));
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(readFileSync20(path2, "utf8"));
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
- writeFileSync17(path2, JSON.stringify(merged), "utf8");
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(join25(root, d) + sep4));
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(join25(root, f));
52989
+ else targets.add(join26(root, f));
52896
52990
  }
52897
52991
  for (const c of children) {
52898
- if (IGNORED_PATH.test(join25(root, c) + sep4)) continue;
52992
+ if (IGNORED_PATH.test(join26(root, c) + sep4)) continue;
52899
52993
  if (hasIgnoredChild(c)) addUnder(c);
52900
- else targets.add(join25(root, c));
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(join25(root, String(e.name)) + sep4)).map((e) => join25(root, String(e.name)));
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) => join25(opts.workspaceRoot, 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 = join25(opts.workspaceRoot, ".git");
53102
- if (existsSync20(gitDir)) {
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 = join25(opts.workspaceRoot, "AGENTS.md");
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(join25(paths.configDir, "priming-handles.json"), [
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 = join25(paths.configDir, "turn-cursors.json");
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(join25(paths.configDir, "priming-handles.json")) : {};
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) console.log(`[errata] corroborate: ${skipped} skipped (this session authored the node)`);
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(join25(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
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 = existsSync20(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
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
- writeFileSync18(
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 (existsSync21(engine.paths.daemonLock)) {
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 existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "node:fs";
54359
- import { join as join26 } from "node:path";
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"] ?? join26(globalDir(), "workspaces.json");
54467
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join27(globalDir(), "workspaces.json");
54362
54468
  }
54363
54469
  function read() {
54364
54470
  const p = registryPath();
54365
- if (!existsSync22(p)) return { version: 1, workspaces: {} };
54471
+ if (!existsSync23(p)) return { version: 1, workspaces: {} };
54366
54472
  try {
54367
- const parsed = JSON.parse(readFileSync21(p, "utf8"));
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
- writeFileSync19(registryPath(), JSON.stringify(reg, null, 2), "utf8");
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 (!existsSync22(entry.path)) {
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 = !existsSync22(entry.path);
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 (existsSync22(lockPath)) {
54511
+ if (existsSync23(lockPath)) {
54406
54512
  try {
54407
- const lock = JSON.parse(readFileSync21(lockPath, "utf8"));
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 readFileSync24, unlinkSync as unlinkSync3, writeFileSync as writeFileSync20 } from "node:fs";
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 existsSync23, readFileSync as readFileSync22 } from "node:fs";
54464
- import { join as join27 } from "node:path";
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 = join27(opts.root, c.file);
54614
- if (!existsSync23(p)) continue;
54719
+ const p = join28(opts.root, c.file);
54720
+ if (!existsSync24(p)) continue;
54615
54721
  let sbom;
54616
54722
  try {
54617
- sbom = c.parse(readFileSync22(p, "utf8"));
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 existsSync24, readFileSync as readFileSync23 } from "node:fs";
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 (!existsSync24(lockPath)) return null;
55182
+ if (!existsSync25(lockPath)) return null;
55077
55183
  try {
55078
- const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
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 existsSync25 } from "node:fs";
55358
- import { dirname as dirname10, join as join28 } from "node:path";
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 (existsSync25(join28(dir, ".git"))) return dir;
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
- writeFileSync20(
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
- writeFileSync20(
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
- writeFileSync20(
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 = readFileSync24(lockPath, "utf8");
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: existsSync27 } = await import("node:fs");
57325
- const { join: join30 } = await import("node:path");
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 (existsSync27(join30(ROOT, ".cursor"))) {
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 (existsSync27(join30(ROOT, ".codex"))) {
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: ${existsSync26(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
57496
- console.log(` event log: ${existsSync26(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
57497
- if (existsSync26(paths.castalia)) {
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 (!existsSync26(paths.reviewQueue)) {
58284
+ if (!existsSync27(paths.reviewQueue)) {
58172
58285
  console.log("(review queue empty)");
58173
58286
  return;
58174
58287
  }
58175
- const queue = JSON.parse(readFileSync25(paths.reviewQueue, "utf8"));
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: existsSync27 } = await import("node:fs");
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 (!existsSync27(dbPath)) continue;
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: writeFileSync21 } = await import("node:fs");
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) writeFileSync21(join29(outDir, f.name), f.html, "utf8");
58899
- const indexPath = join29(outDir, "report.html");
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: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
59018
- const { join: join30 } = await import("node:path");
59019
- const dir = join30(ROOT, ".claude");
59020
- if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
59021
- const file2 = join30(dir, "settings.json");
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 (existsSync27(file2)) {
59136
+ if (existsSync28(file2)) {
59024
59137
  try {
59025
- settings = JSON.parse(readFileSync26(file2, "utf8"));
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
- writeFileSync21(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
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 = join30(ROOT, "CLAUDE.md");
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: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
59087
- const { join: join30, dirname: dirname11 } = await import("node:path");
59088
- const file2 = join30(ROOT, ".mcp.json");
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 (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
59203
+ if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
59091
59204
  let cfg = {};
59092
- if (existsSync27(file2)) {
59205
+ if (existsSync28(file2)) {
59093
59206
  try {
59094
- cfg = JSON.parse(readFileSync26(file2, "utf8"));
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
- writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
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: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
59109
- const { join: join30 } = await import("node:path");
59110
- const dir = join30(ROOT, ".cursor");
59111
- if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
59112
- const file2 = join30(dir, "mcp.json");
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 (existsSync27(file2)) {
59227
+ if (existsSync28(file2)) {
59115
59228
  try {
59116
- cfg = JSON.parse(readFileSync26(file2, "utf8"));
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
- writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
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: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
59133
- const { join: join30 } = await import("node:path");
59134
- const dir = join30(ROOT, ".codex");
59135
- if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
59136
- const file2 = join30(dir, "config.toml");
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 (existsSync27(file2)) {
59141
- existing = readFileSync26(file2, "utf8");
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
- writeFileSync21(file2, final, "utf8");
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(join29(r.root, ".claude", "rules"), items);
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` : "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.282",
3
+ "version": "2.0.2-dev.288",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {