@mrrlin-dev/mcp 0.4.6 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.cjs CHANGED
@@ -6246,7 +6246,7 @@ var require_websocket = __commonJS({
6246
6246
  var http2 = require("http");
6247
6247
  var net = require("net");
6248
6248
  var tls = require("tls");
6249
- var { randomBytes: randomBytes4, createHash: createHash4 } = require("crypto");
6249
+ var { randomBytes: randomBytes4, createHash: createHash5 } = require("crypto");
6250
6250
  var { Duplex, Readable } = require("stream");
6251
6251
  var { URL: URL2 } = require("url");
6252
6252
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -6914,7 +6914,7 @@ var require_websocket = __commonJS({
6914
6914
  abortHandshake(websocket, socket, "Invalid Upgrade header");
6915
6915
  return;
6916
6916
  }
6917
- const digest = createHash4("sha1").update(key + GUID).digest("base64");
6917
+ const digest = createHash5("sha1").update(key + GUID).digest("base64");
6918
6918
  if (res.headers["sec-websocket-accept"] !== digest) {
6919
6919
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
6920
6920
  return;
@@ -7283,7 +7283,7 @@ var require_websocket_server = __commonJS({
7283
7283
  var EventEmitter3 = require("events");
7284
7284
  var http2 = require("http");
7285
7285
  var { Duplex } = require("stream");
7286
- var { createHash: createHash4 } = require("crypto");
7286
+ var { createHash: createHash5 } = require("crypto");
7287
7287
  var extension2 = require_extension();
7288
7288
  var PerMessageDeflate2 = require_permessage_deflate();
7289
7289
  var subprotocol2 = require_subprotocol();
@@ -7590,7 +7590,7 @@ var require_websocket_server = __commonJS({
7590
7590
  );
7591
7591
  }
7592
7592
  if (this._state > RUNNING) return abortHandshake(socket, 503);
7593
- const digest = createHash4("sha1").update(key + GUID).digest("base64");
7593
+ const digest = createHash5("sha1").update(key + GUID).digest("base64");
7594
7594
  const headers = [
7595
7595
  "HTTP/1.1 101 Switching Protocols",
7596
7596
  "Upgrade: websocket",
@@ -7729,14 +7729,14 @@ var require_polyfills = __commonJS({
7729
7729
  fs10.fstatSync = statFixSync(fs10.fstatSync);
7730
7730
  fs10.lstatSync = statFixSync(fs10.lstatSync);
7731
7731
  if (fs10.chmod && !fs10.lchmod) {
7732
- fs10.lchmod = function(path21, mode, cb) {
7732
+ fs10.lchmod = function(path22, mode, cb) {
7733
7733
  if (cb) process.nextTick(cb);
7734
7734
  };
7735
7735
  fs10.lchmodSync = function() {
7736
7736
  };
7737
7737
  }
7738
7738
  if (fs10.chown && !fs10.lchown) {
7739
- fs10.lchown = function(path21, uid, gid, cb) {
7739
+ fs10.lchown = function(path22, uid, gid, cb) {
7740
7740
  if (cb) process.nextTick(cb);
7741
7741
  };
7742
7742
  fs10.lchownSync = function() {
@@ -7744,7 +7744,7 @@ var require_polyfills = __commonJS({
7744
7744
  }
7745
7745
  if (platform === "win32") {
7746
7746
  fs10.rename = typeof fs10.rename !== "function" ? fs10.rename : function(fs$rename) {
7747
- function rename(from, to, cb) {
7747
+ function rename4(from, to, cb) {
7748
7748
  var start = Date.now();
7749
7749
  var backoff = 0;
7750
7750
  fs$rename(from, to, function CB(er) {
@@ -7764,8 +7764,8 @@ var require_polyfills = __commonJS({
7764
7764
  if (cb) cb(er);
7765
7765
  });
7766
7766
  }
7767
- if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
7768
- return rename;
7767
+ if (Object.setPrototypeOf) Object.setPrototypeOf(rename4, fs$rename);
7768
+ return rename4;
7769
7769
  }(fs10.rename);
7770
7770
  }
7771
7771
  fs10.read = typeof fs10.read !== "function" ? fs10.read : function(fs$read) {
@@ -7803,9 +7803,9 @@ var require_polyfills = __commonJS({
7803
7803
  };
7804
7804
  }(fs10.readSync);
7805
7805
  function patchLchmod(fs11) {
7806
- fs11.lchmod = function(path21, mode, callback) {
7806
+ fs11.lchmod = function(path22, mode, callback) {
7807
7807
  fs11.open(
7808
- path21,
7808
+ path22,
7809
7809
  constants2.O_WRONLY | constants2.O_SYMLINK,
7810
7810
  mode,
7811
7811
  function(err, fd) {
@@ -7821,8 +7821,8 @@ var require_polyfills = __commonJS({
7821
7821
  }
7822
7822
  );
7823
7823
  };
7824
- fs11.lchmodSync = function(path21, mode) {
7825
- var fd = fs11.openSync(path21, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
7824
+ fs11.lchmodSync = function(path22, mode) {
7825
+ var fd = fs11.openSync(path22, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
7826
7826
  var threw = true;
7827
7827
  var ret;
7828
7828
  try {
@@ -7843,8 +7843,8 @@ var require_polyfills = __commonJS({
7843
7843
  }
7844
7844
  function patchLutimes(fs11) {
7845
7845
  if (constants2.hasOwnProperty("O_SYMLINK") && fs11.futimes) {
7846
- fs11.lutimes = function(path21, at, mt, cb) {
7847
- fs11.open(path21, constants2.O_SYMLINK, function(er, fd) {
7846
+ fs11.lutimes = function(path22, at, mt, cb) {
7847
+ fs11.open(path22, constants2.O_SYMLINK, function(er, fd) {
7848
7848
  if (er) {
7849
7849
  if (cb) cb(er);
7850
7850
  return;
@@ -7856,8 +7856,8 @@ var require_polyfills = __commonJS({
7856
7856
  });
7857
7857
  });
7858
7858
  };
7859
- fs11.lutimesSync = function(path21, at, mt) {
7860
- var fd = fs11.openSync(path21, constants2.O_SYMLINK);
7859
+ fs11.lutimesSync = function(path22, at, mt) {
7860
+ var fd = fs11.openSync(path22, constants2.O_SYMLINK);
7861
7861
  var ret;
7862
7862
  var threw = true;
7863
7863
  try {
@@ -7975,11 +7975,11 @@ var require_legacy_streams = __commonJS({
7975
7975
  ReadStream,
7976
7976
  WriteStream
7977
7977
  };
7978
- function ReadStream(path21, options) {
7979
- if (!(this instanceof ReadStream)) return new ReadStream(path21, options);
7978
+ function ReadStream(path22, options) {
7979
+ if (!(this instanceof ReadStream)) return new ReadStream(path22, options);
7980
7980
  Stream.call(this);
7981
7981
  var self = this;
7982
- this.path = path21;
7982
+ this.path = path22;
7983
7983
  this.fd = null;
7984
7984
  this.readable = true;
7985
7985
  this.paused = false;
@@ -8024,10 +8024,10 @@ var require_legacy_streams = __commonJS({
8024
8024
  self._read();
8025
8025
  });
8026
8026
  }
8027
- function WriteStream(path21, options) {
8028
- if (!(this instanceof WriteStream)) return new WriteStream(path21, options);
8027
+ function WriteStream(path22, options) {
8028
+ if (!(this instanceof WriteStream)) return new WriteStream(path22, options);
8029
8029
  Stream.call(this);
8030
- this.path = path21;
8030
+ this.path = path22;
8031
8031
  this.fd = null;
8032
8032
  this.writable = true;
8033
8033
  this.flags = "w";
@@ -8169,15 +8169,15 @@ var require_graceful_fs = __commonJS({
8169
8169
  fs11.createReadStream = createReadStream;
8170
8170
  fs11.createWriteStream = createWriteStream;
8171
8171
  var fs$readFile = fs11.readFile;
8172
- fs11.readFile = readFile3;
8173
- function readFile3(path21, options, cb) {
8172
+ fs11.readFile = readFile9;
8173
+ function readFile9(path22, options, cb) {
8174
8174
  if (typeof options === "function")
8175
8175
  cb = options, options = null;
8176
- return go$readFile(path21, options, cb);
8177
- function go$readFile(path22, options2, cb2, startTime) {
8178
- return fs$readFile(path22, options2, function(err) {
8176
+ return go$readFile(path22, options, cb);
8177
+ function go$readFile(path23, options2, cb2, startTime) {
8178
+ return fs$readFile(path23, options2, function(err) {
8179
8179
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8180
- enqueue([go$readFile, [path22, options2, cb2], err, startTime || Date.now(), Date.now()]);
8180
+ enqueue([go$readFile, [path23, options2, cb2], err, startTime || Date.now(), Date.now()]);
8181
8181
  else {
8182
8182
  if (typeof cb2 === "function")
8183
8183
  cb2.apply(this, arguments);
@@ -8186,15 +8186,15 @@ var require_graceful_fs = __commonJS({
8186
8186
  }
8187
8187
  }
8188
8188
  var fs$writeFile = fs11.writeFile;
8189
- fs11.writeFile = writeFile;
8190
- function writeFile(path21, data, options, cb) {
8189
+ fs11.writeFile = writeFile5;
8190
+ function writeFile5(path22, data, options, cb) {
8191
8191
  if (typeof options === "function")
8192
8192
  cb = options, options = null;
8193
- return go$writeFile(path21, data, options, cb);
8194
- function go$writeFile(path22, data2, options2, cb2, startTime) {
8195
- return fs$writeFile(path22, data2, options2, function(err) {
8193
+ return go$writeFile(path22, data, options, cb);
8194
+ function go$writeFile(path23, data2, options2, cb2, startTime) {
8195
+ return fs$writeFile(path23, data2, options2, function(err) {
8196
8196
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8197
- enqueue([go$writeFile, [path22, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8197
+ enqueue([go$writeFile, [path23, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8198
8198
  else {
8199
8199
  if (typeof cb2 === "function")
8200
8200
  cb2.apply(this, arguments);
@@ -8204,15 +8204,15 @@ var require_graceful_fs = __commonJS({
8204
8204
  }
8205
8205
  var fs$appendFile = fs11.appendFile;
8206
8206
  if (fs$appendFile)
8207
- fs11.appendFile = appendFile;
8208
- function appendFile(path21, data, options, cb) {
8207
+ fs11.appendFile = appendFile2;
8208
+ function appendFile2(path22, data, options, cb) {
8209
8209
  if (typeof options === "function")
8210
8210
  cb = options, options = null;
8211
- return go$appendFile(path21, data, options, cb);
8212
- function go$appendFile(path22, data2, options2, cb2, startTime) {
8213
- return fs$appendFile(path22, data2, options2, function(err) {
8211
+ return go$appendFile(path22, data, options, cb);
8212
+ function go$appendFile(path23, data2, options2, cb2, startTime) {
8213
+ return fs$appendFile(path23, data2, options2, function(err) {
8214
8214
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8215
- enqueue([go$appendFile, [path22, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8215
+ enqueue([go$appendFile, [path23, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8216
8216
  else {
8217
8217
  if (typeof cb2 === "function")
8218
8218
  cb2.apply(this, arguments);
@@ -8241,33 +8241,33 @@ var require_graceful_fs = __commonJS({
8241
8241
  }
8242
8242
  }
8243
8243
  var fs$readdir = fs11.readdir;
8244
- fs11.readdir = readdir2;
8244
+ fs11.readdir = readdir5;
8245
8245
  var noReaddirOptionVersions = /^v[0-5]\./;
8246
- function readdir2(path21, options, cb) {
8246
+ function readdir5(path22, options, cb) {
8247
8247
  if (typeof options === "function")
8248
8248
  cb = options, options = null;
8249
- var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path22, options2, cb2, startTime) {
8250
- return fs$readdir(path22, fs$readdirCallback(
8251
- path22,
8249
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path23, options2, cb2, startTime) {
8250
+ return fs$readdir(path23, fs$readdirCallback(
8251
+ path23,
8252
8252
  options2,
8253
8253
  cb2,
8254
8254
  startTime
8255
8255
  ));
8256
- } : function go$readdir2(path22, options2, cb2, startTime) {
8257
- return fs$readdir(path22, options2, fs$readdirCallback(
8258
- path22,
8256
+ } : function go$readdir2(path23, options2, cb2, startTime) {
8257
+ return fs$readdir(path23, options2, fs$readdirCallback(
8258
+ path23,
8259
8259
  options2,
8260
8260
  cb2,
8261
8261
  startTime
8262
8262
  ));
8263
8263
  };
8264
- return go$readdir(path21, options, cb);
8265
- function fs$readdirCallback(path22, options2, cb2, startTime) {
8264
+ return go$readdir(path22, options, cb);
8265
+ function fs$readdirCallback(path23, options2, cb2, startTime) {
8266
8266
  return function(err, files) {
8267
8267
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8268
8268
  enqueue([
8269
8269
  go$readdir,
8270
- [path22, options2, cb2],
8270
+ [path23, options2, cb2],
8271
8271
  err,
8272
8272
  startTime || Date.now(),
8273
8273
  Date.now()
@@ -8338,7 +8338,7 @@ var require_graceful_fs = __commonJS({
8338
8338
  enumerable: true,
8339
8339
  configurable: true
8340
8340
  });
8341
- function ReadStream(path21, options) {
8341
+ function ReadStream(path22, options) {
8342
8342
  if (this instanceof ReadStream)
8343
8343
  return fs$ReadStream.apply(this, arguments), this;
8344
8344
  else
@@ -8358,7 +8358,7 @@ var require_graceful_fs = __commonJS({
8358
8358
  }
8359
8359
  });
8360
8360
  }
8361
- function WriteStream(path21, options) {
8361
+ function WriteStream(path22, options) {
8362
8362
  if (this instanceof WriteStream)
8363
8363
  return fs$WriteStream.apply(this, arguments), this;
8364
8364
  else
@@ -8376,22 +8376,22 @@ var require_graceful_fs = __commonJS({
8376
8376
  }
8377
8377
  });
8378
8378
  }
8379
- function createReadStream(path21, options) {
8380
- return new fs11.ReadStream(path21, options);
8379
+ function createReadStream(path22, options) {
8380
+ return new fs11.ReadStream(path22, options);
8381
8381
  }
8382
- function createWriteStream(path21, options) {
8383
- return new fs11.WriteStream(path21, options);
8382
+ function createWriteStream(path22, options) {
8383
+ return new fs11.WriteStream(path22, options);
8384
8384
  }
8385
8385
  var fs$open = fs11.open;
8386
8386
  fs11.open = open;
8387
- function open(path21, flags, mode, cb) {
8387
+ function open(path22, flags, mode, cb) {
8388
8388
  if (typeof mode === "function")
8389
8389
  cb = mode, mode = null;
8390
- return go$open(path21, flags, mode, cb);
8391
- function go$open(path22, flags2, mode2, cb2, startTime) {
8392
- return fs$open(path22, flags2, mode2, function(err, fd) {
8390
+ return go$open(path22, flags, mode, cb);
8391
+ function go$open(path23, flags2, mode2, cb2, startTime) {
8392
+ return fs$open(path23, flags2, mode2, function(err, fd) {
8393
8393
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8394
- enqueue([go$open, [path22, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
8394
+ enqueue([go$open, [path23, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
8395
8395
  else {
8396
8396
  if (typeof cb2 === "function")
8397
8397
  cb2.apply(this, arguments);
@@ -8882,11 +8882,11 @@ var require_mtime_precision = __commonJS({
8882
8882
  function probe(file2, fs10, callback) {
8883
8883
  const cachedPrecision = fs10[cacheSymbol];
8884
8884
  if (cachedPrecision) {
8885
- return fs10.stat(file2, (err, stat2) => {
8885
+ return fs10.stat(file2, (err, stat3) => {
8886
8886
  if (err) {
8887
8887
  return callback(err);
8888
8888
  }
8889
- callback(null, stat2.mtime, cachedPrecision);
8889
+ callback(null, stat3.mtime, cachedPrecision);
8890
8890
  });
8891
8891
  }
8892
8892
  const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
@@ -8894,13 +8894,13 @@ var require_mtime_precision = __commonJS({
8894
8894
  if (err) {
8895
8895
  return callback(err);
8896
8896
  }
8897
- fs10.stat(file2, (err2, stat2) => {
8897
+ fs10.stat(file2, (err2, stat3) => {
8898
8898
  if (err2) {
8899
8899
  return callback(err2);
8900
8900
  }
8901
- const precision = stat2.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
8901
+ const precision = stat3.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
8902
8902
  Object.defineProperty(fs10, cacheSymbol, { value: precision });
8903
- callback(null, stat2.mtime, precision);
8903
+ callback(null, stat3.mtime, precision);
8904
8904
  });
8905
8905
  });
8906
8906
  }
@@ -8920,7 +8920,7 @@ var require_mtime_precision = __commonJS({
8920
8920
  var require_lockfile = __commonJS({
8921
8921
  "../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/lockfile.js"(exports2, module2) {
8922
8922
  "use strict";
8923
- var path21 = require("path");
8923
+ var path22 = require("path");
8924
8924
  var fs10 = require_graceful_fs();
8925
8925
  var retry = require_retry2();
8926
8926
  var onExit = require_signal_exit();
@@ -8931,7 +8931,7 @@ var require_lockfile = __commonJS({
8931
8931
  }
8932
8932
  function resolveCanonicalPath(file2, options, callback) {
8933
8933
  if (!options.realpath) {
8934
- return callback(null, path21.resolve(file2));
8934
+ return callback(null, path22.resolve(file2));
8935
8935
  }
8936
8936
  options.fs.realpath(file2, callback);
8937
8937
  }
@@ -8954,14 +8954,14 @@ var require_lockfile = __commonJS({
8954
8954
  if (options.stale <= 0) {
8955
8955
  return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
8956
8956
  }
8957
- options.fs.stat(lockfilePath, (err2, stat2) => {
8957
+ options.fs.stat(lockfilePath, (err2, stat3) => {
8958
8958
  if (err2) {
8959
8959
  if (err2.code === "ENOENT") {
8960
8960
  return acquireLock(file2, { ...options, stale: 0 }, callback);
8961
8961
  }
8962
8962
  return callback(err2);
8963
8963
  }
8964
- if (!isLockStale(stat2, options)) {
8964
+ if (!isLockStale(stat3, options)) {
8965
8965
  return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
8966
8966
  }
8967
8967
  removeLock(file2, options, (err3) => {
@@ -8973,8 +8973,8 @@ var require_lockfile = __commonJS({
8973
8973
  });
8974
8974
  });
8975
8975
  }
8976
- function isLockStale(stat2, options) {
8977
- return stat2.mtime.getTime() < Date.now() - options.stale;
8976
+ function isLockStale(stat3, options) {
8977
+ return stat3.mtime.getTime() < Date.now() - options.stale;
8978
8978
  }
8979
8979
  function removeLock(file2, options, callback) {
8980
8980
  options.fs.rmdir(getLockFile(file2, options), (err) => {
@@ -8992,7 +8992,7 @@ var require_lockfile = __commonJS({
8992
8992
  lock2.updateDelay = lock2.updateDelay || options.update;
8993
8993
  lock2.updateTimeout = setTimeout(() => {
8994
8994
  lock2.updateTimeout = null;
8995
- options.fs.stat(lock2.lockfilePath, (err, stat2) => {
8995
+ options.fs.stat(lock2.lockfilePath, (err, stat3) => {
8996
8996
  const isOverThreshold = lock2.lastUpdate + options.stale < Date.now();
8997
8997
  if (err) {
8998
8998
  if (err.code === "ENOENT" || isOverThreshold) {
@@ -9001,7 +9001,7 @@ var require_lockfile = __commonJS({
9001
9001
  lock2.updateDelay = 1e3;
9002
9002
  return updateLock(file2, options);
9003
9003
  }
9004
- const isMtimeOurs = lock2.mtime.getTime() === stat2.mtime.getTime();
9004
+ const isMtimeOurs = lock2.mtime.getTime() === stat3.mtime.getTime();
9005
9005
  if (!isMtimeOurs) {
9006
9006
  return setLockAsCompromised(
9007
9007
  file2,
@@ -9126,11 +9126,11 @@ var require_lockfile = __commonJS({
9126
9126
  if (err) {
9127
9127
  return callback(err);
9128
9128
  }
9129
- options.fs.stat(getLockFile(file3, options), (err2, stat2) => {
9129
+ options.fs.stat(getLockFile(file3, options), (err2, stat3) => {
9130
9130
  if (err2) {
9131
9131
  return err2.code === "ENOENT" ? callback(null, false) : callback(err2);
9132
9132
  }
9133
- return callback(null, !isLockStale(stat2, options));
9133
+ return callback(null, !isLockStale(stat3, options));
9134
9134
  });
9135
9135
  });
9136
9136
  }
@@ -10795,10 +10795,10 @@ var require_segments = __commonJS({
10795
10795
  const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
10796
10796
  const nodes = buildNodes(segs);
10797
10797
  const graph = buildGraph(nodes, version2);
10798
- const path21 = dijkstra.find_path(graph.map, "start", "end");
10798
+ const path22 = dijkstra.find_path(graph.map, "start", "end");
10799
10799
  const optimizedSegs = [];
10800
- for (let i = 1; i < path21.length - 1; i++) {
10801
- optimizedSegs.push(graph.table[path21[i]].node);
10800
+ for (let i = 1; i < path22.length - 1; i++) {
10801
+ optimizedSegs.push(graph.table[path22[i]].node);
10802
10802
  }
10803
10803
  return exports2.fromArray(mergeSegments(optimizedSegs));
10804
10804
  };
@@ -13275,7 +13275,7 @@ var require_png2 = __commonJS({
13275
13275
  });
13276
13276
  png.pack();
13277
13277
  };
13278
- exports2.renderToFile = function renderToFile(path21, qrData, options, cb) {
13278
+ exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
13279
13279
  if (typeof cb === "undefined") {
13280
13280
  cb = options;
13281
13281
  options = void 0;
@@ -13286,7 +13286,7 @@ var require_png2 = __commonJS({
13286
13286
  called = true;
13287
13287
  cb.apply(null, args);
13288
13288
  };
13289
- const stream = fs10.createWriteStream(path21);
13289
+ const stream = fs10.createWriteStream(path22);
13290
13290
  stream.on("error", done);
13291
13291
  stream.on("close", done);
13292
13292
  exports2.renderToFileStream(stream, qrData, options);
@@ -13348,14 +13348,14 @@ var require_utf8 = __commonJS({
13348
13348
  }
13349
13349
  return output3;
13350
13350
  };
13351
- exports2.renderToFile = function renderToFile(path21, qrData, options, cb) {
13351
+ exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
13352
13352
  if (typeof cb === "undefined") {
13353
13353
  cb = options;
13354
13354
  options = void 0;
13355
13355
  }
13356
13356
  const fs10 = require("fs");
13357
13357
  const utf8 = exports2.render(qrData, options);
13358
- fs10.writeFile(path21, utf8, cb);
13358
+ fs10.writeFile(path22, utf8, cb);
13359
13359
  };
13360
13360
  }
13361
13361
  });
@@ -13476,7 +13476,7 @@ var require_svg_tag = __commonJS({
13476
13476
  return str;
13477
13477
  }
13478
13478
  function qrToPath(data, size, margin) {
13479
- let path21 = "";
13479
+ let path22 = "";
13480
13480
  let moveBy = 0;
13481
13481
  let newRow = false;
13482
13482
  let lineLength = 0;
@@ -13487,19 +13487,19 @@ var require_svg_tag = __commonJS({
13487
13487
  if (data[i]) {
13488
13488
  lineLength++;
13489
13489
  if (!(i > 0 && col > 0 && data[i - 1])) {
13490
- path21 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
13490
+ path22 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
13491
13491
  moveBy = 0;
13492
13492
  newRow = false;
13493
13493
  }
13494
13494
  if (!(col + 1 < size && data[i + 1])) {
13495
- path21 += svgCmd("h", lineLength);
13495
+ path22 += svgCmd("h", lineLength);
13496
13496
  lineLength = 0;
13497
13497
  }
13498
13498
  } else {
13499
13499
  moveBy++;
13500
13500
  }
13501
13501
  }
13502
- return path21;
13502
+ return path22;
13503
13503
  }
13504
13504
  exports2.render = function render(qrData, options, cb) {
13505
13505
  const opts = Utils.getOptions(options);
@@ -13507,10 +13507,10 @@ var require_svg_tag = __commonJS({
13507
13507
  const data = qrData.modules.data;
13508
13508
  const qrcodesize = size + opts.margin * 2;
13509
13509
  const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
13510
- const path21 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
13510
+ const path22 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
13511
13511
  const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
13512
13512
  const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
13513
- const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path21 + "</svg>\n";
13513
+ const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path22 + "</svg>\n";
13514
13514
  if (typeof cb === "function") {
13515
13515
  cb(null, svgTag);
13516
13516
  }
@@ -13524,7 +13524,7 @@ var require_svg = __commonJS({
13524
13524
  "../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg.js"(exports2) {
13525
13525
  var svgTagRenderer = require_svg_tag();
13526
13526
  exports2.render = svgTagRenderer.render;
13527
- exports2.renderToFile = function renderToFile(path21, qrData, options, cb) {
13527
+ exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
13528
13528
  if (typeof cb === "undefined") {
13529
13529
  cb = options;
13530
13530
  options = void 0;
@@ -13532,7 +13532,7 @@ var require_svg = __commonJS({
13532
13532
  const fs10 = require("fs");
13533
13533
  const svgTag = exports2.render(qrData, options);
13534
13534
  const xmlStr = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
13535
- fs10.writeFile(path21, xmlStr, cb);
13535
+ fs10.writeFile(path22, xmlStr, cb);
13536
13536
  };
13537
13537
  }
13538
13538
  });
@@ -13690,8 +13690,8 @@ var require_server = __commonJS({
13690
13690
  cb
13691
13691
  };
13692
13692
  }
13693
- function getTypeFromFilename(path21) {
13694
- return path21.slice((path21.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
13693
+ function getTypeFromFilename(path22) {
13694
+ return path22.slice((path22.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
13695
13695
  }
13696
13696
  function getRendererFromType(type) {
13697
13697
  switch (type) {
@@ -13755,17 +13755,17 @@ var require_server = __commonJS({
13755
13755
  const renderer = getRendererFromType(params.opts.type);
13756
13756
  return render(renderer.renderToBuffer, text, params);
13757
13757
  };
13758
- exports2.toFile = function toFile(path21, text, opts, cb) {
13759
- if (typeof path21 !== "string" || !(typeof text === "string" || typeof text === "object")) {
13758
+ exports2.toFile = function toFile(path22, text, opts, cb) {
13759
+ if (typeof path22 !== "string" || !(typeof text === "string" || typeof text === "object")) {
13760
13760
  throw new Error("Invalid argument");
13761
13761
  }
13762
13762
  if (arguments.length < 3 && !canPromise()) {
13763
13763
  throw new Error("Too few arguments provided");
13764
13764
  }
13765
13765
  const params = checkParams(text, opts, cb);
13766
- const type = params.opts.type || getTypeFromFilename(path21);
13766
+ const type = params.opts.type || getTypeFromFilename(path22);
13767
13767
  const renderer = getRendererFromType(type);
13768
- const renderToFile = renderer.renderToFile.bind(null, path21);
13768
+ const renderToFile = renderer.renderToFile.bind(null, path22);
13769
13769
  return render(renderToFile, text, params);
13770
13770
  };
13771
13771
  exports2.toFileStream = function toFileStream(stream, text, opts) {
@@ -16983,8 +16983,8 @@ var require_utils3 = __commonJS({
16983
16983
  }
16984
16984
  return ind;
16985
16985
  }
16986
- function removeDotSegments(path21) {
16987
- let input = path21;
16986
+ function removeDotSegments(path22) {
16987
+ let input = path22;
16988
16988
  const output3 = [];
16989
16989
  let nextSlash = -1;
16990
16990
  let len = 0;
@@ -17236,8 +17236,8 @@ var require_schemes = __commonJS({
17236
17236
  wsComponent.secure = void 0;
17237
17237
  }
17238
17238
  if (wsComponent.resourceName) {
17239
- const [path21, query] = wsComponent.resourceName.split("?");
17240
- wsComponent.path = path21 && path21 !== "/" ? path21 : void 0;
17239
+ const [path22, query] = wsComponent.resourceName.split("?");
17240
+ wsComponent.path = path22 && path22 !== "/" ? path22 : void 0;
17241
17241
  wsComponent.query = query;
17242
17242
  wsComponent.resourceName = void 0;
17243
17243
  }
@@ -20644,11 +20644,11 @@ var require_dist = __commonJS({
20644
20644
  });
20645
20645
 
20646
20646
  // src/bin.ts
20647
- var import_node_path25 = __toESM(require("node:path"), 1);
20647
+ var import_node_path30 = __toESM(require("node:path"), 1);
20648
20648
  var import_node_child_process18 = require("node:child_process");
20649
20649
  var import_node_fs17 = require("node:fs");
20650
20650
  var import_node_os15 = require("node:os");
20651
- var import_node_path26 = __toESM(require("node:path"), 1);
20651
+ var import_node_path31 = __toESM(require("node:path"), 1);
20652
20652
 
20653
20653
  // src/install-codex.ts
20654
20654
  var import_promises = __toESM(require("node:fs/promises"), 1);
@@ -21474,9 +21474,9 @@ async function verifyProviderReadiness(provider, run3, opts = {}) {
21474
21474
  var import_node_fs16 = __toESM(require("node:fs"), 1);
21475
21475
  var import_node_http = __toESM(require("node:http"), 1);
21476
21476
  var import_node_os11 = __toESM(require("node:os"), 1);
21477
- var import_node_path20 = __toESM(require("node:path"), 1);
21477
+ var import_node_path23 = __toESM(require("node:path"), 1);
21478
21478
  var import_node_child_process15 = require("node:child_process");
21479
- var import_node_crypto8 = __toESM(require("node:crypto"), 1);
21479
+ var import_node_crypto9 = __toESM(require("node:crypto"), 1);
21480
21480
 
21481
21481
  // src/turn-replay-buffer.ts
21482
21482
  var DEFAULT_MAX_EVENTS = 2e3;
@@ -22124,13 +22124,21 @@ var CodexBridgeEventMapper = class {
22124
22124
  const buffered = this.outputBuffers.get(item.id);
22125
22125
  this.outputBuffers.delete(item.id);
22126
22126
  let content = "";
22127
- if (item.type === "commandExecution")
22128
- content = buffered ?? item.stdout ?? `exit code: ${item.exitCode ?? 0}`;
22127
+ if (item.type === "commandExecution") {
22128
+ content = buffered ?? item.stdout ?? (item.exitCode !== void 0 ? `exit code: ${item.exitCode}` : "exit code: none");
22129
+ }
22129
22130
  if (item.type === "fileChange")
22130
22131
  content = buffered ?? item.content ?? "";
22131
22132
  if (item.type === "mcpToolCall")
22132
22133
  content = item.result ?? "";
22133
- events.push({ type: "tool_result", tool: { id: item.id }, content });
22134
+ const tool = { id: item.id };
22135
+ if (item.type === "commandExecution") {
22136
+ if (item.exitCode !== void 0)
22137
+ tool.exitCode = item.exitCode;
22138
+ if (item.status !== void 0)
22139
+ tool.status = item.status;
22140
+ }
22141
+ events.push({ type: "tool_result", tool, content });
22134
22142
  }
22135
22143
  return events;
22136
22144
  }
@@ -22960,10 +22968,10 @@ function mergeDefs(...defs) {
22960
22968
  function cloneDef(schema) {
22961
22969
  return mergeDefs(schema._zod.def);
22962
22970
  }
22963
- function getElementAtPath(obj, path21) {
22964
- if (!path21)
22971
+ function getElementAtPath(obj, path22) {
22972
+ if (!path22)
22965
22973
  return obj;
22966
- return path21.reduce((acc, key) => acc?.[key], obj);
22974
+ return path22.reduce((acc, key) => acc?.[key], obj);
22967
22975
  }
22968
22976
  function promiseAllObject(promisesObj) {
22969
22977
  const keys = Object.keys(promisesObj);
@@ -23372,11 +23380,11 @@ function explicitlyAborted(x, startIndex = 0) {
23372
23380
  }
23373
23381
  return false;
23374
23382
  }
23375
- function prefixIssues(path21, issues) {
23383
+ function prefixIssues(path22, issues) {
23376
23384
  return issues.map((iss) => {
23377
23385
  var _a3;
23378
23386
  (_a3 = iss).path ?? (_a3.path = []);
23379
- iss.path.unshift(path21);
23387
+ iss.path.unshift(path22);
23380
23388
  return iss;
23381
23389
  });
23382
23390
  }
@@ -23523,16 +23531,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
23523
23531
  }
23524
23532
  function formatError(error51, mapper = (issue2) => issue2.message) {
23525
23533
  const fieldErrors = { _errors: [] };
23526
- const processError = (error52, path21 = []) => {
23534
+ const processError = (error52, path22 = []) => {
23527
23535
  for (const issue2 of error52.issues) {
23528
23536
  if (issue2.code === "invalid_union" && issue2.errors.length) {
23529
- issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
23537
+ issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
23530
23538
  } else if (issue2.code === "invalid_key") {
23531
- processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
23539
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
23532
23540
  } else if (issue2.code === "invalid_element") {
23533
- processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
23541
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
23534
23542
  } else {
23535
- const fullpath = [...path21, ...issue2.path];
23543
+ const fullpath = [...path22, ...issue2.path];
23536
23544
  if (fullpath.length === 0) {
23537
23545
  fieldErrors._errors.push(mapper(issue2));
23538
23546
  } else {
@@ -23559,17 +23567,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
23559
23567
  }
23560
23568
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
23561
23569
  const result = { errors: [] };
23562
- const processError = (error52, path21 = []) => {
23570
+ const processError = (error52, path22 = []) => {
23563
23571
  var _a3, _b;
23564
23572
  for (const issue2 of error52.issues) {
23565
23573
  if (issue2.code === "invalid_union" && issue2.errors.length) {
23566
- issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
23574
+ issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
23567
23575
  } else if (issue2.code === "invalid_key") {
23568
- processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
23576
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
23569
23577
  } else if (issue2.code === "invalid_element") {
23570
- processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
23578
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
23571
23579
  } else {
23572
- const fullpath = [...path21, ...issue2.path];
23580
+ const fullpath = [...path22, ...issue2.path];
23573
23581
  if (fullpath.length === 0) {
23574
23582
  result.errors.push(mapper(issue2));
23575
23583
  continue;
@@ -23601,8 +23609,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
23601
23609
  }
23602
23610
  function toDotPath(_path) {
23603
23611
  const segs = [];
23604
- const path21 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
23605
- for (const seg of path21) {
23612
+ const path22 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
23613
+ for (const seg of path22) {
23606
23614
  if (typeof seg === "number")
23607
23615
  segs.push(`[${seg}]`);
23608
23616
  else if (typeof seg === "symbol")
@@ -36294,13 +36302,13 @@ function resolveRef(ref, ctx) {
36294
36302
  if (!ref.startsWith("#")) {
36295
36303
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
36296
36304
  }
36297
- const path21 = ref.slice(1).split("/").filter(Boolean);
36298
- if (path21.length === 0) {
36305
+ const path22 = ref.slice(1).split("/").filter(Boolean);
36306
+ if (path22.length === 0) {
36299
36307
  return ctx.rootSchema;
36300
36308
  }
36301
36309
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
36302
- if (path21[0] === defsKey) {
36303
- const key = path21[1];
36310
+ if (path22[0] === defsKey) {
36311
+ const key = path22[1];
36304
36312
  if (!key || !ctx.defs[key]) {
36305
36313
  throw new Error(`Reference not found: ${ref}`);
36306
36314
  }
@@ -36833,7 +36841,8 @@ var openApiOperationIds = {
36833
36841
  promoteSpecReadyCas: "promoteSpecReadyCas",
36834
36842
  recordSpecConsensusReview: "recordSpecConsensusReview",
36835
36843
  getSpecConsensusReview: "getSpecConsensusReview",
36836
- onboardingKickoffTransition: "onboardingKickoffTransition"
36844
+ onboardingKickoffTransition: "onboardingKickoffTransition",
36845
+ ingestTelemetry: "ingestTelemetry"
36837
36846
  };
36838
36847
 
36839
36848
  // ../../packages/schemas/dist/session.js
@@ -37074,6 +37083,116 @@ var mrrlinAsyncJobRequeueSchema = external_exports.object({
37074
37083
  staleSeconds: external_exports.number().int().min(60).max(86400).default(300)
37075
37084
  });
37076
37085
 
37086
+ // ../../packages/schemas/dist/telemetry.js
37087
+ var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing"];
37088
+ var PLUMBING_KINDS = [
37089
+ "socket_close",
37090
+ "ready",
37091
+ "scheduler_tick",
37092
+ "buffer_stats",
37093
+ "rate_limit_status"
37094
+ ];
37095
+ var TURN_LIFECYCLES = ["completed", "failed", "interrupted"];
37096
+ var TOOL_OUTCOMES = ["success", "error", "unknown"];
37097
+ var GATE_MARKERS = ["gated", "projection-only"];
37098
+ var logProjectionSchema = external_exports.object({
37099
+ kind: external_exports.enum(LOG_PROJECTION_KINDS),
37100
+ sessionId: external_exports.string(),
37101
+ seq: external_exports.number(),
37102
+ projectSlug: external_exports.string().optional(),
37103
+ turnId: external_exports.string().optional(),
37104
+ toolId: external_exports.string().optional(),
37105
+ toolName: external_exports.string().optional(),
37106
+ plumbingKind: external_exports.enum(PLUMBING_KINDS).optional(),
37107
+ // lifecycle et al: kind "turn_lifecycle" only — the aggregator's sole legal source for these,
37108
+ // since it may never read `payload` and TurnTelemetry/TurnTokenUsage are runtime objects, not
37109
+ // projections. No "started" value: nothing emits it.
37110
+ lifecycle: external_exports.enum(TURN_LIFECYCLES).optional(),
37111
+ promptBytes: external_exports.number().optional(),
37112
+ inputTokens: external_exports.number().nullable().optional(),
37113
+ cachedInputTokens: external_exports.number().nullable().optional(),
37114
+ outputTokens: external_exports.number().nullable().optional(),
37115
+ rateLimitReached: external_exports.boolean().optional(),
37116
+ argKeys: external_exports.array(external_exports.string()).optional(),
37117
+ binary: external_exports.string().optional(),
37118
+ cwdIsRealCheckout: external_exports.boolean().optional(),
37119
+ ms: external_exports.number().optional(),
37120
+ bytes: external_exports.number().optional(),
37121
+ truncated: external_exports.boolean().optional(),
37122
+ exitCode: external_exports.number().optional(),
37123
+ outcome: external_exports.enum(TOOL_OUTCOMES).optional(),
37124
+ statusHash: external_exports.string().nullable().optional()
37125
+ });
37126
+ var toolSequenceEntrySchema = external_exports.object({
37127
+ toolName: external_exports.string(),
37128
+ ms: external_exports.number(),
37129
+ outcome: external_exports.enum(TOOL_OUTCOMES)
37130
+ });
37131
+ var telemetryRowSchema = external_exports.object({
37132
+ day: external_exports.string(),
37133
+ sessionId: external_exports.string(),
37134
+ turnId: external_exports.string().nullable(),
37135
+ toolSequence: external_exports.array(toolSequenceEntrySchema),
37136
+ promptBytes: external_exports.number().nullable(),
37137
+ inputTokens: external_exports.number().nullable(),
37138
+ cachedInputTokens: external_exports.number().nullable(),
37139
+ outputTokens: external_exports.number().nullable(),
37140
+ resultRecordPresent: external_exports.boolean(),
37141
+ // one counter per plumbingKind, so no projected kind is silently uncounted
37142
+ plumbing: external_exports.object({
37143
+ socketCloses: external_exports.number(),
37144
+ readyNotifs: external_exports.number(),
37145
+ schedulerTicks: external_exports.number(),
37146
+ bufferStats: external_exports.number(),
37147
+ rateLimitStatusRecords: external_exports.number(),
37148
+ rateLimitReached: external_exports.boolean()
37149
+ }),
37150
+ projectionFailures: external_exports.number(),
37151
+ gateMarker: external_exports.enum(GATE_MARKERS)
37152
+ });
37153
+ var telemetryBatchSchema = external_exports.object({
37154
+ day: external_exports.string(),
37155
+ bridgeVersion: external_exports.string(),
37156
+ knownCrashCount: external_exports.number(),
37157
+ // pairs still lacking .processed-* after this run completes; a project that never uploads at
37158
+ // all cannot report its own gap this way — silence is not coverage.
37159
+ unprocessedPartitions: external_exports.array(external_exports.object({ projectSlug: external_exports.string(), day: external_exports.string() })),
37160
+ rows: external_exports.array(telemetryRowSchema)
37161
+ });
37162
+ var evidenceStepSchema = external_exports.object({
37163
+ toolName: external_exports.string(),
37164
+ ms: external_exports.number(),
37165
+ outcome: external_exports.enum(TOOL_OUTCOMES),
37166
+ exitCode: external_exports.number().optional(),
37167
+ excerpt: external_exports.string().optional()
37168
+ });
37169
+ var evidenceArtifactSchema = external_exports.object({
37170
+ reportId: external_exports.string(),
37171
+ sessionId: external_exports.string(),
37172
+ turnIds: external_exports.array(external_exports.string()),
37173
+ daysRead: external_exports.array(external_exports.string()),
37174
+ windowPruned: external_exports.boolean(),
37175
+ steps: external_exports.array(evidenceStepSchema),
37176
+ gateMarker: external_exports.enum(GATE_MARKERS)
37177
+ });
37178
+ var extractManifestSchema = external_exports.object({
37179
+ reportId: external_exports.string().optional(),
37180
+ sessionId: external_exports.string().optional(),
37181
+ since: external_exports.string().optional(),
37182
+ until: external_exports.string().optional(),
37183
+ daysRead: external_exports.array(external_exports.string()),
37184
+ recordCount: external_exports.number(),
37185
+ bytesBeforeTruncation: external_exports.number(),
37186
+ truncated: external_exports.boolean(),
37187
+ secretShapesRedacted: external_exports.number(),
37188
+ // null when --out was used and nothing was uploaded
37189
+ deliveredArtifactId: external_exports.string().nullable()
37190
+ });
37191
+ var ingestResultSchema = external_exports.object({
37192
+ accepted: external_exports.number(),
37193
+ unknownCounts: external_exports.record(external_exports.string(), external_exports.object({ count: external_exports.number(), valueLength: external_exports.number() }))
37194
+ });
37195
+
37077
37196
  // ../../packages/schemas/dist/memory-budget.js
37078
37197
  function evictionKey(item, idx) {
37079
37198
  const memClass = item.memoryClass === "historical" ? 0 : 1;
@@ -39390,11 +39509,21 @@ var ClaudeBridgeEventMapper = class {
39390
39509
  return [{ type: "rate_limits", snapshot }];
39391
39510
  }
39392
39511
  handleResult(line) {
39512
+ const tokenUsageEvents = line.usage !== void 0 ? [
39513
+ {
39514
+ type: "token_usage",
39515
+ usage: {
39516
+ inputTokens: line.usage.input_tokens ?? null,
39517
+ cachedInputTokens: line.usage.cache_read_input_tokens ?? null,
39518
+ outputTokens: line.usage.output_tokens ?? null
39519
+ }
39520
+ }
39521
+ ] : [];
39393
39522
  if (line.is_error === true) {
39394
39523
  const content = typeof line.result === "string" && line.result ? line.result : "Unknown Claude error";
39395
- return [{ type: "error", content }, { type: "turn_completed" }];
39524
+ return [...tokenUsageEvents, { type: "error", content }, { type: "turn_completed" }];
39396
39525
  }
39397
- return [{ type: "result", subtype: "success" }, { type: "turn_completed" }];
39526
+ return [...tokenUsageEvents, { type: "result", subtype: "success" }, { type: "turn_completed" }];
39398
39527
  }
39399
39528
  contentBlocks(line) {
39400
39529
  const content = line.message?.content;
@@ -39997,18 +40126,18 @@ function createMrrlinClient(config2) {
39997
40126
  const customFetch = config2.fetch ?? globalThis.fetch;
39998
40127
  const baseUrl = config2.baseUrl.replace(/\/$/, "");
39999
40128
  const token = config2.token;
40000
- async function request(path21, init) {
40129
+ async function request(path22, init) {
40001
40130
  const method = init?.method ?? "GET";
40002
40131
  const headers = new Headers(init?.headers ?? {});
40003
40132
  if (token && !headers.has("authorization")) {
40004
40133
  headers.set("authorization", `Bearer ${token}`);
40005
40134
  }
40006
- const response = await customFetch(`${baseUrl}${path21}`, { ...init, headers });
40135
+ const response = await customFetch(`${baseUrl}${path22}`, { ...init, headers });
40007
40136
  if (!response.ok) {
40008
40137
  const body = await response.text();
40009
40138
  let code = `HTTP_${response.status}`;
40010
40139
  let violations = null;
40011
- let message = `Mrrlin API ${method} ${path21} failed: ${response.status}`;
40140
+ let message = `Mrrlin API ${method} ${path22} failed: ${response.status}`;
40012
40141
  try {
40013
40142
  const parsed = JSON.parse(body);
40014
40143
  const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
@@ -40028,7 +40157,7 @@ function createMrrlinClient(config2) {
40028
40157
  throw new MrrlinApiError({
40029
40158
  code,
40030
40159
  method,
40031
- path: path21,
40160
+ path: path22,
40032
40161
  responseBody: body,
40033
40162
  status: response.status,
40034
40163
  violations,
@@ -40288,16 +40417,16 @@ function createMrrlinClient(config2) {
40288
40417
  // rejected against the first, MrrlinTask[]-only overload) -- the `any` here is contained to
40289
40418
  // this one implementation signature; MrrlinClient's declared overloads keep callers precise.
40290
40419
  async listTasks(projectSlug, filters = {}, options) {
40291
- const path21 = buildTaskListPath(projectSlug, filters, options?.view);
40292
- const body = await request(path21);
40420
+ const path22 = buildTaskListPath(projectSlug, filters, options?.view);
40421
+ const body = await request(path22);
40293
40422
  if (options?.view === "summary") {
40294
40423
  return taskSummaryListResponseSchema.parse(body).data;
40295
40424
  }
40296
40425
  return taskListResponseSchema.parse(body).data;
40297
40426
  },
40298
40427
  async listTaskSummaries(projectSlug, filters = {}) {
40299
- const path21 = buildTaskListPath(projectSlug, filters, "summary");
40300
- const body = await request(path21);
40428
+ const path22 = buildTaskListPath(projectSlug, filters, "summary");
40429
+ const body = await request(path22);
40301
40430
  return taskSummaryListResponseSchema.parse(body).data;
40302
40431
  },
40303
40432
  async listTaxonomy(projectSlug) {
@@ -40305,22 +40434,22 @@ function createMrrlinClient(config2) {
40305
40434
  return taxonomyListResponseSchema.parse(body).data;
40306
40435
  },
40307
40436
  async listWikiPages(projectSlug, filters = {}) {
40308
- const path21 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
40437
+ const path22 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
40309
40438
  folder: filters.folder,
40310
40439
  q: filters.q,
40311
40440
  taskId: filters.taskId
40312
40441
  });
40313
- const body = await request(path21);
40442
+ const body = await request(path22);
40314
40443
  return wikiPageListResponseSchema.parse(body).data;
40315
40444
  },
40316
40445
  async searchWikiPages(projectSlug, query) {
40317
- const path21 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
40446
+ const path22 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
40318
40447
  folder: query.folder,
40319
40448
  limit: query.limit === void 0 ? void 0 : String(query.limit),
40320
40449
  pathPrefix: query.pathPrefix,
40321
40450
  q: query.q
40322
40451
  });
40323
- const body = await request(path21);
40452
+ const body = await request(path22);
40324
40453
  return wikiPageSearchResponseSchema.parse(body).data;
40325
40454
  },
40326
40455
  async updatePlan(projectSlug, planId, patch) {
@@ -40710,6 +40839,14 @@ function createMrrlinClient(config2) {
40710
40839
  });
40711
40840
  return executionArtifactResponseSchema.parse(body).data;
40712
40841
  },
40842
+ async postTelemetry(projectSlug, batch) {
40843
+ const body = await request(`${projectPath(projectSlug)}/telemetry`, {
40844
+ body: JSON.stringify(batch),
40845
+ headers: { "content-type": "application/json" },
40846
+ method: "POST"
40847
+ });
40848
+ return ingestResultSchema.parse(body);
40849
+ },
40713
40850
  async createArtifactFile(projectSlug, input) {
40714
40851
  const body = await request(`${projectPath(projectSlug)}/artifact-files`, {
40715
40852
  body: JSON.stringify(input),
@@ -41179,7 +41316,7 @@ function sha256(buf) {
41179
41316
  function startSelfUpdate(deps) {
41180
41317
  const log = deps.log ?? (() => {
41181
41318
  });
41182
- const readFile3 = deps.readFileSyncImpl ?? ((p) => (0, import_node_fs2.readFileSync)(p));
41319
+ const readFile9 = deps.readFileSyncImpl ?? ((p) => (0, import_node_fs2.readFileSync)(p));
41183
41320
  const setIntervalFn = deps.setIntervalImpl ?? setInterval;
41184
41321
  const clearIntervalFn = deps.clearIntervalImpl ?? clearInterval;
41185
41322
  const intervalMs = deps.intervalMs ?? readIntervalEnv("MRRLIN_DIRECTOR_BRIDGE_SELF_UPDATE_INTERVAL_MS", DEFAULT_INTERVAL_MS);
@@ -41235,7 +41372,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
41235
41372
  }
41236
41373
  let startupBinSha = null;
41237
41374
  try {
41238
- startupBinSha = sha256(readFile3(deps.binPath));
41375
+ startupBinSha = sha256(readFile9(deps.binPath));
41239
41376
  } catch (e) {
41240
41377
  log("warn", "bridge.self_update.startup_hash_read_failed", {
41241
41378
  err: String(e?.message ?? e)
@@ -41314,14 +41451,14 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
41314
41451
  try {
41315
41452
  if (!startupBinSha) {
41316
41453
  try {
41317
- startupBinSha = sha256(readFile3(deps.binPath));
41454
+ startupBinSha = sha256(readFile9(deps.binPath));
41318
41455
  } catch {
41319
41456
  return;
41320
41457
  }
41321
41458
  }
41322
41459
  let currentBinSha;
41323
41460
  try {
41324
- currentBinSha = sha256(readFile3(deps.binPath));
41461
+ currentBinSha = sha256(readFile9(deps.binPath));
41325
41462
  } catch {
41326
41463
  return;
41327
41464
  }
@@ -41400,7 +41537,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
41400
41537
  }
41401
41538
 
41402
41539
  // src/_generated/version.ts
41403
- var PKG_VERSION = "0.4.6";
41540
+ var PKG_VERSION = "0.4.7";
41404
41541
 
41405
41542
  // src/api-base-url-migrate.ts
41406
41543
  var import_node_fs3 = __toESM(require("node:fs"), 1);
@@ -41711,6 +41848,7 @@ var BridgeHealthTracker = class {
41711
41848
  now;
41712
41849
  processExit;
41713
41850
  logger;
41851
+ hasLiveTurn;
41714
41852
  // Initialized to construction time, NOT 0/undefined: a freshly (re)started process — including
41715
41853
  // one that just restarted BECAUSE this breaker tripped — must not treat its own startup instant
41716
41854
  // as "ages ago that nothing succeeded." Without this, the very first tracked failure after any
@@ -41718,14 +41856,21 @@ var BridgeHealthTracker = class {
41718
41856
  // seconds and inverting this mechanism into the outage it exists to prevent.
41719
41857
  lastSuccessAt;
41720
41858
  disabled = false;
41721
- knownCrashCount = null;
41859
+ // Renamed from knownCrashCount to _knownCrashCount (task 9.4): a class can't have both a
41860
+ // private field and a public method of the same name, and 9.4 asks for the public getter to be
41861
+ // named knownCrashCount().
41862
+ _knownCrashCount = null;
41722
41863
  lastErrorByOperation = /* @__PURE__ */ new Map();
41864
+ // Rate-limits the "deferring crash-exit" log to once per 60s so a tight sweep-retry loop
41865
+ // while a turn stays live doesn't spam it -- the defer itself still applies every call.
41866
+ lastLiveTurnDeferLogAt = null;
41723
41867
  constructor(opts) {
41724
41868
  this.stateDir = opts.stateDir;
41725
41869
  this.stuckMs = opts.stuckMs ?? readStuckMsFromEnv() ?? DEFAULT_STUCK_MS;
41726
41870
  this.now = opts.now ?? Date.now;
41727
41871
  this.processExit = opts.processExit ?? ((code) => process.exit(code));
41728
41872
  this.logger = opts.logger ?? defaultLogger;
41873
+ this.hasLiveTurn = opts.hasLiveTurn ?? (() => false);
41729
41874
  this.lastSuccessAt = this.now();
41730
41875
  }
41731
41876
  /** Wraps a tracked operation: applies the hard timeout, records the outcome, and re-throws or
@@ -41742,13 +41887,18 @@ var BridgeHealthTracker = class {
41742
41887
  }
41743
41888
  async recordSuccess() {
41744
41889
  this.lastSuccessAt = this.now();
41745
- if (this.knownCrashCount === null) {
41890
+ if (this._knownCrashCount === null) {
41746
41891
  await this.reconcileCrashCountOnFirstSuccess();
41747
41892
  }
41748
41893
  }
41749
41894
  recordFailure(id, error51) {
41750
41895
  this.lastErrorByOperation.set(id, error51 instanceof Error ? error51.message : String(error51));
41751
41896
  }
41897
+ /** `null` until the first success reconciles it (see `recordSuccess`) — read by
41898
+ * `daily-uploader.ts`, which stamps the captured value on every `TelemetryBatch` in a run. */
41899
+ knownCrashCount() {
41900
+ return this._knownCrashCount;
41901
+ }
41752
41902
  /** True when no tracked operation has succeeded within `stuckMs`. */
41753
41903
  isStuck() {
41754
41904
  return this.now() - this.lastSuccessAt >= this.stuckMs;
@@ -41758,6 +41908,23 @@ var BridgeHealthTracker = class {
41758
41908
  async maybeCrash() {
41759
41909
  if (this.disabled) return;
41760
41910
  if (!this.isStuck()) return;
41911
+ let hasLiveTurn = false;
41912
+ try {
41913
+ hasLiveTurn = this.hasLiveTurn();
41914
+ } catch (error51) {
41915
+ const message = error51 instanceof Error ? error51.message : String(error51);
41916
+ this.logger.critical(`bridge health: hasLiveTurn() threw, treating as no live turn: ${message}`);
41917
+ }
41918
+ if (hasLiveTurn) {
41919
+ const now = this.now();
41920
+ if (this.lastLiveTurnDeferLogAt === null || now - this.lastLiveTurnDeferLogAt >= 6e4) {
41921
+ this.logger.critical(
41922
+ "bridge health: stuck but a Director turn is still active/resumable \u2014 deferring crash-exit"
41923
+ );
41924
+ this.lastLiveTurnDeferLogAt = now;
41925
+ }
41926
+ return;
41927
+ }
41761
41928
  const decision = await this.decideExitOrDisable();
41762
41929
  if (decision.exit) {
41763
41930
  this.logger.critical(
@@ -41784,10 +41951,10 @@ var BridgeHealthTracker = class {
41784
41951
  }
41785
41952
  async reconcileCrashCountOnFirstSuccess() {
41786
41953
  const sentinel = await readCrashSentinel(this.stateDir, this.now);
41787
- this.knownCrashCount = sentinel.crashCount;
41954
+ this._knownCrashCount = sentinel.crashCount;
41788
41955
  if (sentinel.crashCount > 0) {
41789
41956
  await writeCrashSentinel(this.stateDir, { ...sentinel, crashCount: 0 });
41790
- this.knownCrashCount = 0;
41957
+ this._knownCrashCount = 0;
41791
41958
  }
41792
41959
  }
41793
41960
  formatLastErrors() {
@@ -41930,386 +42097,272 @@ function startSchedulerTickLoop(deps) {
41930
42097
  };
41931
42098
  }
41932
42099
 
41933
- // src/agent-pool-snapshot.ts
41934
- function normalizeLastUsedAt(value) {
41935
- if (value === void 0 || value === null) return null;
41936
- if (typeof value === "number") {
41937
- if (!Number.isFinite(value)) return null;
41938
- const ms = value < 1e12 ? value * 1e3 : value;
41939
- const date5 = new Date(ms);
41940
- return Number.isNaN(date5.getTime()) ? null : date5.toISOString();
41941
- }
41942
- return value;
41943
- }
41944
- function buildAgentPoolSnapshot(statusRows, stats, opts) {
41945
- if (!opts.available) {
41946
- return {
41947
- collected_at: opts.collectedAt,
41948
- status: "unavailable",
41949
- agents: [],
41950
- totals: { calls: 0, tokens_in: 0, tokens_out: 0 },
41951
- estimated_savings_usd: 0
41952
- };
41953
- }
41954
- const costPer1M = opts.paidCostPer1MTokens ?? 3;
41955
- const agents = statusRows.map((row) => {
41956
- const agentStats = stats.by_agent[row.id];
41957
- const count2 = agentStats?.count ?? 0;
41958
- const tokensIn = agentStats?.tokens_in ?? 0;
41959
- const tokensOut = agentStats?.tokens_out ?? 0;
41960
- let successRate = 0;
41961
- if (count2 > 0) {
41962
- const successOutcomes = agentStats?.outcomes.success ?? 0;
41963
- successRate = Number((successOutcomes / count2 * 100).toFixed(2)) / 100;
42100
+ // src/retention/pruner.ts
42101
+ var import_promises4 = require("node:fs/promises");
42102
+ var import_node_path9 = __toESM(require("node:path"), 1);
42103
+ async function prune(stateDir, bounds) {
42104
+ const logsDir = import_node_path9.default.join(stateDir, "logs");
42105
+ let entries;
42106
+ try {
42107
+ entries = await (0, import_promises4.readdir)(logsDir);
42108
+ } catch (err) {
42109
+ if (err?.code === "ENOENT") {
42110
+ await emitPruneLog(stateDir, [], {}, 0, null);
42111
+ return { daysRemoved: [], reasonByDay: {}, bytesRemoved: 0, oldestDayRemaining: null };
41964
42112
  }
41965
- return {
41966
- id: row.id,
41967
- provider: row.provider,
41968
- tier: row.tier,
41969
- tags: row.tags,
41970
- state: row.state ?? "unknown",
41971
- calls: count2,
41972
- tokens_in: tokensIn,
41973
- tokens_out: tokensOut,
41974
- success_rate: successRate,
41975
- last_used_at: normalizeLastUsedAt(row.last_used_at)
41976
- };
41977
- });
41978
- let totalCalls = 0;
41979
- let totalTokensIn = 0;
41980
- let totalTokensOut = 0;
41981
- for (const entry of Object.values(stats.by_agent)) {
41982
- totalCalls += entry.count;
41983
- totalTokensIn += entry.tokens_in;
41984
- totalTokensOut += entry.tokens_out;
42113
+ throw err;
41985
42114
  }
41986
- let savedTokens = 0;
41987
- for (const row of statusRows) {
41988
- if (row.tags.includes("free")) {
41989
- const agentStats = stats.by_agent[row.id];
41990
- if (agentStats) {
41991
- savedTokens += agentStats.tokens_in + agentStats.tokens_out;
42115
+ const bridgeRe = /^bridge-(\d{4}-\d{2}-\d{2})\.jsonl$/;
42116
+ const files = [];
42117
+ for (const entry of entries) {
42118
+ const m = bridgeRe.exec(entry);
42119
+ if (!m?.[1]) continue;
42120
+ const fullPath = import_node_path9.default.join(logsDir, entry);
42121
+ const s = await (0, import_promises4.stat)(fullPath);
42122
+ files.push({ day: m[1], size: s.size, fullPath });
42123
+ }
42124
+ files.sort((a, b) => a.day < b.day ? -1 : a.day > b.day ? 1 : 0);
42125
+ const daysRemoved = [];
42126
+ const reasonByDay = {};
42127
+ let bytesRemoved = 0;
42128
+ async function isDaySafeToDelete(day) {
42129
+ const telemetryDir = import_node_path9.default.join(stateDir, "telemetry");
42130
+ let telemetryEntries;
42131
+ try {
42132
+ telemetryEntries = await (0, import_promises4.readdir)(telemetryDir);
42133
+ } catch (err) {
42134
+ if (err?.code === "ENOENT") return true;
42135
+ throw err;
42136
+ }
42137
+ const rowRe = new RegExp(`^rows-(.+)-${day}\\.jsonl$`);
42138
+ const projectSlugs = [];
42139
+ for (const entry of telemetryEntries) {
42140
+ const m = rowRe.exec(entry);
42141
+ if (m?.[1]) projectSlugs.push(m[1]);
42142
+ }
42143
+ if (projectSlugs.length === 0) return true;
42144
+ for (const slug of projectSlugs) {
42145
+ const markerPath = import_node_path9.default.join(telemetryDir, `.processed-${slug}-${day}`);
42146
+ try {
42147
+ await (0, import_promises4.stat)(markerPath);
42148
+ } catch (err) {
42149
+ if (err?.code === "ENOENT") return false;
42150
+ throw err;
41992
42151
  }
41993
42152
  }
42153
+ return true;
41994
42154
  }
41995
- const estimatedSavings = Number((savedTokens / 1e6 * costPer1M).toFixed(2));
41996
- return {
41997
- collected_at: opts.collectedAt,
41998
- status: "ok",
41999
- agents,
42000
- totals: {
42001
- calls: totalCalls,
42002
- tokens_in: totalTokensIn,
42003
- tokens_out: totalTokensOut
42004
- },
42005
- estimated_savings_usd: estimatedSavings
42006
- };
42007
- }
42008
-
42009
- // src/agent-pool-collector.ts
42010
- async function collectAgentPoolSnapshot(deps) {
42011
- let statusRows;
42012
- let stats;
42013
- try {
42014
- const statusResult = await deps.runCli(["status", "--json"]);
42015
- if (statusResult.code !== 0) throw new Error("non-zero exit on status");
42016
- let statusParsed;
42017
- try {
42018
- statusParsed = JSON.parse(statusResult.stdout);
42019
- } catch {
42020
- throw new Error("invalid status json");
42155
+ const budgetBytes = bounds.budgetMb * 1024 * 1024;
42156
+ let totalSize2 = files.reduce((sum, f) => sum + f.size, 0);
42157
+ let i = 0;
42158
+ while (totalSize2 > budgetBytes && i < files.length) {
42159
+ const candidate = files[i];
42160
+ if (!candidate) break;
42161
+ if (!await isDaySafeToDelete(candidate.day)) {
42162
+ i += 1;
42163
+ continue;
42021
42164
  }
42022
- if (!Array.isArray(statusParsed)) throw new Error("status not array");
42023
- statusRows = statusParsed;
42024
- const statsResult = await deps.runCli(["stats", "--json"]);
42025
- if (statsResult.code !== 0) throw new Error("non-zero exit on stats");
42165
+ await (0, import_promises4.unlink)(candidate.fullPath);
42166
+ daysRemoved.push(candidate.day);
42167
+ reasonByDay[candidate.day] = "size";
42168
+ bytesRemoved += candidate.size;
42169
+ totalSize2 -= candidate.size;
42170
+ files.splice(i, 1);
42171
+ }
42172
+ const now = Date.now();
42173
+ const msPerDay = 864e5;
42174
+ const stillRemaining = [];
42175
+ for (const info of files) {
42176
+ const fileDate = /* @__PURE__ */ new Date(`${info.day}T00:00:00Z`);
42177
+ const ageInDays = (now - fileDate.getTime()) / msPerDay;
42178
+ if (ageInDays > bounds.ageDays && await isDaySafeToDelete(info.day)) {
42179
+ await (0, import_promises4.unlink)(info.fullPath);
42180
+ daysRemoved.push(info.day);
42181
+ reasonByDay[info.day] = "age";
42182
+ bytesRemoved += info.size;
42183
+ continue;
42184
+ }
42185
+ stillRemaining.push(info);
42186
+ }
42187
+ const oldestDayRemaining = stillRemaining.length > 0 ? stillRemaining[0]?.day ?? null : null;
42188
+ await emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining);
42189
+ if (daysRemoved.length > 0) {
42190
+ const sessionsPath = import_node_path9.default.join(logsDir, ".sessions.json");
42191
+ let sessionsObj = {};
42192
+ let fileExists = true;
42026
42193
  try {
42027
- stats = JSON.parse(statsResult.stdout);
42028
- } catch {
42029
- throw new Error("invalid stats json");
42194
+ sessionsObj = JSON.parse(await (0, import_promises4.readFile)(sessionsPath, "utf8"));
42195
+ } catch (err) {
42196
+ if (err?.code === "ENOENT") {
42197
+ fileExists = false;
42198
+ } else {
42199
+ sessionsObj = {};
42200
+ }
42201
+ }
42202
+ if (fileExists) {
42203
+ for (const day of daysRemoved) delete sessionsObj[day];
42204
+ const tmpPath = `${sessionsPath}.tmp`;
42205
+ await (0, import_promises4.writeFile)(tmpPath, JSON.stringify(sessionsObj));
42206
+ await (0, import_promises4.rename)(tmpPath, sessionsPath);
42030
42207
  }
42031
- } catch {
42032
- return buildAgentPoolSnapshot(
42033
- [],
42034
- {},
42035
- { collectedAt: deps.now(), available: false }
42036
- );
42037
42208
  }
42038
- return buildAgentPoolSnapshot(
42039
- statusRows,
42040
- stats,
42041
- { collectedAt: deps.now(), paidCostPer1MTokens: deps.paidCostPer1MTokens, available: true }
42042
- );
42209
+ return { daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining };
42210
+ }
42211
+ async function emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining) {
42212
+ const logsDir = import_node_path9.default.join(stateDir, "logs");
42213
+ const logPath = import_node_path9.default.join(logsDir, ".pruned.jsonl");
42214
+ await (0, import_promises4.mkdir)(logsDir, { recursive: true });
42215
+ const record2 = { ts: Date.now(), dir: "logs", daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining };
42216
+ await (0, import_promises4.appendFile)(logPath, `${JSON.stringify(record2)}
42217
+ `);
42043
42218
  }
42044
42219
 
42045
- // src/external-agents-spawn.ts
42046
- var import_node_child_process8 = require("node:child_process");
42047
-
42048
- // src/external-agents-bin.ts
42049
- function resolveExternalAgentsCliInvocation(override) {
42050
- if (override && override.trim()) return { command: override, prefixArgs: [] };
42220
+ // src/telemetry/turn-aggregator.ts
42221
+ var import_promises5 = require("node:fs/promises");
42222
+ var import_node_path10 = require("node:path");
42223
+ var BRIDGE_FILE_RE = /^bridge-(\d{4}-\d{2}-\d{2})\.jsonl$/;
42224
+ var PLUMBING_COUNTER_KEY = {
42225
+ socket_close: "socketCloses",
42226
+ ready: "readyNotifs",
42227
+ scheduler_tick: "schedulerTicks",
42228
+ buffer_stats: "bufferStats",
42229
+ rate_limit_status: "rateLimitStatusRecords"
42230
+ };
42231
+ async function foldClosedDays(stateDir, today) {
42232
+ const logsDir = (0, import_node_path10.join)(stateDir, "logs");
42233
+ let entries;
42051
42234
  try {
42052
- return {
42053
- command: "node",
42054
- prefixArgs: [resolvePackageBin("@mrrlin-dev/external-agents", "external-agents")]
42055
- };
42235
+ entries = await (0, import_promises5.readdir)(logsDir);
42056
42236
  } catch {
42057
- return { command: "external-agents", prefixArgs: [] };
42058
- }
42059
- }
42060
-
42061
- // src/external-agents-spawn.ts
42062
- function runExternalAgentsCli(args, opts) {
42063
- let command;
42064
- let prefixArgs;
42065
- let source;
42066
- let triedPath;
42067
- if (opts.envCliPath && opts.envCliPath.trim()) {
42068
- command = "node";
42069
- prefixArgs = [opts.envCliPath];
42070
- source = "env";
42071
- triedPath = opts.envCliPath;
42072
- } else {
42073
- ({ command, prefixArgs } = resolveExternalAgentsCliInvocation());
42074
- source = command === "node" && prefixArgs.length === 1 ? "bundled" : "path";
42075
- triedPath = source === "bundled" ? prefixArgs[0] ?? "" : "external-agents (PATH)";
42237
+ return;
42076
42238
  }
42077
- const useStdin = opts.stdinValue !== void 0;
42078
- const stdioConfig = useStdin ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
42079
- return new Promise((resolve) => {
42080
- let stdout = "";
42081
- let stderr = "";
42082
- let settled = false;
42083
- let timedOut = false;
42084
- const done = (code) => {
42085
- if (!settled) {
42086
- settled = true;
42087
- resolve({ stdout, stderr, code, timedOut, source, triedPath });
42088
- }
42089
- };
42090
- let spawned;
42091
- try {
42092
- spawned = (0, import_node_child_process8.spawn)(command, [...prefixArgs, ...args], { stdio: stdioConfig });
42093
- } catch {
42094
- done(1);
42095
- return;
42096
- }
42097
- const child = spawned;
42098
- let sigkillTimer = null;
42099
- let budgetTimer = null;
42100
- if (useStdin && child.stdin) {
42101
- child.stdin.on("error", () => {
42102
- });
42103
- child.stdin.write(opts.stdinValue);
42104
- child.stdin.end();
42105
- }
42106
- child.stdout?.on("data", (d) => {
42107
- stdout += d.toString();
42108
- if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
42109
- });
42110
- child.stderr?.on("data", (d) => {
42111
- stderr += d.toString();
42112
- if (stderr.length > 2e5) stderr = stderr.slice(-2e5);
42113
- });
42114
- budgetTimer = setTimeout(() => {
42115
- budgetTimer = null;
42116
- timedOut = true;
42239
+ for (const entry of entries) {
42240
+ const m = BRIDGE_FILE_RE.exec(entry);
42241
+ if (!m) continue;
42242
+ const day = m[1];
42243
+ if (day === today) continue;
42244
+ const raw = await (0, import_promises5.readFile)((0, import_node_path10.join)(logsDir, entry), "utf8");
42245
+ const groups = /* @__PURE__ */ new Map();
42246
+ for (const line of raw.split("\n")) {
42247
+ const trimmed = line.trim();
42248
+ if (!trimmed) continue;
42249
+ let rec;
42117
42250
  try {
42118
- child.kill("SIGTERM");
42251
+ rec = JSON.parse(trimmed);
42119
42252
  } catch {
42253
+ continue;
42120
42254
  }
42121
- sigkillTimer = setTimeout(() => {
42122
- sigkillTimer = null;
42123
- try {
42124
- child.kill("SIGKILL");
42125
- } catch {
42255
+ const sessionId = typeof rec.sessionId === "string" ? rec.sessionId : null;
42256
+ const turnId = rec.projection?.turnId ?? null;
42257
+ const key = `${sessionId === null ? 0 : 1}:${sessionId}:${turnId === null ? 0 : 1}:${turnId}`;
42258
+ let group = groups.get(key);
42259
+ if (!group) {
42260
+ group = { sessionId, turnId, records: [], projectionFailures: 0 };
42261
+ groups.set(key, group);
42262
+ }
42263
+ group.records.push(rec);
42264
+ if (rec.projectionFailed === true) group.projectionFailures += 1;
42265
+ }
42266
+ const rowsByProject = /* @__PURE__ */ new Map();
42267
+ for (const group of groups.values()) {
42268
+ if (group.sessionId === null) continue;
42269
+ const records = [...group.records].sort((a, b) => {
42270
+ const aSeq = a.projection?.seq;
42271
+ const bSeq = b.projection?.seq;
42272
+ if (aSeq === void 0 && bSeq === void 0) return 0;
42273
+ if (aSeq === void 0) return 1;
42274
+ if (bSeq === void 0) return -1;
42275
+ return aSeq - bSeq;
42276
+ });
42277
+ let projectSlug;
42278
+ for (const rec of records) {
42279
+ const slug = rec.projection?.projectSlug;
42280
+ if (slug) {
42281
+ projectSlug = slug;
42282
+ break;
42126
42283
  }
42127
- }, 2e3);
42128
- sigkillTimer.unref?.();
42129
- done(1);
42130
- }, opts.budgetMs);
42131
- budgetTimer.unref?.();
42132
- child.on("error", () => {
42133
- if (budgetTimer) {
42134
- clearTimeout(budgetTimer);
42135
- budgetTimer = null;
42136
- }
42137
- if (sigkillTimer) {
42138
- clearTimeout(sigkillTimer);
42139
- sigkillTimer = null;
42140
- }
42141
- done(1);
42142
- });
42143
- child.on("close", (code) => {
42144
- if (budgetTimer) {
42145
- clearTimeout(budgetTimer);
42146
- budgetTimer = null;
42147
42284
  }
42148
- if (sigkillTimer) {
42149
- clearTimeout(sigkillTimer);
42150
- sigkillTimer = null;
42285
+ projectSlug ??= "_unattributed";
42286
+ const toolResults = records.filter((r) => r.projection?.kind === "tool_result");
42287
+ const toolSequence = [];
42288
+ for (const rec of records) {
42289
+ if (rec.projection?.kind !== "tool_use") continue;
42290
+ const toolId = rec.projection.toolId;
42291
+ const paired = toolResults.find((r) => r.projection?.toolId === toolId);
42292
+ toolSequence.push({
42293
+ toolName: rec.projection.toolName ?? "",
42294
+ ms: rec.projection.ms ?? 0,
42295
+ outcome: paired?.projection?.outcome ?? "unknown"
42296
+ });
42151
42297
  }
42152
- done(code ?? 1);
42153
- });
42154
- });
42155
- }
42156
-
42157
- // src/agent-pool-loop.ts
42158
- var DEFAULT_INTERVAL_MS2 = 6e4;
42159
- function agentPoolLoopDisabled(env = process.env) {
42160
- return env["MRRLIN_BRIDGE_AGENT_POOL_DISABLE"] === "1";
42161
- }
42162
- function defaultRunCli(args) {
42163
- return runExternalAgentsCli(args, {
42164
- budgetMs: 5e3,
42165
- envCliPath: process.env["EXTERNAL_AGENTS_CLI"]
42166
- }).then(({ stdout, code }) => ({ stdout, code }));
42167
- }
42168
- async function runAgentPoolCycle(deps) {
42169
- try {
42170
- const snapshot = await collectAgentPoolSnapshot({
42171
- runCli: deps.runCli ?? defaultRunCli,
42172
- now: deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
42173
- });
42174
- await deps.push(snapshot);
42175
- } catch (err) {
42176
- deps.onError?.(err);
42177
- }
42178
- }
42179
- function startAgentPoolLoop(deps) {
42180
- const env = deps.env ?? process.env;
42181
- const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_AGENT_POOL_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS2);
42182
- let stopped = false;
42183
- let timer = null;
42184
- const schedule = () => {
42185
- if (stopped) return;
42186
- timer = setTimeout(() => {
42187
- void runAgentPoolCycle(deps).then(() => schedule());
42188
- }, intervalMs);
42189
- timer.unref?.();
42190
- };
42191
- timer = setTimeout(() => {
42192
- void runAgentPoolCycle(deps).then(() => schedule());
42193
- }, 1e3);
42194
- timer.unref?.();
42195
- return {
42196
- stop() {
42197
- stopped = true;
42198
- if (timer) clearTimeout(timer);
42298
+ const lifecycleRecs = records.filter((r) => r.projection?.kind === "turn_lifecycle");
42299
+ const resultRecordPresent = lifecycleRecs.length > 0;
42300
+ let promptBytes = null;
42301
+ let inputTokens = null;
42302
+ let cachedInputTokens = null;
42303
+ let outputTokens = null;
42304
+ const firstLifecycle = lifecycleRecs[0]?.projection;
42305
+ if (firstLifecycle?.lifecycle === "completed") {
42306
+ promptBytes = firstLifecycle.promptBytes ?? null;
42307
+ inputTokens = firstLifecycle.inputTokens ?? null;
42308
+ cachedInputTokens = firstLifecycle.cachedInputTokens ?? null;
42309
+ outputTokens = firstLifecycle.outputTokens ?? null;
42310
+ }
42311
+ const plumbing = {
42312
+ socketCloses: 0,
42313
+ readyNotifs: 0,
42314
+ schedulerTicks: 0,
42315
+ bufferStats: 0,
42316
+ rateLimitStatusRecords: 0,
42317
+ rateLimitReached: false
42318
+ };
42319
+ for (const rec of records) {
42320
+ const proj = rec.projection;
42321
+ if (!proj || proj.kind !== "plumbing" || !proj.plumbingKind) continue;
42322
+ const counterKey = PLUMBING_COUNTER_KEY[proj.plumbingKind];
42323
+ if (!counterKey) continue;
42324
+ plumbing[counterKey] += 1;
42325
+ if (proj.plumbingKind === "rate_limit_status" && proj.rateLimitReached === true) {
42326
+ plumbing.rateLimitReached = true;
42327
+ }
42328
+ }
42329
+ const row = {
42330
+ day,
42331
+ sessionId: group.sessionId,
42332
+ turnId: group.turnId,
42333
+ toolSequence,
42334
+ promptBytes,
42335
+ inputTokens,
42336
+ cachedInputTokens,
42337
+ outputTokens,
42338
+ resultRecordPresent,
42339
+ plumbing,
42340
+ projectionFailures: group.projectionFailures
42341
+ };
42342
+ const rows = rowsByProject.get(projectSlug) ?? [];
42343
+ rows.push(row);
42344
+ rowsByProject.set(projectSlug, rows);
42199
42345
  }
42200
- };
42201
- }
42202
-
42203
- // src/provider-readiness-loop.ts
42204
- var import_node_child_process9 = require("node:child_process");
42205
- var DEFAULT_INTERVAL_MS3 = 6e4;
42206
- function providerReadinessLoopDisabled(env = process.env) {
42207
- return env["MRRLIN_BRIDGE_PROVIDER_READINESS_DISABLE"] === "1";
42208
- }
42209
- function defaultRunnerFor(command) {
42210
- return (args) => {
42211
- const r = (0, import_node_child_process9.spawnSync)(command, args, { encoding: "utf8", timeout: 8e3 });
42212
- return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
42213
- };
42214
- }
42215
- async function runProviderReadinessCycle(deps) {
42216
- try {
42217
- const verify = deps.verify ?? verifyProviderReadiness;
42218
- const runnerFor = deps.runnerFor ?? defaultRunnerFor;
42219
- const [codex, claude] = await Promise.all([
42220
- verify("codex", runnerFor("codex")),
42221
- verify("claude", runnerFor("claude"))
42222
- ]);
42223
- await deps.push({ codex, claude });
42224
- } catch (err) {
42225
- deps.onError?.(err);
42226
- }
42227
- }
42228
- function startProviderReadinessLoop(deps) {
42229
- const env = deps.env ?? process.env;
42230
- const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_PROVIDER_READINESS_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS3);
42231
- let stopped = false;
42232
- let timer = null;
42233
- const schedule = () => {
42234
- if (stopped) return;
42235
- timer = setTimeout(() => {
42236
- void runProviderReadinessCycle(deps).then(() => schedule());
42237
- }, intervalMs);
42238
- timer.unref?.();
42239
- };
42240
- timer = setTimeout(() => {
42241
- void runProviderReadinessCycle(deps).then(() => schedule());
42242
- }, 1e3);
42243
- timer.unref?.();
42244
- return {
42245
- stop() {
42246
- stopped = true;
42247
- if (timer) clearTimeout(timer);
42346
+ if (rowsByProject.size === 0) continue;
42347
+ const telemetryDir = (0, import_node_path10.join)(stateDir, "telemetry");
42348
+ await (0, import_promises5.mkdir)(telemetryDir, { recursive: true });
42349
+ for (const [slug, rows] of rowsByProject) {
42350
+ const finalPath = (0, import_node_path10.join)(telemetryDir, `rows-${slug}-${day}.jsonl`);
42351
+ const tmpPath = `${finalPath}.tmp`;
42352
+ await (0, import_promises5.writeFile)(tmpPath, rows.map((r) => JSON.stringify(r)).join("\n") + "\n", "utf8");
42353
+ await (0, import_promises5.rename)(tmpPath, finalPath);
42248
42354
  }
42249
- };
42250
- }
42251
-
42252
- // src/selected-provider-store.ts
42253
- var current = null;
42254
- function getSelectedProvider() {
42255
- return current;
42256
- }
42257
- function setSelectedProvider(value) {
42258
- current = value;
42355
+ }
42259
42356
  }
42260
42357
 
42261
- // src/execution-consumer.ts
42262
- var import_node_child_process12 = require("node:child_process");
42263
- var import_node_crypto5 = __toESM(require("node:crypto"), 1);
42264
- var import_node_path12 = __toESM(require("node:path"), 1);
42265
- var import_node_util = require("node:util");
42266
-
42267
- // src/consensus/heads.ts
42268
- var DEFAULT_DOMAIN = "code";
42269
- var DOMAINS = ["code", "seo", "marketing", "content"];
42270
- var HEADS_BY_DOMAIN = {
42271
- code: ["plan-reviewer", "architect", "security-analyst", "scope-analyst"],
42272
- seo: ["plan-reviewer", "scope-analyst", "seo-analyst"],
42273
- marketing: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"],
42274
- content: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"]
42275
- };
42276
- var SPEC_HEADS = HEADS_BY_DOMAIN.code;
42277
- var CODE_HEADS_BY_IMPACT = {
42278
- high: HEADS_BY_DOMAIN.code,
42279
- medium: ["plan-reviewer", "security-analyst", "scope-analyst"],
42280
- low: ["plan-reviewer", "scope-analyst"]
42281
- };
42282
- function normalizeDomain(value) {
42283
- if (typeof value !== "string") return DEFAULT_DOMAIN;
42284
- const v = value.trim().toLowerCase();
42285
- return DOMAINS.includes(v) ? v : DEFAULT_DOMAIN;
42286
- }
42287
- function normalizeImpact(value) {
42288
- if (typeof value !== "string") return null;
42289
- const v = value.trim().toLowerCase();
42290
- return v === "low" || v === "medium" || v === "high" ? v : null;
42291
- }
42292
- function resolveHeads(domain2, impact) {
42293
- const d = normalizeDomain(domain2);
42294
- if (d !== "code") return [...HEADS_BY_DOMAIN[d]];
42295
- const i = normalizeImpact(impact) ?? "high";
42296
- return [...CODE_HEADS_BY_IMPACT[i]];
42297
- }
42298
- var PERSONAS_BY_DOMAIN = {
42299
- seo: "seo-writer",
42300
- content: "content-author",
42301
- marketing: "content-author"
42302
- };
42303
- function resolveProducerPersona(domain2) {
42304
- const d = normalizeDomain(domain2);
42305
- if (d === "code") return null;
42306
- return PERSONAS_BY_DOMAIN[d] ?? null;
42307
- }
42358
+ // src/telemetry/daily-uploader.ts
42359
+ var import_promises6 = require("node:fs/promises");
42360
+ var import_node_path12 = require("node:path");
42308
42361
 
42309
42362
  // src/consensus/wiring.ts
42310
42363
  var import_node_crypto3 = __toESM(require("node:crypto"), 1);
42311
42364
  var import_node_fs5 = __toESM(require("node:fs"), 1);
42312
- var import_node_path9 = __toESM(require("node:path"), 1);
42365
+ var import_node_path11 = __toESM(require("node:path"), 1);
42313
42366
  var import_node_url2 = require("node:url");
42314
42367
 
42315
42368
  // src/consensus/verdict.ts
@@ -42741,6 +42794,48 @@ function firstTaskIdToken(text) {
42741
42794
  return m ? m[0] : null;
42742
42795
  }
42743
42796
 
42797
+ // src/consensus/heads.ts
42798
+ var DEFAULT_DOMAIN = "code";
42799
+ var DOMAINS = ["code", "seo", "marketing", "content"];
42800
+ var HEADS_BY_DOMAIN = {
42801
+ code: ["plan-reviewer", "architect", "security-analyst", "scope-analyst"],
42802
+ seo: ["plan-reviewer", "scope-analyst", "seo-analyst"],
42803
+ marketing: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"],
42804
+ content: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"]
42805
+ };
42806
+ var SPEC_HEADS = HEADS_BY_DOMAIN.code;
42807
+ var CODE_HEADS_BY_IMPACT = {
42808
+ high: HEADS_BY_DOMAIN.code,
42809
+ medium: ["plan-reviewer", "security-analyst", "scope-analyst"],
42810
+ low: ["plan-reviewer", "scope-analyst"]
42811
+ };
42812
+ function normalizeDomain(value) {
42813
+ if (typeof value !== "string") return DEFAULT_DOMAIN;
42814
+ const v = value.trim().toLowerCase();
42815
+ return DOMAINS.includes(v) ? v : DEFAULT_DOMAIN;
42816
+ }
42817
+ function normalizeImpact(value) {
42818
+ if (typeof value !== "string") return null;
42819
+ const v = value.trim().toLowerCase();
42820
+ return v === "low" || v === "medium" || v === "high" ? v : null;
42821
+ }
42822
+ function resolveHeads(domain2, impact) {
42823
+ const d = normalizeDomain(domain2);
42824
+ if (d !== "code") return [...HEADS_BY_DOMAIN[d]];
42825
+ const i = normalizeImpact(impact) ?? "high";
42826
+ return [...CODE_HEADS_BY_IMPACT[i]];
42827
+ }
42828
+ var PERSONAS_BY_DOMAIN = {
42829
+ seo: "seo-writer",
42830
+ content: "content-author",
42831
+ marketing: "content-author"
42832
+ };
42833
+ function resolveProducerPersona(domain2) {
42834
+ const d = normalizeDomain(domain2);
42835
+ if (d === "code") return null;
42836
+ return PERSONAS_BY_DOMAIN[d] ?? null;
42837
+ }
42838
+
42744
42839
  // src/consensus/acceptance-criteria.ts
42745
42840
  var HEADING_RE = /^(#{1,6})\s+(.+?)\s*$/;
42746
42841
  var CHECKLIST_ITEM_RE = /^\s*[-*]\s+\[[ xX]\]\s+(.+\S)\s*$/;
@@ -43092,7 +43187,7 @@ ${issuesBlock}`,
43092
43187
  }
43093
43188
 
43094
43189
  // src/consensus/code-gate-git.ts
43095
- var import_node_child_process10 = require("node:child_process");
43190
+ var import_node_child_process8 = require("node:child_process");
43096
43191
  var DIFF_MAX_BYTES = 2e5;
43097
43192
  var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
43098
43193
  var GIT_TIMEOUT_MS = 6e4;
@@ -43108,7 +43203,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
43108
43203
  };
43109
43204
  let child;
43110
43205
  try {
43111
- child = (0, import_node_child_process10.spawn)(cmd, args, {
43206
+ child = (0, import_node_child_process8.spawn)(cmd, args, {
43112
43207
  cwd: opts.cwd,
43113
43208
  env: process.env,
43114
43209
  shell: false,
@@ -43323,15 +43418,15 @@ ${res.stdout}${res.stderr}`);
43323
43418
  var import_meta2 = {};
43324
43419
  function getPersonasDir() {
43325
43420
  if (typeof __dirname !== "undefined") {
43326
- return import_node_path9.default.join(__dirname, "consensus", "personas");
43421
+ return import_node_path11.default.join(__dirname, "consensus", "personas");
43327
43422
  }
43328
- return import_node_path9.default.join(import_node_path9.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
43423
+ return import_node_path11.default.join(import_node_path11.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
43329
43424
  }
43330
43425
  var personaCache = /* @__PURE__ */ new Map();
43331
43426
  function loadPersona(name) {
43332
43427
  const cached2 = personaCache.get(name);
43333
43428
  if (cached2 !== void 0) return cached2;
43334
- const content = import_node_fs5.default.readFileSync(import_node_path9.default.join(getPersonasDir(), `${name}.md`), "utf8");
43429
+ const content = import_node_fs5.default.readFileSync(import_node_path11.default.join(getPersonasDir(), `${name}.md`), "utf8");
43335
43430
  personaCache.set(name, content);
43336
43431
  return content;
43337
43432
  }
@@ -43811,6 +43906,497 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
43811
43906
  };
43812
43907
  }
43813
43908
 
43909
+ // src/telemetry/pii-gate.ts
43910
+ function isRecord(v) {
43911
+ return v !== null && typeof v === "object";
43912
+ }
43913
+ function resolvePath(root, path22) {
43914
+ const parts = path22.split(".");
43915
+ let cur = root;
43916
+ for (let i = 0; i < parts.length - 1; i += 1) {
43917
+ const part = parts[i];
43918
+ const idx = Number(part);
43919
+ if (Array.isArray(cur) && Number.isInteger(idx)) {
43920
+ if (idx < 0 || idx >= cur.length) return null;
43921
+ cur = cur[idx];
43922
+ } else if (isRecord(cur) && part in cur) {
43923
+ cur = cur[part];
43924
+ } else {
43925
+ return null;
43926
+ }
43927
+ }
43928
+ const last = parts[parts.length - 1];
43929
+ const lastIdx = Number(last);
43930
+ if (Array.isArray(cur) && Number.isInteger(lastIdx)) {
43931
+ if (lastIdx < 0 || lastIdx >= cur.length) return null;
43932
+ return { parent: cur, key: lastIdx };
43933
+ }
43934
+ if (isRecord(cur) && last in cur) {
43935
+ return { parent: cur, key: last };
43936
+ }
43937
+ return null;
43938
+ }
43939
+ function withheldExcerptClone(artifact) {
43940
+ const clone2 = { ...artifact };
43941
+ if (Array.isArray(clone2.steps)) {
43942
+ clone2.steps = clone2.steps.map((step) => {
43943
+ if (!isRecord(step)) return step;
43944
+ const copy = { ...step };
43945
+ delete copy.excerpt;
43946
+ return copy;
43947
+ });
43948
+ }
43949
+ return clone2;
43950
+ }
43951
+ async function gate(artifact, prose, ctx) {
43952
+ if (prose.length === 0) {
43953
+ return { ok: true, gated: true, artifact };
43954
+ }
43955
+ const runExec = ctx.runExec ?? runAgentExec;
43956
+ const execResult = await runExec({
43957
+ prompt: JSON.stringify({ fields: prose }),
43958
+ developerInstructions: loadPersona("pii-gate"),
43959
+ cwd: ctx.cwd,
43960
+ timeoutMs: ctx.timeoutMs,
43961
+ sandbox: "read-only",
43962
+ codexExecutable: ctx.codexExecutable,
43963
+ model: ctx.model
43964
+ });
43965
+ if (!execResult.ok) {
43966
+ return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
43967
+ }
43968
+ let parsed;
43969
+ try {
43970
+ parsed = JSON.parse(execResult.text);
43971
+ } catch {
43972
+ return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
43973
+ }
43974
+ const fields = isRecord(parsed) && Array.isArray(parsed.fields) ? parsed.fields : null;
43975
+ const isValidShape = fields !== null && fields.length === prose.length && fields.every(
43976
+ (entry, i) => isRecord(entry) && typeof entry.path === "string" && typeof entry.masked === "string" && entry.path === prose[i]?.path && resolvePath(artifact, entry.path) !== null
43977
+ );
43978
+ if (!isValidShape || fields === null) {
43979
+ return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
43980
+ }
43981
+ const maskedClone = typeof structuredClone === "function" ? structuredClone(artifact) : JSON.parse(JSON.stringify(artifact));
43982
+ for (const { path: path22, masked } of fields) {
43983
+ const target = resolvePath(maskedClone, path22);
43984
+ if (!target) throw new Error(`pii-gate: path "${path22}" failed to resolve on the clone after validating on the original`);
43985
+ target.parent[target.key] = masked;
43986
+ }
43987
+ return { ok: true, gated: false, artifact: maskedClone };
43988
+ }
43989
+
43990
+ // src/telemetry/daily-uploader.ts
43991
+ var ROWS_FILE_RE = /^rows-(.+)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
43992
+ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
43993
+ const telemetryDir = (0, import_node_path12.join)(stateDir, "telemetry");
43994
+ let files;
43995
+ try {
43996
+ files = await (0, import_promises6.readdir)(telemetryDir);
43997
+ } catch (err) {
43998
+ if (err?.code === "ENOENT") return;
43999
+ throw err;
44000
+ }
44001
+ const pending = [];
44002
+ for (const file2 of files) {
44003
+ const match = ROWS_FILE_RE.exec(file2);
44004
+ if (!match) continue;
44005
+ const [, projectSlug, day] = match;
44006
+ const markerPath = (0, import_node_path12.join)(telemetryDir, `.processed-${projectSlug}-${day}`);
44007
+ try {
44008
+ await (0, import_promises6.access)(markerPath);
44009
+ } catch {
44010
+ pending.push({ projectSlug, day, rowsPath: (0, import_node_path12.join)(telemetryDir, file2), markerPath });
44011
+ }
44012
+ }
44013
+ if (pending.length === 0) return;
44014
+ const knownCrashCount = bridgeHealth.knownCrashCount() ?? 0;
44015
+ const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
44016
+ pending.sort((a, b) => a.day.localeCompare(b.day));
44017
+ for (const cur of pending) {
44018
+ let raw;
44019
+ try {
44020
+ raw = await (0, import_promises6.readFile)(cur.rowsPath, "utf8");
44021
+ } catch (err) {
44022
+ console.error(`uploadPendingDays: failed to read ${cur.rowsPath}`, err);
44023
+ continue;
44024
+ }
44025
+ const rows = [];
44026
+ for (const line of raw.split("\n")) {
44027
+ if (!line.trim()) continue;
44028
+ try {
44029
+ rows.push({ ...JSON.parse(line), gateMarker: "gated" });
44030
+ } catch {
44031
+ }
44032
+ }
44033
+ const batch = {
44034
+ day: cur.day,
44035
+ bridgeVersion: PKG_VERSION,
44036
+ knownCrashCount,
44037
+ unprocessedPartitions: fullUnprocessed.filter(
44038
+ (p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
44039
+ ),
44040
+ rows
44041
+ };
44042
+ const gateResult = await gate(batch, [], gateCtx);
44043
+ const gateMarker = gateResult.gated ? "gated" : "projection-only";
44044
+ for (const row of gateResult.artifact.rows) row.gateMarker = gateMarker;
44045
+ const targetProject = cur.projectSlug === "_unattributed" ? process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT : cur.projectSlug;
44046
+ if (!targetProject) {
44047
+ console.error(`uploadPendingDays: no target project resolved for _unattributed/${cur.day}`);
44048
+ continue;
44049
+ }
44050
+ try {
44051
+ await client.postTelemetry(targetProject, gateResult.artifact);
44052
+ } catch (err) {
44053
+ console.error(`uploadPendingDays: postTelemetry failed for ${cur.projectSlug}/${cur.day}`, err);
44054
+ continue;
44055
+ }
44056
+ const tmpMarker = `${cur.markerPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
44057
+ try {
44058
+ await (0, import_promises6.writeFile)(tmpMarker, "");
44059
+ await (0, import_promises6.rename)(tmpMarker, cur.markerPath);
44060
+ } catch (err) {
44061
+ console.error(`uploadPendingDays: failed to write marker for ${cur.projectSlug}/${cur.day}`, err);
44062
+ }
44063
+ }
44064
+ }
44065
+
44066
+ // src/agent-pool-snapshot.ts
44067
+ function normalizeLastUsedAt(value) {
44068
+ if (value === void 0 || value === null) return null;
44069
+ if (typeof value === "number") {
44070
+ if (!Number.isFinite(value)) return null;
44071
+ const ms = value < 1e12 ? value * 1e3 : value;
44072
+ const date5 = new Date(ms);
44073
+ return Number.isNaN(date5.getTime()) ? null : date5.toISOString();
44074
+ }
44075
+ return value;
44076
+ }
44077
+ function buildAgentPoolSnapshot(statusRows, stats, opts) {
44078
+ if (!opts.available) {
44079
+ return {
44080
+ collected_at: opts.collectedAt,
44081
+ status: "unavailable",
44082
+ agents: [],
44083
+ totals: { calls: 0, tokens_in: 0, tokens_out: 0 },
44084
+ estimated_savings_usd: 0
44085
+ };
44086
+ }
44087
+ const costPer1M = opts.paidCostPer1MTokens ?? 3;
44088
+ const agents = statusRows.map((row) => {
44089
+ const agentStats = stats.by_agent[row.id];
44090
+ const count2 = agentStats?.count ?? 0;
44091
+ const tokensIn = agentStats?.tokens_in ?? 0;
44092
+ const tokensOut = agentStats?.tokens_out ?? 0;
44093
+ let successRate = 0;
44094
+ if (count2 > 0) {
44095
+ const successOutcomes = agentStats?.outcomes.success ?? 0;
44096
+ successRate = Number((successOutcomes / count2 * 100).toFixed(2)) / 100;
44097
+ }
44098
+ return {
44099
+ id: row.id,
44100
+ provider: row.provider,
44101
+ tier: row.tier,
44102
+ tags: row.tags,
44103
+ state: row.state ?? "unknown",
44104
+ calls: count2,
44105
+ tokens_in: tokensIn,
44106
+ tokens_out: tokensOut,
44107
+ success_rate: successRate,
44108
+ last_used_at: normalizeLastUsedAt(row.last_used_at)
44109
+ };
44110
+ });
44111
+ let totalCalls = 0;
44112
+ let totalTokensIn = 0;
44113
+ let totalTokensOut = 0;
44114
+ for (const entry of Object.values(stats.by_agent)) {
44115
+ totalCalls += entry.count;
44116
+ totalTokensIn += entry.tokens_in;
44117
+ totalTokensOut += entry.tokens_out;
44118
+ }
44119
+ let savedTokens = 0;
44120
+ for (const row of statusRows) {
44121
+ if (row.tags.includes("free")) {
44122
+ const agentStats = stats.by_agent[row.id];
44123
+ if (agentStats) {
44124
+ savedTokens += agentStats.tokens_in + agentStats.tokens_out;
44125
+ }
44126
+ }
44127
+ }
44128
+ const estimatedSavings = Number((savedTokens / 1e6 * costPer1M).toFixed(2));
44129
+ return {
44130
+ collected_at: opts.collectedAt,
44131
+ status: "ok",
44132
+ agents,
44133
+ totals: {
44134
+ calls: totalCalls,
44135
+ tokens_in: totalTokensIn,
44136
+ tokens_out: totalTokensOut
44137
+ },
44138
+ estimated_savings_usd: estimatedSavings
44139
+ };
44140
+ }
44141
+
44142
+ // src/agent-pool-collector.ts
44143
+ async function collectAgentPoolSnapshot(deps) {
44144
+ let statusRows;
44145
+ let stats;
44146
+ try {
44147
+ const statusResult = await deps.runCli(["status", "--json"]);
44148
+ if (statusResult.code !== 0) throw new Error("non-zero exit on status");
44149
+ let statusParsed;
44150
+ try {
44151
+ statusParsed = JSON.parse(statusResult.stdout);
44152
+ } catch {
44153
+ throw new Error("invalid status json");
44154
+ }
44155
+ if (!Array.isArray(statusParsed)) throw new Error("status not array");
44156
+ statusRows = statusParsed;
44157
+ const statsResult = await deps.runCli(["stats", "--json"]);
44158
+ if (statsResult.code !== 0) throw new Error("non-zero exit on stats");
44159
+ try {
44160
+ stats = JSON.parse(statsResult.stdout);
44161
+ } catch {
44162
+ throw new Error("invalid stats json");
44163
+ }
44164
+ } catch {
44165
+ return buildAgentPoolSnapshot(
44166
+ [],
44167
+ {},
44168
+ { collectedAt: deps.now(), available: false }
44169
+ );
44170
+ }
44171
+ return buildAgentPoolSnapshot(
44172
+ statusRows,
44173
+ stats,
44174
+ { collectedAt: deps.now(), paidCostPer1MTokens: deps.paidCostPer1MTokens, available: true }
44175
+ );
44176
+ }
44177
+
44178
+ // src/external-agents-spawn.ts
44179
+ var import_node_child_process9 = require("node:child_process");
44180
+
44181
+ // src/external-agents-bin.ts
44182
+ function resolveExternalAgentsCliInvocation(override) {
44183
+ if (override && override.trim()) return { command: override, prefixArgs: [] };
44184
+ try {
44185
+ return {
44186
+ command: "node",
44187
+ prefixArgs: [resolvePackageBin("@mrrlin-dev/external-agents", "external-agents")]
44188
+ };
44189
+ } catch {
44190
+ return { command: "external-agents", prefixArgs: [] };
44191
+ }
44192
+ }
44193
+
44194
+ // src/external-agents-spawn.ts
44195
+ function runExternalAgentsCli(args, opts) {
44196
+ let command;
44197
+ let prefixArgs;
44198
+ let source;
44199
+ let triedPath;
44200
+ if (opts.envCliPath && opts.envCliPath.trim()) {
44201
+ command = "node";
44202
+ prefixArgs = [opts.envCliPath];
44203
+ source = "env";
44204
+ triedPath = opts.envCliPath;
44205
+ } else {
44206
+ ({ command, prefixArgs } = resolveExternalAgentsCliInvocation());
44207
+ source = command === "node" && prefixArgs.length === 1 ? "bundled" : "path";
44208
+ triedPath = source === "bundled" ? prefixArgs[0] ?? "" : "external-agents (PATH)";
44209
+ }
44210
+ const useStdin = opts.stdinValue !== void 0;
44211
+ const stdioConfig = useStdin ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
44212
+ return new Promise((resolve) => {
44213
+ let stdout = "";
44214
+ let stderr = "";
44215
+ let settled = false;
44216
+ let timedOut = false;
44217
+ const done = (code) => {
44218
+ if (!settled) {
44219
+ settled = true;
44220
+ resolve({ stdout, stderr, code, timedOut, source, triedPath });
44221
+ }
44222
+ };
44223
+ let spawned;
44224
+ try {
44225
+ spawned = (0, import_node_child_process9.spawn)(command, [...prefixArgs, ...args], { stdio: stdioConfig });
44226
+ } catch {
44227
+ done(1);
44228
+ return;
44229
+ }
44230
+ const child = spawned;
44231
+ let sigkillTimer = null;
44232
+ let budgetTimer = null;
44233
+ if (useStdin && child.stdin) {
44234
+ child.stdin.on("error", () => {
44235
+ });
44236
+ child.stdin.write(opts.stdinValue);
44237
+ child.stdin.end();
44238
+ }
44239
+ child.stdout?.on("data", (d) => {
44240
+ stdout += d.toString();
44241
+ if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
44242
+ });
44243
+ child.stderr?.on("data", (d) => {
44244
+ stderr += d.toString();
44245
+ if (stderr.length > 2e5) stderr = stderr.slice(-2e5);
44246
+ });
44247
+ budgetTimer = setTimeout(() => {
44248
+ budgetTimer = null;
44249
+ timedOut = true;
44250
+ try {
44251
+ child.kill("SIGTERM");
44252
+ } catch {
44253
+ }
44254
+ sigkillTimer = setTimeout(() => {
44255
+ sigkillTimer = null;
44256
+ try {
44257
+ child.kill("SIGKILL");
44258
+ } catch {
44259
+ }
44260
+ }, 2e3);
44261
+ sigkillTimer.unref?.();
44262
+ done(1);
44263
+ }, opts.budgetMs);
44264
+ budgetTimer.unref?.();
44265
+ child.on("error", () => {
44266
+ if (budgetTimer) {
44267
+ clearTimeout(budgetTimer);
44268
+ budgetTimer = null;
44269
+ }
44270
+ if (sigkillTimer) {
44271
+ clearTimeout(sigkillTimer);
44272
+ sigkillTimer = null;
44273
+ }
44274
+ done(1);
44275
+ });
44276
+ child.on("close", (code) => {
44277
+ if (budgetTimer) {
44278
+ clearTimeout(budgetTimer);
44279
+ budgetTimer = null;
44280
+ }
44281
+ if (sigkillTimer) {
44282
+ clearTimeout(sigkillTimer);
44283
+ sigkillTimer = null;
44284
+ }
44285
+ done(code ?? 1);
44286
+ });
44287
+ });
44288
+ }
44289
+
44290
+ // src/agent-pool-loop.ts
44291
+ var DEFAULT_INTERVAL_MS2 = 6e4;
44292
+ function agentPoolLoopDisabled(env = process.env) {
44293
+ return env["MRRLIN_BRIDGE_AGENT_POOL_DISABLE"] === "1";
44294
+ }
44295
+ function defaultRunCli(args) {
44296
+ return runExternalAgentsCli(args, {
44297
+ budgetMs: 5e3,
44298
+ envCliPath: process.env["EXTERNAL_AGENTS_CLI"]
44299
+ }).then(({ stdout, code }) => ({ stdout, code }));
44300
+ }
44301
+ async function runAgentPoolCycle(deps) {
44302
+ try {
44303
+ const snapshot = await collectAgentPoolSnapshot({
44304
+ runCli: deps.runCli ?? defaultRunCli,
44305
+ now: deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
44306
+ });
44307
+ await deps.push(snapshot);
44308
+ } catch (err) {
44309
+ deps.onError?.(err);
44310
+ }
44311
+ }
44312
+ function startAgentPoolLoop(deps) {
44313
+ const env = deps.env ?? process.env;
44314
+ const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_AGENT_POOL_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS2);
44315
+ let stopped = false;
44316
+ let timer = null;
44317
+ const schedule = () => {
44318
+ if (stopped) return;
44319
+ timer = setTimeout(() => {
44320
+ void runAgentPoolCycle(deps).then(() => schedule());
44321
+ }, intervalMs);
44322
+ timer.unref?.();
44323
+ };
44324
+ timer = setTimeout(() => {
44325
+ void runAgentPoolCycle(deps).then(() => schedule());
44326
+ }, 1e3);
44327
+ timer.unref?.();
44328
+ return {
44329
+ stop() {
44330
+ stopped = true;
44331
+ if (timer) clearTimeout(timer);
44332
+ }
44333
+ };
44334
+ }
44335
+
44336
+ // src/provider-readiness-loop.ts
44337
+ var import_node_child_process10 = require("node:child_process");
44338
+ var DEFAULT_INTERVAL_MS3 = 6e4;
44339
+ function providerReadinessLoopDisabled(env = process.env) {
44340
+ return env["MRRLIN_BRIDGE_PROVIDER_READINESS_DISABLE"] === "1";
44341
+ }
44342
+ function defaultRunnerFor(command) {
44343
+ return (args) => {
44344
+ const r = (0, import_node_child_process10.spawnSync)(command, args, { encoding: "utf8", timeout: 8e3 });
44345
+ return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
44346
+ };
44347
+ }
44348
+ async function runProviderReadinessCycle(deps) {
44349
+ try {
44350
+ const verify = deps.verify ?? verifyProviderReadiness;
44351
+ const runnerFor = deps.runnerFor ?? defaultRunnerFor;
44352
+ const [codex, claude] = await Promise.all([
44353
+ verify("codex", runnerFor("codex")),
44354
+ verify("claude", runnerFor("claude"))
44355
+ ]);
44356
+ await deps.push({ codex, claude });
44357
+ } catch (err) {
44358
+ deps.onError?.(err);
44359
+ }
44360
+ }
44361
+ function startProviderReadinessLoop(deps) {
44362
+ const env = deps.env ?? process.env;
44363
+ const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_PROVIDER_READINESS_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS3);
44364
+ let stopped = false;
44365
+ let timer = null;
44366
+ const schedule = () => {
44367
+ if (stopped) return;
44368
+ timer = setTimeout(() => {
44369
+ void runProviderReadinessCycle(deps).then(() => schedule());
44370
+ }, intervalMs);
44371
+ timer.unref?.();
44372
+ };
44373
+ timer = setTimeout(() => {
44374
+ void runProviderReadinessCycle(deps).then(() => schedule());
44375
+ }, 1e3);
44376
+ timer.unref?.();
44377
+ return {
44378
+ stop() {
44379
+ stopped = true;
44380
+ if (timer) clearTimeout(timer);
44381
+ }
44382
+ };
44383
+ }
44384
+
44385
+ // src/selected-provider-store.ts
44386
+ var current = null;
44387
+ function getSelectedProvider() {
44388
+ return current;
44389
+ }
44390
+ function setSelectedProvider(value) {
44391
+ current = value;
44392
+ }
44393
+
44394
+ // src/execution-consumer.ts
44395
+ var import_node_child_process12 = require("node:child_process");
44396
+ var import_node_crypto5 = __toESM(require("node:crypto"), 1);
44397
+ var import_node_path15 = __toESM(require("node:path"), 1);
44398
+ var import_node_util = require("node:util");
44399
+
43814
44400
  // src/consensus/deliverable-gate-outcome.ts
43815
44401
  var MAX_DELIVERABLE_DIAGNOSTICS = 5;
43816
44402
  var MAX_DELIVERABLE_DIAGNOSTIC_LENGTH = 240;
@@ -45055,15 +45641,15 @@ async function awaitTurnWithDeadline(opts) {
45055
45641
  var import_node_child_process11 = require("node:child_process");
45056
45642
  var import_node_fs7 = require("node:fs");
45057
45643
  var import_node_os6 = require("node:os");
45058
- var import_node_path11 = require("node:path");
45644
+ var import_node_path14 = require("node:path");
45059
45645
 
45060
45646
  // src/checkout-lock.ts
45061
45647
  var import_node_fs6 = require("node:fs");
45062
- var import_node_path10 = require("node:path");
45648
+ var import_node_path13 = require("node:path");
45063
45649
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
45064
45650
  async function withCheckoutLock(locksDir, slug, fn) {
45065
45651
  (0, import_node_fs6.mkdirSync)(locksDir, { recursive: true });
45066
- const target = (0, import_node_path10.join)(locksDir, `${slug}.lock`);
45652
+ const target = (0, import_node_path13.join)(locksDir, `${slug}.lock`);
45067
45653
  if (!(0, import_node_fs6.existsSync)(target)) (0, import_node_fs6.writeFileSync)(target, "");
45068
45654
  const release = await import_proper_lockfile.default.lock(target, {
45069
45655
  retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
@@ -45089,7 +45675,7 @@ function git(checkout, args) {
45089
45675
  });
45090
45676
  }
45091
45677
  async function createRunWorktree(opts) {
45092
- const worktreePath = (0, import_node_path11.join)(opts.worktreeRoot, opts.slug, opts.runId);
45678
+ const worktreePath = (0, import_node_path14.join)(opts.worktreeRoot, opts.slug, opts.runId);
45093
45679
  await withCheckoutLock(opts.locksDir, opts.slug, async () => {
45094
45680
  (0, import_node_fs7.mkdirSync)(opts.worktreeRoot, { recursive: true });
45095
45681
  try {
@@ -45166,8 +45752,8 @@ async function doPushRunBranch(opts, execGit) {
45166
45752
  if (localConfig.trim()) {
45167
45753
  throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
45168
45754
  }
45169
- const dir = (0, import_node_fs7.mkdtempSync)((0, import_node_path11.join)((0, import_node_os6.tmpdir)(), "mrrlin-push-"));
45170
- const askpass = (0, import_node_path11.join)(dir, "askpass");
45755
+ const dir = (0, import_node_fs7.mkdtempSync)((0, import_node_path14.join)((0, import_node_os6.tmpdir)(), "mrrlin-push-"));
45756
+ const askpass = (0, import_node_path14.join)(dir, "askpass");
45171
45757
  try {
45172
45758
  (0, import_node_fs7.writeFileSync)(
45173
45759
  askpass,
@@ -45204,7 +45790,7 @@ async function sweepOrphanWorktrees(opts) {
45204
45790
  } catch {
45205
45791
  return opts.worktreeRoot;
45206
45792
  }
45207
- })() + import_node_path11.sep + opts.slug + import_node_path11.sep;
45793
+ })() + import_node_path14.sep + opts.slug + import_node_path14.sep;
45208
45794
  await withCheckoutLock(opts.locksDir, opts.slug, async () => {
45209
45795
  const listing = git(opts.checkout, ["worktree", "list", "--porcelain"]);
45210
45796
  for (const block of listing.split("\n\n")) {
@@ -45496,6 +46082,11 @@ var BASE_INSTRUCTIONS_PREFIX = [
45496
46082
  "- Pick the right open status when you stop a CODE task: if the code work itself is done and only an",
45497
46083
  " already-open PR still awaits operator merge or follow-up, leave the task at `awaiting_verification`;",
45498
46084
  " if you are blocked and a human must decide before the work can continue, leave it at `handoff_needed`.",
46085
+ "- Before calling update_task with status=handoff_needed because you are missing a concrete",
46086
+ " operational fact (an email address, credential, pricing detail, account name, or similar) --",
46087
+ " NOT a product/scope decision, which is legitimately the operator's call -- first search for it:",
46088
+ " search_wiki_pages / retrieve_context, and re-read anything already loaded in this run's context",
46089
+ " bundle. Only hand off for that input if the search comes up empty.",
45499
46090
  "",
45500
46091
  "File artifacts:",
45501
46092
  "- Decide BEFORE writing your result, by PROVENANCE: output assembled from data you RETRIEVED",
@@ -45677,8 +46268,8 @@ function newArtifactId() {
45677
46268
  return `EA-${import_node_crypto5.default.randomUUID()}`;
45678
46269
  }
45679
46270
  var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
45680
- function isBlastRadiusFloorPath(path21) {
45681
- return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(path21));
46271
+ function isBlastRadiusFloorPath(path22) {
46272
+ return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(path22));
45682
46273
  }
45683
46274
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process12.execFile);
45684
46275
  async function defaultListRunDiffPaths(opts) {
@@ -47041,8 +47632,8 @@ async function runBackstopSweep(deps, drive = (slug, id) => driveRun(deps, slug,
47041
47632
  function isRunRecoverableByThisBridge(run3, worktreeRoot) {
47042
47633
  if (!worktreeRoot) return true;
47043
47634
  if (!run3.worktreeId) return false;
47044
- const relative = import_node_path12.default.relative(import_node_path12.default.resolve(worktreeRoot), import_node_path12.default.resolve(run3.worktreeId));
47045
- return relative === "" || relative.length > 0 && !relative.startsWith("..") && !import_node_path12.default.isAbsolute(relative);
47635
+ const relative = import_node_path15.default.relative(import_node_path15.default.resolve(worktreeRoot), import_node_path15.default.resolve(run3.worktreeId));
47636
+ return relative === "" || relative.length > 0 && !relative.startsWith("..") && !import_node_path15.default.isAbsolute(relative);
47046
47637
  }
47047
47638
  async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId) {
47048
47639
  await deps.client.updateExecutionRun(projectSlug, runId, { status: "failed", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), leaseId: leaseId ?? void 0 }).catch(() => {
@@ -47079,7 +47670,7 @@ function maxLeaseReclaims() {
47079
47670
  }
47080
47671
 
47081
47672
  // src/async-job-consumer.ts
47082
- var import_node_crypto6 = __toESM(require("node:crypto"), 1);
47673
+ var import_node_crypto7 = __toESM(require("node:crypto"), 1);
47083
47674
 
47084
47675
  // src/async-tools/registry.ts
47085
47676
  var registry2 = /* @__PURE__ */ new Map();
@@ -47090,9 +47681,303 @@ function getAsyncToolDescriptor(toolName) {
47090
47681
  return registry2.get(toolName);
47091
47682
  }
47092
47683
 
47684
+ // src/bridge-log.ts
47685
+ var import_node_fs8 = require("node:fs");
47686
+ var import_promises7 = require("node:fs/promises");
47687
+ var import_node_path16 = require("node:path");
47688
+
47689
+ // src/redact.ts
47690
+ var REDACTED = "[REDACTED]";
47691
+ var SECRET_PATTERNS = [
47692
+ /ghp_[A-Za-z0-9]{20,}/g,
47693
+ // GitHub personal access token (classic)
47694
+ /github_pat_[A-Za-z0-9_]{20,}/g,
47695
+ // GitHub fine-grained PAT
47696
+ /\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi,
47697
+ // Authorization: Bearer <token>
47698
+ /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
47699
+ // JWT (header.payload.signature)
47700
+ /\b[A-Fa-f0-9]{32,}\b/g,
47701
+ // long hex run (hashes, hex secrets)
47702
+ /\b[A-Za-z0-9+/]{40,}={0,2}\b/g
47703
+ // long base64-ish run (opaque tokens)
47704
+ ];
47705
+ function redact(input) {
47706
+ let out = input;
47707
+ for (const re of SECRET_PATTERNS) out = out.replace(re, REDACTED);
47708
+ return out;
47709
+ }
47710
+
47711
+ // src/telemetry/projector.ts
47712
+ var import_node_crypto6 = require("node:crypto");
47713
+ function isRecord2(x) {
47714
+ return typeof x === "object" && x !== null;
47715
+ }
47716
+ function buildProjection(payload, type, ms, telemetry) {
47717
+ if (!isRecord2(payload)) return null;
47718
+ const seqRaw = payload.seq;
47719
+ const turnIdRaw = payload.turnId;
47720
+ const maybeSeq = typeof seqRaw === "number" ? seqRaw : void 0;
47721
+ const maybeTurnId = typeof turnIdRaw === "string" ? turnIdRaw : void 0;
47722
+ if (type === "event") {
47723
+ const rawEvent = payload.event;
47724
+ if (!isRecord2(rawEvent) || typeof rawEvent.type !== "string") return null;
47725
+ if (rawEvent.type === "tool_use") {
47726
+ const tool = rawEvent.tool;
47727
+ if (!isRecord2(tool)) return null;
47728
+ const toolId = tool.id;
47729
+ const toolName = tool.name;
47730
+ if (typeof toolId !== "string" || typeof toolName !== "string") return null;
47731
+ const input = tool.input;
47732
+ const argKeys = isRecord2(input) ? Object.keys(input) : [];
47733
+ const projectSlug = isRecord2(input) && typeof input.projectSlug === "string" ? input.projectSlug : void 0;
47734
+ const proj = { kind: "tool_use", toolId, toolName, argKeys, seq: maybeSeq ?? 0 };
47735
+ if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
47736
+ if (ms !== void 0) proj.ms = ms;
47737
+ if (projectSlug !== void 0) proj.projectSlug = projectSlug;
47738
+ return proj;
47739
+ }
47740
+ if (rawEvent.type === "tool_result") {
47741
+ const tool = rawEvent.tool;
47742
+ if (!isRecord2(tool)) return null;
47743
+ const toolId = tool.id;
47744
+ if (typeof toolId !== "string") return null;
47745
+ const exitCode = tool.exitCode;
47746
+ const outcome = typeof exitCode === "number" ? exitCode === 0 ? "success" : "error" : "unknown";
47747
+ const proj = { kind: "tool_result", toolId, outcome, seq: maybeSeq ?? 0 };
47748
+ if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
47749
+ if (ms !== void 0) proj.ms = ms;
47750
+ if (typeof exitCode === "number") proj.exitCode = exitCode;
47751
+ const status = tool.status;
47752
+ if (typeof status === "string" && status.trim() !== "") {
47753
+ proj.statusHash = (0, import_node_crypto6.createHash)("sha256").update(status.trim().toLowerCase()).digest("hex").slice(0, 8);
47754
+ }
47755
+ return proj;
47756
+ }
47757
+ if (rawEvent.type === "result") {
47758
+ const subtype = rawEvent.subtype;
47759
+ if (subtype !== "success" && subtype !== "interrupted") return null;
47760
+ const lifecycle = subtype === "success" ? "completed" : "interrupted";
47761
+ const proj = { kind: "turn_lifecycle", lifecycle, seq: maybeSeq ?? 0 };
47762
+ if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
47763
+ if (ms !== void 0) proj.ms = ms;
47764
+ if (lifecycle === "completed" && telemetry !== void 0) {
47765
+ proj.promptBytes = telemetry.promptBytes;
47766
+ if (telemetry.usage !== null) {
47767
+ proj.inputTokens = telemetry.usage.inputTokens ?? null;
47768
+ proj.cachedInputTokens = telemetry.usage.cachedInputTokens ?? null;
47769
+ proj.outputTokens = telemetry.usage.outputTokens ?? null;
47770
+ }
47771
+ }
47772
+ return proj;
47773
+ }
47774
+ if (rawEvent.type === "error") {
47775
+ const proj = { kind: "turn_lifecycle", lifecycle: "failed", seq: maybeSeq ?? 0 };
47776
+ if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
47777
+ if (ms !== void 0) proj.ms = ms;
47778
+ return proj;
47779
+ }
47780
+ return null;
47781
+ }
47782
+ if (type === "ready") {
47783
+ return { kind: "plumbing", plumbingKind: "ready", seq: maybeSeq ?? 0, ...ms !== void 0 ? { ms } : {} };
47784
+ }
47785
+ if (type === "rateLimits") {
47786
+ const rateLimits = payload.rateLimits;
47787
+ const proj = { kind: "plumbing", plumbingKind: "rate_limit_status", seq: maybeSeq ?? 0 };
47788
+ if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
47789
+ if (ms !== void 0) proj.ms = ms;
47790
+ if (isRecord2(rateLimits)) proj.rateLimitReached = rateLimits.rateLimitReachedType != null;
47791
+ return proj;
47792
+ }
47793
+ const bracketMatch = /^<([a-z-]+)>$/.exec(type);
47794
+ if (bracketMatch) {
47795
+ const candidate = bracketMatch[1]?.replace(/-/g, "_");
47796
+ if (candidate === "scheduler_tick" || candidate === "buffer_stats") {
47797
+ return { kind: "plumbing", plumbingKind: candidate, seq: maybeSeq ?? 0, ...ms !== void 0 ? { ms } : {} };
47798
+ }
47799
+ }
47800
+ return null;
47801
+ }
47802
+
47803
+ // src/bridge-log.ts
47804
+ var NOOP_LOGGER = {
47805
+ logIn() {
47806
+ },
47807
+ logOut() {
47808
+ },
47809
+ close() {
47810
+ }
47811
+ };
47812
+ var REDACT_DEPTH_CAP = 8;
47813
+ var IMAGE_DATA_URI_RE = /^(data:image\/[a-zA-Z0-9.+-]+;base64,)([A-Za-z0-9+/=]+)$/;
47814
+ function redactImageDataUri(value) {
47815
+ const m = value.match(IMAGE_DATA_URI_RE);
47816
+ if (!m) return value;
47817
+ const [, prefix, body] = m;
47818
+ if (prefix === void 0 || body === void 0) return value;
47819
+ return `${prefix}\u2026(${body.length} bytes)`;
47820
+ }
47821
+ function redactValue(value, depth, counter) {
47822
+ if (typeof value === "string") {
47823
+ const redacted = redact(redactImageDataUri(value));
47824
+ if (redacted !== value) counter.count += 1;
47825
+ return redacted;
47826
+ }
47827
+ if (value === null || typeof value !== "object") return value;
47828
+ if (depth >= REDACT_DEPTH_CAP) {
47829
+ try {
47830
+ const flattened = JSON.stringify(value);
47831
+ const redacted = redact(flattened);
47832
+ if (redacted !== flattened) counter.count += 1;
47833
+ return redacted;
47834
+ } catch {
47835
+ counter.count += 1;
47836
+ return REDACTED;
47837
+ }
47838
+ }
47839
+ if (Array.isArray(value)) return value.map((item) => redactValue(item, depth + 1, counter));
47840
+ const out = {};
47841
+ for (const [k, v] of Object.entries(value)) {
47842
+ out[k] = redactValue(v, depth + 1, counter);
47843
+ }
47844
+ return out;
47845
+ }
47846
+ function redactMessage(payload, opts) {
47847
+ const counter = { count: 0 };
47848
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
47849
+ const msg = payload;
47850
+ if (msg.type === "pairing-qr") {
47851
+ const clone2 = { ...msg };
47852
+ for (const key of ["payload", "svg"]) {
47853
+ if (typeof clone2[key] === "string") clone2[key] = `[REDACTED len=${clone2[key].length}]`;
47854
+ }
47855
+ return { payload: redactValue(clone2, 1, counter), redactedCount: counter.count };
47856
+ }
47857
+ if (!opts.includePrompts && msg.type === "turn" && typeof msg.message === "string") {
47858
+ return { payload: redactValue({ ...msg, message: "[prompt omitted]" }, 1, counter), redactedCount: counter.count };
47859
+ }
47860
+ }
47861
+ return { payload: redactValue(payload, 0, counter), redactedCount: counter.count };
47862
+ }
47863
+ function resolveBridgeLogEnabled(env = process.env) {
47864
+ const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
47865
+ return !(raw === "0" || raw === "false");
47866
+ }
47867
+ function resolvePromptsEnabled(env) {
47868
+ const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
47869
+ return !(raw === "0" || raw === "false");
47870
+ }
47871
+ function createBridgeLogger(stateDir, env = process.env) {
47872
+ if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
47873
+ const logsDir = (0, import_node_path16.join)(stateDir, "logs");
47874
+ try {
47875
+ (0, import_node_fs8.mkdirSync)(logsDir, { recursive: true });
47876
+ } catch {
47877
+ return NOOP_LOGGER;
47878
+ }
47879
+ const includePrompts = resolvePromptsEnabled(env);
47880
+ const fileFor = () => (0, import_node_path16.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
47881
+ const gainDay = (sessionId) => {
47882
+ const sessionsPath = (0, import_node_path16.join)(logsDir, ".sessions.json");
47883
+ let sessionsObj = {};
47884
+ try {
47885
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(sessionsPath, "utf8"));
47886
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) sessionsObj = parsed;
47887
+ } catch {
47888
+ sessionsObj = {};
47889
+ }
47890
+ const day = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
47891
+ const idsToday = Array.isArray(sessionsObj[day]) ? sessionsObj[day] : [];
47892
+ if (idsToday.includes(sessionId)) return;
47893
+ sessionsObj[day] = [...idsToday, sessionId];
47894
+ const tmpPath = `${sessionsPath}.tmp`;
47895
+ (0, import_node_fs8.writeFileSync)(tmpPath, JSON.stringify(sessionsObj));
47896
+ (0, import_node_fs8.renameSync)(tmpPath, sessionsPath);
47897
+ };
47898
+ const write = (dir, rec) => {
47899
+ try {
47900
+ let projection = null;
47901
+ let projectionFailed = false;
47902
+ if (rec.sessionId !== null) {
47903
+ try {
47904
+ const built = buildProjection(rec.payload, rec.type, rec.ms, rec.telemetry);
47905
+ if (built) projection = { ...built, sessionId: rec.sessionId };
47906
+ } catch {
47907
+ projectionFailed = true;
47908
+ }
47909
+ }
47910
+ const { payload: redactedPayload, redactedCount } = redactMessage(rec.payload, { includePrompts });
47911
+ const line = JSON.stringify({
47912
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
47913
+ dir,
47914
+ spanId: rec.spanId,
47915
+ sessionId: rec.sessionId,
47916
+ type: rec.type,
47917
+ ...rec.ms !== void 0 ? { ms: rec.ms } : {},
47918
+ payload: redactedPayload,
47919
+ redactedCount,
47920
+ projection,
47921
+ ...projectionFailed ? { projectionFailed: true } : {}
47922
+ }) + "\n";
47923
+ (0, import_node_fs8.appendFileSync)(fileFor(), line);
47924
+ if (rec.sessionId !== null) gainDay(rec.sessionId);
47925
+ } catch {
47926
+ }
47927
+ };
47928
+ return {
47929
+ logIn: (rec) => write("in", rec),
47930
+ logOut: (rec) => write("out", rec),
47931
+ close() {
47932
+ }
47933
+ };
47934
+ }
47935
+ async function findSessionDays(stateDir, sessionId) {
47936
+ const sessionsPath = (0, import_node_path16.join)(stateDir, "logs", ".sessions.json");
47937
+ let sessionsObj;
47938
+ try {
47939
+ const parsed = JSON.parse(await (0, import_promises7.readFile)(sessionsPath, "utf8"));
47940
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
47941
+ sessionsObj = parsed;
47942
+ } catch {
47943
+ return [];
47944
+ }
47945
+ const days = [];
47946
+ for (const [day, ids] of Object.entries(sessionsObj)) {
47947
+ if (Array.isArray(ids) && ids.includes(sessionId)) days.push(day);
47948
+ }
47949
+ return days;
47950
+ }
47951
+
47093
47952
  // src/async-job-consumer.ts
47094
47953
  var ASYNC_JOB_MAX_ATTEMPTS = 2;
47954
+ function ASYNC_UNOWNED_TTL_DAYS() {
47955
+ const raw = Number(process.env.MRRLIN_ASYNC_UNOWNED_TTL_DAYS);
47956
+ return Number.isFinite(raw) && raw > 0 ? raw : 7;
47957
+ }
47095
47958
  async function driveAsyncJob(deps, projectSlug, jobId) {
47959
+ const preClaimJob = await deps.client.getAsyncJob(projectSlug, jobId);
47960
+ if (!preClaimJob) return;
47961
+ const preClaimDescriptor = getAsyncToolDescriptor(preClaimJob.toolName);
47962
+ if (preClaimDescriptor?.locationDependent) {
47963
+ const owns = preClaimJob.directorSessionId != null && (await findSessionDays(deps.stateDir, preClaimJob.directorSessionId)).length > 0;
47964
+ if (!owns) {
47965
+ const ttlMs = ASYNC_UNOWNED_TTL_DAYS() * 24 * 60 * 60 * 1e3;
47966
+ const ageMs = Date.now() - new Date(preClaimJob.createdAt).getTime();
47967
+ if (ageMs > ttlMs) {
47968
+ const claimedToTerminate = await deps.client.claimAsyncJob(projectSlug, jobId);
47969
+ if (claimedToTerminate?.leaseId) {
47970
+ await deps.client.terminalizeAsyncJob(projectSlug, jobId, {
47971
+ leaseId: claimedToTerminate.leaseId,
47972
+ status: "failed",
47973
+ failureReason: "provider_unavailable",
47974
+ error: `No machine held the logs for directorSessionId=${String(preClaimJob.directorSessionId)} within MRRLIN_ASYNC_UNOWNED_TTL_DAYS`
47975
+ });
47976
+ }
47977
+ }
47978
+ return;
47979
+ }
47980
+ }
47096
47981
  const claimed = await deps.client.claimAsyncJob(projectSlug, jobId);
47097
47982
  if (!claimed || !claimed.leaseId) return;
47098
47983
  const leaseId = claimed.leaseId;
@@ -47134,7 +48019,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
47134
48019
  outcome = await deps.run(
47135
48020
  "async",
47136
48021
  () => descriptor2.run(
47137
- { client: deps.client, cwd: deps.cwd, codexExecutable: deps.codexExecutable, seat, projectSlug },
48022
+ { client: deps.client, cwd: deps.cwd, codexExecutable: deps.codexExecutable, stateDir: deps.stateDir, seat, projectSlug },
47138
48023
  input
47139
48024
  )
47140
48025
  );
@@ -47180,7 +48065,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
47180
48065
  const delivery = descriptor2.onComplete(outcome, input);
47181
48066
  if (!delivery.suppressInbox) {
47182
48067
  await deps.client.createInboxItem(projectSlug, {
47183
- id: delivery.id ?? `II-${import_node_crypto6.default.randomUUID()}`,
48068
+ id: delivery.id ?? `II-${import_node_crypto7.default.randomUUID()}`,
47184
48069
  kind: delivery.kind,
47185
48070
  body: delivery.body,
47186
48071
  ...delivery.taskId ? { taskId: delivery.taskId } : {},
@@ -47198,13 +48083,13 @@ async function deriveRequestedHash(client, toolName, input) {
47198
48083
  if (input.requestedHash) return input.requestedHash;
47199
48084
  if (toolName === "run_spec_consensus" && input.pageId) {
47200
48085
  const page = await client.getWikiPage(input.projectSlug, input.pageId);
47201
- return page.contentHash ?? import_node_crypto6.default.createHash("sha256").update(page.markdownBody).digest("hex");
48086
+ return page.contentHash ?? import_node_crypto7.default.createHash("sha256").update(page.markdownBody).digest("hex");
47202
48087
  }
47203
48088
  if (toolName === "draft_task_spec" && input.taskId) {
47204
48089
  const task = await client.getTask(input.projectSlug, input.taskId);
47205
- return task.updatedAt ?? import_node_crypto6.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
48090
+ return task.updatedAt ?? import_node_crypto7.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
47206
48091
  }
47207
- return import_node_crypto6.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
48092
+ return import_node_crypto7.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
47208
48093
  }
47209
48094
  async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
47210
48095
  const projects = await deps.client.listProjects();
@@ -47392,19 +48277,19 @@ function agentIdleMs(provider) {
47392
48277
  }
47393
48278
 
47394
48279
  // src/operator-token.ts
47395
- var import_node_fs8 = require("node:fs");
48280
+ var import_node_fs9 = require("node:fs");
47396
48281
  var import_node_os7 = __toESM(require("node:os"), 1);
47397
- var import_node_path13 = __toESM(require("node:path"), 1);
48282
+ var import_node_path17 = __toESM(require("node:path"), 1);
47398
48283
  function operatorDir() {
47399
- const base = process.env.CODEX_HOME ? import_node_path13.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path13.default.join(import_node_os7.default.homedir(), ".mrrlin");
48284
+ const base = process.env.CODEX_HOME ? import_node_path17.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path17.default.join(import_node_os7.default.homedir(), ".mrrlin");
47400
48285
  return base;
47401
48286
  }
47402
48287
  function operatorTokenPath() {
47403
- return import_node_path13.default.join(operatorDir(), "operator-token");
48288
+ return import_node_path17.default.join(operatorDir(), "operator-token");
47404
48289
  }
47405
48290
  function readOperatorToken() {
47406
48291
  try {
47407
- const token = (0, import_node_fs8.readFileSync)(operatorTokenPath(), "utf8").trim();
48292
+ const token = (0, import_node_fs9.readFileSync)(operatorTokenPath(), "utf8").trim();
47408
48293
  return token.length > 0 ? token : null;
47409
48294
  } catch {
47410
48295
  return null;
@@ -47412,24 +48297,24 @@ function readOperatorToken() {
47412
48297
  }
47413
48298
  function persistOperatorToken(token) {
47414
48299
  const dir = operatorDir();
47415
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true, mode: 448 });
47416
- (0, import_node_fs8.writeFileSync)(operatorTokenPath(), `${token.trim()}
48300
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true, mode: 448 });
48301
+ (0, import_node_fs9.writeFileSync)(operatorTokenPath(), `${token.trim()}
47417
48302
  `, { encoding: "utf8", mode: 384 });
47418
48303
  }
47419
48304
  function agentCredentialPath() {
47420
- return import_node_path13.default.join(operatorDir(), "agent-credential");
48305
+ return import_node_path17.default.join(operatorDir(), "agent-credential");
47421
48306
  }
47422
48307
  function persistAgentSecret(secret) {
47423
48308
  const dir = operatorDir();
47424
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true, mode: 448 });
47425
- (0, import_node_fs8.writeFileSync)(agentCredentialPath(), `${secret.trim()}
48309
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true, mode: 448 });
48310
+ (0, import_node_fs9.writeFileSync)(agentCredentialPath(), `${secret.trim()}
47426
48311
  `, { encoding: "utf8", mode: 384 });
47427
48312
  }
47428
48313
  function readAgentSecret() {
47429
48314
  const fromEnv = process.env.MRRLIN_AGENT_SECRET?.trim();
47430
48315
  if (fromEnv) return fromEnv;
47431
48316
  try {
47432
- const raw = (0, import_node_fs8.readFileSync)(agentCredentialPath(), "utf8").trim();
48317
+ const raw = (0, import_node_fs9.readFileSync)(agentCredentialPath(), "utf8").trim();
47433
48318
  return raw || void 0;
47434
48319
  } catch {
47435
48320
  return void 0;
@@ -47437,16 +48322,16 @@ function readAgentSecret() {
47437
48322
  }
47438
48323
 
47439
48324
  // src/thread-index.ts
47440
- var import_node_fs9 = require("node:fs");
47441
- var import_node_path14 = __toESM(require("node:path"), 1);
48325
+ var import_node_fs10 = require("node:fs");
48326
+ var import_node_path18 = __toESM(require("node:path"), 1);
47442
48327
  function threadIndexPath(stateDir) {
47443
- return import_node_path14.default.join(stateDir, "threads.json");
48328
+ return import_node_path18.default.join(stateDir, "threads.json");
47444
48329
  }
47445
48330
  function loadThreadIndex(stateDir, ttlMs, now) {
47446
48331
  const result = /* @__PURE__ */ new Map();
47447
48332
  let parsed;
47448
48333
  try {
47449
- parsed = JSON.parse((0, import_node_fs9.readFileSync)(threadIndexPath(stateDir), "utf8"));
48334
+ parsed = JSON.parse((0, import_node_fs10.readFileSync)(threadIndexPath(stateDir), "utf8"));
47450
48335
  } catch {
47451
48336
  return result;
47452
48337
  }
@@ -47469,8 +48354,8 @@ function loadThreadIndex(stateDir, ttlMs, now) {
47469
48354
  return result;
47470
48355
  }
47471
48356
  function saveThreadIndex(stateDir, entries) {
47472
- (0, import_node_fs9.mkdirSync)(stateDir, { recursive: true, mode: 448 });
47473
- (0, import_node_fs9.writeFileSync)(threadIndexPath(stateDir), `${JSON.stringify(Object.fromEntries(entries), null, 2)}
48357
+ (0, import_node_fs10.mkdirSync)(stateDir, { recursive: true, mode: 448 });
48358
+ (0, import_node_fs10.writeFileSync)(threadIndexPath(stateDir), `${JSON.stringify(Object.fromEntries(entries), null, 2)}
47474
48359
  `, {
47475
48360
  encoding: "utf8",
47476
48361
  mode: 384
@@ -47605,10 +48490,10 @@ function createToolBusyClock(opts) {
47605
48490
  }
47606
48491
 
47607
48492
  // src/worker-token.ts
47608
- var import_node_crypto7 = require("node:crypto");
47609
- var import_node_fs10 = require("node:fs");
48493
+ var import_node_crypto8 = require("node:crypto");
48494
+ var import_node_fs11 = require("node:fs");
47610
48495
  var import_node_os8 = __toESM(require("node:os"), 1);
47611
- var import_node_path15 = __toESM(require("node:path"), 1);
48496
+ var import_node_path19 = __toESM(require("node:path"), 1);
47612
48497
  var DEFAULT_WORKER_PORT = 8792;
47613
48498
  function workerPort() {
47614
48499
  const raw = process.env.MRRLIN_WORKER_PORT;
@@ -47617,15 +48502,15 @@ function workerPort() {
47617
48502
  return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
47618
48503
  }
47619
48504
  function workerDir() {
47620
- const base = process.env.CODEX_HOME ? import_node_path15.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path15.default.join(import_node_os8.default.homedir(), ".mrrlin");
47621
- return import_node_path15.default.join(base, "worker");
48505
+ const base = process.env.CODEX_HOME ? import_node_path19.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path19.default.join(import_node_os8.default.homedir(), ".mrrlin");
48506
+ return import_node_path19.default.join(base, "worker");
47622
48507
  }
47623
48508
  function workerTokenPath() {
47624
- return import_node_path15.default.join(workerDir(), "token");
48509
+ return import_node_path19.default.join(workerDir(), "token");
47625
48510
  }
47626
48511
  function readWorkerToken() {
47627
48512
  try {
47628
- const token = (0, import_node_fs10.readFileSync)(workerTokenPath(), "utf8").trim();
48513
+ const token = (0, import_node_fs11.readFileSync)(workerTokenPath(), "utf8").trim();
47629
48514
  return token.length > 0 ? token : null;
47630
48515
  } catch {
47631
48516
  return null;
@@ -47635,18 +48520,18 @@ function readOrCreateWorkerToken() {
47635
48520
  const existing = readWorkerToken();
47636
48521
  if (existing) return existing;
47637
48522
  const dir = workerDir();
47638
- (0, import_node_fs10.mkdirSync)(dir, { recursive: true, mode: 448 });
47639
- const token = (0, import_node_crypto7.randomBytes)(32).toString("hex");
47640
- (0, import_node_fs10.writeFileSync)(workerTokenPath(), `${token}
48523
+ (0, import_node_fs11.mkdirSync)(dir, { recursive: true, mode: 448 });
48524
+ const token = (0, import_node_crypto8.randomBytes)(32).toString("hex");
48525
+ (0, import_node_fs11.writeFileSync)(workerTokenPath(), `${token}
47641
48526
  `, { encoding: "utf8", mode: 384 });
47642
48527
  return token;
47643
48528
  }
47644
48529
 
47645
48530
  // src/remote-phone-relay.ts
47646
48531
  var import_node_events2 = require("node:events");
47647
- var import_node_fs11 = require("node:fs");
48532
+ var import_node_fs12 = require("node:fs");
47648
48533
  var import_node_os9 = require("node:os");
47649
- var import_node_path16 = require("node:path");
48534
+ var import_node_path20 = require("node:path");
47650
48535
 
47651
48536
  // ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
47652
48537
  var nc = __toESM(require("node:crypto"), 1);
@@ -51217,9 +52102,9 @@ var DirectorRelay = class {
51217
52102
 
51218
52103
  // src/remote-phone-relay.ts
51219
52104
  function loadOrCreateAgentDeviceKey() {
51220
- const path21 = (0, import_node_path16.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-device-key");
52105
+ const path22 = (0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-device-key");
51221
52106
  try {
51222
- const raw = JSON.parse((0, import_node_fs11.readFileSync)(path21, "utf8"));
52107
+ const raw = JSON.parse((0, import_node_fs12.readFileSync)(path22, "utf8"));
51223
52108
  if (typeof raw.priv === "string" && typeof raw.pub === "string") {
51224
52109
  return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
51225
52110
  }
@@ -51227,9 +52112,9 @@ function loadOrCreateAgentDeviceKey() {
51227
52112
  }
51228
52113
  const kp = generateIdentityKeyPair();
51229
52114
  try {
51230
- (0, import_node_fs11.mkdirSync)((0, import_node_path16.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
51231
- (0, import_node_fs11.writeFileSync)(
51232
- path21,
52115
+ (0, import_node_fs12.mkdirSync)((0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
52116
+ (0, import_node_fs12.writeFileSync)(
52117
+ path22,
51233
52118
  JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
51234
52119
  { mode: 384 }
51235
52120
  );
@@ -51237,10 +52122,10 @@ function loadOrCreateAgentDeviceKey() {
51237
52122
  }
51238
52123
  return kp;
51239
52124
  }
51240
- var AGENT_PAIRING_PATH = (0, import_node_path16.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-pairing.json");
52125
+ var AGENT_PAIRING_PATH = (0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-pairing.json");
51241
52126
  function loadAgentPairing() {
51242
52127
  try {
51243
- const raw = JSON.parse((0, import_node_fs11.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
52128
+ const raw = JSON.parse((0, import_node_fs12.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
51244
52129
  if (typeof raw.channelId === "string" && typeof raw.agentControlSecret === "string" && typeof raw.relayAuth === "string" && typeof raw.peerIdentityKey === "string") {
51245
52130
  return {
51246
52131
  channelId: raw.channelId,
@@ -51255,8 +52140,8 @@ function loadAgentPairing() {
51255
52140
  }
51256
52141
  function saveAgentPairing(record2) {
51257
52142
  try {
51258
- (0, import_node_fs11.mkdirSync)((0, import_node_path16.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
51259
- (0, import_node_fs11.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
52143
+ (0, import_node_fs12.mkdirSync)((0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
52144
+ (0, import_node_fs12.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
51260
52145
  } catch {
51261
52146
  }
51262
52147
  }
@@ -51433,18 +52318,18 @@ async function renderPairingQrSvg(payload) {
51433
52318
  }
51434
52319
 
51435
52320
  // src/checkout-registry.ts
51436
- var import_node_fs12 = require("node:fs");
51437
- var import_node_path17 = require("node:path");
52321
+ var import_node_fs13 = require("node:fs");
52322
+ var import_node_path21 = require("node:path");
51438
52323
  var CheckoutRegistry = class {
51439
52324
  file;
51440
52325
  constructor(stateDir) {
51441
- this.file = (0, import_node_path17.join)(stateDir, "checkouts.json");
51442
- (0, import_node_fs12.mkdirSync)(stateDir, { recursive: true });
52326
+ this.file = (0, import_node_path21.join)(stateDir, "checkouts.json");
52327
+ (0, import_node_fs13.mkdirSync)(stateDir, { recursive: true });
51443
52328
  }
51444
52329
  read() {
51445
- if (!(0, import_node_fs12.existsSync)(this.file)) return {};
52330
+ if (!(0, import_node_fs13.existsSync)(this.file)) return {};
51446
52331
  try {
51447
- return JSON.parse((0, import_node_fs12.readFileSync)(this.file, "utf8"));
52332
+ return JSON.parse((0, import_node_fs13.readFileSync)(this.file, "utf8"));
51448
52333
  } catch {
51449
52334
  return {};
51450
52335
  }
@@ -51452,16 +52337,16 @@ var CheckoutRegistry = class {
51452
52337
  get(slug) {
51453
52338
  return this.read()[slug] ?? null;
51454
52339
  }
51455
- confirm(slug, path21, now) {
52340
+ confirm(slug, path22, now) {
51456
52341
  const all = this.read();
51457
- all[slug] = { path: path21, confirmedAt: now };
51458
- (0, import_node_fs12.writeFileSync)(this.file, JSON.stringify(all, null, 2));
52342
+ all[slug] = { path: path22, confirmedAt: now };
52343
+ (0, import_node_fs13.writeFileSync)(this.file, JSON.stringify(all, null, 2));
51459
52344
  }
51460
52345
  };
51461
52346
 
51462
52347
  // src/checkout-handlers.ts
51463
52348
  var import_node_child_process13 = require("node:child_process");
51464
- var import_node_fs13 = require("node:fs");
52349
+ var import_node_fs14 = require("node:fs");
51465
52350
 
51466
52351
  // src/git-remote-match.ts
51467
52352
  function normalizeRemote(url2) {
@@ -51496,7 +52381,7 @@ function validateCheckoutPath(checkoutPath, repo) {
51496
52381
  }
51497
52382
  let resolvedPath;
51498
52383
  try {
51499
- resolvedPath = (0, import_node_fs13.realpathSync)(trimmedPath);
52384
+ resolvedPath = (0, import_node_fs14.realpathSync)(trimmedPath);
51500
52385
  } catch {
51501
52386
  return {
51502
52387
  ok: false,
@@ -51801,131 +52686,13 @@ function extractVerificationSection(markdown) {
51801
52686
  return body.length > 0 ? body : null;
51802
52687
  }
51803
52688
 
51804
- // src/bridge-log.ts
51805
- var import_node_fs14 = require("node:fs");
51806
- var import_node_path18 = require("node:path");
51807
-
51808
- // src/redact.ts
51809
- var REDACTED = "[REDACTED]";
51810
- var SECRET_PATTERNS = [
51811
- /ghp_[A-Za-z0-9]{20,}/g,
51812
- // GitHub personal access token (classic)
51813
- /github_pat_[A-Za-z0-9_]{20,}/g,
51814
- // GitHub fine-grained PAT
51815
- /\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi,
51816
- // Authorization: Bearer <token>
51817
- /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
51818
- // JWT (header.payload.signature)
51819
- /\b[A-Fa-f0-9]{32,}\b/g,
51820
- // long hex run (hashes, hex secrets)
51821
- /\b[A-Za-z0-9+/]{40,}={0,2}\b/g
51822
- // long base64-ish run (opaque tokens)
51823
- ];
51824
- function redact(input) {
51825
- let out = input;
51826
- for (const re of SECRET_PATTERNS) out = out.replace(re, REDACTED);
51827
- return out;
51828
- }
51829
-
51830
- // src/bridge-log.ts
51831
- var NOOP_LOGGER = {
51832
- logIn() {
51833
- },
51834
- logOut() {
51835
- },
51836
- close() {
51837
- }
51838
- };
51839
- var REDACT_DEPTH_CAP = 8;
51840
- var IMAGE_DATA_URI_RE = /^(data:image\/[a-zA-Z0-9.+-]+;base64,)([A-Za-z0-9+/=]+)$/;
51841
- function redactImageDataUri(value) {
51842
- const m = value.match(IMAGE_DATA_URI_RE);
51843
- if (!m) return value;
51844
- const [, prefix, body] = m;
51845
- if (prefix === void 0 || body === void 0) return value;
51846
- return `${prefix}\u2026(${body.length} bytes)`;
51847
- }
51848
- function redactValue(value, depth) {
51849
- if (typeof value === "string") return redact(redactImageDataUri(value));
51850
- if (value === null || typeof value !== "object") return value;
51851
- if (depth >= REDACT_DEPTH_CAP) {
51852
- try {
51853
- return redact(JSON.stringify(value));
51854
- } catch {
51855
- return REDACTED;
51856
- }
51857
- }
51858
- if (Array.isArray(value)) return value.map((item) => redactValue(item, depth + 1));
51859
- const out = {};
51860
- for (const [k, v] of Object.entries(value)) {
51861
- out[k] = redactValue(v, depth + 1);
51862
- }
51863
- return out;
51864
- }
51865
- function redactMessage(payload, opts) {
51866
- if (payload && typeof payload === "object" && !Array.isArray(payload)) {
51867
- const msg = payload;
51868
- if (msg.type === "pairing-qr") {
51869
- const clone2 = { ...msg };
51870
- for (const key of ["payload", "svg"]) {
51871
- if (typeof clone2[key] === "string") clone2[key] = `[REDACTED len=${clone2[key].length}]`;
51872
- }
51873
- return redactValue(clone2, 1);
51874
- }
51875
- if (!opts.includePrompts && msg.type === "turn" && typeof msg.message === "string") {
51876
- return redactValue({ ...msg, message: "[prompt omitted]" }, 1);
51877
- }
51878
- }
51879
- return redactValue(payload, 0);
51880
- }
51881
- function resolveBridgeLogEnabled(env = process.env) {
51882
- const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
51883
- return !(raw === "0" || raw === "false");
51884
- }
51885
- function resolvePromptsEnabled(env) {
51886
- const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
51887
- return !(raw === "0" || raw === "false");
51888
- }
51889
- function createBridgeLogger(stateDir, env = process.env) {
51890
- if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
51891
- const logsDir = (0, import_node_path18.join)(stateDir, "logs");
51892
- try {
51893
- (0, import_node_fs14.mkdirSync)(logsDir, { recursive: true });
51894
- } catch {
51895
- return NOOP_LOGGER;
51896
- }
51897
- const includePrompts = resolvePromptsEnabled(env);
51898
- const fileFor = () => (0, import_node_path18.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
51899
- const write = (dir, rec) => {
51900
- try {
51901
- const line = JSON.stringify({
51902
- ts: (/* @__PURE__ */ new Date()).toISOString(),
51903
- dir,
51904
- spanId: rec.spanId,
51905
- sessionId: rec.sessionId,
51906
- type: rec.type,
51907
- ...rec.ms !== void 0 ? { ms: rec.ms } : {},
51908
- payload: redactMessage(rec.payload, { includePrompts })
51909
- }) + "\n";
51910
- (0, import_node_fs14.appendFileSync)(fileFor(), line);
51911
- } catch {
51912
- }
51913
- };
51914
- return {
51915
- logIn: (rec) => write("in", rec),
51916
- logOut: (rec) => write("out", rec),
51917
- close() {
51918
- }
51919
- };
51920
- }
51921
-
51922
52689
  // src/external-agents-scrub.ts
51923
52690
  var import_node_fs15 = __toESM(require("node:fs"), 1);
51924
52691
  var import_node_os10 = __toESM(require("node:os"), 1);
51925
- var import_node_path19 = __toESM(require("node:path"), 1);
52692
+ var import_node_path22 = __toESM(require("node:path"), 1);
51926
52693
  var REDACTION = "[REDACTED]";
51927
52694
  var SHORT_VALUE_THRESHOLD = 8;
51928
- var KEYS_ENV_PATH = () => import_node_path19.default.join(import_node_os10.default.homedir(), ".local", "state", "external-agents", "keys.env");
52695
+ var KEYS_ENV_PATH = () => import_node_path22.default.join(import_node_os10.default.homedir(), ".local", "state", "external-agents", "keys.env");
51929
52696
  var keysEnvCache = null;
51930
52697
  function readKeysEnv() {
51931
52698
  const filePath = KEYS_ENV_PATH();
@@ -52346,9 +53113,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
52346
53113
  return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
52347
53114
  }
52348
53115
  function readCodexFallbackModels() {
52349
- const codexHome = process.env.CODEX_HOME?.trim() || import_node_path20.default.join(import_node_os11.default.homedir(), ".codex");
53116
+ const codexHome = process.env.CODEX_HOME?.trim() || import_node_path23.default.join(import_node_os11.default.homedir(), ".codex");
52350
53117
  const models = /* @__PURE__ */ new Map();
52351
- const cachePath = import_node_path20.default.join(codexHome, "models_cache.json");
53118
+ const cachePath = import_node_path23.default.join(codexHome, "models_cache.json");
52352
53119
  const cacheRaw = readTextIfExists(cachePath);
52353
53120
  if (cacheRaw) {
52354
53121
  try {
@@ -52398,7 +53165,7 @@ function readCodexFallbackModels() {
52398
53165
  );
52399
53166
  }
52400
53167
  }
52401
- for (const slug of readKnownGptSlugsFromTomlFile(import_node_path20.default.join(codexHome, "config.toml"))) {
53168
+ for (const slug of readKnownGptSlugsFromTomlFile(import_node_path23.default.join(codexHome, "config.toml"))) {
52402
53169
  addBridgeModel(
52403
53170
  models,
52404
53171
  mapBridgeModel({
@@ -52412,11 +53179,11 @@ function readCodexFallbackModels() {
52412
53179
  })
52413
53180
  );
52414
53181
  }
52415
- const automationsDir = import_node_path20.default.join(codexHome, "automations");
53182
+ const automationsDir = import_node_path23.default.join(codexHome, "automations");
52416
53183
  try {
52417
53184
  for (const entry of import_node_fs16.default.readdirSync(automationsDir, { withFileTypes: true })) {
52418
53185
  if (!entry.isDirectory()) continue;
52419
- for (const slug of readKnownGptSlugsFromTomlFile(import_node_path20.default.join(automationsDir, entry.name, "automation.toml"))) {
53186
+ for (const slug of readKnownGptSlugsFromTomlFile(import_node_path23.default.join(automationsDir, entry.name, "automation.toml"))) {
52420
53187
  addBridgeModel(
52421
53188
  models,
52422
53189
  mapBridgeModel({
@@ -52436,7 +53203,7 @@ function readCodexFallbackModels() {
52436
53203
  return [...models.values()];
52437
53204
  }
52438
53205
  function neutralCheckoutCwd(stateDir) {
52439
- const dir = import_node_path20.default.join(stateDir, "no-checkout");
53206
+ const dir = import_node_path23.default.join(stateDir, "no-checkout");
52440
53207
  try {
52441
53208
  import_node_fs16.default.mkdirSync(dir, { recursive: true });
52442
53209
  } catch {
@@ -52906,8 +53673,8 @@ async function runOrphanWorktreeSweep(client, opts) {
52906
53673
  }
52907
53674
  }
52908
53675
  function readStateDir() {
52909
- if (process.env.CODEX_HOME) return import_node_path20.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
52910
- return import_node_path20.default.join(import_node_os11.default.homedir(), ".mrrlin", "director-bridge");
53676
+ if (process.env.CODEX_HOME) return import_node_path23.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
53677
+ return import_node_path23.default.join(import_node_os11.default.homedir(), ".mrrlin", "director-bridge");
52911
53678
  }
52912
53679
  function readAllowedOrigins() {
52913
53680
  const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
@@ -52982,7 +53749,7 @@ function createBridgeRequestListener(opts) {
52982
53749
  res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
52983
53750
  return;
52984
53751
  }
52985
- const nonce = import_node_crypto8.default.randomBytes(16).toString("base64url");
53752
+ const nonce = import_node_crypto9.default.randomBytes(16).toString("base64url");
52986
53753
  res.writeHead(200, { "content-type": "application/json" });
52987
53754
  res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
52988
53755
  return;
@@ -53033,7 +53800,11 @@ function attachBridgeWss(server, opts) {
53033
53800
  sessionId: sessionIdOf(msg),
53034
53801
  type: msg.type,
53035
53802
  ms: span.at ? Date.now() - span.at : void 0,
53036
- payload: msg
53803
+ payload: msg,
53804
+ // send() is generic across every OutgoingMessage variant; only the "event" variant ever
53805
+ // carries telemetry (task 4.5), so this is simply undefined — and omitted by BridgeLogRecordInput's
53806
+ // optional telemetry? — for every other message type.
53807
+ telemetry: msg.telemetry
53037
53808
  });
53038
53809
  socket.send(JSON.stringify(msg));
53039
53810
  };
@@ -53097,6 +53868,20 @@ function attachSeqMetadata(msg, seq, turnId) {
53097
53868
  }
53098
53869
  return msg;
53099
53870
  }
53871
+ function describeZeroOutputLimit(signal) {
53872
+ if (!signal) {
53873
+ return {
53874
+ message: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan.",
53875
+ reason: "Director turn completed without output; Codex likely hit its usage or credits limit.",
53876
+ resetAt: null
53877
+ };
53878
+ }
53879
+ return {
53880
+ message: signal.resetAt ? `Director turn completed without any output \u2014 Codex's usage/credits limit is exhausted; it resets at ${signal.resetAt}.` : "Director turn completed without any output \u2014 Codex's usage/credits limit is exhausted (no reset time reported).",
53881
+ reason: "Codex provider limit exhausted during a Director turn.",
53882
+ resetAt: signal.resetAt
53883
+ };
53884
+ }
53100
53885
  function createBridgeMessageHandler(deps) {
53101
53886
  const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
53102
53887
  const pendingTurnSessions = /* @__PURE__ */ new Set();
@@ -53263,7 +54048,7 @@ function createBridgeMessageHandler(deps) {
53263
54048
  }
53264
54049
  }
53265
54050
  socket.on("message", async (data) => {
53266
- const spanId = import_node_crypto8.default.randomUUID();
54051
+ const spanId = import_node_crypto9.default.randomUUID();
53267
54052
  if (logCtx) {
53268
54053
  logCtx.span.id = spanId;
53269
54054
  logCtx.span.at = Date.now();
@@ -53785,7 +54570,7 @@ function createBridgeMessageHandler(deps) {
53785
54570
  thread.inFlight = true;
53786
54571
  pendingTurnSessions.delete(directorSessionId);
53787
54572
  thread.replay = createReplayBuffer({
53788
- turnId: (0, import_node_crypto8.randomUUID)(),
54573
+ turnId: (0, import_node_crypto9.randomUUID)(),
53789
54574
  spanId,
53790
54575
  ...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
53791
54576
  ...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
@@ -53860,6 +54645,9 @@ function createBridgeMessageHandler(deps) {
53860
54645
  rejectTurn = (error51) => reject(error51);
53861
54646
  });
53862
54647
  let outputEvents = 0;
54648
+ let exhaustedLimitSignal = null;
54649
+ let turnTokenUsage = null;
54650
+ let promptBytes = 0;
53863
54651
  const deferredResults = [];
53864
54652
  let pokeActivity = () => {
53865
54653
  };
@@ -53869,7 +54657,12 @@ function createBridgeMessageHandler(deps) {
53869
54657
  deferredResults.push(event);
53870
54658
  return;
53871
54659
  }
53872
- if (event.type === "turn_completed" || event.type === "rate_limits" || event.type === "token_usage") {
54660
+ if (event.type === "token_usage") {
54661
+ const usage = event.usage;
54662
+ turnTokenUsage = addTurnTokenUsage(turnTokenUsage, usage);
54663
+ return;
54664
+ }
54665
+ if (event.type === "turn_completed" || event.type === "rate_limits") {
53873
54666
  return;
53874
54667
  }
53875
54668
  outputEvents += 1;
@@ -53888,6 +54681,7 @@ function createBridgeMessageHandler(deps) {
53888
54681
  sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: event.snapshot });
53889
54682
  }
53890
54683
  const signal = detectExhaustedProviderLimit(event.snapshot, Date.now());
54684
+ exhaustedLimitSignal = signal;
53891
54685
  if (signal) {
53892
54686
  deps.reportLimitPause?.("Codex provider limit exhausted during a Director turn.", signal.resetAt);
53893
54687
  }
@@ -53968,6 +54762,7 @@ ${contextPrefix}` : updateOffer : contextPrefix;
53968
54762
  const composed = composedPrefix ? `${composedPrefix}
53969
54763
 
53970
54764
  ${effectiveText}` : effectiveText;
54765
+ promptBytes = Buffer.byteLength(composed, "utf8");
53971
54766
  turnInput.push({ type: "text", text: composed, text_elements: [] });
53972
54767
  }
53973
54768
  if (imageDataUri) {
@@ -53983,18 +54778,17 @@ ${effectiveText}` : effectiveText;
53983
54778
  await Promise.race([runSequence, watchdogExpired]);
53984
54779
  deps.setCodexAuth?.("ok");
53985
54780
  if (outputEvents === 0) {
53986
- deps.reportLimitPause?.(
53987
- "Director turn completed without output; Codex likely hit its usage or credits limit.",
53988
- null
53989
- );
54781
+ const zeroOutputLimit = describeZeroOutputLimit(exhaustedLimitSignal);
54782
+ deps.reportLimitPause?.(zeroOutputLimit.reason, zeroOutputLimit.resetAt);
53990
54783
  sendInTurn({
53991
54784
  type: "error",
53992
54785
  directorSessionId,
53993
- error: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan."
54786
+ error: zeroOutputLimit.message
53994
54787
  });
53995
54788
  }
54789
+ const telemetry = turnTokenUsage !== null ? { promptBytes, usage: turnTokenUsage } : void 0;
53996
54790
  for (const event of deferredResults) {
53997
- sendInTurn({ type: "event", directorSessionId, event });
54791
+ sendInTurn({ type: "event", directorSessionId, event, telemetry });
53998
54792
  }
53999
54793
  } finally {
54000
54794
  if (thread.replay && (thread.replay.state === "live" || thread.replay.state === "detached")) {
@@ -54130,6 +54924,9 @@ function scanForOtherBridges() {
54130
54924
  }
54131
54925
  async function startDirectorBridge() {
54132
54926
  const config2 = parseConfig();
54927
+ if (!process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT?.trim()) {
54928
+ throw new Error("MRRLIN_TELEMETRY_DEFAULT_PROJECT must be set (non-empty) at bridge startup.");
54929
+ }
54133
54930
  const turnLock = createTurnLock();
54134
54931
  let lastTurnEndedAt = Date.now();
54135
54932
  const wrappedTurnLock = {
@@ -54266,8 +55063,8 @@ async function startDirectorBridge() {
54266
55063
  codexCwd: config2.codexCwd,
54267
55064
  codexExecutable: config2.codexExecutable,
54268
55065
  checkoutRegistry,
54269
- worktreeRoot: import_node_path20.default.join(config2.stateDir, "worktrees"),
54270
- locksDir: import_node_path20.default.join(config2.stateDir, "locks"),
55066
+ worktreeRoot: import_node_path23.default.join(config2.stateDir, "worktrees"),
55067
+ locksDir: import_node_path23.default.join(config2.stateDir, "locks"),
54271
55068
  // Wire the executor server for code-execution runs. Each run gets its own provider process
54272
55069
  // (app-server for codex, a resident CLI child for claude) at the run worktree, running
54273
55070
  // UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
@@ -54311,7 +55108,7 @@ async function startDirectorBridge() {
54311
55108
  // egressDomains is retained in the seam signature (verification-turn.ts still computes the
54312
55109
  // env host) but no longer constrains anything — the executor is unrestricted.
54313
55110
  startSandbox: async (_egressDomains, providerId) => {
54314
- const cwd = import_node_fs16.default.mkdtempSync(import_node_path20.default.join(import_node_os11.default.tmpdir(), "mrrlin-verify-"));
55111
+ const cwd = import_node_fs16.default.mkdtempSync(import_node_path23.default.join(import_node_os11.default.tmpdir(), "mrrlin-verify-"));
54315
55112
  let executor;
54316
55113
  try {
54317
55114
  executor = await startExecutorServer({ worktree: cwd, provider: providerId });
@@ -54356,12 +55153,13 @@ async function startDirectorBridge() {
54356
55153
  };
54357
55154
  const sessionSinks = createSessionSinkRegistry();
54358
55155
  const tombstones = /* @__PURE__ */ new Map();
54359
- const bridgeInstanceId = (0, import_node_crypto8.randomUUID)();
55156
+ const bridgeInstanceId = (0, import_node_crypto9.randomUUID)();
54360
55157
  const asyncConsumerDeps = {
54361
55158
  client,
54362
55159
  run: wrappedTurnLock.run,
54363
55160
  cwd: config2.codexCwd ?? process.cwd(),
54364
55161
  codexExecutable: config2.codexExecutable,
55162
+ stateDir: config2.stateDir,
54365
55163
  staleSeconds,
54366
55164
  touchIntervalMs: Math.min(DEFAULT_TOUCH_INTERVAL_MS, Math.floor(staleSeconds * 1e3 / 2)),
54367
55165
  wake: (slug, directorSessionId, body, deliveryKind) => {
@@ -54511,7 +55309,7 @@ async function startDirectorBridge() {
54511
55309
  fileUpdateInboxItem: async (projectSlug) => {
54512
55310
  const body = selfUpdateHandle.updateInboxBody();
54513
55311
  if (!body) return;
54514
- const id = `II-MCPUPD-${(0, import_node_crypto8.randomUUID)()}`;
55312
+ const id = `II-MCPUPD-${(0, import_node_crypto9.randomUUID)()}`;
54515
55313
  try {
54516
55314
  const row = await client.createInboxItem(projectSlug, { id, kind: "info", body });
54517
55315
  process.stderr.write(
@@ -54541,7 +55339,7 @@ async function startDirectorBridge() {
54541
55339
  const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
54542
55340
  let bridgeBinShaShort = "unknown00000";
54543
55341
  try {
54544
- bridgeBinShaShort = import_node_crypto8.default.createHash("sha256").update(import_node_fs16.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
55342
+ bridgeBinShaShort = import_node_crypto9.default.createHash("sha256").update(import_node_fs16.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
54545
55343
  } catch {
54546
55344
  }
54547
55345
  attachBridgeWss(server, {
@@ -54628,7 +55426,10 @@ async function startDirectorBridge() {
54628
55426
  dispatchServer.on("error", reject);
54629
55427
  dispatchServer.listen(workerPort(), "127.0.0.1", () => resolve());
54630
55428
  });
54631
- const bridgeHealth = new BridgeHealthTracker({ stateDir: config2.stateDir });
55429
+ const bridgeHealth = new BridgeHealthTracker({
55430
+ stateDir: config2.stateDir,
55431
+ hasLiveTurn: () => wrappedTurnLock.activeCount() > 0 || (resumableCountHolder.fn?.() ?? 0) > 0
55432
+ });
54632
55433
  const runTrackedSweep = async (id, label, fn) => {
54633
55434
  try {
54634
55435
  await fn();
@@ -54665,8 +55466,8 @@ async function startDirectorBridge() {
54665
55466
  );
54666
55467
  void runOrphanWorktreeSweep(client, {
54667
55468
  checkoutRegistry,
54668
- worktreeRoot: import_node_path20.default.join(config2.stateDir, "worktrees"),
54669
- locksDir: import_node_path20.default.join(config2.stateDir, "locks")
55469
+ worktreeRoot: import_node_path23.default.join(config2.stateDir, "worktrees"),
55470
+ locksDir: import_node_path23.default.join(config2.stateDir, "locks")
54670
55471
  });
54671
55472
  {
54672
55473
  const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
@@ -54707,6 +55508,28 @@ async function startDirectorBridge() {
54707
55508
  });
54708
55509
  }
54709
55510
  }
55511
+ void (async () => {
55512
+ try {
55513
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
55514
+ await foldClosedDays(config2.stateDir, today);
55515
+ await uploadPendingDays(config2.stateDir, client, bridgeHealth, {
55516
+ cwd: config2.codexCwd ?? process.cwd(),
55517
+ codexExecutable: config2.codexExecutable,
55518
+ timeoutMs: readEnvInt("MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS", 60) * 1e3
55519
+ });
55520
+ await prune(config2.stateDir, {
55521
+ ageDays: readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30),
55522
+ budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024)
55523
+ });
55524
+ } catch (error51) {
55525
+ bridgeLogger.logOut({
55526
+ spanId: "gc",
55527
+ sessionId: null,
55528
+ type: "<telemetry-pipeline-error>",
55529
+ payload: { error: error51 instanceof Error ? error51.message : String(error51) }
55530
+ });
55531
+ }
55532
+ })();
54710
55533
  scheduleClaimLoop();
54711
55534
  }, claimIntervalMs());
54712
55535
  claimTimer.unref?.();
@@ -54927,7 +55750,7 @@ function timingSafeTokenEqual(provided, expected) {
54927
55750
  const a = Buffer.from(provided);
54928
55751
  const b = Buffer.from(expected);
54929
55752
  if (a.length !== b.length) return false;
54930
- return import_node_crypto8.default.timingSafeEqual(a, b);
55753
+ return import_node_crypto9.default.timingSafeEqual(a, b);
54931
55754
  }
54932
55755
  function readDispatchBody(req) {
54933
55756
  return new Promise((resolve, reject) => {
@@ -54949,14 +55772,14 @@ function readDispatchBody(req) {
54949
55772
  function readOrCreateBridgeToken(stateDir) {
54950
55773
  const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
54951
55774
  if (explicit) return explicit;
54952
- const tokenPath = import_node_path20.default.join(stateDir, "token.txt");
55775
+ const tokenPath = import_node_path23.default.join(stateDir, "token.txt");
54953
55776
  try {
54954
55777
  const existing = import_node_fs16.default.readFileSync(tokenPath, "utf8").trim();
54955
55778
  if (existing) return existing;
54956
55779
  } catch {
54957
55780
  }
54958
55781
  import_node_fs16.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
54959
- const token = import_node_crypto8.default.randomBytes(32).toString("base64url");
55782
+ const token = import_node_crypto9.default.randomBytes(32).toString("base64url");
54960
55783
  import_node_fs16.default.writeFileSync(tokenPath, `${token}
54961
55784
  `, { mode: 384 });
54962
55785
  return token;
@@ -58341,36 +59164,36 @@ var StdioServerTransport = class {
58341
59164
  };
58342
59165
 
58343
59166
  // src/tools.ts
58344
- var import_node_crypto11 = require("node:crypto");
58345
- var import_promises5 = require("node:fs/promises");
58346
- var import_node_path22 = __toESM(require("node:path"), 1);
59167
+ var import_node_crypto12 = require("node:crypto");
59168
+ var import_promises10 = require("node:fs/promises");
59169
+ var import_node_path26 = __toESM(require("node:path"), 1);
58347
59170
  var import_node_os12 = __toESM(require("node:os"), 1);
58348
59171
 
58349
59172
  // ../../packages/wiki/dist/index.js
58350
- var import_promises4 = __toESM(require("node:fs/promises"), 1);
58351
- var import_node_path21 = __toESM(require("node:path"), 1);
59173
+ var import_promises8 = __toESM(require("node:fs/promises"), 1);
59174
+ var import_node_path24 = __toESM(require("node:path"), 1);
58352
59175
  var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
58353
59176
  function toPosixPath(input) {
58354
- return input.split(import_node_path21.default.sep).join("/");
59177
+ return input.split(import_node_path24.default.sep).join("/");
58355
59178
  }
58356
59179
  function slugifyWikiSegment(input) {
58357
59180
  return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
58358
59181
  }
58359
59182
  async function pathExists3(input) {
58360
59183
  try {
58361
- await import_promises4.default.access(input);
59184
+ await import_promises8.default.access(input);
58362
59185
  return true;
58363
59186
  } catch {
58364
59187
  return false;
58365
59188
  }
58366
59189
  }
58367
59190
  async function findWorkspaceRoot(start = process.cwd()) {
58368
- let current2 = import_node_path21.default.resolve(start);
59191
+ let current2 = import_node_path24.default.resolve(start);
58369
59192
  while (true) {
58370
- if (await pathExists3(import_node_path21.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path21.default.join(current2, "docs"))) {
59193
+ if (await pathExists3(import_node_path24.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path24.default.join(current2, "docs"))) {
58371
59194
  return current2;
58372
59195
  }
58373
- const parent = import_node_path21.default.dirname(current2);
59196
+ const parent = import_node_path24.default.dirname(current2);
58374
59197
  if (parent === current2) {
58375
59198
  throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
58376
59199
  }
@@ -58379,28 +59202,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
58379
59202
  }
58380
59203
  async function resolveDocsRoot(input) {
58381
59204
  if (input) {
58382
- return import_node_path21.default.resolve(input);
59205
+ return import_node_path24.default.resolve(input);
58383
59206
  }
58384
59207
  if (process.env.MRRLIN_DOCS_ROOT) {
58385
- return import_node_path21.default.resolve(process.env.MRRLIN_DOCS_ROOT);
59208
+ return import_node_path24.default.resolve(process.env.MRRLIN_DOCS_ROOT);
58386
59209
  }
58387
- return import_node_path21.default.join(await findWorkspaceRoot(), "docs");
59210
+ return import_node_path24.default.join(await findWorkspaceRoot(), "docs");
58388
59211
  }
58389
59212
  async function resolveIndexPath(input) {
58390
59213
  if (input) {
58391
- return import_node_path21.default.resolve(input);
59214
+ return import_node_path24.default.resolve(input);
58392
59215
  }
58393
59216
  if (process.env.MRRLIN_WIKI_INDEX_PATH) {
58394
- return import_node_path21.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
59217
+ return import_node_path24.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
58395
59218
  }
58396
59219
  const workspaceRoot = await findWorkspaceRoot();
58397
- return import_node_path21.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
59220
+ return import_node_path24.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
58398
59221
  }
58399
59222
  async function walkMarkdownFiles(root, dir = root) {
58400
- const entries = await import_promises4.default.readdir(dir, { withFileTypes: true });
59223
+ const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
58401
59224
  const files = [];
58402
59225
  for (const entry of entries) {
58403
- const absolute = import_node_path21.default.join(dir, entry.name);
59226
+ const absolute = import_node_path24.default.join(dir, entry.name);
58404
59227
  if (entry.isDirectory()) {
58405
59228
  files.push(...await walkMarkdownFiles(root, absolute));
58406
59229
  continue;
@@ -58419,7 +59242,7 @@ function parseTitle(markdown, sourcePath) {
58419
59242
  return title;
58420
59243
  }
58421
59244
  function documentFromFile(docsRoot, absolutePath, markdown) {
58422
- const relativePath = toPosixPath(import_node_path21.default.relative(docsRoot, absolutePath));
59245
+ const relativePath = toPosixPath(import_node_path24.default.relative(docsRoot, absolutePath));
58423
59246
  const [section, fileName] = relativePath.split("/");
58424
59247
  if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
58425
59248
  return null;
@@ -58439,7 +59262,7 @@ async function listWikiDocuments(options = {}) {
58439
59262
  const files = await walkMarkdownFiles(docsRoot);
58440
59263
  const documents = [];
58441
59264
  for (const file2 of files) {
58442
- const markdown = await import_promises4.default.readFile(file2, "utf8");
59265
+ const markdown = await import_promises8.default.readFile(file2, "utf8");
58443
59266
  const document2 = documentFromFile(docsRoot, file2, markdown);
58444
59267
  if (document2) {
58445
59268
  documents.push(document2);
@@ -58493,7 +59316,7 @@ async function buildWikiKnowledgeIndex(options = {}) {
58493
59316
  }
58494
59317
  async function loadBuiltWikiKnowledgeIndex(indexPath) {
58495
59318
  const resolvedIndexPath = await resolveIndexPath(indexPath);
58496
- const raw = await import_promises4.default.readFile(resolvedIndexPath, "utf8");
59319
+ const raw = await import_promises8.default.readFile(resolvedIndexPath, "utf8");
58497
59320
  return wikiKnowledgeIndexSchema.parse(JSON.parse(raw));
58498
59321
  }
58499
59322
  function tokenize(input) {
@@ -58584,9 +59407,9 @@ async function runCodeGate(_target, deps) {
58584
59407
  accepted
58585
59408
  );
58586
59409
  }
58587
- let gate;
59410
+ let gate2;
58588
59411
  try {
58589
- gate = await deps.fastGate();
59412
+ gate2 = await deps.fastGate();
58590
59413
  } catch (gateErr) {
58591
59414
  await deps.restore(ref);
58592
59415
  throw new CodeGateUnfixableError(
@@ -58594,7 +59417,7 @@ async function runCodeGate(_target, deps) {
58594
59417
  accepted
58595
59418
  );
58596
59419
  }
58597
- if (!gate.ok) {
59420
+ if (!gate2.ok) {
58598
59421
  await deps.restore(ref);
58599
59422
  throw new CodeGateUnfixableError("fast-gate red after revision", accepted);
58600
59423
  }
@@ -59031,7 +59854,7 @@ async function resolveActiveRunHead(input, deps) {
59031
59854
  }
59032
59855
 
59033
59856
  // src/async-tools/consensus.ts
59034
- var import_node_crypto9 = require("node:crypto");
59857
+ var import_node_crypto10 = require("node:crypto");
59035
59858
 
59036
59859
  // src/consensus/question-similarity.ts
59037
59860
  var SUPPRESSION_SIMILARITY_THRESHOLD = 0.6;
@@ -59307,9 +60130,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
59307
60130
  }
59308
60131
  if (taskId) {
59309
60132
  const scopeId = taskId;
59310
- const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto9.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
60133
+ const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto10.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
59311
60134
  for (const clarification of toFile) {
59312
- const id = `II-${scopeId}-gate-${(0, import_node_crypto9.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
60135
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto10.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
59313
60136
  try {
59314
60137
  const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
59315
60138
  await ctx.client.createInboxItem(input.projectSlug, {
@@ -59327,9 +60150,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
59327
60150
  filedQuestionCount = toFile.length;
59328
60151
  } else if (planId) {
59329
60152
  const scopeId = planId;
59330
- const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto9.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
60153
+ const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto10.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
59331
60154
  for (const clarification of toFile) {
59332
- const id = `II-${scopeId}-gate-${(0, import_node_crypto9.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
60155
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto10.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
59333
60156
  try {
59334
60157
  const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
59335
60158
  await ctx.client.createInboxItem(input.projectSlug, {
@@ -59353,7 +60176,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
59353
60176
  taskId: page.taskId ?? null
59354
60177
  });
59355
60178
  const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
59356
- const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto9.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
60179
+ const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto10.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
59357
60180
  const reviewAgainAvailable = !taskInboxItems.some(
59358
60181
  (item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
59359
60182
  );
@@ -59923,8 +60746,159 @@ function createIntentCheckDescriptor() {
59923
60746
  }
59924
60747
  var intentCheckDescriptor = createIntentCheckDescriptor();
59925
60748
 
60749
+ // src/evidence/assembler.ts
60750
+ var import_promises9 = require("node:fs/promises");
60751
+ var import_node_path25 = require("node:path");
60752
+ function evidenceDedupKey(sessionId, reportId) {
60753
+ return `${sessionId}:${reportId}`;
60754
+ }
60755
+ function isRecord3(v) {
60756
+ return v !== null && typeof v === "object";
60757
+ }
60758
+ async function readDayLines(stateDir, day, sessionId) {
60759
+ let raw;
60760
+ try {
60761
+ raw = await (0, import_promises9.readFile)((0, import_node_path25.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
60762
+ } catch {
60763
+ return [];
60764
+ }
60765
+ const kept = [];
60766
+ for (const line of raw.split("\n")) {
60767
+ if (!line.trim()) continue;
60768
+ let rec;
60769
+ try {
60770
+ rec = JSON.parse(line);
60771
+ } catch {
60772
+ continue;
60773
+ }
60774
+ if (!isRecord3(rec) || !isRecord3(rec.payload)) continue;
60775
+ if (rec.payload.directorSessionId !== sessionId) continue;
60776
+ kept.push(rec);
60777
+ }
60778
+ return kept;
60779
+ }
60780
+ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
60781
+ const daysRead = await findSessionDays(stateDir, sessionId);
60782
+ const allLines = [];
60783
+ for (const day of daysRead) {
60784
+ allLines.push(...await readDayLines(stateDir, day, sessionId));
60785
+ }
60786
+ const groups = /* @__PURE__ */ new Map();
60787
+ for (const line of allLines) {
60788
+ const turnKey = line.payload?.turnId ?? null;
60789
+ const bucket = groups.get(turnKey);
60790
+ if (bucket) bucket.push(line);
60791
+ else groups.set(turnKey, [line]);
60792
+ }
60793
+ const orderedGroups = [...groups.entries()].sort(([, a], [, b]) => {
60794
+ const aTs = a[0]?.ts ?? "";
60795
+ const bTs = b[0]?.ts ?? "";
60796
+ return aTs < bTs ? -1 : aTs > bTs ? 1 : 0;
60797
+ });
60798
+ const steps = [];
60799
+ const turnIds = [];
60800
+ for (const [turnId, groupLines] of orderedGroups) {
60801
+ const ordered = [...groupLines].sort((a, b) => (a.payload?.seq ?? 0) - (b.payload?.seq ?? 0));
60802
+ const groupHasFailedLifecycle = ordered.some(
60803
+ (l) => l.projection?.kind === "turn_lifecycle" && l.projection.lifecycle === "failed"
60804
+ );
60805
+ const resultByToolId = /* @__PURE__ */ new Map();
60806
+ for (const line of ordered) {
60807
+ if (line.projection?.kind !== "tool_result") continue;
60808
+ const toolId = line.payload?.event?.tool?.id;
60809
+ if (typeof toolId === "string") resultByToolId.set(toolId, line);
60810
+ }
60811
+ let groupProducedStep = false;
60812
+ for (const line of ordered) {
60813
+ if (line.projection?.kind !== "tool_use") continue;
60814
+ const rawToolId = line.payload?.event?.tool?.id;
60815
+ const paired = typeof rawToolId === "string" ? resultByToolId.get(rawToolId) : void 0;
60816
+ const toolName = line.projection.toolName ?? line.payload?.event?.tool?.name ?? "";
60817
+ const ms = line.projection.ms ?? 0;
60818
+ const outcome = paired?.projection?.kind === "tool_result" ? paired.projection.outcome ?? "unknown" : "unknown";
60819
+ const step = { toolName, ms, outcome };
60820
+ if (paired?.projection?.kind === "tool_result" && paired.projection.exitCode !== void 0) {
60821
+ step.exitCode = paired.projection.exitCode;
60822
+ }
60823
+ const needsExcerpt = outcome === "error" || groupHasFailedLifecycle;
60824
+ const rawContent = paired?.payload?.event?.content;
60825
+ if (needsExcerpt && typeof rawContent === "string") {
60826
+ step.excerpt = redact(rawContent).slice(0, 8192);
60827
+ }
60828
+ steps.push(step);
60829
+ groupProducedStep = true;
60830
+ }
60831
+ if (groupProducedStep && turnId !== null) turnIds.push(turnId);
60832
+ }
60833
+ let windowPruned = false;
60834
+ try {
60835
+ const raw = await (0, import_promises9.readFile)((0, import_node_path25.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
60836
+ outer: for (const line of raw.split("\n")) {
60837
+ if (!line.trim()) continue;
60838
+ let rec;
60839
+ try {
60840
+ rec = JSON.parse(line);
60841
+ } catch {
60842
+ continue;
60843
+ }
60844
+ if (!isRecord3(rec) || !Array.isArray(rec.daysRemoved)) continue;
60845
+ for (const removedDay of rec.daysRemoved) {
60846
+ if (daysRead.includes(removedDay)) {
60847
+ windowPruned = true;
60848
+ break outer;
60849
+ }
60850
+ }
60851
+ }
60852
+ } catch {
60853
+ }
60854
+ const provisional = { reportId, sessionId, turnIds, daysRead, windowPruned, steps, gateMarker: "gated" };
60855
+ const prose = [];
60856
+ steps.forEach((step, i) => {
60857
+ if (step.excerpt !== void 0) prose.push({ path: `steps.${i}.excerpt`, value: step.excerpt });
60858
+ });
60859
+ const gateResult = await gate(provisional, prose, gateCtx);
60860
+ return { ...gateResult.artifact, gateMarker: gateResult.gated ? "gated" : "projection-only" };
60861
+ }
60862
+
60863
+ // src/async-tools/report-evidence.ts
60864
+ function gateTimeoutMs() {
60865
+ const raw = (process.env.MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS ?? "").trim();
60866
+ const parsed = Number.parseInt(raw, 10);
60867
+ const seconds = Number.isInteger(parsed) && parsed > 0 ? parsed : 60;
60868
+ return seconds * 1e3;
60869
+ }
60870
+ var REPORT_EVIDENCE_TOOL_NAME = "report-evidence";
60871
+ async function runReportEvidence(ctx, input) {
60872
+ const gateCtx = {
60873
+ cwd: ctx.cwd,
60874
+ codexExecutable: ctx.codexExecutable,
60875
+ timeoutMs: gateTimeoutMs(),
60876
+ runExec: ctx.gateRunExec
60877
+ };
60878
+ const artifact = await assembleEvidence(ctx.stateDir, input.directorSessionId, input.reportId, gateCtx);
60879
+ return { kind: "done", resultJson: JSON.stringify(artifact), finalReviewedHash: null };
60880
+ }
60881
+ function onComplete5(outcome, input) {
60882
+ if (outcome.kind === "done") {
60883
+ return { kind: "info", body: `Evidence assembled for report ${input.reportId}.`, suppressInbox: true };
60884
+ }
60885
+ return { kind: "info", body: `Evidence assembly failed for report ${input.reportId}: ${outcome.error}` };
60886
+ }
60887
+ function createReportEvidenceDescriptor() {
60888
+ return {
60889
+ toolName: REPORT_EVIDENCE_TOOL_NAME,
60890
+ dedupKey: (input) => evidenceDedupKey(input.directorSessionId, input.reportId),
60891
+ run: runReportEvidence,
60892
+ onComplete: onComplete5,
60893
+ // Runs long after the reporting user's turn ended, sometimes with no live session left to wake.
60894
+ wakeDirector: false,
60895
+ locationDependent: true
60896
+ };
60897
+ }
60898
+ var reportEvidenceDescriptor = createReportEvidenceDescriptor();
60899
+
59926
60900
  // src/async-tools/enqueue.ts
59927
- var import_node_crypto10 = __toESM(require("node:crypto"), 1);
60901
+ var import_node_crypto11 = __toESM(require("node:crypto"), 1);
59928
60902
  async function enqueueAsyncTool(client, descriptor2, input) {
59929
60903
  if (descriptor2.cachedResult) {
59930
60904
  const cached2 = await descriptor2.cachedResult(client, input);
@@ -59937,7 +60911,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
59937
60911
  if (active) {
59938
60912
  return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
59939
60913
  }
59940
- const jobId = `AJ-${import_node_crypto10.default.randomUUID()}`;
60914
+ const jobId = `AJ-${import_node_crypto11.default.randomUUID()}`;
59941
60915
  try {
59942
60916
  await client.createAsyncJob(input.projectSlug, {
59943
60917
  id: jobId,
@@ -60506,6 +61480,7 @@ registerAsyncTool(consensusDescriptor);
60506
61480
  registerAsyncTool(deliverableConsensusDescriptor);
60507
61481
  registerAsyncTool(draftSpecDescriptor);
60508
61482
  registerAsyncTool(intentCheckDescriptor);
61483
+ registerAsyncTool(reportEvidenceDescriptor);
60509
61484
  var projectScopedSchema = external_exports.object({ projectSlug: mrrlinProjectSlugSchema });
60510
61485
  var taskScopedSchema = projectScopedSchema.extend({ taskId: mrrlinTaskIdSchema });
60511
61486
  var planScopedSchema = projectScopedSchema.extend({ planId: mrrlinPlanIdSchema });
@@ -61516,7 +62491,7 @@ function createMrrlinTools(options) {
61516
62491
  "PRODUCED_URL_RECORD_FAILED",
61517
62492
  "Unable to record produced URL.",
61518
62493
  async (c, { projectSlug, runId, url: url2, label }) => {
61519
- const id = `EA-pu-${(0, import_node_crypto11.randomBytes)(4).toString("hex")}`;
62494
+ const id = `EA-pu-${(0, import_node_crypto12.randomBytes)(4).toString("hex")}`;
61520
62495
  const payload = label ? { url: url2, label } : { url: url2 };
61521
62496
  return await c.appendExecutionArtifact(projectSlug, runId, {
61522
62497
  id,
@@ -61590,7 +62565,7 @@ function createMrrlinTools(options) {
61590
62565
  "ARTIFACT_FILE_UPLOAD_FAILED",
61591
62566
  "Unable to upload artifact file.",
61592
62567
  async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
61593
- const extension2 = import_node_path22.default.extname(filePath).toLowerCase();
62568
+ const extension2 = import_node_path26.default.extname(filePath).toLowerCase();
61594
62569
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
61595
62570
  if (!contentType) {
61596
62571
  throw new McpToolCodedError(
@@ -61598,7 +62573,7 @@ function createMrrlinTools(options) {
61598
62573
  `Unsupported artifact extension '${extension2}'. Allowed: ${Object.keys(ARTIFACT_EXTENSION_TYPES).join(", ")}.`
61599
62574
  );
61600
62575
  }
61601
- const stats = await (0, import_promises5.stat)(filePath);
62576
+ const stats = await (0, import_promises10.stat)(filePath);
61602
62577
  if (stats.size > MRRLIN_ARTIFACT_FILE_MAX_BYTES) {
61603
62578
  throw new McpToolCodedError(
61604
62579
  "ARTIFACT_FILE_TOO_LARGE",
@@ -61611,14 +62586,14 @@ function createMrrlinTools(options) {
61611
62586
  "File is empty (0 bytes); write content before uploading."
61612
62587
  );
61613
62588
  }
61614
- const bytes3 = new Uint8Array(await (0, import_promises5.readFile)(filePath));
62589
+ const bytes3 = new Uint8Array(await (0, import_promises10.readFile)(filePath));
61615
62590
  if (bytes3.byteLength > MRRLIN_ARTIFACT_FILE_MAX_BYTES) {
61616
62591
  throw new McpToolCodedError(
61617
62592
  "ARTIFACT_FILE_TOO_LARGE",
61618
62593
  "Artifact exceeds 5MB; split or summarize instead."
61619
62594
  );
61620
62595
  }
61621
- const filename = import_node_path22.default.basename(filePath);
62596
+ const filename = import_node_path26.default.basename(filePath);
61622
62597
  return uploadArtifactBytes(c, {
61623
62598
  bytes: bytes3,
61624
62599
  class: artifactClass,
@@ -61643,7 +62618,7 @@ function createMrrlinTools(options) {
61643
62618
  `Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
61644
62619
  );
61645
62620
  }
61646
- const extension2 = import_node_path22.default.extname(filename).toLowerCase();
62621
+ const extension2 = import_node_path26.default.extname(filename).toLowerCase();
61647
62622
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
61648
62623
  if (!contentType) {
61649
62624
  throw new McpToolCodedError(
@@ -61710,7 +62685,7 @@ function createMrrlinTools(options) {
61710
62685
  "LOCAL_CHECKOUT_REGISTER_FAILED",
61711
62686
  "Unable to register local checkout.",
61712
62687
  async (_c, { projectSlug, path: checkoutPath, repo }) => {
61713
- const stateDir = process.env.CODEX_HOME ? import_node_path22.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path22.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
62688
+ const stateDir = process.env.CODEX_HOME ? import_node_path26.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path26.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
61714
62689
  const registry3 = new CheckoutRegistry(stateDir);
61715
62690
  const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os12.default.hostname());
61716
62691
  if (!result.ok) {
@@ -61950,7 +62925,7 @@ function runSetCredential(args) {
61950
62925
 
61951
62926
  // src/install-service.ts
61952
62927
  var import_node_os13 = __toESM(require("node:os"), 1);
61953
- var import_node_path23 = __toESM(require("node:path"), 1);
62928
+ var import_node_path27 = __toESM(require("node:path"), 1);
61954
62929
  function installService(deps) {
61955
62930
  if (!deps.hasSecret()) {
61956
62931
  deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
@@ -61972,7 +62947,7 @@ function installService(deps) {
61972
62947
  return { ok: false };
61973
62948
  }
61974
62949
  const resolvedBins = bins.filter((b) => b !== null);
61975
- const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path23.default.dirname(b)))).join(":");
62950
+ const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path27.default.dirname(b)))).join(":");
61976
62951
  const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
61977
62952
  const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
61978
62953
  const text = renderEcosystemConfig({
@@ -61983,7 +62958,7 @@ function installService(deps) {
61983
62958
  staging,
61984
62959
  apiBaseUrl
61985
62960
  });
61986
- const ecoPath = import_node_path23.default.join(home, ".mrrlin", "ecosystem.config.cjs");
62961
+ const ecoPath = import_node_path27.default.join(home, ".mrrlin", "ecosystem.config.cjs");
61987
62962
  deps.writeFile(ecoPath, text);
61988
62963
  const start = deps.runPm2(["startOrReload", ecoPath]);
61989
62964
  if (start.code !== 0) {
@@ -62013,18 +62988,18 @@ function uninstallService(deps) {
62013
62988
  }
62014
62989
 
62015
62990
  // src/uninstall-codex.ts
62016
- var import_promises6 = __toESM(require("node:fs/promises"), 1);
62991
+ var import_promises11 = __toESM(require("node:fs/promises"), 1);
62017
62992
  var import_node_os14 = __toESM(require("node:os"), 1);
62018
- var import_node_path24 = __toESM(require("node:path"), 1);
62993
+ var import_node_path28 = __toESM(require("node:path"), 1);
62019
62994
  var toml3 = __toESM(require_toml(), 1);
62020
62995
  function resolveCodexHome3(options) {
62021
62996
  if (options.codexHome) return options.codexHome;
62022
62997
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
62023
- return import_node_path24.default.join(options.homeDir ?? import_node_os14.default.homedir(), ".codex");
62998
+ return import_node_path28.default.join(options.homeDir ?? import_node_os14.default.homedir(), ".codex");
62024
62999
  }
62025
63000
  async function pathExists4(target) {
62026
63001
  try {
62027
- await import_promises6.default.access(target);
63002
+ await import_promises11.default.access(target);
62028
63003
  return true;
62029
63004
  } catch {
62030
63005
  return false;
@@ -62033,13 +63008,13 @@ async function pathExists4(target) {
62033
63008
  var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
62034
63009
  async function uninstallCodex(options = {}) {
62035
63010
  const codexHome = resolveCodexHome3(options);
62036
- const configPath = import_node_path24.default.join(codexHome, "config.toml");
63011
+ const configPath = import_node_path28.default.join(codexHome, "config.toml");
62037
63012
  const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
62038
63013
  if (!await pathExists4(configPath)) {
62039
63014
  return { action: "missing", configPath, prompts: await removePrompts() };
62040
63015
  }
62041
- const realPath = await import_promises6.default.realpath(configPath).catch(() => configPath);
62042
- const existing = await import_promises6.default.readFile(realPath, "utf8");
63016
+ const realPath = await import_promises11.default.realpath(configPath).catch(() => configPath);
63017
+ const existing = await import_promises11.default.readFile(realPath, "utf8");
62043
63018
  let parsed = null;
62044
63019
  try {
62045
63020
  parsed = toml3.parse(existing);
@@ -62056,17 +63031,17 @@ async function uninstallCodex(options = {}) {
62056
63031
  return { action: "noop", configPath: realPath, prompts: await removePrompts() };
62057
63032
  }
62058
63033
  const stripped = existing.replace(MRRLIN_BLOCK_RE, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
62059
- await import_promises6.default.writeFile(realPath, stripped, { mode: 384 });
63034
+ await import_promises11.default.writeFile(realPath, stripped, { mode: 384 });
62060
63035
  return { action: "removed", configPath: realPath, prompts: await removePrompts() };
62061
63036
  }
62062
63037
  async function uninstallPrompts(codexHome, names) {
62063
63038
  if (names.length === 0) return [];
62064
- const promptsDir = import_node_path24.default.join(codexHome, "prompts");
63039
+ const promptsDir = import_node_path28.default.join(codexHome, "prompts");
62065
63040
  const out = [];
62066
63041
  for (const name of names) {
62067
- const promptPath = import_node_path24.default.join(promptsDir, `${name}.md`);
63042
+ const promptPath = import_node_path28.default.join(promptsDir, `${name}.md`);
62068
63043
  try {
62069
- await import_promises6.default.unlink(promptPath);
63044
+ await import_promises11.default.unlink(promptPath);
62070
63045
  out.push({ name, action: "removed", promptPath });
62071
63046
  } catch (error51) {
62072
63047
  const code = error51?.code;
@@ -62080,6 +63055,129 @@ async function uninstallPrompts(codexHome, names) {
62080
63055
  return out;
62081
63056
  }
62082
63057
 
63058
+ // src/extract/command.ts
63059
+ var import_promises12 = require("node:fs/promises");
63060
+ var import_node_path29 = require("node:path");
63061
+ function parseArgs(args) {
63062
+ const map2 = /* @__PURE__ */ new Map();
63063
+ for (let i = 0; i < args.length; i++) {
63064
+ const arg = args[i];
63065
+ if (arg?.startsWith("--")) {
63066
+ const key = arg.slice(2);
63067
+ const next = args[i + 1];
63068
+ if (next && !next.startsWith("--")) {
63069
+ map2.set(key, next);
63070
+ i++;
63071
+ }
63072
+ }
63073
+ }
63074
+ return map2;
63075
+ }
63076
+ function isRecord4(v) {
63077
+ return v !== null && typeof v === "object";
63078
+ }
63079
+ async function runExtract(args, deps) {
63080
+ const flags = parseArgs(args);
63081
+ const sessionId = flags.get("session");
63082
+ const projectSlug = flags.get("project");
63083
+ const outPath = flags.get("out") ?? null;
63084
+ if (!sessionId || !projectSlug) {
63085
+ const missing = [];
63086
+ if (!sessionId) missing.push("--session");
63087
+ if (!projectSlug) missing.push("--project");
63088
+ const usage = `Usage: mrrlin-mcp extract --session <directorSessionId> --project <projectSlug> [--out <path>]
63089
+ Missing required flag(s): ${missing.join(
63090
+ ", "
63091
+ )}`;
63092
+ return { ok: false, message: usage, deliveredArtifactId: null };
63093
+ }
63094
+ const days = await findSessionDays(deps.stateDir, sessionId);
63095
+ const matchingLines = [];
63096
+ for (const day of days) {
63097
+ const logPath = (0, import_node_path29.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
63098
+ let raw;
63099
+ try {
63100
+ raw = await (0, import_promises12.readFile)(logPath, "utf8");
63101
+ } catch {
63102
+ continue;
63103
+ }
63104
+ const lines2 = raw.split("\n");
63105
+ for (const line of lines2) {
63106
+ if (!line.trim()) continue;
63107
+ let parsed;
63108
+ try {
63109
+ parsed = JSON.parse(line);
63110
+ } catch {
63111
+ continue;
63112
+ }
63113
+ const payload = isRecord4(parsed) ? parsed.payload : void 0;
63114
+ if (isRecord4(payload) && payload.directorSessionId === sessionId) {
63115
+ matchingLines.push(line);
63116
+ }
63117
+ }
63118
+ }
63119
+ const maxBytes = deps.maxBytes ?? MRRLIN_ARTIFACT_FILE_MAX_BYTES;
63120
+ const cappedLines = [];
63121
+ let totalBytes = 0;
63122
+ for (const rawLine of matchingLines) {
63123
+ const redacted = redact(rawLine);
63124
+ const lineWithNewline = redacted + "\n";
63125
+ const prospective = totalBytes + Buffer.byteLength(lineWithNewline, "utf8");
63126
+ if (prospective > maxBytes) {
63127
+ break;
63128
+ }
63129
+ cappedLines.push(redacted);
63130
+ totalBytes = prospective;
63131
+ }
63132
+ const outputText = cappedLines.join("\n");
63133
+ if (outPath) {
63134
+ await (0, import_promises12.writeFile)(outPath, outputText, "utf8");
63135
+ return {
63136
+ ok: true,
63137
+ message: `Wrote extract to ${outPath}`,
63138
+ deliveredArtifactId: null
63139
+ };
63140
+ }
63141
+ const firstDay = days[0] ?? "unknown";
63142
+ const lastDay = days[days.length - 1] ?? "unknown";
63143
+ const filename = `extract-${sessionId}-${firstDay}-${lastDay}.txt`;
63144
+ const sizeBytes = Buffer.byteLength(outputText, "utf8");
63145
+ const created = await deps.client.createArtifactFile(projectSlug, {
63146
+ class: "temp",
63147
+ contentType: "text/plain",
63148
+ filename,
63149
+ sizeBytes
63150
+ });
63151
+ if (created.upload.kind === "presigned-post") {
63152
+ const form = new FormData();
63153
+ for (const [k, v] of Object.entries(created.upload.fields)) {
63154
+ form.append(k, v);
63155
+ }
63156
+ const blob = new Blob([outputText], { type: "text/plain" });
63157
+ form.append("file", blob, filename);
63158
+ const resp = await fetch(created.upload.url, { method: "POST", body: form });
63159
+ if (!resp.ok) {
63160
+ throw new Error(`Presigned POST failed with ${resp.status}`);
63161
+ }
63162
+ } else {
63163
+ await deps.client.uploadArtifactFileContent(
63164
+ projectSlug,
63165
+ created.artifact.id,
63166
+ new TextEncoder().encode(outputText),
63167
+ "text/plain"
63168
+ );
63169
+ }
63170
+ const completed = await deps.client.completeArtifactFile(
63171
+ projectSlug,
63172
+ created.artifact.id
63173
+ );
63174
+ return {
63175
+ ok: true,
63176
+ message: `Uploaded artifact ${completed.id} (${created.stableUrl})`,
63177
+ deliveredArtifactId: completed.id
63178
+ };
63179
+ }
63180
+
62083
63181
  // src/bin.ts
62084
63182
  function pm2Runner(args) {
62085
63183
  const r = (0, import_node_child_process18.spawnSync)("pm2", args, { encoding: "utf8" });
@@ -62244,6 +63342,11 @@ Usage:
62244
63342
  support/debug packaging flow:
62245
63343
  printf %s "$HINT" | mrrlin-mcp redact
62246
63344
 
63345
+ mrrlin-mcp extract Pull a director session's raw bridge log lines,
63346
+ scrub them, cap the output size, and either write
63347
+ them locally (with --out) or upload as a temporary
63348
+ artifact file.
63349
+
62247
63350
  mrrlin-mcp --help Show this help.
62248
63351
 
62249
63352
  Operator notes:
@@ -62333,8 +63436,8 @@ async function main() {
62333
63436
  }
62334
63437
  }
62335
63438
  try {
62336
- const codexHome = process.env.CODEX_HOME ?? import_node_path26.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
62337
- (0, import_node_fs17.rmSync)(import_node_path26.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
63439
+ const codexHome = process.env.CODEX_HOME ?? import_node_path31.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
63440
+ (0, import_node_fs17.rmSync)(import_node_path31.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
62338
63441
  } catch {
62339
63442
  }
62340
63443
  const claudeResult = await installClaude({ binPath, force, serveEnv });
@@ -62369,6 +63472,16 @@ async function main() {
62369
63472
  process.stdout.write(redact(input));
62370
63473
  return;
62371
63474
  }
63475
+ case "extract": {
63476
+ const stateDir = readStateDir();
63477
+ const apiBaseUrl = readConfiguredApiBaseUrl();
63478
+ const client = createMrrlinClient(withAuth({ apiBaseUrl }));
63479
+ const result = await runExtract(rest, { stateDir, client });
63480
+ process.stderr.write(`${result.message}
63481
+ `);
63482
+ if (!result.ok) process.exit(2);
63483
+ return;
63484
+ }
62372
63485
  case "director-bridge": {
62373
63486
  await startDirectorBridge();
62374
63487
  return;
@@ -62385,7 +63498,7 @@ async function main() {
62385
63498
  env: process.env,
62386
63499
  cwd: process.cwd(),
62387
63500
  writeFile: (p, c) => {
62388
- (0, import_node_fs17.mkdirSync)(import_node_path26.default.dirname(p), { recursive: true, mode: 448 });
63501
+ (0, import_node_fs17.mkdirSync)(import_node_path31.default.dirname(p), { recursive: true, mode: 448 });
62389
63502
  (0, import_node_fs17.writeFileSync)(p, c, { mode: 384 });
62390
63503
  },
62391
63504
  runPm2: pm2Runner,
@@ -62410,7 +63523,7 @@ async function main() {
62410
63523
  purgeSecret: purge,
62411
63524
  secretPath: agentCredentialPath(),
62412
63525
  tokenPath: operatorTokenPath(),
62413
- ecoPath: import_node_path26.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
63526
+ ecoPath: import_node_path31.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
62414
63527
  log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
62415
63528
  `)
62416
63529
  });
@@ -62431,7 +63544,7 @@ async function main() {
62431
63544
  purgeSecret: true,
62432
63545
  secretPath: agentCredentialPath(),
62433
63546
  tokenPath: operatorTokenPath(),
62434
- ecoPath: import_node_path26.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
63547
+ ecoPath: import_node_path31.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
62435
63548
  log
62436
63549
  });
62437
63550
  let codexOk = true;
@@ -62451,7 +63564,7 @@ async function main() {
62451
63564
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
62452
63565
  }
62453
63566
  try {
62454
- (0, import_node_fs17.rmSync)(import_node_path26.default.join(home, ".mrrlin"), { recursive: true, force: true });
63567
+ (0, import_node_fs17.rmSync)(import_node_path31.default.join(home, ".mrrlin"), { recursive: true, force: true });
62455
63568
  } catch {
62456
63569
  }
62457
63570
  log("removed ~/.mrrlin");
@@ -62492,7 +63605,7 @@ ${HELP_TEXT}`);
62492
63605
  }
62493
63606
  }
62494
63607
  function resolveSelfBinPath() {
62495
- return import_node_path25.default.resolve(process.argv[1] ?? process.execPath);
63608
+ return import_node_path30.default.resolve(process.argv[1] ?? process.execPath);
62496
63609
  }
62497
63610
  main().catch((error51) => {
62498
63611
  process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}