@inerrata-corporation/errata 2.0.8-dev.2895 → 2.0.8-dev.2914

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 +374 -223
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -29131,6 +29131,12 @@ function statuslineText(sessionId, now = Date.now()) {
29131
29131
  if (!hit || now - hit.at > STATUS_CARD_TTL_MS) return IDLE_STATUS;
29132
29132
  return renderStatusCard(hit.card);
29133
29133
  }
29134
+ function statuslineDir(body2) {
29135
+ const ws = body2["workspace"];
29136
+ const current = ws && typeof ws === "object" ? ws["current_dir"] : void 0;
29137
+ if (typeof current === "string" && current) return current;
29138
+ return typeof body2["cwd"] === "string" && body2["cwd"] ? body2["cwd"] : null;
29139
+ }
29134
29140
  function recallCardEnabled(env2 = process.env) {
29135
29141
  const v = (env2["ERRATA_RECALL_CARD"] ?? "").trim().toLowerCase();
29136
29142
  return !(v === "0" || v === "off" || v === "false" || v === "no");
@@ -54319,8 +54325,8 @@ var require_request = __commonJS({
54319
54325
  var require_dispatcher = __commonJS({
54320
54326
  "../../node_modules/.pnpm/undici@6.24.1/node_modules/undici/lib/dispatcher/dispatcher.js"(exports, module2) {
54321
54327
  "use strict";
54322
- var EventEmitter2 = __require("node:events");
54323
- var Dispatcher = class extends EventEmitter2 {
54328
+ var EventEmitter3 = __require("node:events");
54329
+ var Dispatcher = class extends EventEmitter3 {
54324
54330
  dispatch() {
54325
54331
  throw new Error("not implemented");
54326
54332
  }
@@ -70935,9 +70941,9 @@ __export(witness_ledger_exports, {
70935
70941
  witnessLedgerPath: () => witnessLedgerPath
70936
70942
  });
70937
70943
  import { appendFileSync as appendFileSync3, existsSync as existsSync24, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "node:fs";
70938
- import { join as join31 } from "node:path";
70944
+ import { join as join32 } from "node:path";
70939
70945
  function witnessLedgerPath(configDir) {
70940
- return join31(configDir, "witness-ledger.jsonl");
70946
+ return join32(configDir, "witness-ledger.jsonl");
70941
70947
  }
70942
70948
  function appendWitnessLedger(configDir, entry) {
70943
70949
  const path2 = witnessLedgerPath(configDir);
@@ -71393,8 +71399,8 @@ var init_report_render = __esm({
71393
71399
 
71394
71400
  // src/cli.ts
71395
71401
  init_src6();
71396
- import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync35, renameSync as renameSync4, statSync as statSync9 } from "node:fs";
71397
- import { join as join42, resolve as pathResolve2 } from "node:path";
71402
+ import { closeSync as closeSync2, existsSync as existsSync35, openSync as openSync2, readFileSync as readFileSync36, renameSync as renameSync4, statSync as statSync10 } from "node:fs";
71403
+ import { join as join43, resolve as pathResolve2 } from "node:path";
71398
71404
  import { spawn as spawn5 } from "node:child_process";
71399
71405
 
71400
71406
  // src/daemon.ts
@@ -71978,8 +71984,13 @@ init_config();
71978
71984
 
71979
71985
  // src/engine.ts
71980
71986
  import { execFileSync as execFileSync4 } from "node:child_process";
71981
- import { existsSync as existsSync25, statSync as statSync7, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "node:fs";
71982
- import { join as join33, relative as relative6, sep as sep4 } from "node:path";
71987
+ import { existsSync as existsSync25, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "node:fs";
71988
+ import { join as join34, relative as relative6, sep as sep4 } from "node:path";
71989
+
71990
+ // src/source-watcher.ts
71991
+ import { EventEmitter as EventEmitter2 } from "node:events";
71992
+ import { statSync as statSync5, watch as watch2 } from "node:fs";
71993
+ import { join as join19 } from "node:path";
71983
71994
 
71984
71995
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
71985
71996
  import { stat as statcb } from "fs";
@@ -72710,9 +72721,9 @@ var NodeFsHandler = class {
72710
72721
  if (this.fsw.closed) {
72711
72722
  return;
72712
72723
  }
72713
- const dirname13 = sysPath.dirname(file2);
72724
+ const dirname14 = sysPath.dirname(file2);
72714
72725
  const basename8 = sysPath.basename(file2);
72715
- const parent = this.fsw._getWatchedDir(dirname13);
72726
+ const parent = this.fsw._getWatchedDir(dirname14);
72716
72727
  let prevStats = stats;
72717
72728
  if (parent.has(basename8))
72718
72729
  return;
@@ -72739,7 +72750,7 @@ var NodeFsHandler = class {
72739
72750
  prevStats = newStats2;
72740
72751
  }
72741
72752
  } catch (error48) {
72742
- this.fsw._remove(dirname13, basename8);
72753
+ this.fsw._remove(dirname14, basename8);
72743
72754
  }
72744
72755
  } else if (parent.has(basename8)) {
72745
72756
  const at = newStats.atimeMs;
@@ -73672,6 +73683,95 @@ function watch(paths, options = {}) {
73672
73683
  }
73673
73684
  var esm_default = { watch, FSWatcher };
73674
73685
 
73686
+ // src/source-watcher.ts
73687
+ var NATIVE_RECURSIVE_PLATFORMS = ["win32", "darwin"];
73688
+ var SETTLE_MS = 50;
73689
+ function createSourceWatcher(targets, opts) {
73690
+ const native = opts.native ?? NATIVE_RECURSIVE_PLATFORMS.includes(process.platform);
73691
+ return native ? new NativeSourceWatcher(targets, opts.ignored) : chokidarSourceWatcher(targets, opts.ignored);
73692
+ }
73693
+ function chokidarSourceWatcher(targets, ignored) {
73694
+ const w = esm_default.watch([...targets], { ignored, ignoreInitial: true, persistent: true });
73695
+ const self = {
73696
+ on(event, listener) {
73697
+ w.on(event, listener);
73698
+ return self;
73699
+ },
73700
+ add: (p) => void w.add(p),
73701
+ unwatch: (p) => void w.unwatch(p),
73702
+ close: () => w.close()
73703
+ };
73704
+ return self;
73705
+ }
73706
+ var NativeSourceWatcher = class extends EventEmitter2 {
73707
+ constructor(targets, ignored) {
73708
+ super();
73709
+ this.ignored = ignored;
73710
+ for (const t of targets) this.add(t);
73711
+ }
73712
+ handles = /* @__PURE__ */ new Map();
73713
+ pending = /* @__PURE__ */ new Map();
73714
+ known = /* @__PURE__ */ new Set();
73715
+ closed = false;
73716
+ add(target) {
73717
+ if (this.closed || this.handles.has(target)) return;
73718
+ let isDir;
73719
+ try {
73720
+ isDir = statSync5(target).isDirectory();
73721
+ } catch {
73722
+ return;
73723
+ }
73724
+ try {
73725
+ const h = watch2(target, { recursive: isDir, persistent: true }, (event, name2) => {
73726
+ const path2 = isDir ? name2 ? join19(target, name2.toString()) : null : target;
73727
+ if (!path2) return;
73728
+ this.emit("raw", event, path2, { watchedPath: target });
73729
+ if (!this.ignored(path2)) this.schedule(path2, event === "rename");
73730
+ });
73731
+ h.on("error", () => this.unwatch(target));
73732
+ this.handles.set(target, h);
73733
+ } catch {
73734
+ }
73735
+ }
73736
+ unwatch(target) {
73737
+ this.handles.get(target)?.close();
73738
+ this.handles.delete(target);
73739
+ }
73740
+ async close() {
73741
+ this.closed = true;
73742
+ for (const h of this.handles.values()) h.close();
73743
+ this.handles.clear();
73744
+ for (const p of this.pending.values()) clearTimeout(p.timer);
73745
+ this.pending.clear();
73746
+ }
73747
+ schedule(path2, renamed) {
73748
+ const prev = this.pending.get(path2);
73749
+ if (prev) clearTimeout(prev.timer);
73750
+ const timer = setTimeout(() => {
73751
+ this.pending.delete(path2);
73752
+ this.classify(path2, renamed || (prev?.renamed ?? false));
73753
+ }, SETTLE_MS);
73754
+ this.pending.set(path2, { timer, renamed: renamed || (prev?.renamed ?? false) });
73755
+ }
73756
+ classify(path2, renamed) {
73757
+ if (this.closed) return;
73758
+ let isFile;
73759
+ try {
73760
+ const s = statSync5(path2);
73761
+ if (s.isDirectory()) return;
73762
+ isFile = s.isFile();
73763
+ } catch {
73764
+ this.known.delete(path2);
73765
+ this.emit("unlink", path2);
73766
+ return;
73767
+ }
73768
+ if (!isFile) return;
73769
+ const first = !this.known.has(path2);
73770
+ this.known.add(path2);
73771
+ this.emit(renamed && first ? "add" : "change", path2);
73772
+ }
73773
+ };
73774
+
73675
73775
  // src/engine.ts
73676
73776
  init_generalize_graph();
73677
73777
  init_src();
@@ -73928,8 +74028,8 @@ init_review2();
73928
74028
 
73929
74029
  // src/turn.ts
73930
74030
  init_checkout_root();
73931
- import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync5 } from "node:fs";
73932
- import { basename as basename5, delimiter, dirname as dirname10, join as join19, normalize as normalize3 } from "node:path";
74031
+ import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
74032
+ import { basename as basename5, delimiter, dirname as dirname10, join as join20, normalize as normalize3 } from "node:path";
73933
74033
  import { homedir as homedir4 } from "node:os";
73934
74034
  import { createHash as createHash14 } from "node:crypto";
73935
74035
  function readFrom(path2, fromByte, maxBytes) {
@@ -74307,7 +74407,7 @@ function turnsSince(turns, mark) {
74307
74407
  return at >= 0 ? turns.slice(at + 1) : turns;
74308
74408
  }
74309
74409
  function claudeProjectDir(cwd, home = homedir4()) {
74310
- return join19(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
74410
+ return join20(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
74311
74411
  }
74312
74412
  function recentTranscripts(cwd, opts = {}) {
74313
74413
  const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
@@ -74322,10 +74422,10 @@ function recentTranscripts(cwd, opts = {}) {
74322
74422
  const refs = [];
74323
74423
  for (const name2 of names) {
74324
74424
  if (!name2.endsWith(".jsonl")) continue;
74325
- const path2 = join19(dir, name2);
74425
+ const path2 = join20(dir, name2);
74326
74426
  let mtimeMs;
74327
74427
  try {
74328
- mtimeMs = statSync5(path2).mtimeMs;
74428
+ mtimeMs = statSync6(path2).mtimeMs;
74329
74429
  } catch {
74330
74430
  continue;
74331
74431
  }
@@ -74337,7 +74437,7 @@ function recentTranscripts(cwd, opts = {}) {
74337
74437
  }
74338
74438
  function subagentTranscripts(mainTranscriptPath, sessionId) {
74339
74439
  if (!mainTranscriptPath || !sessionId) return [];
74340
- const dir = join19(dirname10(mainTranscriptPath), sessionId, "subagents");
74440
+ const dir = join20(dirname10(mainTranscriptPath), sessionId, "subagents");
74341
74441
  if (!existsSync16(dir)) return [];
74342
74442
  let names;
74343
74443
  try {
@@ -74348,10 +74448,10 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
74348
74448
  const refs = [];
74349
74449
  for (const name2 of names) {
74350
74450
  if (!name2.endsWith(".jsonl")) continue;
74351
- const path2 = join19(dir, name2);
74451
+ const path2 = join20(dir, name2);
74352
74452
  let mtimeMs;
74353
74453
  try {
74354
- mtimeMs = statSync5(path2).mtimeMs;
74454
+ mtimeMs = statSync6(path2).mtimeMs;
74355
74455
  } catch {
74356
74456
  continue;
74357
74457
  }
@@ -74367,8 +74467,8 @@ function splitPathList(value, sep5 = delimiter) {
74367
74467
  function codexSessionRoots(env2 = process.env, home = homedir4()) {
74368
74468
  const roots = /* @__PURE__ */ new Set();
74369
74469
  for (const d of splitPathList(env2["ERRATA_CODEX_SESSIONS_DIRS"])) roots.add(d);
74370
- if (env2["CODEX_HOME"]) roots.add(join19(env2["CODEX_HOME"], "sessions"));
74371
- roots.add(join19(home, ".codex", "sessions"));
74470
+ if (env2["CODEX_HOME"]) roots.add(join20(env2["CODEX_HOME"], "sessions"));
74471
+ roots.add(join20(home, ".codex", "sessions"));
74372
74472
  return [...roots];
74373
74473
  }
74374
74474
  function readCodexRolloutCwd(path2) {
@@ -74426,10 +74526,10 @@ function codexRolloutsForCwd(cwd, opts = {}) {
74426
74526
  continue;
74427
74527
  }
74428
74528
  for (const name2 of names) {
74429
- const full = join19(dir, name2);
74529
+ const full = join20(dir, name2);
74430
74530
  let st;
74431
74531
  try {
74432
- st = statSync5(full);
74532
+ st = statSync6(full);
74433
74533
  } catch {
74434
74534
  continue;
74435
74535
  }
@@ -74458,8 +74558,8 @@ function codexRolloutsForCwd(cwd, opts = {}) {
74458
74558
  function geminiSessionRoots(env2 = process.env, home = homedir4()) {
74459
74559
  const roots = /* @__PURE__ */ new Set();
74460
74560
  for (const d of splitPathList(env2["ERRATA_GEMINI_SESSIONS_DIRS"])) roots.add(d);
74461
- if (env2["GEMINI_CLI_HOME"]) roots.add(join19(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
74462
- roots.add(join19(home, ".gemini", "tmp"));
74561
+ if (env2["GEMINI_CLI_HOME"]) roots.add(join20(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
74562
+ roots.add(join20(home, ".gemini", "tmp"));
74463
74563
  return [...roots];
74464
74564
  }
74465
74565
  function geminiProjectHash(cwd) {
@@ -74507,7 +74607,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74507
74607
  continue;
74508
74608
  }
74509
74609
  for (const slug2 of slugs) {
74510
- const chats = join19(root, slug2, "chats");
74610
+ const chats = join20(root, slug2, "chats");
74511
74611
  let names;
74512
74612
  try {
74513
74613
  names = readdirSync6(chats);
@@ -74516,10 +74616,10 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74516
74616
  }
74517
74617
  for (const name2 of names) {
74518
74618
  if (!name2.startsWith("session-") || !name2.endsWith(".jsonl")) continue;
74519
- const full = join19(chats, name2);
74619
+ const full = join20(chats, name2);
74520
74620
  let st;
74521
74621
  try {
74522
- st = statSync5(full);
74622
+ st = statSync6(full);
74523
74623
  } catch {
74524
74624
  continue;
74525
74625
  }
@@ -74536,8 +74636,8 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74536
74636
  function opencodeSessionRoots(env2 = process.env, home = homedir4()) {
74537
74637
  const roots = /* @__PURE__ */ new Set();
74538
74638
  for (const d of splitPathList(env2["ERRATA_OPENCODE_SESSIONS_DIRS"])) roots.add(d);
74539
- if (env2["XDG_DATA_HOME"]) roots.add(join19(env2["XDG_DATA_HOME"], "opencode", "errata"));
74540
- roots.add(join19(home, ".local", "share", "opencode", "errata"));
74639
+ if (env2["XDG_DATA_HOME"]) roots.add(join20(env2["XDG_DATA_HOME"], "opencode", "errata"));
74640
+ roots.add(join20(home, ".local", "share", "opencode", "errata"));
74541
74641
  return [...roots];
74542
74642
  }
74543
74643
  function readOpencodeTranscriptDirectory(path2) {
@@ -74579,10 +74679,10 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
74579
74679
  }
74580
74680
  for (const name2 of names) {
74581
74681
  if (!name2.endsWith(".jsonl")) continue;
74582
- const full = join19(root, name2);
74682
+ const full = join20(root, name2);
74583
74683
  let st;
74584
74684
  try {
74585
- st = statSync5(full);
74685
+ st = statSync6(full);
74586
74686
  } catch {
74587
74687
  continue;
74588
74688
  }
@@ -75765,7 +75865,7 @@ ${conversation}` }]
75765
75865
  init_src5();
75766
75866
  init_src2();
75767
75867
  import { existsSync as existsSync17, readFileSync as readFileSync15, readdirSync as readdirSync7, writeFileSync as writeFileSync13 } from "node:fs";
75768
- import { join as join20 } from "node:path";
75868
+ import { join as join21 } from "node:path";
75769
75869
  import { homedir as homedir5 } from "node:os";
75770
75870
  var BACKFILL_VERSION = 1;
75771
75871
  var EMPTY = {
@@ -75779,7 +75879,7 @@ var EMPTY = {
75779
75879
  recoverable: 0
75780
75880
  };
75781
75881
  function markerPath(configDir) {
75782
- return join20(configDir, "constraint-backfill.json");
75882
+ return join21(configDir, "constraint-backfill.json");
75783
75883
  }
75784
75884
  function alreadyDone(configDir) {
75785
75885
  const p = markerPath(configDir);
@@ -75805,7 +75905,7 @@ function replay(root) {
75805
75905
  for (const f of names) {
75806
75906
  let lines;
75807
75907
  try {
75808
- lines = readFileSync15(join20(dir, f), "utf8").split("\n");
75908
+ lines = readFileSync15(join21(dir, f), "utf8").split("\n");
75809
75909
  } catch {
75810
75910
  continue;
75811
75911
  }
@@ -75933,7 +76033,7 @@ function backfillConstraintKind(store, opts) {
75933
76033
  init_src();
75934
76034
  init_src5();
75935
76035
  import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
75936
- import { join as join21 } from "node:path";
76036
+ import { join as join22 } from "node:path";
75937
76037
  function citeEdgeId(from, type, to) {
75938
76038
  return `edge_${digest({ from, type, to })}`.slice(0, 24);
75939
76039
  }
@@ -75948,7 +76048,7 @@ var EMPTY2 = {
75948
76048
  byType: {}
75949
76049
  };
75950
76050
  function markerPath2(configDir) {
75951
- return join21(configDir, "edge-repair.json");
76051
+ return join22(configDir, "edge-repair.json");
75952
76052
  }
75953
76053
  function alreadyDone2(configDir) {
75954
76054
  const p = markerPath2(configDir);
@@ -76018,7 +76118,7 @@ init_reconcile();
76018
76118
 
76019
76119
  // src/pass-ledger.ts
76020
76120
  import { appendFileSync as appendFileSync2, existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
76021
- import { join as join22 } from "node:path";
76121
+ import { join as join23 } from "node:path";
76022
76122
 
76023
76123
  // src/isolate-census.ts
76024
76124
  var live = 0;
@@ -76041,7 +76141,7 @@ var PER_KIND_MAX = 100;
76041
76141
  var TRIM_EVERY = 50;
76042
76142
  var appendsSinceTrim = /* @__PURE__ */ new Map();
76043
76143
  function passLedgerPath(configDir) {
76044
- return join22(configDir, "pass-ledger.jsonl");
76144
+ return join23(configDir, "pass-ledger.jsonl");
76045
76145
  }
76046
76146
  function appendPassLedger(configDir, kind, durationMs, counts) {
76047
76147
  const path2 = passLedgerPath(configDir);
@@ -76468,10 +76568,10 @@ init_src9();
76468
76568
  init_src();
76469
76569
  init_src2();
76470
76570
  import { readFileSync as readFileSync18 } from "node:fs";
76471
- import { join as join23 } from "node:path";
76571
+ import { join as join24 } from "node:path";
76472
76572
  function loadClaimIgnorePatterns(workspaceRoot) {
76473
76573
  try {
76474
- return readFileSync18(join23(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
76574
+ return readFileSync18(join24(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
76475
76575
  } catch {
76476
76576
  return [];
76477
76577
  }
@@ -76834,9 +76934,9 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
76834
76934
  // src/retrieval-stack.ts
76835
76935
  init_src();
76836
76936
  import { execFileSync as execFileSync3 } from "node:child_process";
76837
- import { existsSync as existsSync20, readFileSync as readFileSync19, statSync as statSync6 } from "node:fs";
76937
+ import { existsSync as existsSync20, readFileSync as readFileSync19, statSync as statSync7 } from "node:fs";
76838
76938
  import { homedir as homedir6 } from "node:os";
76839
- import { join as join24 } from "node:path";
76939
+ import { join as join25 } from "node:path";
76840
76940
  var RETRIEVAL_STACK_CAP = 24;
76841
76941
  var MANIFEST_SCAN_CAP = 400;
76842
76942
  var RUNTIME_TOKENS = /* @__PURE__ */ new Set([
@@ -77133,44 +77233,44 @@ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
77133
77233
  };
77134
77234
  const texts = (...paths) => paths.map(read2).filter((t) => t !== null);
77135
77235
  const home = homedir6();
77136
- const npm = parseNpmrcPolicy(texts(join24(root, ".npmrc"), join24(home, ".npmrc")));
77236
+ const npm = parseNpmrcPolicy(texts(join25(root, ".npmrc"), join25(home, ".npmrc")));
77137
77237
  const blocked = /* @__PURE__ */ new Set();
77138
77238
  if (!npm.defaultPublic) blocked.add("npm");
77139
77239
  if (pypiIndexIsPrivate(
77140
77240
  texts(
77141
- join24(root, "pip.conf"),
77142
- join24(root, "pip.ini"),
77143
- join24(root, "pyproject.toml"),
77144
- join24(root, "requirements.txt"),
77145
- join24(home, ".pip", "pip.conf"),
77146
- join24(home, ".config", "pip", "pip.conf"),
77147
- join24(env2["APPDATA"] ?? home, "pip", "pip.ini")
77241
+ join25(root, "pip.conf"),
77242
+ join25(root, "pip.ini"),
77243
+ join25(root, "pyproject.toml"),
77244
+ join25(root, "requirements.txt"),
77245
+ join25(home, ".pip", "pip.conf"),
77246
+ join25(home, ".config", "pip", "pip.conf"),
77247
+ join25(env2["APPDATA"] ?? home, "pip", "pip.ini")
77148
77248
  )
77149
77249
  )) {
77150
77250
  blocked.add("pypi");
77151
77251
  }
77152
77252
  if (cargoRegistryIsPrivate(
77153
77253
  texts(
77154
- join24(root, ".cargo", "config.toml"),
77155
- join24(root, ".cargo", "config"),
77156
- join24(home, ".cargo", "config.toml"),
77157
- join24(home, ".cargo", "config")
77254
+ join25(root, ".cargo", "config.toml"),
77255
+ join25(root, ".cargo", "config"),
77256
+ join25(home, ".cargo", "config.toml"),
77257
+ join25(home, ".cargo", "config")
77158
77258
  )
77159
77259
  )) {
77160
77260
  blocked.add("cargo");
77161
77261
  }
77162
77262
  if (nugetSourcesArePrivate(
77163
77263
  texts(
77164
- join24(root, "NuGet.config"),
77165
- join24(root, "nuget.config"),
77166
- join24(root, "NuGet.Config"),
77167
- join24(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
77168
- join24(home, ".nuget", "NuGet", "NuGet.Config")
77264
+ join25(root, "NuGet.config"),
77265
+ join25(root, "nuget.config"),
77266
+ join25(root, "NuGet.Config"),
77267
+ join25(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
77268
+ join25(home, ".nuget", "NuGet", "NuGet.Config")
77169
77269
  )
77170
77270
  )) {
77171
77271
  blocked.add("nuget");
77172
77272
  }
77173
- const goEnvFile = env2["GOENV"] ?? join24(env2["APPDATA"] ?? join24(home, ".config"), "go", "env");
77273
+ const goEnvFile = env2["GOENV"] ?? join25(env2["APPDATA"] ?? join25(home, ".config"), "go", "env");
77174
77274
  const goEnvText = read2(goEnvFile) ?? "";
77175
77275
  const fromFile = ["GOPRIVATE", "GONOSUMDB", "GONOSUMCHECK"].map(
77176
77276
  (k) => new RegExp(`^${k}=(.*)$`, "m").exec(goEnvText)?.[1]
@@ -77181,10 +77281,10 @@ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
77181
77281
  env2["GONOSUMCHECK"],
77182
77282
  ...fromFile
77183
77283
  ]);
77184
- const gemfiles = texts(join24(root, "Gemfile"));
77284
+ const gemfiles = texts(join25(root, "Gemfile"));
77185
77285
  if (gemSourceIsPrivate(gemfiles)) blocked.add("gem");
77186
77286
  if (mavenReposArePrivate(
77187
- texts(join24(root, "pom.xml"), join24(home, ".m2", "settings.xml"))
77287
+ texts(join25(root, "pom.xml"), join25(home, ".m2", "settings.xml"))
77188
77288
  )) {
77189
77289
  blocked.add("maven");
77190
77290
  }
@@ -77351,10 +77451,10 @@ function readDirectDependencies(root) {
77351
77451
  const familiesSeen = /* @__PURE__ */ new Set();
77352
77452
  for (const c of LOCKFILES) {
77353
77453
  if (familiesSeen.has(c.family)) continue;
77354
- const p = join24(root, c.file);
77454
+ const p = join25(root, c.file);
77355
77455
  if (!existsSync20(p)) continue;
77356
77456
  try {
77357
- const s = statSync6(p);
77457
+ const s = statSync7(p);
77358
77458
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
77359
77459
  } catch {
77360
77460
  continue;
@@ -77415,14 +77515,14 @@ function manifestPaths(root) {
77415
77515
  "project.godot"
77416
77516
  ];
77417
77517
  return {
77418
- paths: ROOT_MANIFESTS.filter((f) => existsSync20(join24(root, f))),
77518
+ paths: ROOT_MANIFESTS.filter((f) => existsSync20(join25(root, f))),
77419
77519
  tracked: false,
77420
77520
  truncated: false
77421
77521
  };
77422
77522
  }
77423
77523
  var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
77424
77524
  function rootDeclaresWorkspace(root, texts) {
77425
- if (WORKSPACE_MARKERS.some((f) => existsSync20(join24(root, f)))) return true;
77525
+ if (WORKSPACE_MARKERS.some((f) => existsSync20(join25(root, f)))) return true;
77426
77526
  return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
77427
77527
  }
77428
77528
  var EMPTY_SCAN = { deps: [], self: [], complete: true };
@@ -77436,9 +77536,9 @@ function scanManifests(root) {
77436
77536
  const texts = /* @__PURE__ */ new Map();
77437
77537
  const stamps = [];
77438
77538
  for (const rel of paths) {
77439
- const abs = join24(root, rel);
77539
+ const abs = join25(root, rel);
77440
77540
  try {
77441
- const s = statSync6(abs);
77541
+ const s = statSync7(abs);
77442
77542
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
77443
77543
  texts.set(rel, readFileSync19(abs, "utf8"));
77444
77544
  } catch {
@@ -77470,7 +77570,7 @@ function readManifestDependencies(root) {
77470
77570
 
77471
77571
  // src/git-sensor.ts
77472
77572
  import { existsSync as existsSync21, readFileSync as readFileSync20, watch as fsWatch } from "node:fs";
77473
- import { join as join25 } from "node:path";
77573
+ import { join as join26 } from "node:path";
77474
77574
  function readFirstLine(path2) {
77475
77575
  try {
77476
77576
  return readFileSync20(path2, "utf8").split(/\r?\n/, 1)[0].trim();
@@ -77479,12 +77579,12 @@ function readFirstLine(path2) {
77479
77579
  }
77480
77580
  }
77481
77581
  function readGitRefState(gitDir) {
77482
- const head2 = readFirstLine(join25(gitDir, "HEAD"));
77582
+ const head2 = readFirstLine(join26(gitDir, "HEAD"));
77483
77583
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
77484
77584
  const branch = m ? m[1] : null;
77485
77585
  let sha2 = null;
77486
77586
  if (branch) {
77487
- sha2 = readFirstLine(join25(gitDir, "refs", "heads", branch));
77587
+ sha2 = readFirstLine(join26(gitDir, "refs", "heads", branch));
77488
77588
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
77489
77589
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
77490
77590
  sha2 = head2;
@@ -77492,13 +77592,13 @@ function readGitRefState(gitDir) {
77492
77592
  return {
77493
77593
  branch,
77494
77594
  sha: sha2,
77495
- mergeHeadExists: existsSync21(join25(gitDir, "MERGE_HEAD")),
77496
- origHeadExists: existsSync21(join25(gitDir, "ORIG_HEAD"))
77595
+ mergeHeadExists: existsSync21(join26(gitDir, "MERGE_HEAD")),
77596
+ origHeadExists: existsSync21(join26(gitDir, "ORIG_HEAD"))
77497
77597
  };
77498
77598
  }
77499
77599
  function shaFromPackedRefs(gitDir, ref) {
77500
77600
  try {
77501
- for (const line of readFileSync20(join25(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
77601
+ for (const line of readFileSync20(join26(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
77502
77602
  const [sha2, name2] = line.split(/\s+/);
77503
77603
  if (name2 === ref && sha2) return sha2;
77504
77604
  }
@@ -77532,7 +77632,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
77532
77632
  const settle = () => {
77533
77633
  if (timer) clearTimeout(timer);
77534
77634
  timer = setTimeout(() => {
77535
- if (existsSync21(join25(gitDir, "index.lock"))) {
77635
+ if (existsSync21(join26(gitDir, "index.lock"))) {
77536
77636
  settle();
77537
77637
  return;
77538
77638
  }
@@ -77543,7 +77643,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
77543
77643
  }, debounceMs);
77544
77644
  };
77545
77645
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
77546
- const p = join25(gitDir, sub);
77646
+ const p = join26(gitDir, sub);
77547
77647
  try {
77548
77648
  watchers.push(fsWatch(p, settle));
77549
77649
  } catch {
@@ -77768,7 +77868,7 @@ var TelemetryRecorder = class {
77768
77868
 
77769
77869
  // src/file-activity.ts
77770
77870
  import { readFileSync as readFileSync22 } from "node:fs";
77771
- import { join as join27 } from "node:path";
77871
+ import { join as join28 } from "node:path";
77772
77872
  import { createHash as createHash15 } from "node:crypto";
77773
77873
 
77774
77874
  // ../../packages/privacy/src/patterns/credentials.ts
@@ -78520,7 +78620,7 @@ init_git_remote();
78520
78620
  // src/history-bundle.ts
78521
78621
  import { execFile as execFile2 } from "node:child_process";
78522
78622
  import { readFileSync as readFileSync21 } from "node:fs";
78523
- import { join as join26 } from "node:path";
78623
+ import { join as join27 } from "node:path";
78524
78624
  var DEFAULT_MAX_TOKENS = 6e3;
78525
78625
  var FILE_LIST_CAP = 60;
78526
78626
  var DIFF_FILE_CAP = 40;
@@ -78557,7 +78657,7 @@ function pathAllowedByFloor(path2) {
78557
78657
  function loadRepoIgnore(root, extraPatterns = []) {
78558
78658
  let source = "";
78559
78659
  try {
78560
- source = readFileSync21(join26(root, ".errataignore"), "utf8");
78660
+ source = readFileSync21(join27(root, ".errataignore"), "utf8");
78561
78661
  } catch {
78562
78662
  source = "";
78563
78663
  }
@@ -78975,7 +79075,7 @@ function readActivityBranch(root) {
78975
79075
  try {
78976
79076
  const gitDir = resolveGitDir(root);
78977
79077
  if (!gitDir) return null;
78978
- const head2 = readFileSync22(join27(gitDir, "HEAD"), "utf8").trim();
79078
+ const head2 = readFileSync22(join28(gitDir, "HEAD"), "utf8").trim();
78979
79079
  const branch = head2.startsWith("ref: refs/heads/") ? head2.slice(16) : /^[a-f0-9]{40,64}$/i.test(head2) ? "HEAD" : null;
78980
79080
  return branch && branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(branch) ? branch : null;
78981
79081
  } catch {
@@ -79139,7 +79239,7 @@ import {
79139
79239
  unlinkSync as unlinkSync2,
79140
79240
  writeFileSync as writeFileSync16
79141
79241
  } from "node:fs";
79142
- import { basename as basename6, join as join28 } from "node:path";
79242
+ import { basename as basename6, join as join29 } from "node:path";
79143
79243
  function skillFileName(id) {
79144
79244
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
79145
79245
  }
@@ -79170,7 +79270,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
79170
79270
  for (const s of res.skills) {
79171
79271
  const fileName = skillFileName(s.id);
79172
79272
  keep.add(fileName);
79173
- writeFileSync16(join28(paths.skillsDir, fileName), s.markdown, "utf8");
79273
+ writeFileSync16(join29(paths.skillsDir, fileName), s.markdown, "utf8");
79174
79274
  rows.push({
79175
79275
  id: s.id,
79176
79276
  title: s.title,
@@ -79183,7 +79283,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
79183
79283
  const fileName = skillFileName(p.id);
79184
79284
  if (keep.has(fileName)) continue;
79185
79285
  keep.add(fileName);
79186
- writeFileSync16(join28(paths.skillsDir, fileName), p.markdown, "utf8");
79286
+ writeFileSync16(join29(paths.skillsDir, fileName), p.markdown, "utf8");
79187
79287
  rows.push({
79188
79288
  id: p.id,
79189
79289
  title: p.title,
@@ -79197,7 +79297,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
79197
79297
  if (!f.endsWith(".md")) continue;
79198
79298
  if (keep.has(basename6(f))) continue;
79199
79299
  try {
79200
- unlinkSync2(join28(paths.skillsDir, f));
79300
+ unlinkSync2(join29(paths.skillsDir, f));
79201
79301
  pruned++;
79202
79302
  } catch {
79203
79303
  }
@@ -79224,13 +79324,13 @@ import {
79224
79324
  symlinkSync,
79225
79325
  writeFileSync as writeFileSync17
79226
79326
  } from "node:fs";
79227
- import { join as join29 } from "node:path";
79327
+ import { join as join30 } from "node:path";
79228
79328
  var SKILL_NS = "errata-";
79229
79329
  var HARNESS_SKILL_DIRS = [
79230
- { configDir: ".claude", skillsDir: join29(".claude", "skills") },
79330
+ { configDir: ".claude", skillsDir: join30(".claude", "skills") },
79231
79331
  // Cursor adopted the standard; its exact project dir is still moving — kept
79232
79332
  // best-effort and gated on `.cursor/` presence so we never create it blind.
79233
- { configDir: ".cursor", skillsDir: join29(".cursor", "skills") }
79333
+ { configDir: ".cursor", skillsDir: join30(".cursor", "skills") }
79234
79334
  ];
79235
79335
  function skillSlug(title, id) {
79236
79336
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -79280,7 +79380,7 @@ function reconcileNamespaced(dir, keep) {
79280
79380
  for (const name2 of readdirSync9(dir)) {
79281
79381
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
79282
79382
  try {
79283
- rmSync3(join29(dir, name2), { recursive: true, force: true });
79383
+ rmSync3(join30(dir, name2), { recursive: true, force: true });
79284
79384
  pruned++;
79285
79385
  } catch {
79286
79386
  }
@@ -79310,7 +79410,7 @@ function safeLstat(p) {
79310
79410
  }
79311
79411
  }
79312
79412
  function emitAndProjectSkills(root, skills) {
79313
- const agentsSkillsDir = join29(root, ".agents", "skills");
79413
+ const agentsSkillsDir = join30(root, ".agents", "skills");
79314
79414
  mkdirSync8(agentsSkillsDir, { recursive: true });
79315
79415
  const slugs = [];
79316
79416
  const keep = /* @__PURE__ */ new Set();
@@ -79327,9 +79427,9 @@ function emitAndProjectSkills(root, skills) {
79327
79427
  keep.add(slug2);
79328
79428
  slugs.push(slug2);
79329
79429
  const description = deriveDescription(s.title, s.layer, body2);
79330
- mkdirSync8(join29(agentsSkillsDir, slug2), { recursive: true });
79430
+ mkdirSync8(join30(agentsSkillsDir, slug2), { recursive: true });
79331
79431
  writeFileSync17(
79332
- join29(agentsSkillsDir, slug2, "SKILL.md"),
79432
+ join30(agentsSkillsDir, slug2, "SKILL.md"),
79333
79433
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
79334
79434
  "utf8"
79335
79435
  );
@@ -79338,11 +79438,11 @@ function emitAndProjectSkills(root, skills) {
79338
79438
  reconcileNamespaced(agentsSkillsDir, keep);
79339
79439
  let projected = 0;
79340
79440
  for (const h of HARNESS_SKILL_DIRS) {
79341
- if (!existsSync23(join29(root, h.configDir))) continue;
79342
- const dir = join29(root, h.skillsDir);
79441
+ if (!existsSync23(join30(root, h.configDir))) continue;
79442
+ const dir = join30(root, h.skillsDir);
79343
79443
  mkdirSync8(dir, { recursive: true });
79344
79444
  for (const slug2 of slugs) {
79345
- linkOrCopy(join29(dir, slug2), join29(agentsSkillsDir, slug2));
79445
+ linkOrCopy(join30(dir, slug2), join30(agentsSkillsDir, slug2));
79346
79446
  projected++;
79347
79447
  }
79348
79448
  reconcileNamespaced(dir, keep);
@@ -79359,7 +79459,7 @@ function emitInputsFromManifest(erretaDir, manifestPath) {
79359
79459
  title: s.title ?? s.id,
79360
79460
  layer: s.layer ?? "technique",
79361
79461
  confidence: s.confidence ?? 0,
79362
- bodyPath: join29(erretaDir, s.file)
79462
+ bodyPath: join30(erretaDir, s.file)
79363
79463
  }));
79364
79464
  } catch {
79365
79465
  return [];
@@ -79373,7 +79473,7 @@ var GITIGNORE_LINES = [
79373
79473
  ".cursor/skills/errata-*/"
79374
79474
  ];
79375
79475
  function ensureSkillGitignore(root) {
79376
- const path2 = join29(root, ".gitignore");
79476
+ const path2 = join30(root, ".gitignore");
79377
79477
  let current = "";
79378
79478
  try {
79379
79479
  current = existsSync23(path2) ? readFileSync24(path2, "utf8") : "";
@@ -79480,12 +79580,12 @@ init_profile2();
79480
79580
 
79481
79581
  // src/witness-queue.ts
79482
79582
  import { readFileSync as readFileSync25, renameSync as renameSync2, writeFileSync as writeFileSync18 } from "node:fs";
79483
- import { dirname as dirname11, join as join30 } from "node:path";
79583
+ import { dirname as dirname11, join as join31 } from "node:path";
79484
79584
  var WITNESS_QUEUE_CAP = 500;
79485
79585
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
79486
79586
  var WITNESS_MAX_ATTEMPTS = 5;
79487
79587
  function witnessQueuePath(workspaceConfigDir) {
79488
- return join30(workspaceConfigDir, "witness-queue.json");
79588
+ return join31(workspaceConfigDir, "witness-queue.json");
79489
79589
  }
79490
79590
  function loadWitnessQueueWithLosses(path2) {
79491
79591
  let raw2;
@@ -79503,7 +79603,7 @@ function loadWitnessQueueWithLosses(path2) {
79503
79603
  }
79504
79604
  function saveWitnessQueue(path2, queue) {
79505
79605
  try {
79506
- const tmp = join30(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
79606
+ const tmp = join31(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
79507
79607
  writeFileSync18(tmp, JSON.stringify(queue), "utf8");
79508
79608
  renameSync2(tmp, path2);
79509
79609
  } catch {
@@ -79812,7 +79912,7 @@ function maybeFlushDigests() {
79812
79912
  // src/liveness-watch.ts
79813
79913
  init_src5();
79814
79914
  import { readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "node:fs";
79815
- import { join as join32 } from "node:path";
79915
+ import { join as join33 } from "node:path";
79816
79916
 
79817
79917
  // src/loop-lag.ts
79818
79918
  var HEARTBEAT_MS = 500;
@@ -79943,7 +80043,7 @@ function watchCensusLine(c = watchCensus(), now = Date.now()) {
79943
80043
  var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
79944
80044
  var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
79945
80045
  function alarmStatePath(configDir) {
79946
- return join32(configDir, "liveness-alarms.json");
80046
+ return join33(configDir, "liveness-alarms.json");
79947
80047
  }
79948
80048
  function loadAlarmState(configDir) {
79949
80049
  try {
@@ -79982,22 +80082,22 @@ function createLivenessWatch(deps) {
79982
80082
  const rows = evaluateMechanisms(deps.store, invocations);
79983
80083
  const workspaceActive = invocations.has("capture") || invocations.has("render");
79984
80084
  const bad = workspaceActive ? rows.filter((r) => hasStarvedMechanism([r])) : [];
79985
- const watch2 = watchCensus();
80085
+ const watch3 = watchCensus();
79986
80086
  const pass = passState();
79987
80087
  appendPassLedger(deps.configDir, "liveness-watch", Date.now() - started2, {
79988
80088
  mechanisms: rows.length,
79989
80089
  alarms: bad.length,
79990
80090
  ...Object.fromEntries(bad.map((r) => [`starved:${r.id}`, 1])),
79991
80091
  ...deps.witnessParked ? { witnessParked: deps.witnessParked() } : {},
79992
- watchDispatched: watch2.dispatched,
79993
- watchEmitted: watch2.emitted,
79994
- watchLogged: watch2.logged,
79995
- watchRejected: watch2.rejected,
80092
+ watchDispatched: watch3.dispatched,
80093
+ watchEmitted: watch3.emitted,
80094
+ watchLogged: watch3.logged,
80095
+ watchRejected: watch3.rejected,
79996
80096
  // HZ-watch-breaker: a recycle count trending upward across hours is a
79997
80097
  // handle that keeps wedging — the restart-survivable trace the 8-16
79998
80098
  // phantom-rename storm never left.
79999
- watchBreakerRecycles: watch2.breakerRecycles,
80000
- watchBreakerQuarantined: watch2.breakerQuarantined.length,
80099
+ watchBreakerRecycles: watch3.breakerRecycles,
80100
+ watchBreakerQuarantined: watch3.breakerQuarantined.length,
80001
80101
  // Concurrency and the longest single holder — the two readings that
80002
80102
  // named the 6017s zombie pass. A pass legitimately running for hours
80003
80103
  // and one wedged forever look identical without a trend.
@@ -80124,7 +80224,7 @@ function createWatchBreaker(deps) {
80124
80224
  }
80125
80225
 
80126
80226
  // src/engine.ts
80127
- var DAEMON_VERSION = true ? "2.0.8-dev.2895" : "2.0.0-alpha.0";
80227
+ var DAEMON_VERSION = true ? "2.0.8-dev.2914" : "2.0.0-alpha.0";
80128
80228
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
80129
80229
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
80130
80230
  var GIT_OP_MUTE_MS = 4e3;
@@ -80136,7 +80236,7 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
80136
80236
  function appendIdentityAudit(path2, record2, line) {
80137
80237
  if (!record2.accepted && record2.score <= 0) return;
80138
80238
  try {
80139
- if (existsSync25(path2) && statSync7(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
80239
+ if (existsSync25(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
80140
80240
  renameSync3(path2, `${path2}.1`);
80141
80241
  }
80142
80242
  appendFileSync4(path2, line);
@@ -80194,7 +80294,7 @@ function gitSourceWatchTargets(root) {
80194
80294
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
80195
80295
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
80196
80296
  );
80197
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join33(root, d) + sep4));
80297
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join34(root, d) + sep4));
80198
80298
  } catch {
80199
80299
  }
80200
80300
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -80206,19 +80306,19 @@ function gitSourceWatchTargets(root) {
80206
80306
  if (!f.startsWith(prefix)) continue;
80207
80307
  const rest2 = f.slice(prefix.length);
80208
80308
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
80209
- else targets.add(join33(root, f));
80309
+ else targets.add(join34(root, f));
80210
80310
  }
80211
80311
  for (const c of children) {
80212
- if (IGNORED_PATH.test(join33(root, c) + sep4)) continue;
80312
+ if (IGNORED_PATH.test(join34(root, c) + sep4)) continue;
80213
80313
  if (hasIgnoredChild(c)) addUnder(c);
80214
- else targets.add(join33(root, c));
80314
+ else targets.add(join34(root, c));
80215
80315
  }
80216
80316
  };
80217
80317
  addUnder("");
80218
80318
  if (targets.size > 0) return [...targets];
80219
80319
  } catch {
80220
80320
  }
80221
- return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join33(root, String(e.name)) + sep4)).map((e) => join33(root, String(e.name)));
80321
+ return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join34(root, String(e.name)) + sep4)).map((e) => join34(root, String(e.name)));
80222
80322
  }
80223
80323
  function createWorkspaceEngine(opts) {
80224
80324
  const paths = workspacePaths(opts.workspaceRoot);
@@ -80278,12 +80378,10 @@ function createWorkspaceEngine(opts) {
80278
80378
  let flushTimer = null;
80279
80379
  if (!opts.skipWatchers) {
80280
80380
  const watchTargets = gitSourceWatchTargets(opts.workspaceRoot);
80281
- watcher = esm_default.watch(watchTargets, {
80381
+ watcher = createSourceWatcher(watchTargets, {
80282
80382
  // Still apply the ignore as defense-in-depth: nested node_modules inside a
80283
80383
  // watched dir, and Windows-mangled store paths (IGNORED_NOISE), never reach us.
80284
- ignored: (p) => IGNORED_PATH.test(p) || IGNORED_NOISE.test(p),
80285
- ignoreInitial: true,
80286
- persistent: true
80384
+ ignored: (p) => IGNORED_PATH.test(p) || IGNORED_NOISE.test(p)
80287
80385
  });
80288
80386
  noteWatcherOpened();
80289
80387
  watchBreaker = createWatchBreaker({
@@ -80311,7 +80409,7 @@ function createWorkspaceEngine(opts) {
80311
80409
  }
80312
80410
  let size = 0;
80313
80411
  try {
80314
- size = statSync7(path2).size;
80412
+ size = statSync8(path2).size;
80315
80413
  } catch {
80316
80414
  }
80317
80415
  lastActivityTs = Date.now();
@@ -80426,7 +80524,7 @@ function createWorkspaceEngine(opts) {
80426
80524
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
80427
80525
  let episodeId2;
80428
80526
  if (srcPaths.length > 0) {
80429
- const abs = srcPaths.map((p) => join33(opts.workspaceRoot, p));
80527
+ const abs = srcPaths.map((p) => join34(opts.workspaceRoot, p));
80430
80528
  try {
80431
80529
  const r = await runReindexPass(
80432
80530
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -80462,7 +80560,7 @@ function createWorkspaceEngine(opts) {
80462
80560
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
80463
80561
  );
80464
80562
  };
80465
- const gitDir = join33(opts.workspaceRoot, ".git");
80563
+ const gitDir = join34(opts.workspaceRoot, ".git");
80466
80564
  if (existsSync25(gitDir)) {
80467
80565
  stopGit = startGitSensor(gitDir, (ev) => {
80468
80566
  void handleGitEvent(ev).catch((err2) => {
@@ -80644,10 +80742,10 @@ function createWorkspaceEngine(opts) {
80644
80742
  console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
80645
80743
  }
80646
80744
  writeContextFile(opts.workspaceRoot, body2);
80647
- const target = join33(opts.workspaceRoot, "AGENTS.md");
80745
+ const target = join34(opts.workspaceRoot, "AGENTS.md");
80648
80746
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
80649
80747
  if (elicit) {
80650
- writePrimingHandles(join33(paths.configDir, "priming-handles.json"), [
80748
+ writePrimingHandles(join34(paths.configDir, "priming-handles.json"), [
80651
80749
  ...snapshot.recentProblems.map((r) => r.node),
80652
80750
  // Resolved-band handles: the ✓ problem AND its Solution are citable
80653
80751
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -80989,7 +81087,7 @@ function createWorkspaceEngine(opts) {
80989
81087
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
80990
81088
  });
80991
81089
  };
80992
- const turnCursorPath = join33(paths.configDir, "turn-cursors.json");
81090
+ const turnCursorPath = join34(paths.configDir, "turn-cursors.json");
80993
81091
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
80994
81092
  const turnOffset = loadTurnOffsets(turnCursorPath);
80995
81093
  const readLosses = { parseFailures: 0, ioFailures: 0, bytesUnreachable: 0, sliceGuardHits: 0 };
@@ -81044,7 +81142,7 @@ function createWorkspaceEngine(opts) {
81044
81142
  let processedTurns = 0;
81045
81143
  const seqAtStart = store.currentIngestSeq();
81046
81144
  const elicit = isEdgeElicitationEnabled();
81047
- const handleMap = elicit ? readPrimingHandles(join33(paths.configDir, "priming-handles.json")) : {};
81145
+ const handleMap = elicit ? readPrimingHandles(join34(paths.configDir, "priming-handles.json")) : {};
81048
81146
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
81049
81147
  const toRel = (abs) => {
81050
81148
  const p = abs.replace(/\\/g, "/");
@@ -81336,10 +81434,10 @@ function createWorkspaceEngine(opts) {
81336
81434
  let enclosing = {};
81337
81435
  if (p.location?.line !== void 0) {
81338
81436
  try {
81339
- const headSha = readGitRefState(join33(opts.workspaceRoot, ".git")).sha ?? void 0;
81437
+ const headSha = readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0;
81340
81438
  enclosing = {
81341
81439
  line: p.location.line,
81342
- fileText: readFileSync28(join33(opts.workspaceRoot, anchorPath), "utf8"),
81440
+ fileText: readFileSync28(join34(opts.workspaceRoot, anchorPath), "utf8"),
81343
81441
  ...headSha ? { headSha } : {}
81344
81442
  };
81345
81443
  } catch {
@@ -82102,7 +82200,7 @@ B: ${b}`,
82102
82200
  try {
82103
82201
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
82104
82202
  emitAndProjectSkills(opts.workspaceRoot, inputs);
82105
- writePrimingHandles(join33(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
82203
+ writePrimingHandles(join34(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
82106
82204
  } catch (err2) {
82107
82205
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
82108
82206
  }
@@ -82605,7 +82703,7 @@ init_reconcile();
82605
82703
  // src/lockfile-auto.ts
82606
82704
  init_src();
82607
82705
  import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
82608
- import { join as join34 } from "node:path";
82706
+ import { join as join35 } from "node:path";
82609
82707
 
82610
82708
  // src/package-index.ts
82611
82709
  init_src();
@@ -82754,7 +82852,7 @@ function runLockfilePass(opts) {
82754
82852
  { file: "package-lock.json", parse: parsePackageLockJson }
82755
82853
  ];
82756
82854
  for (const c of candidates) {
82757
- const p = join34(opts.root, c.file);
82855
+ const p = join35(opts.root, c.file);
82758
82856
  if (!existsSync27(p)) continue;
82759
82857
  let sbom;
82760
82858
  try {
@@ -82819,7 +82917,7 @@ init_profile2();
82819
82917
 
82820
82918
  // src/public-symbols.ts
82821
82919
  import { readFileSync as readFileSync30, readdirSync as readdirSync11, existsSync as existsSync28 } from "node:fs";
82822
- import { join as join35 } from "node:path";
82920
+ import { join as join36 } from "node:path";
82823
82921
  var HEAD_BYTES = 8 * 1024;
82824
82922
  var INDEX_TTL_MS = 10 * 60 * 1e3;
82825
82923
  var MIN_SYMBOL_LEN = 4;
@@ -82852,7 +82950,7 @@ function bindingNames(clause) {
82852
82950
  function internalPackageNames(workspaceRoot) {
82853
82951
  const names = /* @__PURE__ */ new Set();
82854
82952
  const tryRead = (dir) => {
82855
- const pj = join35(dir, "package.json");
82953
+ const pj = join36(dir, "package.json");
82856
82954
  if (!existsSync28(pj)) return;
82857
82955
  try {
82858
82956
  const name2 = JSON.parse(readFileSync30(pj, "utf8")).name;
@@ -82862,10 +82960,10 @@ function internalPackageNames(workspaceRoot) {
82862
82960
  };
82863
82961
  tryRead(workspaceRoot);
82864
82962
  for (const group of ["packages", "apps"]) {
82865
- const groupDir = join35(workspaceRoot, group);
82963
+ const groupDir = join36(workspaceRoot, group);
82866
82964
  if (!existsSync28(groupDir)) continue;
82867
82965
  try {
82868
- for (const entry of readdirSync11(groupDir)) tryRead(join35(groupDir, entry));
82966
+ for (const entry of readdirSync11(groupDir)) tryRead(join36(groupDir, entry));
82869
82967
  } catch {
82870
82968
  }
82871
82969
  }
@@ -82904,7 +83002,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
82904
83002
  }
82905
83003
  const symbols = /* @__PURE__ */ new Set();
82906
83004
  for (const rel of files) {
82907
- const head2 = readHead(join35(workspaceRoot, rel));
83005
+ const head2 = readHead(join36(workspaceRoot, rel));
82908
83006
  if (!head2) continue;
82909
83007
  for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
82910
83008
  re.lastIndex = 0;
@@ -84341,7 +84439,7 @@ init_src7();
84341
84439
  init_src();
84342
84440
  import { execFile as execFile4 } from "node:child_process";
84343
84441
  import { readFileSync as readFileSync32 } from "node:fs";
84344
- import { join as join36 } from "node:path";
84442
+ import { join as join37 } from "node:path";
84345
84443
  import { promisify as promisify2 } from "node:util";
84346
84444
 
84347
84445
  // src/history-walk.ts
@@ -84782,7 +84880,7 @@ async function defaultGit(root, args2) {
84782
84880
  function readIgnoreLines(root, profile) {
84783
84881
  let lines = [];
84784
84882
  try {
84785
- lines = readFileSync32(join36(root, ".errataignore"), "utf8").split("\n");
84883
+ lines = readFileSync32(join37(root, ".errataignore"), "utf8").split("\n");
84786
84884
  } catch {
84787
84885
  }
84788
84886
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -85205,7 +85303,7 @@ init_cloud_auth();
85205
85303
  import { createHash as createHash16 } from "node:crypto";
85206
85304
  import { execFileSync as execFileSync5 } from "node:child_process";
85207
85305
  import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
85208
- import { join as join37 } from "node:path";
85306
+ import { join as join38 } from "node:path";
85209
85307
 
85210
85308
  // src/device-poll.ts
85211
85309
  var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
@@ -85663,7 +85761,7 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
85663
85761
  delete nextProfile.projectLinkHold;
85664
85762
  let wroteIgnore = false;
85665
85763
  if (decision.writeIgnoreStarter !== false) {
85666
- const target = join37(root, ".errataignore");
85764
+ const target = join38(root, ".errataignore");
85667
85765
  if (!existsSync30(target)) {
85668
85766
  writeFileSync23(target, IGNORE_STARTER, "utf8");
85669
85767
  wroteIgnore = true;
@@ -85679,11 +85777,11 @@ init_registry();
85679
85777
  // src/adopt.ts
85680
85778
  init_git_remote();
85681
85779
  import { existsSync as existsSync31 } from "node:fs";
85682
- import { dirname as dirname12, join as join38 } from "node:path";
85780
+ import { dirname as dirname12, join as join39 } from "node:path";
85683
85781
  function findGitRoot(absPath) {
85684
85782
  let dir = absPath;
85685
85783
  for (let depth = 0; depth < 64; depth++) {
85686
- if (existsSync31(join38(dir, ".git"))) return dir;
85784
+ if (existsSync31(join39(dir, ".git"))) return dir;
85687
85785
  const parent = dirname12(dir);
85688
85786
  if (parent === dir) return null;
85689
85787
  dir = parent;
@@ -86614,6 +86712,15 @@ async function startMultiDaemon(opts = {}) {
86614
86712
  app.post("/api/context-inject", (c) => forward(c, cwdOf, { affinity: "follow" }));
86615
86713
  app.post("/api/statusline", async (c) => {
86616
86714
  const body2 = await c.req.json().catch(() => ({}));
86715
+ const dir = statuslineDir(body2);
86716
+ if (dir !== null) {
86717
+ const d = normPath(dir);
86718
+ const known = listWorkspaceEntries().some((e) => {
86719
+ const root = normPath(e.path);
86720
+ return d === root || d.startsWith(`${root}/`);
86721
+ });
86722
+ if (!known) return c.text("");
86723
+ }
86617
86724
  return c.text(statuslineText(String(body2["session_id"] ?? "")));
86618
86725
  });
86619
86726
  for (const r of records) {
@@ -88067,15 +88174,15 @@ function shouldUseOAuthLogin(flags2, env2 = process.env) {
88067
88174
  import { spawnSync } from "node:child_process";
88068
88175
 
88069
88176
  // src/codex-runtime.ts
88070
- import { readdirSync as readdirSync12, statSync as statSync8 } from "node:fs";
88071
- import { join as join39 } from "node:path";
88177
+ import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
88178
+ import { join as join40 } from "node:path";
88072
88179
  function resolveCodexExecutable(options = {}) {
88073
88180
  const platform = options.platform ?? process.platform;
88074
88181
  const env2 = options.env ?? process.env;
88075
88182
  if (platform !== "win32") return "codex";
88076
88183
  const fileTime = (path2) => {
88077
88184
  try {
88078
- const s = statSync8(path2);
88185
+ const s = statSync9(path2);
88079
88186
  return s.isFile() ? s.mtimeMs : null;
88080
88187
  } catch {
88081
88188
  return null;
@@ -88083,13 +88190,13 @@ function resolveCodexExecutable(options = {}) {
88083
88190
  };
88084
88191
  for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
88085
88192
  if (!dir.trim()) continue;
88086
- const path2 = join39(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
88193
+ const path2 = join40(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
88087
88194
  if (fileTime(path2) !== null) return path2;
88088
88195
  }
88089
88196
  if (!env2["LOCALAPPDATA"]) return "codex";
88090
- const root = join39(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
88197
+ const root = join40(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
88091
88198
  try {
88092
- const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join39(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
88199
+ const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join40(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
88093
88200
  return candidates[0]?.path ?? "codex";
88094
88201
  } catch {
88095
88202
  return "codex";
@@ -88210,7 +88317,7 @@ import { createInterface } from "node:readline";
88210
88317
  // src/codex-hooks.ts
88211
88318
  import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "node:fs";
88212
88319
  import { homedir as homedir7 } from "node:os";
88213
- import { join as join40 } from "node:path";
88320
+ import { join as join41 } from "node:path";
88214
88321
 
88215
88322
  // src/hook-commands.ts
88216
88323
  function hookCurlCommand(port, path2 = "/api/hook") {
@@ -88286,8 +88393,8 @@ try {
88286
88393
 
88287
88394
  // src/codex-hooks.ts
88288
88395
  var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
88289
- function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join40(homedir7(), ".codex")) {
88290
- return existsSync33(join40(root, ".codex")) || existsSync33(codexHome);
88396
+ function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join41(homedir7(), ".codex")) {
88397
+ return existsSync33(join41(root, ".codex")) || existsSync33(codexHome);
88291
88398
  }
88292
88399
  function replaceCodexHooks(existing, block) {
88293
88400
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -88303,12 +88410,12 @@ function replaceCodexHooks(existing, block) {
88303
88410
  return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
88304
88411
  }
88305
88412
  function writeCodexHooks(root, port, nodePath = process.execPath) {
88306
- const dir = join40(root, ".codex");
88307
- const file2 = join40(dir, "config.toml");
88308
- const relay = join40(dir, "hooks", "errata-relay.mjs");
88413
+ const dir = join41(root, ".codex");
88414
+ const file2 = join41(dir, "config.toml");
88415
+ const relay = join41(dir, "hooks", "errata-relay.mjs");
88309
88416
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
88310
88417
  const final = replaceCodexHooks(existsSync33(file2) ? readFileSync34(file2, "utf8") : "", block);
88311
- mkdirSync9(join40(dir, "hooks"), { recursive: true });
88418
+ mkdirSync9(join41(dir, "hooks"), { recursive: true });
88312
88419
  writeFileSync25(relay, CODEX_RELAY_SOURCE, "utf8");
88313
88420
  writeFileSync25(file2, final, "utf8");
88314
88421
  return file2;
@@ -88474,9 +88581,10 @@ function consolidationGapMs(lastPassMs, policy) {
88474
88581
  }
88475
88582
 
88476
88583
  // src/claude-statusline.ts
88477
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync26 } from "node:fs";
88478
- import { join as join41 } from "node:path";
88479
- var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks claude
88584
+ import { existsSync as existsSync34, mkdirSync as mkdirSync10, readFileSync as readFileSync35, writeFileSync as writeFileSync26 } from "node:fs";
88585
+ import { homedir as homedir8 } from "node:os";
88586
+ import { dirname as dirname13, join as join42 } from "node:path";
88587
+ var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
88480
88588
  import { readFileSync } from 'node:fs';
88481
88589
 
88482
88590
  try {
@@ -88502,15 +88610,57 @@ function buildStatusLine(port, nodePath, relayPath) {
88502
88610
  function isErrataStatusLine(value) {
88503
88611
  return !!value && typeof value === "object" && typeof value["command"] === "string" && value["command"].includes(STATUSLINE_RELAY_FILE);
88504
88612
  }
88505
- function installStatusLine(settings, root, port, nodePath = process.execPath) {
88506
- if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return false;
88507
- const dir = join41(root, ".claude", "hooks");
88508
- const relay = join41(dir, STATUSLINE_RELAY_FILE);
88509
- mkdirSync10(dir, { recursive: true });
88510
- writeFileSync26(relay, STATUSLINE_RELAY_SOURCE, "utf8");
88511
- settings["statusLine"] = buildStatusLine(port, nodePath, relay);
88613
+ function removeProjectStatusLine(settings) {
88614
+ if (!isErrataStatusLine(settings["statusLine"])) return false;
88615
+ delete settings["statusLine"];
88512
88616
  return true;
88513
88617
  }
88618
+ function userClaudeSettingsPath() {
88619
+ const base = process.env["CLAUDE_CONFIG_DIR"] ?? join42(homedir8(), ".claude");
88620
+ return join42(base, "settings.json");
88621
+ }
88622
+ function ensureUserStatusLine(opts) {
88623
+ const env2 = opts.env ?? process.env;
88624
+ const off = (env2["ERRATA_STATUSLINE"] ?? "").trim().toLowerCase();
88625
+ if (off === "0" || off === "off" || off === "false" || off === "no") return "disabled";
88626
+ const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
88627
+ let settings = {};
88628
+ if (existsSync34(settingsPath)) {
88629
+ try {
88630
+ const parsed = JSON.parse(readFileSync35(settingsPath, "utf8"));
88631
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
88632
+ settings = parsed;
88633
+ } catch {
88634
+ return "unreadable";
88635
+ }
88636
+ }
88637
+ if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
88638
+ const relay = join42(opts.relayDir, STATUSLINE_RELAY_FILE);
88639
+ mkdirSync10(opts.relayDir, { recursive: true });
88640
+ if (!existsSync34(relay) || readFileSync35(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
88641
+ writeFileSync26(relay, STATUSLINE_RELAY_SOURCE, "utf8");
88642
+ }
88643
+ const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
88644
+ if (JSON.stringify(settings["statusLine"]) === JSON.stringify(next)) return "unchanged";
88645
+ settings["statusLine"] = next;
88646
+ mkdirSync10(dirname13(settingsPath), { recursive: true });
88647
+ writeFileSync26(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
88648
+ return "installed";
88649
+ }
88650
+ function describeStatusLineOutcome(outcome) {
88651
+ switch (outcome) {
88652
+ case "installed":
88653
+ return "status line: errata recall card in colour (user settings; ERRATA_STATUSLINE=off opts out)";
88654
+ case "unchanged":
88655
+ return "status line: errata recall card already set up";
88656
+ case "kept-own":
88657
+ return "status line: kept your own \u2014 errata's recall card shows inline only";
88658
+ case "disabled":
88659
+ return "status line: skipped (ERRATA_STATUSLINE=off)";
88660
+ case "unreadable":
88661
+ return "status line: skipped \u2014 ~/.claude/settings.json is not valid JSON";
88662
+ }
88663
+ }
88514
88664
 
88515
88665
  // src/opencode-plugin.ts
88516
88666
  var OPENCODE_PLUGIN_MARKER = "// @inerrata opencode plugin \u2014 errata-managed (errata install-hooks opencode)";
@@ -88917,14 +89067,14 @@ async function cmdInit() {
88917
89067
  if (!skipHooks) {
88918
89068
  console.log("");
88919
89069
  console.log("installing harness hooks...");
88920
- const { existsSync: existsSync35 } = await import("node:fs");
88921
- const { join: join43 } = await import("node:path");
89070
+ const { existsSync: existsSync36 } = await import("node:fs");
89071
+ const { join: join44 } = await import("node:path");
88922
89072
  try {
88923
89073
  await installClaudeHooks(port);
88924
89074
  } catch (err2) {
88925
89075
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
88926
89076
  }
88927
- if (existsSync35(join43(ROOT, ".cursor"))) {
89077
+ if (existsSync36(join44(ROOT, ".cursor"))) {
88928
89078
  try {
88929
89079
  await installCursorMcpConfig();
88930
89080
  } catch (err2) {
@@ -89026,6 +89176,7 @@ async function cmdStart() {
89026
89176
  await ensureProfile();
89027
89177
  const profile = loadProfile(ROOT);
89028
89178
  if (profile) registerWorkspace(profile, ROOT);
89179
+ if (profile) console.log(`errata: ${ensureStatusLine(resolveHookPort())}`);
89029
89180
  const lockPath = globalDaemonLock();
89030
89181
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
89031
89182
  const where = profile ? `${profile.name} (${profile.id})` : ROOT;
@@ -89113,9 +89264,9 @@ async function cmdStatus() {
89113
89264
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
89114
89265
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
89115
89266
  }
89116
- console.log(` graph db: ${existsSync34(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
89117
- console.log(` event log: ${existsSync34(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
89118
- if (existsSync34(paths.castalia)) {
89267
+ console.log(` graph db: ${existsSync35(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
89268
+ console.log(` event log: ${existsSync35(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
89269
+ if (existsSync35(paths.castalia)) {
89119
89270
  try {
89120
89271
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
89121
89272
  const store = openGraphStore2({ path: paths.castalia });
@@ -89748,6 +89899,7 @@ async function cmdLink(args2) {
89748
89899
  process.exitCode = 1;
89749
89900
  return;
89750
89901
  }
89902
+ console.log(ensureStatusLine(resolveHookPort()));
89751
89903
  delete profile.projectLinkDisabled;
89752
89904
  const remote = flag("--remote");
89753
89905
  if (remote) {
@@ -90084,11 +90236,11 @@ function cmdInstallationProfile(args2) {
90084
90236
  }
90085
90237
  async function cmdReview() {
90086
90238
  const paths = workspacePaths(ROOT);
90087
- if (!existsSync34(paths.reviewQueue)) {
90239
+ if (!existsSync35(paths.reviewQueue)) {
90088
90240
  console.log("(review queue empty)");
90089
90241
  return;
90090
90242
  }
90091
- const queue = JSON.parse(readFileSync35(paths.reviewQueue, "utf8"));
90243
+ const queue = JSON.parse(readFileSync36(paths.reviewQueue, "utf8"));
90092
90244
  if (queue.length === 0) {
90093
90245
  console.log("(review queue empty)");
90094
90246
  return;
@@ -90759,7 +90911,7 @@ async function gatherRepo(store, ws) {
90759
90911
  };
90760
90912
  }
90761
90913
  async function gatherReportData(generatedAt) {
90762
- const { existsSync: existsSync35 } = await import("node:fs");
90914
+ const { existsSync: existsSync36 } = await import("node:fs");
90763
90915
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
90764
90916
  const cfg = loadConfig();
90765
90917
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -90767,7 +90919,7 @@ async function gatherReportData(generatedAt) {
90767
90919
  for (const ws of listWorkspaces()) {
90768
90920
  if (ws.missing) continue;
90769
90921
  const dbPath = workspacePaths(ws.path).castalia;
90770
- if (!existsSync35(dbPath)) continue;
90922
+ if (!existsSync36(dbPath)) continue;
90771
90923
  let store = null;
90772
90924
  try {
90773
90925
  store = openGraphStore2({ path: dbPath });
@@ -90811,8 +90963,8 @@ async function cmdReport(args2) {
90811
90963
  const outDir = workspacePaths(ROOT).configDir;
90812
90964
  mkdirSync11(outDir, { recursive: true });
90813
90965
  const files = renderReport2(data, { includeFutureVerbs });
90814
- for (const f of files) writeFileSync27(join42(outDir, f.name), f.html, "utf8");
90815
- const indexPath = join42(outDir, "report.html");
90966
+ for (const f of files) writeFileSync27(join43(outDir, f.name), f.html, "utf8");
90967
+ const indexPath = join43(outDir, "report.html");
90816
90968
  console.log(`report \u2192 ${indexPath}`);
90817
90969
  console.log(
90818
90970
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -90867,7 +91019,7 @@ function spawnDaemonDetached(options = {}) {
90867
91019
  try {
90868
91020
  const logPath = daemonLogPath();
90869
91021
  try {
90870
- if (statSync9(logPath).size > 5 * 1024 * 1024) renameSync4(logPath, `${logPath}.1`);
91022
+ if (statSync10(logPath).size > 5 * 1024 * 1024) renameSync4(logPath, `${logPath}.1`);
90871
91023
  } catch {
90872
91024
  }
90873
91025
  out2 = openSync2(logPath, "a");
@@ -90932,24 +91084,24 @@ async function cmdInstallHooks(args2) {
90932
91084
  }
90933
91085
  }
90934
91086
  async function installOpencodePlugin(port) {
90935
- const { mkdirSync: mkdirSync11, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
90936
- const { join: join43 } = await import("node:path");
90937
- const dir = join43(ROOT, ".opencode", "plugin");
90938
- if (!existsSync35(dir)) mkdirSync11(dir, { recursive: true });
90939
- const file2 = join43(dir, "inerrata.js");
90940
- if (existsSync35(file2)) {
90941
- const head2 = readFileSync36(file2, "utf8").split("\n")[0] ?? "";
91087
+ const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
91088
+ const { join: join44 } = await import("node:path");
91089
+ const dir = join44(ROOT, ".opencode", "plugin");
91090
+ if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
91091
+ const file2 = join44(dir, "inerrata.js");
91092
+ if (existsSync36(file2)) {
91093
+ const head2 = readFileSync37(file2, "utf8").split("\n")[0] ?? "";
90942
91094
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
90943
91095
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
90944
91096
  process.exit(2);
90945
91097
  }
90946
91098
  }
90947
91099
  writeFileSync27(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
90948
- const cfgFile = join43(ROOT, "opencode.json");
91100
+ const cfgFile = join44(ROOT, "opencode.json");
90949
91101
  let cfg = { $schema: "https://opencode.ai/config.json" };
90950
- if (existsSync35(cfgFile)) {
91102
+ if (existsSync36(cfgFile)) {
90951
91103
  try {
90952
- cfg = JSON.parse(readFileSync36(cfgFile, "utf8"));
91104
+ cfg = JSON.parse(readFileSync37(cfgFile, "utf8"));
90953
91105
  } catch {
90954
91106
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
90955
91107
  process.exit(2);
@@ -90979,16 +91131,23 @@ function errataMcpInvocation() {
90979
91131
  const { cmd: cmd2, args: args2 } = selfArgv("mcp");
90980
91132
  return { command: cmd2, args: args2 };
90981
91133
  }
91134
+ function ensureStatusLine(port) {
91135
+ try {
91136
+ return describeStatusLineOutcome(ensureUserStatusLine({ port, relayDir: globalDir() }));
91137
+ } catch (err2) {
91138
+ return `status line: not installed (${err2 instanceof Error ? err2.message : err2})`;
91139
+ }
91140
+ }
90982
91141
  async function installClaudeHooks(port) {
90983
- const { mkdirSync: mkdirSync11, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
90984
- const { join: join43 } = await import("node:path");
90985
- const dir = join43(ROOT, ".claude");
90986
- if (!existsSync35(dir)) mkdirSync11(dir, { recursive: true });
90987
- const file2 = join43(dir, "settings.json");
91142
+ const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
91143
+ const { join: join44 } = await import("node:path");
91144
+ const dir = join44(ROOT, ".claude");
91145
+ if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
91146
+ const file2 = join44(dir, "settings.json");
90988
91147
  let settings = {};
90989
- if (existsSync35(file2)) {
91148
+ if (existsSync36(file2)) {
90990
91149
  try {
90991
- settings = JSON.parse(readFileSync36(file2, "utf8"));
91150
+ settings = JSON.parse(readFileSync37(file2, "utf8"));
90992
91151
  } catch {
90993
91152
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
90994
91153
  process.exit(2);
@@ -91035,20 +91194,12 @@ async function installClaudeHooks(port) {
91035
91194
  dropErrata(list);
91036
91195
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
91037
91196
  }
91038
- const { homedir: homedir8 } = await import("node:os");
91039
- let userStatusLine;
91040
- try {
91041
- userStatusLine = JSON.parse(readFileSync36(join43(homedir8(), ".claude", "settings.json"), "utf8"))["statusLine"];
91042
- } catch {
91043
- }
91044
- const statusLineInstalled = (userStatusLine === void 0 || isErrataStatusLine(userStatusLine)) && installStatusLine(settings, ROOT, port);
91197
+ removeProjectStatusLine(settings);
91045
91198
  writeFileSync27(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
91046
91199
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
91047
- console.log(
91048
- statusLineInstalled ? " status line: errata recall card in colour (daemon env ERRATA_RECALL_CARD=off hides the cards)" : " status line: kept your own \u2014 errata's recall card shows inline only"
91049
- );
91200
+ console.log(` ${ensureStatusLine(port)}`);
91050
91201
  await installClaudeMcpConfig();
91051
- const claudeMd = join43(ROOT, "CLAUDE.md");
91202
+ const claudeMd = join44(ROOT, "CLAUDE.md");
91052
91203
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
91053
91204
  if (recall.kind === "collision") {
91054
91205
  console.warn(
@@ -91060,15 +91211,15 @@ async function installClaudeHooks(port) {
91060
91211
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
91061
91212
  }
91062
91213
  async function installClaudeMcpConfig() {
91063
- const { mkdirSync: mkdirSync11, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
91064
- const { join: join43, dirname: dirname13 } = await import("node:path");
91065
- const file2 = join43(ROOT, ".mcp.json");
91066
- const dir = dirname13(file2);
91067
- if (!existsSync35(dir)) mkdirSync11(dir, { recursive: true });
91214
+ const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
91215
+ const { join: join44, dirname: dirname14 } = await import("node:path");
91216
+ const file2 = join44(ROOT, ".mcp.json");
91217
+ const dir = dirname14(file2);
91218
+ if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
91068
91219
  let cfg = {};
91069
- if (existsSync35(file2)) {
91220
+ if (existsSync36(file2)) {
91070
91221
  try {
91071
- cfg = JSON.parse(readFileSync36(file2, "utf8"));
91222
+ cfg = JSON.parse(readFileSync37(file2, "utf8"));
91072
91223
  } catch {
91073
91224
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
91074
91225
  process.exit(2);
@@ -91082,15 +91233,15 @@ async function installClaudeMcpConfig() {
91082
91233
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
91083
91234
  }
91084
91235
  async function installCursorMcpConfig() {
91085
- const { mkdirSync: mkdirSync11, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
91086
- const { join: join43 } = await import("node:path");
91087
- const dir = join43(ROOT, ".cursor");
91088
- if (!existsSync35(dir)) mkdirSync11(dir, { recursive: true });
91089
- const file2 = join43(dir, "mcp.json");
91236
+ const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
91237
+ const { join: join44 } = await import("node:path");
91238
+ const dir = join44(ROOT, ".cursor");
91239
+ if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
91240
+ const file2 = join44(dir, "mcp.json");
91090
91241
  let cfg = {};
91091
- if (existsSync35(file2)) {
91242
+ if (existsSync36(file2)) {
91092
91243
  try {
91093
- cfg = JSON.parse(readFileSync36(file2, "utf8"));
91244
+ cfg = JSON.parse(readFileSync37(file2, "utf8"));
91094
91245
  } catch {
91095
91246
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
91096
91247
  process.exit(2);
@@ -91109,7 +91260,7 @@ async function installCodexHooks(port) {
91109
91260
  const gitRoot = nearestGitRoot(process.cwd());
91110
91261
  const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
91111
91262
  const file2 = writeCodexHooks(hookRoot, port);
91112
- const instructions = writeManagedBlock(join42(hookRoot, "AGENTS.md"), {
91263
+ const instructions = writeManagedBlock(join43(hookRoot, "AGENTS.md"), {
91113
91264
  body: AGENTS_POINTER_BODY,
91114
91265
  stable: true
91115
91266
  });
@@ -91513,7 +91664,7 @@ async function cmdDash(args2) {
91513
91664
  await yieldToLoop2();
91514
91665
  try {
91515
91666
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
91516
- const res = bleedRules(join42(r.root, ".claude", "rules"), items);
91667
+ const res = bleedRules(join43(r.root, ".claude", "rules"), items);
91517
91668
  if (res.written || res.pruned) {
91518
91669
  console.log(
91519
91670
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")