@inerrata-corporation/errata 2.0.16-dev.3355 → 2.0.16-dev.3362

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 +409 -211
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -960,7 +960,7 @@ function lemma(token) {
960
960
  }
961
961
  return token;
962
962
  }
963
- function tokenize(text, resolve7) {
963
+ function tokenize(text, resolve8) {
964
964
  const matches = text.normalize("NFC").toLowerCase().match(TOKEN_RE) ?? [];
965
965
  const out2 = /* @__PURE__ */ new Set();
966
966
  for (const raw2 of matches) {
@@ -970,7 +970,7 @@ function tokenize(text, resolve7) {
970
970
  out2.add(token);
971
971
  continue;
972
972
  }
973
- const canonical = resolve7(token);
973
+ const canonical = resolve8(token);
974
974
  out2.add(canonical ?? lemma(token));
975
975
  }
976
976
  return [...out2].sort();
@@ -17574,7 +17574,7 @@ var init_agents_md = __esm({
17574
17574
  });
17575
17575
 
17576
17576
  // ../../packages/context-writer/src/context-file.ts
17577
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
17577
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
17578
17578
  import { dirname as dirname2, join } from "node:path";
17579
17579
  function contextFilePath(root) {
17580
17580
  return join(root, ".errata", "context.md");
@@ -17584,7 +17584,13 @@ function writeContextFile(root, body2) {
17584
17584
  mkdirSync(dirname2(path2), { recursive: true });
17585
17585
  const text = `${body2.trim()}
17586
17586
  `;
17587
- writeFileSync2(path2, text, "utf8");
17587
+ const temp = `${path2}.${process.pid}.tmp`;
17588
+ try {
17589
+ writeFileSync2(temp, text, { encoding: "utf8", mode: 384 });
17590
+ renameSync(temp, path2);
17591
+ } finally {
17592
+ if (existsSync2(temp)) unlinkSync(temp);
17593
+ }
17588
17594
  return contextHash(text);
17589
17595
  }
17590
17596
  function contextHash(body2) {
@@ -32169,7 +32175,11 @@ function contextCard(store, snapshot) {
32169
32175
  return deliveredCard(store, intent ? `${count} for \u201C${clipIntent(intent)}\u201D` : `${count} in context`, delivered);
32170
32176
  }
32171
32177
  function writeContextCard(root, hash2, card) {
32172
- writeFileSync6(join7(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({ hash: hash2, card }));
32178
+ writeFileSync6(join7(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({
32179
+ hash: hash2,
32180
+ card,
32181
+ line: card && recallCardEnabled() ? renderRecallLine(card) : null
32182
+ }));
32173
32183
  }
32174
32184
  function readContextCard(root, hash2) {
32175
32185
  const path2 = join7(root, ".errata", CONTEXT_CARD_FILE);
@@ -32634,7 +32644,7 @@ var init_process_identity = __esm({
32634
32644
  });
32635
32645
 
32636
32646
  // src/lock.ts
32637
- import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync } from "node:fs";
32647
+ import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "node:fs";
32638
32648
  function daemonLockPayload(lock) {
32639
32649
  return JSON.stringify({
32640
32650
  pid: lock.pid,
@@ -32715,7 +32725,7 @@ function stopLockedDaemon(lockPath) {
32715
32725
  }
32716
32726
  if (state === "unknown") return "unknown";
32717
32727
  if (state === "stale") {
32718
- unlinkSync(lockPath);
32728
+ unlinkSync2(lockPath);
32719
32729
  return "stale";
32720
32730
  }
32721
32731
  process.kill(lock.pid, "SIGTERM");
@@ -36116,13 +36126,13 @@ async function Module2(moduleArg = {}) {
36116
36126
  }
36117
36127
  readAsync = /* @__PURE__ */ __name(async (url2) => {
36118
36128
  if (isFileURI(url2)) {
36119
- return new Promise((resolve7, reject) => {
36129
+ return new Promise((resolve8, reject) => {
36120
36130
  var xhr = new XMLHttpRequest();
36121
36131
  xhr.open("GET", url2, true);
36122
36132
  xhr.responseType = "arraybuffer";
36123
36133
  xhr.onload = () => {
36124
36134
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
36125
- resolve7(xhr.response);
36135
+ resolve8(xhr.response);
36126
36136
  return;
36127
36137
  }
36128
36138
  reject(xhr.status);
@@ -36318,9 +36328,9 @@ async function Module2(moduleArg = {}) {
36318
36328
  __name(receiveInstantiationResult, "receiveInstantiationResult");
36319
36329
  var info2 = getWasmImports();
36320
36330
  if (Module["instantiateWasm"]) {
36321
- return new Promise((resolve7, reject) => {
36331
+ return new Promise((resolve8, reject) => {
36322
36332
  Module["instantiateWasm"](info2, (mod, inst) => {
36323
- resolve7(receiveInstance(mod, inst));
36333
+ resolve8(receiveInstance(mod, inst));
36324
36334
  });
36325
36335
  });
36326
36336
  }
@@ -37651,8 +37661,8 @@ async function Module2(moduleArg = {}) {
37651
37661
  if (runtimeInitialized) {
37652
37662
  moduleRtn = Module;
37653
37663
  } else {
37654
- moduleRtn = new Promise((resolve7, reject) => {
37655
- readyPromiseResolve = resolve7;
37664
+ moduleRtn = new Promise((resolve8, reject) => {
37665
+ readyPromiseResolve = resolve8;
37656
37666
  readyPromiseReject = reject;
37657
37667
  });
37658
37668
  }
@@ -52553,8 +52563,8 @@ import {
52553
52563
  existsSync as existsSync17,
52554
52564
  readdirSync as readdirSync5,
52555
52565
  readFileSync as readFileSync16,
52556
- renameSync,
52557
- unlinkSync as unlinkSync2,
52566
+ renameSync as renameSync2,
52567
+ unlinkSync as unlinkSync3,
52558
52568
  writeFileSync as writeFileSync12
52559
52569
  } from "node:fs";
52560
52570
  import { join as join17 } from "node:path";
@@ -52573,7 +52583,7 @@ async function flushOutbox(paths, client, store) {
52573
52583
  let failed = 0;
52574
52584
  const quarantine = (abs, reason) => {
52575
52585
  try {
52576
- renameSync(abs, `${abs}.bad`);
52586
+ renameSync2(abs, `${abs}.bad`);
52577
52587
  console.warn(`[errata] outbox: quarantined ${abs} (${reason})`);
52578
52588
  } catch {
52579
52589
  }
@@ -52617,7 +52627,7 @@ async function flushOutbox(paths, client, store) {
52617
52627
  }
52618
52628
  }
52619
52629
  }
52620
- unlinkSync2(abs);
52630
+ unlinkSync3(abs);
52621
52631
  if (res.accepted === 0) uploaded++;
52622
52632
  } catch (err2) {
52623
52633
  failed++;
@@ -55721,9 +55731,9 @@ var require_dispatcher_base = __commonJS({
55721
55731
  }
55722
55732
  close(callback) {
55723
55733
  if (callback === void 0) {
55724
- return new Promise((resolve7, reject) => {
55734
+ return new Promise((resolve8, reject) => {
55725
55735
  this.close((err2, data) => {
55726
- return err2 ? reject(err2) : resolve7(data);
55736
+ return err2 ? reject(err2) : resolve8(data);
55727
55737
  });
55728
55738
  });
55729
55739
  }
@@ -55761,12 +55771,12 @@ var require_dispatcher_base = __commonJS({
55761
55771
  err2 = null;
55762
55772
  }
55763
55773
  if (callback === void 0) {
55764
- return new Promise((resolve7, reject) => {
55774
+ return new Promise((resolve8, reject) => {
55765
55775
  this.destroy(err2, (err3, data) => {
55766
55776
  return err3 ? (
55767
55777
  /* istanbul ignore next: should never error */
55768
55778
  reject(err3)
55769
- ) : resolve7(data);
55779
+ ) : resolve8(data);
55770
55780
  });
55771
55781
  });
55772
55782
  }
@@ -58033,8 +58043,8 @@ var require_util2 = __commonJS({
58033
58043
  function createDeferredPromise() {
58034
58044
  let res;
58035
58045
  let rej;
58036
- const promise2 = new Promise((resolve7, reject) => {
58037
- res = resolve7;
58046
+ const promise2 = new Promise((resolve8, reject) => {
58047
+ res = resolve8;
58038
58048
  rej = reject;
58039
58049
  });
58040
58050
  return { promise: promise2, resolve: res, reject: rej };
@@ -60175,12 +60185,12 @@ upgrade: ${upgrade}\r
60175
60185
  cb();
60176
60186
  }
60177
60187
  }
60178
- const waitForDrain = () => new Promise((resolve7, reject) => {
60188
+ const waitForDrain = () => new Promise((resolve8, reject) => {
60179
60189
  assert2(callback === null);
60180
60190
  if (socket[kError]) {
60181
60191
  reject(socket[kError]);
60182
60192
  } else {
60183
- callback = resolve7;
60193
+ callback = resolve8;
60184
60194
  }
60185
60195
  });
60186
60196
  socket.on("close", onDrain).on("drain", onDrain);
@@ -60817,12 +60827,12 @@ var require_client_h2 = __commonJS({
60817
60827
  cb();
60818
60828
  }
60819
60829
  }
60820
- const waitForDrain = () => new Promise((resolve7, reject) => {
60830
+ const waitForDrain = () => new Promise((resolve8, reject) => {
60821
60831
  assert2(callback === null);
60822
60832
  if (socket[kError]) {
60823
60833
  reject(socket[kError]);
60824
60834
  } else {
60825
- callback = resolve7;
60835
+ callback = resolve8;
60826
60836
  }
60827
60837
  });
60828
60838
  h2stream.on("close", onDrain).on("drain", onDrain);
@@ -61299,16 +61309,16 @@ var require_client = __commonJS({
61299
61309
  return this[kNeedDrain] < 2;
61300
61310
  }
61301
61311
  async [kClose]() {
61302
- return new Promise((resolve7) => {
61312
+ return new Promise((resolve8) => {
61303
61313
  if (this[kSize]) {
61304
- this[kClosedResolve] = resolve7;
61314
+ this[kClosedResolve] = resolve8;
61305
61315
  } else {
61306
- resolve7(null);
61316
+ resolve8(null);
61307
61317
  }
61308
61318
  });
61309
61319
  }
61310
61320
  async [kDestroy](err2) {
61311
- return new Promise((resolve7) => {
61321
+ return new Promise((resolve8) => {
61312
61322
  const requests = this[kQueue].splice(this[kPendingIdx]);
61313
61323
  for (let i2 = 0; i2 < requests.length; i2++) {
61314
61324
  const request = requests[i2];
@@ -61319,7 +61329,7 @@ var require_client = __commonJS({
61319
61329
  this[kClosedResolve]();
61320
61330
  this[kClosedResolve] = null;
61321
61331
  }
61322
- resolve7(null);
61332
+ resolve8(null);
61323
61333
  };
61324
61334
  if (this[kHTTPContext]) {
61325
61335
  this[kHTTPContext].destroy(err2, callback);
@@ -61370,7 +61380,7 @@ var require_client = __commonJS({
61370
61380
  });
61371
61381
  }
61372
61382
  try {
61373
- const socket = await new Promise((resolve7, reject) => {
61383
+ const socket = await new Promise((resolve8, reject) => {
61374
61384
  client[kConnector]({
61375
61385
  host,
61376
61386
  hostname: hostname3,
@@ -61382,7 +61392,7 @@ var require_client = __commonJS({
61382
61392
  if (err2) {
61383
61393
  reject(err2);
61384
61394
  } else {
61385
- resolve7(socket2);
61395
+ resolve8(socket2);
61386
61396
  }
61387
61397
  });
61388
61398
  });
@@ -61718,8 +61728,8 @@ var require_pool_base = __commonJS({
61718
61728
  if (this[kQueue].isEmpty()) {
61719
61729
  await Promise.all(this[kClients].map((c) => c.close()));
61720
61730
  } else {
61721
- await new Promise((resolve7) => {
61722
- this[kClosedResolve] = resolve7;
61731
+ await new Promise((resolve8) => {
61732
+ this[kClosedResolve] = resolve8;
61723
61733
  });
61724
61734
  }
61725
61735
  }
@@ -62934,7 +62944,7 @@ var require_readable = __commonJS({
62934
62944
  if (this._readableState.closeEmitted) {
62935
62945
  return null;
62936
62946
  }
62937
- return await new Promise((resolve7, reject) => {
62947
+ return await new Promise((resolve8, reject) => {
62938
62948
  if (this[kContentLength] > limit) {
62939
62949
  this.destroy(new AbortError());
62940
62950
  }
@@ -62947,7 +62957,7 @@ var require_readable = __commonJS({
62947
62957
  if (signal?.aborted) {
62948
62958
  reject(signal.reason ?? new AbortError());
62949
62959
  } else {
62950
- resolve7(null);
62960
+ resolve8(null);
62951
62961
  }
62952
62962
  }).on("error", noop).on("data", function(chunk) {
62953
62963
  limit -= chunk.length;
@@ -62966,7 +62976,7 @@ var require_readable = __commonJS({
62966
62976
  }
62967
62977
  async function consume(stream, type) {
62968
62978
  assert2(!stream[kConsume]);
62969
- return new Promise((resolve7, reject) => {
62979
+ return new Promise((resolve8, reject) => {
62970
62980
  if (isUnusable(stream)) {
62971
62981
  const rState = stream._readableState;
62972
62982
  if (rState.destroyed && rState.closeEmitted === false) {
@@ -62983,7 +62993,7 @@ var require_readable = __commonJS({
62983
62993
  stream[kConsume] = {
62984
62994
  type,
62985
62995
  stream,
62986
- resolve: resolve7,
62996
+ resolve: resolve8,
62987
62997
  reject,
62988
62998
  length: 0,
62989
62999
  body: []
@@ -63053,18 +63063,18 @@ var require_readable = __commonJS({
63053
63063
  return buffer;
63054
63064
  }
63055
63065
  function consumeEnd(consume2) {
63056
- const { type, body: body2, resolve: resolve7, stream, length } = consume2;
63066
+ const { type, body: body2, resolve: resolve8, stream, length } = consume2;
63057
63067
  try {
63058
63068
  if (type === "text") {
63059
- resolve7(chunksDecode(body2, length));
63069
+ resolve8(chunksDecode(body2, length));
63060
63070
  } else if (type === "json") {
63061
- resolve7(JSON.parse(chunksDecode(body2, length)));
63071
+ resolve8(JSON.parse(chunksDecode(body2, length)));
63062
63072
  } else if (type === "arrayBuffer") {
63063
- resolve7(chunksConcat(body2, length).buffer);
63073
+ resolve8(chunksConcat(body2, length).buffer);
63064
63074
  } else if (type === "blob") {
63065
- resolve7(new Blob(body2, { type: stream[kContentType] }));
63075
+ resolve8(new Blob(body2, { type: stream[kContentType] }));
63066
63076
  } else if (type === "bytes") {
63067
- resolve7(chunksConcat(body2, length));
63077
+ resolve8(chunksConcat(body2, length));
63068
63078
  }
63069
63079
  consumeFinish(consume2);
63070
63080
  } catch (err2) {
@@ -63321,9 +63331,9 @@ var require_api_request = __commonJS({
63321
63331
  };
63322
63332
  function request(opts, callback) {
63323
63333
  if (callback === void 0) {
63324
- return new Promise((resolve7, reject) => {
63334
+ return new Promise((resolve8, reject) => {
63325
63335
  request.call(this, opts, (err2, data) => {
63326
- return err2 ? reject(err2) : resolve7(data);
63336
+ return err2 ? reject(err2) : resolve8(data);
63327
63337
  });
63328
63338
  });
63329
63339
  }
@@ -63546,9 +63556,9 @@ var require_api_stream = __commonJS({
63546
63556
  };
63547
63557
  function stream(opts, factory, callback) {
63548
63558
  if (callback === void 0) {
63549
- return new Promise((resolve7, reject) => {
63559
+ return new Promise((resolve8, reject) => {
63550
63560
  stream.call(this, opts, factory, (err2, data) => {
63551
- return err2 ? reject(err2) : resolve7(data);
63561
+ return err2 ? reject(err2) : resolve8(data);
63552
63562
  });
63553
63563
  });
63554
63564
  }
@@ -63833,9 +63843,9 @@ var require_api_upgrade = __commonJS({
63833
63843
  };
63834
63844
  function upgrade(opts, callback) {
63835
63845
  if (callback === void 0) {
63836
- return new Promise((resolve7, reject) => {
63846
+ return new Promise((resolve8, reject) => {
63837
63847
  upgrade.call(this, opts, (err2, data) => {
63838
- return err2 ? reject(err2) : resolve7(data);
63848
+ return err2 ? reject(err2) : resolve8(data);
63839
63849
  });
63840
63850
  });
63841
63851
  }
@@ -63927,9 +63937,9 @@ var require_api_connect = __commonJS({
63927
63937
  };
63928
63938
  function connect(opts, callback) {
63929
63939
  if (callback === void 0) {
63930
- return new Promise((resolve7, reject) => {
63940
+ return new Promise((resolve8, reject) => {
63931
63941
  connect.call(this, opts, (err2, data) => {
63932
- return err2 ? reject(err2) : resolve7(data);
63942
+ return err2 ? reject(err2) : resolve8(data);
63933
63943
  });
63934
63944
  });
63935
63945
  }
@@ -67791,7 +67801,7 @@ var require_fetch = __commonJS({
67791
67801
  function dispatch({ body: body2 }) {
67792
67802
  const url2 = requestCurrentURL(request);
67793
67803
  const agent = fetchParams.controller.dispatcher;
67794
- return new Promise((resolve7, reject) => agent.dispatch(
67804
+ return new Promise((resolve8, reject) => agent.dispatch(
67795
67805
  {
67796
67806
  path: url2.pathname + url2.search,
67797
67807
  origin: url2.origin,
@@ -67867,7 +67877,7 @@ var require_fetch = __commonJS({
67867
67877
  }
67868
67878
  }
67869
67879
  const onError = this.onError.bind(this);
67870
- resolve7({
67880
+ resolve8({
67871
67881
  status,
67872
67882
  statusText,
67873
67883
  headersList,
@@ -67913,7 +67923,7 @@ var require_fetch = __commonJS({
67913
67923
  for (let i2 = 0; i2 < rawHeaders.length; i2 += 2) {
67914
67924
  headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i2]), rawHeaders[i2 + 1].toString("latin1"), true);
67915
67925
  }
67916
- resolve7({
67926
+ resolve8({
67917
67927
  status,
67918
67928
  statusText: STATUS_CODES[status],
67919
67929
  headersList,
@@ -71552,8 +71562,8 @@ var require_util8 = __commonJS({
71552
71562
  return true;
71553
71563
  }
71554
71564
  function delay(ms) {
71555
- return new Promise((resolve7) => {
71556
- setTimeout(resolve7, ms).unref();
71565
+ return new Promise((resolve8) => {
71566
+ setTimeout(resolve8, ms).unref();
71557
71567
  });
71558
71568
  }
71559
71569
  module2.exports = {
@@ -72700,8 +72710,8 @@ var init_report_render = __esm({
72700
72710
 
72701
72711
  // src/cli.ts
72702
72712
  init_src6();
72703
- import { closeSync as closeSync2, existsSync as existsSync36, openSync as openSync2, readFileSync as readFileSync38, renameSync as renameSync4, statSync as statSync10 } from "node:fs";
72704
- import { join as join44, resolve as pathResolve2 } from "node:path";
72713
+ import { closeSync as closeSync2, existsSync as existsSync37, openSync as openSync2, readFileSync as readFileSync40, renameSync as renameSync6, statSync as statSync11 } from "node:fs";
72714
+ import { join as join47, resolve as pathResolve2 } from "node:path";
72705
72715
  import { spawn as spawn5 } from "node:child_process";
72706
72716
 
72707
72717
  // src/daemon.ts
@@ -73135,7 +73145,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
73135
73145
  });
73136
73146
  if (!chunk) {
73137
73147
  if (i2 === 1) {
73138
- await new Promise((resolve7) => setTimeout(resolve7));
73148
+ await new Promise((resolve8) => setTimeout(resolve8));
73139
73149
  maxReadCount = 3;
73140
73150
  continue;
73141
73151
  }
@@ -73282,10 +73292,11 @@ var serve = (options, listeningListener) => {
73282
73292
  init_cloud_auth();
73283
73293
  init_webui();
73284
73294
  init_config();
73295
+ init_lock();
73285
73296
 
73286
73297
  // src/engine.ts
73287
73298
  import { execFileSync as execFileSync5 } from "node:child_process";
73288
- import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
73299
+ import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
73289
73300
  import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
73290
73301
 
73291
73302
  // src/source-watcher.ts
@@ -74022,9 +74033,9 @@ var NodeFsHandler = class {
74022
74033
  if (this.fsw.closed) {
74023
74034
  return;
74024
74035
  }
74025
- const dirname14 = sysPath.dirname(file2);
74036
+ const dirname15 = sysPath.dirname(file2);
74026
74037
  const basename9 = sysPath.basename(file2);
74027
- const parent = this.fsw._getWatchedDir(dirname14);
74038
+ const parent = this.fsw._getWatchedDir(dirname15);
74028
74039
  let prevStats = stats;
74029
74040
  if (parent.has(basename9))
74030
74041
  return;
@@ -74051,7 +74062,7 @@ var NodeFsHandler = class {
74051
74062
  prevStats = newStats2;
74052
74063
  }
74053
74064
  } catch (error48) {
74054
- this.fsw._remove(dirname14, basename9);
74065
+ this.fsw._remove(dirname15, basename9);
74055
74066
  }
74056
74067
  } else if (parent.has(basename9)) {
74057
74068
  const at = newStats.atimeMs;
@@ -74147,7 +74158,7 @@ var NodeFsHandler = class {
74147
74158
  this._addToNodeFs(path2, initialAdd, wh, depth + 1);
74148
74159
  }
74149
74160
  }).on(EV.ERROR, this._boundHandleError);
74150
- return new Promise((resolve7, reject) => {
74161
+ return new Promise((resolve8, reject) => {
74151
74162
  if (!stream)
74152
74163
  return reject();
74153
74164
  stream.once(STR_END, () => {
@@ -74156,7 +74167,7 @@ var NodeFsHandler = class {
74156
74167
  return;
74157
74168
  }
74158
74169
  const wasThrottled = throttler ? throttler.clear() : false;
74159
- resolve7(void 0);
74170
+ resolve8(void 0);
74160
74171
  previous.getChildren().filter((item2) => {
74161
74172
  return item2 !== directory && !current.has(item2);
74162
74173
  }).forEach((item2) => {
@@ -77875,8 +77886,8 @@ var PassWorker = class {
77875
77886
  const id = this.nextId++;
77876
77887
  try {
77877
77888
  await this.ready;
77878
- return await new Promise((resolve7, reject) => {
77879
- this.pending.set(id, { resolve: resolve7, reject });
77889
+ return await new Promise((resolve8, reject) => {
77890
+ this.pending.set(id, { resolve: resolve8, reject });
77880
77891
  this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
77881
77892
  });
77882
77893
  } finally {
@@ -77910,12 +77921,12 @@ var PassWorker = class {
77910
77921
  });
77911
77922
  noteIsolateSpawned();
77912
77923
  this.worker = worker;
77913
- this.ready = new Promise((resolve7, reject) => {
77924
+ this.ready = new Promise((resolve8, reject) => {
77914
77925
  const onReady = (m) => {
77915
77926
  if (m?.ready) {
77916
77927
  worker.off("message", onReady);
77917
77928
  worker.off("error", onErr);
77918
- resolve7();
77929
+ resolve8();
77919
77930
  }
77920
77931
  };
77921
77932
  const onErr = (err2) => reject(err2);
@@ -79071,7 +79082,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
79071
79082
  // src/git-delta.ts
79072
79083
  import { execFile } from "node:child_process";
79073
79084
  function git(repoDir, args2) {
79074
- return new Promise((resolve7, reject) => {
79085
+ return new Promise((resolve8, reject) => {
79075
79086
  execFile(
79076
79087
  "git",
79077
79088
  ["-C", repoDir, ...args2],
@@ -79082,7 +79093,7 @@ function git(repoDir, args2) {
79082
79093
  // git-sensor runs on every commit/checkout.
79083
79094
  windowsHide: true
79084
79095
  },
79085
- (err2, stdout) => err2 ? reject(err2) : resolve7(stdout)
79096
+ (err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
79086
79097
  );
79087
79098
  });
79088
79099
  }
@@ -80240,12 +80251,12 @@ function headerPaths(diff) {
80240
80251
  return out2.filter((p) => p !== "/dev/null");
80241
80252
  }
80242
80253
  function git2(repoDir, args2) {
80243
- return new Promise((resolve7, reject) => {
80254
+ return new Promise((resolve8, reject) => {
80244
80255
  execFile2(
80245
80256
  "git",
80246
80257
  ["-C", repoDir, ...args2],
80247
80258
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024, windowsHide: true },
80248
- (err2, stdout) => err2 ? reject(err2) : resolve7(stdout)
80259
+ (err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
80249
80260
  );
80250
80261
  });
80251
80262
  }
@@ -80518,7 +80529,7 @@ import {
80518
80529
  mkdirSync as mkdirSync7,
80519
80530
  readFileSync as readFileSync26,
80520
80531
  readdirSync as readdirSync8,
80521
- unlinkSync as unlinkSync3,
80532
+ unlinkSync as unlinkSync4,
80522
80533
  writeFileSync as writeFileSync17
80523
80534
  } from "node:fs";
80524
80535
  import { basename as basename6, join as join30 } from "node:path";
@@ -80579,7 +80590,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80579
80590
  if (!f.endsWith(".md")) continue;
80580
80591
  if (keep.has(basename6(f))) continue;
80581
80592
  try {
80582
- unlinkSync3(join30(paths.skillsDir, f));
80593
+ unlinkSync4(join30(paths.skillsDir, f));
80583
80594
  pruned++;
80584
80595
  } catch {
80585
80596
  }
@@ -80861,7 +80872,7 @@ init_paths();
80861
80872
  init_profile2();
80862
80873
 
80863
80874
  // src/witness-queue.ts
80864
- import { readFileSync as readFileSync28, renameSync as renameSync2, writeFileSync as writeFileSync19 } from "node:fs";
80875
+ import { readFileSync as readFileSync28, renameSync as renameSync3, writeFileSync as writeFileSync19 } from "node:fs";
80865
80876
  import { dirname as dirname11, join as join32 } from "node:path";
80866
80877
  var WITNESS_QUEUE_CAP = 500;
80867
80878
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
@@ -80887,7 +80898,7 @@ function saveWitnessQueue(path2, queue) {
80887
80898
  try {
80888
80899
  const tmp = join32(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
80889
80900
  writeFileSync19(tmp, JSON.stringify(queue), "utf8");
80890
- renameSync2(tmp, path2);
80901
+ renameSync3(tmp, path2);
80891
80902
  } catch {
80892
80903
  }
80893
80904
  }
@@ -81506,7 +81517,7 @@ function createWatchBreaker(deps) {
81506
81517
  }
81507
81518
 
81508
81519
  // src/engine.ts
81509
- var DAEMON_VERSION = true ? "2.0.16-dev.3355" : "2.0.0-alpha.0";
81520
+ var DAEMON_VERSION = true ? "2.0.16-dev.3362" : "2.0.0-alpha.0";
81510
81521
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
81511
81522
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
81512
81523
  var GIT_OP_MUTE_MS = 4e3;
@@ -81519,7 +81530,7 @@ function appendIdentityAudit(path2, record2, line) {
81519
81530
  if (!record2.accepted && record2.score <= 0) return;
81520
81531
  try {
81521
81532
  if (existsSync27(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
81522
- renameSync3(path2, `${path2}.1`);
81533
+ renameSync4(path2, `${path2}.1`);
81523
81534
  }
81524
81535
  appendFileSync4(path2, line);
81525
81536
  } catch {
@@ -83386,7 +83397,7 @@ function createWorkspaceEngine(opts) {
83386
83397
  }
83387
83398
  turns = next.turns;
83388
83399
  nextOffset = next.nextOffset;
83389
- await new Promise((resolve7) => setImmediate(resolve7));
83400
+ await new Promise((resolve8) => setImmediate(resolve8));
83390
83401
  }
83391
83402
  };
83392
83403
  const seenMessageIds = /* @__PURE__ */ new Set();
@@ -84013,6 +84024,7 @@ B: ${b}`,
84013
84024
 
84014
84025
  // src/daemon.ts
84015
84026
  async function startDaemon(opts) {
84027
+ const processStartedAt = Date.now();
84016
84028
  const cfg = loadConfig();
84017
84029
  const merged = { ...cfg, cloudUrl: opts.cloudUrl ?? cfg.cloudUrl };
84018
84030
  if (opts.apiKey) {
@@ -84036,7 +84048,7 @@ async function startDaemon(opts) {
84036
84048
  const writeLockFile = (url2) => {
84037
84049
  writeFileSync23(
84038
84050
  engine.paths.daemonLock,
84039
- JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
84051
+ daemonLockPayload({ pid: process.pid, webUiUrl: url2, processStartedAt, version: DAEMON_VERSION }),
84040
84052
  "utf8"
84041
84053
  );
84042
84054
  };
@@ -84085,9 +84097,9 @@ async function startDaemon(opts) {
84085
84097
  };
84086
84098
  }
84087
84099
  async function listenServer(fetchFn, port) {
84088
- return new Promise((resolve7) => {
84100
+ return new Promise((resolve8) => {
84089
84101
  const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
84090
- resolve7({ server, port: info2.port });
84102
+ resolve8({ server, port: info2.port });
84091
84103
  });
84092
84104
  });
84093
84105
  }
@@ -84278,7 +84290,7 @@ function instanceReceiptSequence(n) {
84278
84290
  // src/multi.ts
84279
84291
  init_dist();
84280
84292
  init_src5();
84281
- import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as unlinkSync4, writeFileSync as writeFileSync25 } from "node:fs";
84293
+ import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as unlinkSync5, writeFileSync as writeFileSync25 } from "node:fs";
84282
84294
  import { resolve as pathResolve } from "node:path";
84283
84295
 
84284
84296
  // src/principle-sync.ts
@@ -85300,8 +85312,8 @@ var ConsolidateWorker = class {
85300
85312
  const id = this.nextId++;
85301
85313
  try {
85302
85314
  await this.ready;
85303
- return await new Promise((resolve7, reject) => {
85304
- this.pending.set(id, { resolve: resolve7, reject });
85315
+ return await new Promise((resolve8, reject) => {
85316
+ this.pending.set(id, { resolve: resolve8, reject });
85305
85317
  this.worker.postMessage({ ...req, id });
85306
85318
  });
85307
85319
  } finally {
@@ -85330,12 +85342,12 @@ var ConsolidateWorker = class {
85330
85342
  });
85331
85343
  noteIsolateSpawned();
85332
85344
  this.worker = worker;
85333
- this.ready = new Promise((resolve7, reject) => {
85345
+ this.ready = new Promise((resolve8, reject) => {
85334
85346
  const onReady = (m) => {
85335
85347
  if (m?.ready) {
85336
85348
  worker.off("message", onReady);
85337
85349
  worker.off("error", onErr);
85338
- resolve7();
85350
+ resolve8();
85339
85351
  }
85340
85352
  };
85341
85353
  const onErr = (err2) => {
@@ -85420,6 +85432,7 @@ init_config();
85420
85432
 
85421
85433
  // src/update.ts
85422
85434
  import { spawn as spawn2 } from "node:child_process";
85435
+ import { isAbsolute as isAbsolute5, join as join38 } from "node:path";
85423
85436
  var PACKAGE_NAME = "@inerrata-corporation/errata";
85424
85437
  function parse3(v) {
85425
85438
  const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z][0-9A-Za-z.-]*))?/.exec(v.trim());
@@ -85539,13 +85552,40 @@ function startUpdatePoller(opts) {
85539
85552
  };
85540
85553
  }
85541
85554
  function runNpmInstall(channel) {
85542
- return new Promise((resolve7) => {
85555
+ return new Promise((resolve8) => {
85543
85556
  const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
85544
85557
  stdio: "inherit",
85545
85558
  shell: true
85546
85559
  });
85547
- child.on("close", (code) => resolve7(code ?? 1));
85548
- child.on("error", () => resolve7(1));
85560
+ child.on("close", (code) => resolve8(code ?? 1));
85561
+ child.on("error", () => resolve8(1));
85562
+ });
85563
+ }
85564
+ async function runInstalledHookRefresh() {
85565
+ const root = await new Promise((resolve8) => {
85566
+ const child = spawn2("npm", ["root", "-g"], {
85567
+ shell: true,
85568
+ windowsHide: true,
85569
+ stdio: ["ignore", "pipe", "ignore"],
85570
+ timeout: 15e3
85571
+ });
85572
+ let output = "";
85573
+ child.stdout.on("data", (chunk) => {
85574
+ output += chunk;
85575
+ if (output.length > 32768) child.kill();
85576
+ });
85577
+ child.on("error", () => resolve8(""));
85578
+ child.on("close", (code) => resolve8(code === 0 ? output.trim() : ""));
85579
+ });
85580
+ if (!isAbsolute5(root)) return 1;
85581
+ return new Promise((resolve8) => {
85582
+ const child = spawn2(process.execPath, [join38(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
85583
+ windowsHide: true,
85584
+ stdio: "inherit",
85585
+ timeout: 3e4
85586
+ });
85587
+ child.on("error", () => resolve8(1));
85588
+ child.on("close", (code) => resolve8(code ?? 1));
85549
85589
  });
85550
85590
  }
85551
85591
 
@@ -85560,7 +85600,7 @@ function liveCloudClient(src) {
85560
85600
  let current = null;
85561
85601
  let currentKey = "";
85562
85602
  let checkedAt = -Infinity;
85563
- const resolve7 = () => {
85603
+ const resolve8 = () => {
85564
85604
  const t = now();
85565
85605
  if (current && t - checkedAt < recheckMs) return current;
85566
85606
  checkedAt = t;
@@ -85580,7 +85620,7 @@ function liveCloudClient(src) {
85580
85620
  };
85581
85621
  return new Proxy({}, {
85582
85622
  get(_target, prop) {
85583
- const client = resolve7();
85623
+ const client = resolve8();
85584
85624
  const value = Reflect.get(client, prop, client);
85585
85625
  return typeof value === "function" ? value.bind(client) : value;
85586
85626
  }
@@ -86015,7 +86055,7 @@ async function syncHistoryRevision(opts) {
86015
86055
  changed += result.changed;
86016
86056
  remaining = result.remaining;
86017
86057
  if (!remaining || Date.now() - started2 >= (opts.budgetMs ?? 45e3)) break;
86018
- await new Promise((resolve7) => setImmediate(resolve7));
86058
+ await new Promise((resolve8) => setImmediate(resolve8));
86019
86059
  }
86020
86060
  return { changed, remaining };
86021
86061
  })();
@@ -86119,7 +86159,7 @@ init_src7();
86119
86159
  init_src();
86120
86160
  import { execFile as execFile5 } from "node:child_process";
86121
86161
  import { readFileSync as readFileSync34 } from "node:fs";
86122
- import { join as join38 } from "node:path";
86162
+ import { join as join39 } from "node:path";
86123
86163
  import { promisify as promisify3 } from "node:util";
86124
86164
 
86125
86165
  // src/history-walk.ts
@@ -86519,8 +86559,8 @@ var GitBlobReader = class {
86519
86559
  if (this.failed) return Promise.reject(this.failed);
86520
86560
  if (/[\r\n]/.test(spec)) return Promise.resolve(null);
86521
86561
  const proc = this.start();
86522
- return new Promise((resolve7, reject) => {
86523
- this.queue.push({ resolve: resolve7, reject });
86562
+ return new Promise((resolve8, reject) => {
86563
+ this.queue.push({ resolve: resolve8, reject });
86524
86564
  proc.stdin.write(`${spec}
86525
86565
  `);
86526
86566
  });
@@ -86534,14 +86574,14 @@ var GitBlobReader = class {
86534
86574
  const proc = this.proc;
86535
86575
  this.proc = null;
86536
86576
  if (!proc || proc.exitCode !== null) return Promise.resolve();
86537
- return new Promise((resolve7) => {
86577
+ return new Promise((resolve8) => {
86538
86578
  const timer = setTimeout(() => {
86539
86579
  proc.kill();
86540
- resolve7();
86580
+ resolve8();
86541
86581
  }, timeoutMs);
86542
86582
  proc.once("exit", () => {
86543
86583
  clearTimeout(timer);
86544
- resolve7();
86584
+ resolve8();
86545
86585
  });
86546
86586
  proc.stdin.end();
86547
86587
  });
@@ -86666,7 +86706,7 @@ async function defaultGit(root, args2) {
86666
86706
  function readIgnoreLines(root, profile) {
86667
86707
  let lines = [];
86668
86708
  try {
86669
- lines = readFileSync34(join38(root, ".errataignore"), "utf8").split("\n");
86709
+ lines = readFileSync34(join39(root, ".errataignore"), "utf8").split("\n");
86670
86710
  } catch {
86671
86711
  }
86672
86712
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -87097,7 +87137,7 @@ init_cloud_auth();
87097
87137
  import { createHash as createHash19 } from "node:crypto";
87098
87138
  import { execFileSync as execFileSync6 } from "node:child_process";
87099
87139
  import { existsSync as existsSync31, writeFileSync as writeFileSync24 } from "node:fs";
87100
- import { join as join39 } from "node:path";
87140
+ import { join as join40 } from "node:path";
87101
87141
 
87102
87142
  // src/device-poll.ts
87103
87143
  var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
@@ -87186,7 +87226,7 @@ async function loginOAuthDevice(opts) {
87186
87226
  let deviceSession = null;
87187
87227
  let approvedInstallation = null;
87188
87228
  while (Date.now() < deadline) {
87189
- await (opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))))(waitMs);
87229
+ await (opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms))))(waitMs);
87190
87230
  waitMs = intervalMs;
87191
87231
  const poll = await fetchDevicePoll(fetchFn, device.token, {
87192
87232
  method: "POST",
@@ -87311,7 +87351,7 @@ async function loginOAuthLoopback(opts) {
87311
87351
  const state = randomState();
87312
87352
  const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
87313
87353
  const { code, redirectUri, clientId } = await new Promise(
87314
- (resolve7, reject) => {
87354
+ (resolve8, reject) => {
87315
87355
  const server = createServer((req, res) => {
87316
87356
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
87317
87357
  if (u.pathname !== "/callback") {
@@ -87334,7 +87374,7 @@ async function loginOAuthLoopback(opts) {
87334
87374
  res.writeHead(200, { "content-type": "text/html" });
87335
87375
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
87336
87376
  server.close();
87337
- resolve7({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
87377
+ resolve8({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
87338
87378
  });
87339
87379
  let activeClientId = oauthClientId();
87340
87380
  server.on("error", reject);
@@ -87433,7 +87473,7 @@ async function linkThroughConsole(opts) {
87433
87473
  const deadline = Date.now() + Math.min(code.expires_in * 1e3, opts.timeoutMs ?? Number.POSITIVE_INFINITY);
87434
87474
  let intervalMs = Math.max(2, code.interval ?? 5) * 1e3;
87435
87475
  let waitMs = intervalMs;
87436
- const sleep = opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)));
87476
+ const sleep = opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
87437
87477
  while (Date.now() < deadline) {
87438
87478
  await sleep(waitMs);
87439
87479
  waitMs = intervalMs;
@@ -87555,7 +87595,7 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
87555
87595
  delete nextProfile.projectLinkHold;
87556
87596
  let wroteIgnore = false;
87557
87597
  if (decision.writeIgnoreStarter !== false) {
87558
- const target = join39(root, ".errataignore");
87598
+ const target = join40(root, ".errataignore");
87559
87599
  if (!existsSync31(target)) {
87560
87600
  writeFileSync24(target, IGNORE_STARTER, "utf8");
87561
87601
  wroteIgnore = true;
@@ -87571,11 +87611,11 @@ init_registry();
87571
87611
  // src/adopt.ts
87572
87612
  init_git_remote();
87573
87613
  import { existsSync as existsSync32 } from "node:fs";
87574
- import { dirname as dirname12, join as join40 } from "node:path";
87614
+ import { dirname as dirname12, join as join41 } from "node:path";
87575
87615
  function findGitRoot(absPath) {
87576
87616
  let dir = absPath;
87577
87617
  for (let depth = 0; depth < 64; depth++) {
87578
- if (existsSync32(join40(dir, ".git"))) return dir;
87618
+ if (existsSync32(join41(dir, ".git"))) return dir;
87579
87619
  const parent = dirname12(dir);
87580
87620
  if (parent === dir) return null;
87581
87621
  dir = parent;
@@ -88868,7 +88908,7 @@ async function startMultiDaemon(opts = {}) {
88868
88908
  const packageAutoAll = async () => {
88869
88909
  const out2 = /* @__PURE__ */ new Map();
88870
88910
  for (const r of records) {
88871
- await new Promise((resolve7) => setImmediate(resolve7));
88911
+ await new Promise((resolve8) => setImmediate(resolve8));
88872
88912
  const done = markPass(`package-index:${r.entry.name}`);
88873
88913
  try {
88874
88914
  out2.set(
@@ -89607,7 +89647,7 @@ async function startMultiDaemon(opts = {}) {
89607
89647
  clearTimeout(codexWakeBoot);
89608
89648
  try {
89609
89649
  const cur = readFileSync35(lockPath, "utf8");
89610
- if (JSON.parse(cur).pid === process.pid) unlinkSync4(lockPath);
89650
+ if (JSON.parse(cur).pid === process.pid) unlinkSync5(lockPath);
89611
89651
  } catch {
89612
89652
  }
89613
89653
  await new Promise(
@@ -90030,7 +90070,7 @@ import { spawnSync } from "node:child_process";
90030
90070
 
90031
90071
  // src/codex-runtime.ts
90032
90072
  import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
90033
- import { join as join41 } from "node:path";
90073
+ import { join as join42 } from "node:path";
90034
90074
  function resolveCodexExecutable(options = {}) {
90035
90075
  const platform = options.platform ?? process.platform;
90036
90076
  const env2 = options.env ?? process.env;
@@ -90045,13 +90085,13 @@ function resolveCodexExecutable(options = {}) {
90045
90085
  };
90046
90086
  for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
90047
90087
  if (!dir.trim()) continue;
90048
- const path2 = join41(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
90088
+ const path2 = join42(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
90049
90089
  if (fileTime(path2) !== null) return path2;
90050
90090
  }
90051
90091
  if (!env2["LOCALAPPDATA"]) return "codex";
90052
- const root = join41(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
90092
+ const root = join42(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
90053
90093
  try {
90054
- const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join41(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));
90094
+ const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join42(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));
90055
90095
  return candidates[0]?.path ?? "codex";
90056
90096
  } catch {
90057
90097
  return "codex";
@@ -90167,12 +90207,14 @@ async function diagnoseInstallation(cfg, dependencies) {
90167
90207
 
90168
90208
  // src/codex-doctor.ts
90169
90209
  import { spawn as spawn4 } from "node:child_process";
90210
+ import { readFileSync as readFileSync37, statSync as statSync10 } from "node:fs";
90211
+ import { join as join44 } from "node:path";
90170
90212
  import { createInterface } from "node:readline";
90171
90213
 
90172
90214
  // src/codex-hooks.ts
90173
- import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, writeFileSync as writeFileSync26 } from "node:fs";
90215
+ import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, renameSync as renameSync5, unlinkSync as unlinkSync6, writeFileSync as writeFileSync26 } from "node:fs";
90174
90216
  import { homedir as homedir7 } from "node:os";
90175
- import { join as join42 } from "node:path";
90217
+ import { join as join43 } from "node:path";
90176
90218
 
90177
90219
  // src/hook-commands.ts
90178
90220
  function hookCurlCommand(port, path2 = "/api/hook") {
@@ -90211,9 +90253,12 @@ function buildCodexHooksToml(port, options) {
90211
90253
 
90212
90254
  // src/codex-hook-relay.ts
90213
90255
  var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
90214
- import { readFileSync, statSync } from 'node:fs';
90256
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
90257
+ import { createHash } from 'node:crypto';
90215
90258
  import { join } from 'node:path';
90216
90259
  const workspaceRoot = null;
90260
+ // Stdout closing early is not delivery. Never stamp a receipt on EPIPE.
90261
+ process.stdout.on('error', () => process.exit(0));
90217
90262
 
90218
90263
  try {
90219
90264
  const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
@@ -90225,6 +90270,19 @@ try {
90225
90270
  if (!Number.isInteger(port) || port < 1 || port > 65535) process.exit(0);
90226
90271
  const contexts = [];
90227
90272
  const messages = [];
90273
+ const hash = (text) => createHash('sha256').update(text).digest('hex');
90274
+ const boundedRead = (path, max) => statSync(path).size <= max ? readFileSync(path, 'utf8') : '';
90275
+ const stateDir = workspaceRoot && join(workspaceRoot, '.errata', 'codex-hook-state');
90276
+ const statePath = stateDir && typeof payload.session_id === 'string' && payload.session_id
90277
+ ? join(stateDir, hash(payload.session_id) + '.json') : null;
90278
+ let previous = {};
90279
+ try {
90280
+ if (statePath) {
90281
+ const saved = JSON.parse(boundedRead(statePath, 4096));
90282
+ if (saved && typeof saved === 'object') previous = saved;
90283
+ }
90284
+ } catch {}
90285
+ let receipt = null;
90228
90286
  const post = async (endpoint, relay = false) => {
90229
90287
  try {
90230
90288
  const response = await fetch('http://127.0.0.1:' + port + '/api/' + endpoint, {
@@ -90244,33 +90302,52 @@ try {
90244
90302
  if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
90245
90303
  // Stop sees the final assistant message, including turns with no tools.
90246
90304
  if (event === 'PostToolUse' || event === 'Stop') await post('turn');
90247
- if (['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
90248
- // Run after capture, so changes already rendered by the daemon arrive now.
90249
- // Background extraction finishing later arrives at the next tool boundary.
90250
- const available = await post('context-inject', true);
90251
- // Startup/resume/compaction must not depend on the daemon's busy event loop.
90252
- // Read only the installer's resolved workspace, never a caller-supplied path
90253
- // or tracked AGENTS.md. SessionStart already re-injects unconditionally;
90254
- // prompt/tool refreshes retain daemon hash deduplication (no repeated copies).
90255
- if (!available && event === 'SessionStart' && workspaceRoot) {
90256
- try {
90257
- const path = join(workspaceRoot, '.errata', 'context.md');
90258
- if (statSync(path).size <= 128 * 1024) {
90259
- const body = readFileSync(path, 'utf8').trim();
90260
- if (body) {
90261
- contexts.push('Errata loaded the maintained local workspace context while the daemon response was unavailable. This block REPLACES any earlier errata context block in this conversation. It is the last saved snapshot; live updates resume when the daemon responds.\n\n' + body);
90262
- if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) messages.push('⚡ errata · saved workspace priors loaded');
90263
- }
90305
+ if (['SessionStart', 'UserPromptSubmit'].includes(event)) {
90306
+ // Wake/route the engine, bounded independently of context delivery. Older
90307
+ // daemons may stamp their HTTP dedup gate before a timed-out response arrives;
90308
+ // that gate is deliberately NOT authoritative for this file-based relay.
90309
+ await post('context-inject', !workspaceRoot);
90310
+ }
90311
+ if (workspaceRoot && ['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
90312
+ let body = '';
90313
+ try { body = boundedRead(join(workspaceRoot, '.errata', 'context.md'), 128 * 1024).trim(); } catch {}
90314
+ if (body) {
90315
+ const digest = hash(body.replace(/\r\n?/g, '\n')).slice(0, 16);
90316
+ // Receipt is local to this graph + session, survives daemon restarts, and
90317
+ // records stdout emission, not a server's intention to send a response.
90318
+ if (event === 'SessionStart' || previous.hash !== digest) {
90319
+ contexts.push('Errata loaded the maintained local workspace context. This block REPLACES any earlier errata context block in this conversation. It is the latest saved snapshot; the daemon maintains it as work proceeds.\n\n' + body);
90320
+ if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) {
90321
+ try {
90322
+ const card = JSON.parse(boundedRead(join(workspaceRoot, '.errata', 'context-card.json'), 128 * 1024));
90323
+ if (card.hash === digest && typeof card.line === 'string' && card.line) messages.push(card.line);
90324
+ } catch { /* Never show a card for a different snapshot. */ }
90264
90325
  }
90265
- } catch { /* No saved context is honest; never substitute another project. */ }
90326
+ receipt = { hash: digest, at: Date.now() };
90327
+ }
90328
+ } else if (event === 'SessionStart' || !previous.unavailable) {
90329
+ messages.push('errata: workspace priors are unavailable; run errata doctor in this checkout.');
90330
+ receipt = { unavailable: true, at: Date.now() };
90266
90331
  }
90332
+ } else if (!workspaceRoot && event === 'PostToolUse') {
90333
+ await post('context-inject', true);
90267
90334
  }
90268
90335
  if (contexts.length || messages.length) {
90269
- process.stdout.write(JSON.stringify({
90336
+ await new Promise((resolve) => process.stdout.write(JSON.stringify({
90270
90337
  ...(messages.length ? { systemMessage: messages.join('\n\n') } : {}),
90271
90338
  ...(contexts.length ? { hookSpecificOutput: {
90272
90339
  hookEventName: event, additionalContext: contexts.join('\n\n'),
90273
90340
  } } : {}),
90341
+ }), (error) => {
90342
+ if (!error && receipt && statePath) {
90343
+ try {
90344
+ mkdirSync(stateDir, { recursive: true });
90345
+ const temp = statePath + '.' + process.pid + '.tmp';
90346
+ writeFileSync(temp, JSON.stringify(receipt), { mode: 0o600 });
90347
+ renameSync(temp, statePath);
90348
+ } catch { /* Read-only workspace: retry next time rather than drop context. */ }
90349
+ }
90350
+ resolve();
90274
90351
  }));
90275
90352
  }
90276
90353
  } catch { /* Invalid input is also fail-open. */ }
@@ -90282,8 +90359,35 @@ function buildCodexRelaySource(workspaceRoot) {
90282
90359
  // src/codex-hooks.ts
90283
90360
  init_checkout_root();
90284
90361
  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.";
90285
- function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join42(homedir7(), ".codex")) {
90286
- return existsSync34(join42(root, ".codex")) || existsSync34(codexHome);
90362
+ function writeRelay(file2, source) {
90363
+ if (existsSync34(file2) && readFileSync36(file2, "utf8") === source) return;
90364
+ const temp = `${file2}.${process.pid}.tmp`;
90365
+ try {
90366
+ writeFileSync26(temp, source, { encoding: "utf8", mode: 384 });
90367
+ renameSync5(temp, file2);
90368
+ } finally {
90369
+ if (existsSync34(temp)) unlinkSync6(temp);
90370
+ }
90371
+ }
90372
+ function refreshCodexRelay(root) {
90373
+ const config2 = join43(root, ".codex", "config.toml");
90374
+ if (!existsSync34(config2)) return "absent";
90375
+ const existing = readFileSync36(config2, "utf8");
90376
+ if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
90377
+ replaceCodexHooks(existing, "");
90378
+ const relay = join43(root, ".codex", "hooks", "errata-relay.mjs");
90379
+ const prior = existsSync34(relay) ? readFileSync36(relay, "utf8") : "";
90380
+ if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
90381
+ throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
90382
+ }
90383
+ const source = buildCodexRelaySource(checkoutRootOf(root));
90384
+ if (prior === source) return "current";
90385
+ mkdirSync9(join43(root, ".codex", "hooks"), { recursive: true });
90386
+ writeRelay(relay, source);
90387
+ return "updated";
90388
+ }
90389
+ function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join43(homedir7(), ".codex")) {
90390
+ return existsSync34(join43(root, ".codex")) || existsSync34(codexHome);
90287
90391
  }
90288
90392
  function replaceCodexHooks(existing, block) {
90289
90393
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -90299,20 +90403,43 @@ function replaceCodexHooks(existing, block) {
90299
90403
  return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
90300
90404
  }
90301
90405
  function writeCodexHooks(root, port, nodePath = process.execPath) {
90302
- const dir = join42(root, ".codex");
90303
- const file2 = join42(dir, "config.toml");
90304
- const relay = join42(dir, "hooks", "errata-relay.mjs");
90406
+ const dir = join43(root, ".codex");
90407
+ const file2 = join43(dir, "config.toml");
90408
+ const relay = join43(dir, "hooks", "errata-relay.mjs");
90305
90409
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
90306
90410
  const final = replaceCodexHooks(existsSync34(file2) ? readFileSync36(file2, "utf8") : "", block);
90307
- mkdirSync9(join42(dir, "hooks"), { recursive: true });
90308
- writeFileSync26(relay, buildCodexRelaySource(checkoutRootOf(root)), "utf8");
90309
- writeFileSync26(file2, final, "utf8");
90411
+ mkdirSync9(join43(dir, "hooks"), { recursive: true });
90412
+ writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
90413
+ if (!existsSync34(file2) || readFileSync36(file2, "utf8") !== final) writeFileSync26(file2, final, "utf8");
90310
90414
  return file2;
90311
90415
  }
90312
90416
 
90313
90417
  // src/codex-doctor.ts
90418
+ init_checkout_root();
90419
+ function inspectCodexRelay(cwd) {
90420
+ const root = nearestGitRoot(cwd) ?? cwd;
90421
+ try {
90422
+ const source = readFileSync37(join44(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
90423
+ if (source === buildCodexRelaySource(checkoutRootOf(root))) {
90424
+ return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
90425
+ }
90426
+ } catch {
90427
+ }
90428
+ return { id: "codex_relay", status: "fail", detail: "Codex relay is missing or outdated; run errata install-hooks codex --refresh-existing, or errata install-hooks codex for a new setup" };
90429
+ }
90430
+ function inspectCodexContext(cwd) {
90431
+ const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
90432
+ try {
90433
+ const file2 = join44(root, ".errata", "context.md");
90434
+ if (statSync10(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
90435
+ return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
90436
+ }
90437
+ } catch {
90438
+ }
90439
+ return { id: "codex_context", status: "fail", detail: "No usable saved workspace context; run errata start here and check the daemon log if context.md remains unavailable" };
90440
+ }
90314
90441
  function readCodexHookState(cwd, options = {}) {
90315
- return new Promise((resolve7, reject) => {
90442
+ return new Promise((resolve8, reject) => {
90316
90443
  const child = spawn4(options.bin ?? resolveCodexExecutable(), options.args ?? ["app-server", "--stdio"], {
90317
90444
  cwd,
90318
90445
  windowsHide: true,
@@ -90328,9 +90455,14 @@ function readCodexHookState(cwd, options = {}) {
90328
90455
  settled = true;
90329
90456
  clearTimeout(timer);
90330
90457
  lines.close();
90458
+ const reap = setTimeout(() => child.kill("SIGKILL"), 1e3);
90459
+ reap.unref();
90460
+ child.once("close", () => {
90461
+ clearTimeout(reap);
90462
+ if (error48) reject(error48);
90463
+ else resolve8({ ...hooks, features });
90464
+ });
90331
90465
  child.kill();
90332
- if (error48) reject(error48);
90333
- else resolve7({ ...hooks, features });
90334
90466
  };
90335
90467
  const timer = setTimeout(() => finish(new Error("Codex hook inspection timed out")), options.timeoutMs ?? 1e4);
90336
90468
  const send = (id, method, params) => {
@@ -90395,10 +90527,11 @@ function assessCodexHooks(state, platform = process.platform) {
90395
90527
  return checks.length ? checks : check2("pass", "Codex discovers enabled, trusted Errata hooks; verify live context and capture in a session");
90396
90528
  }
90397
90529
  async function diagnoseCodexHooks(cwd) {
90530
+ const local = [inspectCodexRelay(cwd), inspectCodexContext(cwd)];
90398
90531
  try {
90399
- return assessCodexHooks(await readCodexHookState(cwd));
90532
+ return [...local, ...assessCodexHooks(await readCodexHookState(cwd))];
90400
90533
  } catch (error48) {
90401
- return [{ id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
90534
+ return [...local, { id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
90402
90535
  }
90403
90536
  }
90404
90537
 
@@ -90472,10 +90605,51 @@ function consolidationGapMs(lastPassMs, policy) {
90472
90605
  return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
90473
90606
  }
90474
90607
 
90608
+ // src/codex-hook-refresh.ts
90609
+ init_checkout_root();
90610
+ import { existsSync as existsSync35, readdirSync as readdirSync13, readFileSync as readFileSync38 } from "node:fs";
90611
+ import { dirname as dirname13, join as join45, resolve as resolve7 } from "node:path";
90612
+ init_registry();
90613
+ function codexHookRoots(roots) {
90614
+ const found = new Set(roots.map((root) => resolve7(root)));
90615
+ for (const root of [...found]) {
90616
+ const main2 = mainCheckoutOfWorktree(root) ?? root;
90617
+ found.add(main2);
90618
+ const dir = join45(main2, ".git", "worktrees");
90619
+ if (!existsSync35(dir)) continue;
90620
+ let names;
90621
+ try {
90622
+ names = readdirSync13(dir);
90623
+ } catch {
90624
+ continue;
90625
+ }
90626
+ for (const name2 of names) {
90627
+ try {
90628
+ const checkout = dirname13(readFileSync38(join45(dir, name2, "gitdir"), "utf8").trim());
90629
+ if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
90630
+ } catch {
90631
+ }
90632
+ }
90633
+ }
90634
+ return [...found];
90635
+ }
90636
+ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry) => entry.path)) {
90637
+ const results = [];
90638
+ for (const root of codexHookRoots(roots)) {
90639
+ try {
90640
+ const status = refreshCodexRelay(root);
90641
+ if (status !== "absent") results.push({ root, status });
90642
+ } catch (error48) {
90643
+ results.push({ root, status: "error", detail: error48 instanceof Error ? error48.message : String(error48) });
90644
+ }
90645
+ }
90646
+ return results;
90647
+ }
90648
+
90475
90649
  // src/claude-statusline.ts
90476
- import { existsSync as existsSync35, mkdirSync as mkdirSync10, readFileSync as readFileSync37, writeFileSync as writeFileSync27 } from "node:fs";
90650
+ import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
90477
90651
  import { homedir as homedir8 } from "node:os";
90478
- import { dirname as dirname13, join as join43 } from "node:path";
90652
+ import { dirname as dirname14, join as join46 } from "node:path";
90479
90653
  var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
90480
90654
  import { readFileSync } from 'node:fs';
90481
90655
 
@@ -90508,8 +90682,8 @@ function removeProjectStatusLine(settings) {
90508
90682
  return true;
90509
90683
  }
90510
90684
  function userClaudeSettingsPath() {
90511
- const base = process.env["CLAUDE_CONFIG_DIR"] ?? join43(homedir8(), ".claude");
90512
- return join43(base, "settings.json");
90685
+ const base = process.env["CLAUDE_CONFIG_DIR"] ?? join46(homedir8(), ".claude");
90686
+ return join46(base, "settings.json");
90513
90687
  }
90514
90688
  function ensureUserStatusLine(opts) {
90515
90689
  const env2 = opts.env ?? process.env;
@@ -90517,9 +90691,9 @@ function ensureUserStatusLine(opts) {
90517
90691
  if (off === "0" || off === "off" || off === "false" || off === "no") return "disabled";
90518
90692
  const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
90519
90693
  let settings = {};
90520
- if (existsSync35(settingsPath)) {
90694
+ if (existsSync36(settingsPath)) {
90521
90695
  try {
90522
- const parsed = JSON.parse(readFileSync37(settingsPath, "utf8"));
90696
+ const parsed = JSON.parse(readFileSync39(settingsPath, "utf8"));
90523
90697
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
90524
90698
  settings = parsed;
90525
90699
  } catch {
@@ -90527,15 +90701,15 @@ function ensureUserStatusLine(opts) {
90527
90701
  }
90528
90702
  }
90529
90703
  if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
90530
- const relay = join43(opts.relayDir, STATUSLINE_RELAY_FILE);
90704
+ const relay = join46(opts.relayDir, STATUSLINE_RELAY_FILE);
90531
90705
  mkdirSync10(opts.relayDir, { recursive: true });
90532
- if (!existsSync35(relay) || readFileSync37(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
90706
+ if (!existsSync36(relay) || readFileSync39(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
90533
90707
  writeFileSync27(relay, STATUSLINE_RELAY_SOURCE, "utf8");
90534
90708
  }
90535
90709
  const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
90536
90710
  if (JSON.stringify(settings["statusLine"]) === JSON.stringify(next)) return "unchanged";
90537
90711
  settings["statusLine"] = next;
90538
- mkdirSync10(dirname13(settingsPath), { recursive: true });
90712
+ mkdirSync10(dirname14(settingsPath), { recursive: true });
90539
90713
  writeFileSync27(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
90540
90714
  return "installed";
90541
90715
  }
@@ -90959,14 +91133,14 @@ async function cmdInit() {
90959
91133
  if (!skipHooks) {
90960
91134
  console.log("");
90961
91135
  console.log("installing harness hooks...");
90962
- const { existsSync: existsSync37 } = await import("node:fs");
90963
- const { join: join45 } = await import("node:path");
91136
+ const { existsSync: existsSync38 } = await import("node:fs");
91137
+ const { join: join48 } = await import("node:path");
90964
91138
  try {
90965
91139
  await installClaudeHooks(port);
90966
91140
  } catch (err2) {
90967
91141
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
90968
91142
  }
90969
- if (existsSync37(join45(ROOT, ".cursor"))) {
91143
+ if (existsSync38(join48(ROOT, ".cursor"))) {
90970
91144
  try {
90971
91145
  await installCursorMcpConfig();
90972
91146
  } catch (err2) {
@@ -91050,6 +91224,7 @@ async function cmdNotifyTest() {
91050
91224
  }
91051
91225
  }
91052
91226
  async function cmdStart() {
91227
+ refreshExistingCodexHooks();
91053
91228
  if (!loadProfile(ROOT)) {
91054
91229
  const cfg = loadConfig();
91055
91230
  const locator = detectRepoLocator(ROOT);
@@ -91159,9 +91334,9 @@ async function cmdStatus() {
91159
91334
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
91160
91335
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
91161
91336
  }
91162
- console.log(` graph db: ${existsSync36(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
91163
- console.log(` event log: ${existsSync36(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
91164
- if (existsSync36(paths.castalia)) {
91337
+ console.log(` graph db: ${existsSync37(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
91338
+ console.log(` event log: ${existsSync37(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
91339
+ if (existsSync37(paths.castalia)) {
91165
91340
  try {
91166
91341
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
91167
91342
  const store = openGraphStore2({ path: paths.castalia });
@@ -91497,6 +91672,9 @@ async function cmdUpdate(args2) {
91497
91672
  `);
91498
91673
  const code = await runNpmInstall(channel);
91499
91674
  if (code === 0) {
91675
+ if (await runInstalledHookRefresh() !== 0) {
91676
+ console.warn("[!] Package updated, but some Codex relays could not be refreshed. Run `errata install-hooks codex --refresh-existing`; daemon startup also retries.");
91677
+ }
91500
91678
  console.log(`
91501
91679
  [OK] updated to ${status.latest}. Restart the daemon to run it:`);
91502
91680
  console.log(` errata stop (autostart relaunches it at next logon, or run 'errata dash')`);
@@ -92129,11 +92307,11 @@ async function cmdInstallationProfile(args2) {
92129
92307
  }
92130
92308
  async function cmdReview() {
92131
92309
  const paths = workspacePaths(ROOT);
92132
- if (!existsSync36(paths.reviewQueue)) {
92310
+ if (!existsSync37(paths.reviewQueue)) {
92133
92311
  console.log("(review queue empty)");
92134
92312
  return;
92135
92313
  }
92136
- const queue = JSON.parse(readFileSync38(paths.reviewQueue, "utf8"));
92314
+ const queue = JSON.parse(readFileSync40(paths.reviewQueue, "utf8"));
92137
92315
  if (queue.length === 0) {
92138
92316
  console.log("(review queue empty)");
92139
92317
  return;
@@ -92804,7 +92982,7 @@ async function gatherRepo(store, ws) {
92804
92982
  };
92805
92983
  }
92806
92984
  async function gatherReportData(generatedAt) {
92807
- const { existsSync: existsSync37 } = await import("node:fs");
92985
+ const { existsSync: existsSync38 } = await import("node:fs");
92808
92986
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
92809
92987
  const cfg = loadConfig();
92810
92988
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -92812,7 +92990,7 @@ async function gatherReportData(generatedAt) {
92812
92990
  for (const ws of listWorkspaces()) {
92813
92991
  if (ws.missing) continue;
92814
92992
  const dbPath = workspacePaths(ws.path).castalia;
92815
- if (!existsSync37(dbPath)) continue;
92993
+ if (!existsSync38(dbPath)) continue;
92816
92994
  let store = null;
92817
92995
  try {
92818
92996
  store = openGraphStore2({ path: dbPath });
@@ -92856,8 +93034,8 @@ async function cmdReport(args2) {
92856
93034
  const outDir = workspacePaths(ROOT).configDir;
92857
93035
  mkdirSync11(outDir, { recursive: true });
92858
93036
  const files = renderReport2(data, { includeFutureVerbs });
92859
- for (const f of files) writeFileSync28(join44(outDir, f.name), f.html, "utf8");
92860
- const indexPath = join44(outDir, "report.html");
93037
+ for (const f of files) writeFileSync28(join47(outDir, f.name), f.html, "utf8");
93038
+ const indexPath = join47(outDir, "report.html");
92861
93039
  console.log(`report \u2192 ${indexPath}`);
92862
93040
  console.log(
92863
93041
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -92901,7 +93079,7 @@ function spawnDaemonDetached(options = {}) {
92901
93079
  try {
92902
93080
  const logPath = daemonLogPath();
92903
93081
  try {
92904
- if (statSync10(logPath).size > 5 * 1024 * 1024) renameSync4(logPath, `${logPath}.1`);
93082
+ if (statSync11(logPath).size > 5 * 1024 * 1024) renameSync6(logPath, `${logPath}.1`);
92905
93083
  } catch {
92906
93084
  }
92907
93085
  out2 = openSync2(logPath, "a");
@@ -92951,6 +93129,10 @@ async function cmdInstallHooks(args2) {
92951
93129
  await installCursorMcpConfig();
92952
93130
  return;
92953
93131
  case "codex":
93132
+ if (args2.includes("--refresh-existing")) {
93133
+ if (!refreshExistingCodexHooks()) process.exitCode = 1;
93134
+ return;
93135
+ }
92954
93136
  await installCodexHooks(port);
92955
93137
  return;
92956
93138
  case "opencode":
@@ -92966,24 +93148,24 @@ async function cmdInstallHooks(args2) {
92966
93148
  }
92967
93149
  }
92968
93150
  async function installOpencodePlugin(port) {
92969
- const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
92970
- const { join: join45 } = await import("node:path");
92971
- const dir = join45(ROOT, ".opencode", "plugin");
92972
- if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
92973
- const file2 = join45(dir, "inerrata.js");
92974
- if (existsSync37(file2)) {
92975
- const head2 = readFileSync39(file2, "utf8").split("\n")[0] ?? "";
93151
+ const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
93152
+ const { join: join48 } = await import("node:path");
93153
+ const dir = join48(ROOT, ".opencode", "plugin");
93154
+ if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
93155
+ const file2 = join48(dir, "inerrata.js");
93156
+ if (existsSync38(file2)) {
93157
+ const head2 = readFileSync41(file2, "utf8").split("\n")[0] ?? "";
92976
93158
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
92977
93159
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
92978
93160
  process.exit(2);
92979
93161
  }
92980
93162
  }
92981
93163
  writeFileSync28(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
92982
- const cfgFile = join45(ROOT, "opencode.json");
93164
+ const cfgFile = join48(ROOT, "opencode.json");
92983
93165
  let cfg = { $schema: "https://opencode.ai/config.json" };
92984
- if (existsSync37(cfgFile)) {
93166
+ if (existsSync38(cfgFile)) {
92985
93167
  try {
92986
- cfg = JSON.parse(readFileSync39(cfgFile, "utf8"));
93168
+ cfg = JSON.parse(readFileSync41(cfgFile, "utf8"));
92987
93169
  } catch {
92988
93170
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
92989
93171
  process.exit(2);
@@ -93021,15 +93203,15 @@ function ensureStatusLine(port) {
93021
93203
  }
93022
93204
  }
93023
93205
  async function installClaudeHooks(port) {
93024
- const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
93025
- const { join: join45 } = await import("node:path");
93026
- const dir = join45(ROOT, ".claude");
93027
- if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
93028
- const file2 = join45(dir, "settings.json");
93206
+ const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
93207
+ const { join: join48 } = await import("node:path");
93208
+ const dir = join48(ROOT, ".claude");
93209
+ if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
93210
+ const file2 = join48(dir, "settings.json");
93029
93211
  let settings = {};
93030
- if (existsSync37(file2)) {
93212
+ if (existsSync38(file2)) {
93031
93213
  try {
93032
- settings = JSON.parse(readFileSync39(file2, "utf8"));
93214
+ settings = JSON.parse(readFileSync41(file2, "utf8"));
93033
93215
  } catch {
93034
93216
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93035
93217
  process.exit(2);
@@ -93081,7 +93263,7 @@ async function installClaudeHooks(port) {
93081
93263
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
93082
93264
  console.log(` ${ensureStatusLine(port)}`);
93083
93265
  await installClaudeMcpConfig();
93084
- const claudeMd = join45(ROOT, "CLAUDE.md");
93266
+ const claudeMd = join48(ROOT, "CLAUDE.md");
93085
93267
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
93086
93268
  if (recall.kind === "collision") {
93087
93269
  console.warn(
@@ -93093,15 +93275,15 @@ async function installClaudeHooks(port) {
93093
93275
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
93094
93276
  }
93095
93277
  async function installClaudeMcpConfig() {
93096
- const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
93097
- const { join: join45, dirname: dirname14 } = await import("node:path");
93098
- const file2 = join45(ROOT, ".mcp.json");
93099
- const dir = dirname14(file2);
93100
- if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
93278
+ const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
93279
+ const { join: join48, dirname: dirname15 } = await import("node:path");
93280
+ const file2 = join48(ROOT, ".mcp.json");
93281
+ const dir = dirname15(file2);
93282
+ if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
93101
93283
  let cfg = {};
93102
- if (existsSync37(file2)) {
93284
+ if (existsSync38(file2)) {
93103
93285
  try {
93104
- cfg = JSON.parse(readFileSync39(file2, "utf8"));
93286
+ cfg = JSON.parse(readFileSync41(file2, "utf8"));
93105
93287
  } catch {
93106
93288
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93107
93289
  process.exit(2);
@@ -93115,15 +93297,15 @@ async function installClaudeMcpConfig() {
93115
93297
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
93116
93298
  }
93117
93299
  async function installCursorMcpConfig() {
93118
- const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
93119
- const { join: join45 } = await import("node:path");
93120
- const dir = join45(ROOT, ".cursor");
93121
- if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
93122
- const file2 = join45(dir, "mcp.json");
93300
+ const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
93301
+ const { join: join48 } = await import("node:path");
93302
+ const dir = join48(ROOT, ".cursor");
93303
+ if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
93304
+ const file2 = join48(dir, "mcp.json");
93123
93305
  let cfg = {};
93124
- if (existsSync37(file2)) {
93306
+ if (existsSync38(file2)) {
93125
93307
  try {
93126
- cfg = JSON.parse(readFileSync39(file2, "utf8"));
93308
+ cfg = JSON.parse(readFileSync41(file2, "utf8"));
93127
93309
  } catch {
93128
93310
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93129
93311
  process.exit(2);
@@ -93142,7 +93324,7 @@ async function installCodexHooks(port) {
93142
93324
  const gitRoot = nearestGitRoot(process.cwd());
93143
93325
  const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
93144
93326
  const file2 = writeCodexHooks(hookRoot, port);
93145
- const instructions = writeManagedBlock(join44(hookRoot, "AGENTS.md"), {
93327
+ const instructions = writeManagedBlock(join47(hookRoot, "AGENTS.md"), {
93146
93328
  body: AGENTS_POINTER_BODY,
93147
93329
  stable: true
93148
93330
  });
@@ -93160,6 +93342,21 @@ async function installCodexHooks(port) {
93160
93342
  console.log(" Run `errata doctor` here to check hook discovery and trust; installation alone is not activation.");
93161
93343
  console.log(" Respect an explicit [features] hooks = false setting (older builds use codex_hooks).");
93162
93344
  console.log(" Older Codex versions may not support every event; update if hooks do not fire.");
93345
+ for (const check2 of await diagnoseCodexHooks(hookRoot)) {
93346
+ console.log(` ${check2.status === "pass" ? "\u2713" : "!"} ${check2.detail}`);
93347
+ }
93348
+ }
93349
+ function refreshExistingCodexHooks() {
93350
+ let ok = true;
93351
+ const roots = [...listWorkspaceEntries().map((entry) => entry.path), process.cwd()];
93352
+ for (const result of refreshInstalledCodexRelays(roots)) {
93353
+ if (result.status === "updated") console.log(`updated existing Codex relay \u2192 ${result.root} (hook definitions preserved)`);
93354
+ if (result.status === "error") {
93355
+ ok = false;
93356
+ console.warn(`Codex relay refresh needs attention in ${result.root}: ${result.detail}`);
93357
+ }
93358
+ }
93359
+ return ok;
93163
93360
  }
93164
93361
  async function refreshLinkedCodexHooks(args2) {
93165
93362
  if (args2.includes("--skip-hooks") || !hasCodexConfig(ROOT)) return;
@@ -93314,6 +93511,7 @@ function installLogTimestamps() {
93314
93511
  async function cmdDash(args2) {
93315
93512
  process.title = "errata-daemon";
93316
93513
  installLogTimestamps();
93514
+ refreshExistingCodexHooks();
93317
93515
  const portIdx = args2.indexOf("--port");
93318
93516
  const port = portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : 7891;
93319
93517
  const reindexOnStart = !args2.includes("--no-reindex");
@@ -93468,7 +93666,7 @@ async function cmdDash(args2) {
93468
93666
  const hotspotScanMark = /* @__PURE__ */ new Map();
93469
93667
  const HOTSPOT_FANIN = 20;
93470
93668
  const runNightlyPass = async (dueIds) => {
93471
- const yieldToLoop2 = () => new Promise((resolve7) => setImmediate(resolve7));
93669
+ const yieldToLoop2 = () => new Promise((resolve8) => setImmediate(resolve8));
93472
93670
  const fullReclusterPass = nightlyCount++ % FULL_RECLUSTER_EVERY === 0;
93473
93671
  const m = dueIds ? await handle2.nightlyFor(dueIds) : await handle2.nightlyAll();
93474
93672
  let skillsLearned = 0;
@@ -93546,9 +93744,9 @@ async function cmdDash(args2) {
93546
93744
  await yieldToLoop2();
93547
93745
  try {
93548
93746
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
93549
- atCommit: readGitRefState(join44(r.root, ".git")).sha ?? void 0
93747
+ atCommit: readGitRefState(join47(r.root, ".git")).sha ?? void 0
93550
93748
  });
93551
- const res = bleedRules(join44(r.root, ".claude", "rules"), items);
93749
+ const res = bleedRules(join47(r.root, ".claude", "rules"), items);
93552
93750
  if (res.written || res.pruned) {
93553
93751
  console.log(
93554
93752
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")