@mrrlin-dev/mcp 0.3.2 → 0.3.5

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
@@ -4273,7 +4273,7 @@ var require_websocket = __commonJS({
4273
4273
  var http2 = require("http");
4274
4274
  var net = require("net");
4275
4275
  var tls = require("tls");
4276
- var { randomBytes: randomBytes3, createHash: createHash2 } = require("crypto");
4276
+ var { randomBytes: randomBytes3, createHash: createHash3 } = require("crypto");
4277
4277
  var { Duplex, Readable } = require("stream");
4278
4278
  var { URL: URL2 } = require("url");
4279
4279
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -4941,7 +4941,7 @@ var require_websocket = __commonJS({
4941
4941
  abortHandshake(websocket, socket, "Invalid Upgrade header");
4942
4942
  return;
4943
4943
  }
4944
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
4944
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
4945
4945
  if (res.headers["sec-websocket-accept"] !== digest) {
4946
4946
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
4947
4947
  return;
@@ -5310,7 +5310,7 @@ var require_websocket_server = __commonJS({
5310
5310
  var EventEmitter3 = require("events");
5311
5311
  var http2 = require("http");
5312
5312
  var { Duplex } = require("stream");
5313
- var { createHash: createHash2 } = require("crypto");
5313
+ var { createHash: createHash3 } = require("crypto");
5314
5314
  var extension2 = require_extension();
5315
5315
  var PerMessageDeflate2 = require_permessage_deflate();
5316
5316
  var subprotocol2 = require_subprotocol();
@@ -5617,7 +5617,7 @@ var require_websocket_server = __commonJS({
5617
5617
  );
5618
5618
  }
5619
5619
  if (this._state > RUNNING) return abortHandshake(socket, 503);
5620
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
5620
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
5621
5621
  const headers = [
5622
5622
  "HTTP/1.1 101 Switching Protocols",
5623
5623
  "Upgrade: websocket",
@@ -7703,54 +7703,54 @@ var require_polyfills = __commonJS({
7703
7703
  }
7704
7704
  var chdir;
7705
7705
  module2.exports = patch;
7706
- function patch(fs6) {
7706
+ function patch(fs7) {
7707
7707
  if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
7708
- patchLchmod(fs6);
7709
- }
7710
- if (!fs6.lutimes) {
7711
- patchLutimes(fs6);
7712
- }
7713
- fs6.chown = chownFix(fs6.chown);
7714
- fs6.fchown = chownFix(fs6.fchown);
7715
- fs6.lchown = chownFix(fs6.lchown);
7716
- fs6.chmod = chmodFix(fs6.chmod);
7717
- fs6.fchmod = chmodFix(fs6.fchmod);
7718
- fs6.lchmod = chmodFix(fs6.lchmod);
7719
- fs6.chownSync = chownFixSync(fs6.chownSync);
7720
- fs6.fchownSync = chownFixSync(fs6.fchownSync);
7721
- fs6.lchownSync = chownFixSync(fs6.lchownSync);
7722
- fs6.chmodSync = chmodFixSync(fs6.chmodSync);
7723
- fs6.fchmodSync = chmodFixSync(fs6.fchmodSync);
7724
- fs6.lchmodSync = chmodFixSync(fs6.lchmodSync);
7725
- fs6.stat = statFix(fs6.stat);
7726
- fs6.fstat = statFix(fs6.fstat);
7727
- fs6.lstat = statFix(fs6.lstat);
7728
- fs6.statSync = statFixSync(fs6.statSync);
7729
- fs6.fstatSync = statFixSync(fs6.fstatSync);
7730
- fs6.lstatSync = statFixSync(fs6.lstatSync);
7731
- if (fs6.chmod && !fs6.lchmod) {
7732
- fs6.lchmod = function(path15, mode, cb) {
7708
+ patchLchmod(fs7);
7709
+ }
7710
+ if (!fs7.lutimes) {
7711
+ patchLutimes(fs7);
7712
+ }
7713
+ fs7.chown = chownFix(fs7.chown);
7714
+ fs7.fchown = chownFix(fs7.fchown);
7715
+ fs7.lchown = chownFix(fs7.lchown);
7716
+ fs7.chmod = chmodFix(fs7.chmod);
7717
+ fs7.fchmod = chmodFix(fs7.fchmod);
7718
+ fs7.lchmod = chmodFix(fs7.lchmod);
7719
+ fs7.chownSync = chownFixSync(fs7.chownSync);
7720
+ fs7.fchownSync = chownFixSync(fs7.fchownSync);
7721
+ fs7.lchownSync = chownFixSync(fs7.lchownSync);
7722
+ fs7.chmodSync = chmodFixSync(fs7.chmodSync);
7723
+ fs7.fchmodSync = chmodFixSync(fs7.fchmodSync);
7724
+ fs7.lchmodSync = chmodFixSync(fs7.lchmodSync);
7725
+ fs7.stat = statFix(fs7.stat);
7726
+ fs7.fstat = statFix(fs7.fstat);
7727
+ fs7.lstat = statFix(fs7.lstat);
7728
+ fs7.statSync = statFixSync(fs7.statSync);
7729
+ fs7.fstatSync = statFixSync(fs7.fstatSync);
7730
+ fs7.lstatSync = statFixSync(fs7.lstatSync);
7731
+ if (fs7.chmod && !fs7.lchmod) {
7732
+ fs7.lchmod = function(path16, mode, cb) {
7733
7733
  if (cb) process.nextTick(cb);
7734
7734
  };
7735
- fs6.lchmodSync = function() {
7735
+ fs7.lchmodSync = function() {
7736
7736
  };
7737
7737
  }
7738
- if (fs6.chown && !fs6.lchown) {
7739
- fs6.lchown = function(path15, uid, gid, cb) {
7738
+ if (fs7.chown && !fs7.lchown) {
7739
+ fs7.lchown = function(path16, uid, gid, cb) {
7740
7740
  if (cb) process.nextTick(cb);
7741
7741
  };
7742
- fs6.lchownSync = function() {
7742
+ fs7.lchownSync = function() {
7743
7743
  };
7744
7744
  }
7745
7745
  if (platform2 === "win32") {
7746
- fs6.rename = typeof fs6.rename !== "function" ? fs6.rename : function(fs$rename) {
7746
+ fs7.rename = typeof fs7.rename !== "function" ? fs7.rename : function(fs$rename) {
7747
7747
  function rename(from, to, cb) {
7748
7748
  var start = Date.now();
7749
7749
  var backoff = 0;
7750
7750
  fs$rename(from, to, function CB(er) {
7751
7751
  if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) {
7752
7752
  setTimeout(function() {
7753
- fs6.stat(to, function(stater, st) {
7753
+ fs7.stat(to, function(stater, st) {
7754
7754
  if (stater && stater.code === "ENOENT")
7755
7755
  fs$rename(from, to, CB);
7756
7756
  else
@@ -7766,9 +7766,9 @@ var require_polyfills = __commonJS({
7766
7766
  }
7767
7767
  if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
7768
7768
  return rename;
7769
- }(fs6.rename);
7769
+ }(fs7.rename);
7770
7770
  }
7771
- fs6.read = typeof fs6.read !== "function" ? fs6.read : function(fs$read) {
7771
+ fs7.read = typeof fs7.read !== "function" ? fs7.read : function(fs$read) {
7772
7772
  function read(fd, buffer, offset, length, position, callback_) {
7773
7773
  var callback;
7774
7774
  if (callback_ && typeof callback_ === "function") {
@@ -7776,22 +7776,22 @@ var require_polyfills = __commonJS({
7776
7776
  callback = function(er, _, __) {
7777
7777
  if (er && er.code === "EAGAIN" && eagCounter < 10) {
7778
7778
  eagCounter++;
7779
- return fs$read.call(fs6, fd, buffer, offset, length, position, callback);
7779
+ return fs$read.call(fs7, fd, buffer, offset, length, position, callback);
7780
7780
  }
7781
7781
  callback_.apply(this, arguments);
7782
7782
  };
7783
7783
  }
7784
- return fs$read.call(fs6, fd, buffer, offset, length, position, callback);
7784
+ return fs$read.call(fs7, fd, buffer, offset, length, position, callback);
7785
7785
  }
7786
7786
  if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
7787
7787
  return read;
7788
- }(fs6.read);
7789
- fs6.readSync = typeof fs6.readSync !== "function" ? fs6.readSync : /* @__PURE__ */ function(fs$readSync) {
7788
+ }(fs7.read);
7789
+ fs7.readSync = typeof fs7.readSync !== "function" ? fs7.readSync : /* @__PURE__ */ function(fs$readSync) {
7790
7790
  return function(fd, buffer, offset, length, position) {
7791
7791
  var eagCounter = 0;
7792
7792
  while (true) {
7793
7793
  try {
7794
- return fs$readSync.call(fs6, fd, buffer, offset, length, position);
7794
+ return fs$readSync.call(fs7, fd, buffer, offset, length, position);
7795
7795
  } catch (er) {
7796
7796
  if (er.code === "EAGAIN" && eagCounter < 10) {
7797
7797
  eagCounter++;
@@ -7801,11 +7801,11 @@ var require_polyfills = __commonJS({
7801
7801
  }
7802
7802
  }
7803
7803
  };
7804
- }(fs6.readSync);
7805
- function patchLchmod(fs7) {
7806
- fs7.lchmod = function(path15, mode, callback) {
7807
- fs7.open(
7808
- path15,
7804
+ }(fs7.readSync);
7805
+ function patchLchmod(fs8) {
7806
+ fs8.lchmod = function(path16, mode, callback) {
7807
+ fs8.open(
7808
+ path16,
7809
7809
  constants.O_WRONLY | constants.O_SYMLINK,
7810
7810
  mode,
7811
7811
  function(err, fd) {
@@ -7813,80 +7813,80 @@ var require_polyfills = __commonJS({
7813
7813
  if (callback) callback(err);
7814
7814
  return;
7815
7815
  }
7816
- fs7.fchmod(fd, mode, function(err2) {
7817
- fs7.close(fd, function(err22) {
7816
+ fs8.fchmod(fd, mode, function(err2) {
7817
+ fs8.close(fd, function(err22) {
7818
7818
  if (callback) callback(err2 || err22);
7819
7819
  });
7820
7820
  });
7821
7821
  }
7822
7822
  );
7823
7823
  };
7824
- fs7.lchmodSync = function(path15, mode) {
7825
- var fd = fs7.openSync(path15, constants.O_WRONLY | constants.O_SYMLINK, mode);
7824
+ fs8.lchmodSync = function(path16, mode) {
7825
+ var fd = fs8.openSync(path16, constants.O_WRONLY | constants.O_SYMLINK, mode);
7826
7826
  var threw = true;
7827
7827
  var ret;
7828
7828
  try {
7829
- ret = fs7.fchmodSync(fd, mode);
7829
+ ret = fs8.fchmodSync(fd, mode);
7830
7830
  threw = false;
7831
7831
  } finally {
7832
7832
  if (threw) {
7833
7833
  try {
7834
- fs7.closeSync(fd);
7834
+ fs8.closeSync(fd);
7835
7835
  } catch (er) {
7836
7836
  }
7837
7837
  } else {
7838
- fs7.closeSync(fd);
7838
+ fs8.closeSync(fd);
7839
7839
  }
7840
7840
  }
7841
7841
  return ret;
7842
7842
  };
7843
7843
  }
7844
- function patchLutimes(fs7) {
7845
- if (constants.hasOwnProperty("O_SYMLINK") && fs7.futimes) {
7846
- fs7.lutimes = function(path15, at, mt, cb) {
7847
- fs7.open(path15, constants.O_SYMLINK, function(er, fd) {
7844
+ function patchLutimes(fs8) {
7845
+ if (constants.hasOwnProperty("O_SYMLINK") && fs8.futimes) {
7846
+ fs8.lutimes = function(path16, at, mt, cb) {
7847
+ fs8.open(path16, constants.O_SYMLINK, function(er, fd) {
7848
7848
  if (er) {
7849
7849
  if (cb) cb(er);
7850
7850
  return;
7851
7851
  }
7852
- fs7.futimes(fd, at, mt, function(er2) {
7853
- fs7.close(fd, function(er22) {
7852
+ fs8.futimes(fd, at, mt, function(er2) {
7853
+ fs8.close(fd, function(er22) {
7854
7854
  if (cb) cb(er2 || er22);
7855
7855
  });
7856
7856
  });
7857
7857
  });
7858
7858
  };
7859
- fs7.lutimesSync = function(path15, at, mt) {
7860
- var fd = fs7.openSync(path15, constants.O_SYMLINK);
7859
+ fs8.lutimesSync = function(path16, at, mt) {
7860
+ var fd = fs8.openSync(path16, constants.O_SYMLINK);
7861
7861
  var ret;
7862
7862
  var threw = true;
7863
7863
  try {
7864
- ret = fs7.futimesSync(fd, at, mt);
7864
+ ret = fs8.futimesSync(fd, at, mt);
7865
7865
  threw = false;
7866
7866
  } finally {
7867
7867
  if (threw) {
7868
7868
  try {
7869
- fs7.closeSync(fd);
7869
+ fs8.closeSync(fd);
7870
7870
  } catch (er) {
7871
7871
  }
7872
7872
  } else {
7873
- fs7.closeSync(fd);
7873
+ fs8.closeSync(fd);
7874
7874
  }
7875
7875
  }
7876
7876
  return ret;
7877
7877
  };
7878
- } else if (fs7.futimes) {
7879
- fs7.lutimes = function(_a3, _b, _c, cb) {
7878
+ } else if (fs8.futimes) {
7879
+ fs8.lutimes = function(_a3, _b, _c, cb) {
7880
7880
  if (cb) process.nextTick(cb);
7881
7881
  };
7882
- fs7.lutimesSync = function() {
7882
+ fs8.lutimesSync = function() {
7883
7883
  };
7884
7884
  }
7885
7885
  }
7886
7886
  function chmodFix(orig) {
7887
7887
  if (!orig) return orig;
7888
7888
  return function(target, mode, cb) {
7889
- return orig.call(fs6, target, mode, function(er) {
7889
+ return orig.call(fs7, target, mode, function(er) {
7890
7890
  if (chownErOk(er)) er = null;
7891
7891
  if (cb) cb.apply(this, arguments);
7892
7892
  });
@@ -7896,7 +7896,7 @@ var require_polyfills = __commonJS({
7896
7896
  if (!orig) return orig;
7897
7897
  return function(target, mode) {
7898
7898
  try {
7899
- return orig.call(fs6, target, mode);
7899
+ return orig.call(fs7, target, mode);
7900
7900
  } catch (er) {
7901
7901
  if (!chownErOk(er)) throw er;
7902
7902
  }
@@ -7905,7 +7905,7 @@ var require_polyfills = __commonJS({
7905
7905
  function chownFix(orig) {
7906
7906
  if (!orig) return orig;
7907
7907
  return function(target, uid, gid, cb) {
7908
- return orig.call(fs6, target, uid, gid, function(er) {
7908
+ return orig.call(fs7, target, uid, gid, function(er) {
7909
7909
  if (chownErOk(er)) er = null;
7910
7910
  if (cb) cb.apply(this, arguments);
7911
7911
  });
@@ -7915,7 +7915,7 @@ var require_polyfills = __commonJS({
7915
7915
  if (!orig) return orig;
7916
7916
  return function(target, uid, gid) {
7917
7917
  try {
7918
- return orig.call(fs6, target, uid, gid);
7918
+ return orig.call(fs7, target, uid, gid);
7919
7919
  } catch (er) {
7920
7920
  if (!chownErOk(er)) throw er;
7921
7921
  }
@@ -7935,13 +7935,13 @@ var require_polyfills = __commonJS({
7935
7935
  }
7936
7936
  if (cb) cb.apply(this, arguments);
7937
7937
  }
7938
- return options ? orig.call(fs6, target, options, callback) : orig.call(fs6, target, callback);
7938
+ return options ? orig.call(fs7, target, options, callback) : orig.call(fs7, target, callback);
7939
7939
  };
7940
7940
  }
7941
7941
  function statFixSync(orig) {
7942
7942
  if (!orig) return orig;
7943
7943
  return function(target, options) {
7944
- var stats = options ? orig.call(fs6, target, options) : orig.call(fs6, target);
7944
+ var stats = options ? orig.call(fs7, target, options) : orig.call(fs7, target);
7945
7945
  if (stats) {
7946
7946
  if (stats.uid < 0) stats.uid += 4294967296;
7947
7947
  if (stats.gid < 0) stats.gid += 4294967296;
@@ -7970,16 +7970,16 @@ var require_legacy_streams = __commonJS({
7970
7970
  "../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/legacy-streams.js"(exports2, module2) {
7971
7971
  var Stream = require("stream").Stream;
7972
7972
  module2.exports = legacy;
7973
- function legacy(fs6) {
7973
+ function legacy(fs7) {
7974
7974
  return {
7975
7975
  ReadStream,
7976
7976
  WriteStream
7977
7977
  };
7978
- function ReadStream(path15, options) {
7979
- if (!(this instanceof ReadStream)) return new ReadStream(path15, options);
7978
+ function ReadStream(path16, options) {
7979
+ if (!(this instanceof ReadStream)) return new ReadStream(path16, options);
7980
7980
  Stream.call(this);
7981
7981
  var self = this;
7982
- this.path = path15;
7982
+ this.path = path16;
7983
7983
  this.fd = null;
7984
7984
  this.readable = true;
7985
7985
  this.paused = false;
@@ -8013,7 +8013,7 @@ var require_legacy_streams = __commonJS({
8013
8013
  });
8014
8014
  return;
8015
8015
  }
8016
- fs6.open(this.path, this.flags, this.mode, function(err, fd) {
8016
+ fs7.open(this.path, this.flags, this.mode, function(err, fd) {
8017
8017
  if (err) {
8018
8018
  self.emit("error", err);
8019
8019
  self.readable = false;
@@ -8024,10 +8024,10 @@ var require_legacy_streams = __commonJS({
8024
8024
  self._read();
8025
8025
  });
8026
8026
  }
8027
- function WriteStream(path15, options) {
8028
- if (!(this instanceof WriteStream)) return new WriteStream(path15, options);
8027
+ function WriteStream(path16, options) {
8028
+ if (!(this instanceof WriteStream)) return new WriteStream(path16, options);
8029
8029
  Stream.call(this);
8030
- this.path = path15;
8030
+ this.path = path16;
8031
8031
  this.fd = null;
8032
8032
  this.writable = true;
8033
8033
  this.flags = "w";
@@ -8052,7 +8052,7 @@ var require_legacy_streams = __commonJS({
8052
8052
  this.busy = false;
8053
8053
  this._queue = [];
8054
8054
  if (this.fd === null) {
8055
- this._open = fs6.open;
8055
+ this._open = fs7.open;
8056
8056
  this._queue.push([this._open, this.path, this.flags, this.mode, void 0]);
8057
8057
  this.flush();
8058
8058
  }
@@ -8087,7 +8087,7 @@ var require_clone = __commonJS({
8087
8087
  // ../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js
8088
8088
  var require_graceful_fs = __commonJS({
8089
8089
  "../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js"(exports2, module2) {
8090
- var fs6 = require("fs");
8090
+ var fs7 = require("fs");
8091
8091
  var polyfills = require_polyfills();
8092
8092
  var legacy = require_legacy_streams();
8093
8093
  var clone2 = require_clone();
@@ -8119,12 +8119,12 @@ var require_graceful_fs = __commonJS({
8119
8119
  m = "GFS4: " + m.split(/\n/).join("\nGFS4: ");
8120
8120
  console.error(m);
8121
8121
  };
8122
- if (!fs6[gracefulQueue]) {
8122
+ if (!fs7[gracefulQueue]) {
8123
8123
  queue = global[gracefulQueue] || [];
8124
- publishQueue(fs6, queue);
8125
- fs6.close = function(fs$close) {
8124
+ publishQueue(fs7, queue);
8125
+ fs7.close = function(fs$close) {
8126
8126
  function close(fd, cb) {
8127
- return fs$close.call(fs6, fd, function(err) {
8127
+ return fs$close.call(fs7, fd, function(err) {
8128
8128
  if (!err) {
8129
8129
  resetQueue();
8130
8130
  }
@@ -8136,48 +8136,48 @@ var require_graceful_fs = __commonJS({
8136
8136
  value: fs$close
8137
8137
  });
8138
8138
  return close;
8139
- }(fs6.close);
8140
- fs6.closeSync = function(fs$closeSync) {
8139
+ }(fs7.close);
8140
+ fs7.closeSync = function(fs$closeSync) {
8141
8141
  function closeSync(fd) {
8142
- fs$closeSync.apply(fs6, arguments);
8142
+ fs$closeSync.apply(fs7, arguments);
8143
8143
  resetQueue();
8144
8144
  }
8145
8145
  Object.defineProperty(closeSync, previousSymbol, {
8146
8146
  value: fs$closeSync
8147
8147
  });
8148
8148
  return closeSync;
8149
- }(fs6.closeSync);
8149
+ }(fs7.closeSync);
8150
8150
  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
8151
8151
  process.on("exit", function() {
8152
- debug(fs6[gracefulQueue]);
8153
- require("assert").equal(fs6[gracefulQueue].length, 0);
8152
+ debug(fs7[gracefulQueue]);
8153
+ require("assert").equal(fs7[gracefulQueue].length, 0);
8154
8154
  });
8155
8155
  }
8156
8156
  }
8157
8157
  var queue;
8158
8158
  if (!global[gracefulQueue]) {
8159
- publishQueue(global, fs6[gracefulQueue]);
8160
- }
8161
- module2.exports = patch(clone2(fs6));
8162
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs6.__patched) {
8163
- module2.exports = patch(fs6);
8164
- fs6.__patched = true;
8165
- }
8166
- function patch(fs7) {
8167
- polyfills(fs7);
8168
- fs7.gracefulify = patch;
8169
- fs7.createReadStream = createReadStream;
8170
- fs7.createWriteStream = createWriteStream;
8171
- var fs$readFile = fs7.readFile;
8172
- fs7.readFile = readFile2;
8173
- function readFile2(path15, options, cb) {
8159
+ publishQueue(global, fs7[gracefulQueue]);
8160
+ }
8161
+ module2.exports = patch(clone2(fs7));
8162
+ if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs7.__patched) {
8163
+ module2.exports = patch(fs7);
8164
+ fs7.__patched = true;
8165
+ }
8166
+ function patch(fs8) {
8167
+ polyfills(fs8);
8168
+ fs8.gracefulify = patch;
8169
+ fs8.createReadStream = createReadStream;
8170
+ fs8.createWriteStream = createWriteStream;
8171
+ var fs$readFile = fs8.readFile;
8172
+ fs8.readFile = readFile2;
8173
+ function readFile2(path16, options, cb) {
8174
8174
  if (typeof options === "function")
8175
8175
  cb = options, options = null;
8176
- return go$readFile(path15, options, cb);
8177
- function go$readFile(path16, options2, cb2, startTime) {
8178
- return fs$readFile(path16, options2, function(err) {
8176
+ return go$readFile(path16, options, cb);
8177
+ function go$readFile(path17, options2, cb2, startTime) {
8178
+ return fs$readFile(path17, options2, function(err) {
8179
8179
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8180
- enqueue([go$readFile, [path16, options2, cb2], err, startTime || Date.now(), Date.now()]);
8180
+ enqueue([go$readFile, [path17, options2, cb2], err, startTime || Date.now(), Date.now()]);
8181
8181
  else {
8182
8182
  if (typeof cb2 === "function")
8183
8183
  cb2.apply(this, arguments);
@@ -8185,16 +8185,16 @@ var require_graceful_fs = __commonJS({
8185
8185
  });
8186
8186
  }
8187
8187
  }
8188
- var fs$writeFile = fs7.writeFile;
8189
- fs7.writeFile = writeFile;
8190
- function writeFile(path15, data, options, cb) {
8188
+ var fs$writeFile = fs8.writeFile;
8189
+ fs8.writeFile = writeFile;
8190
+ function writeFile(path16, data, options, cb) {
8191
8191
  if (typeof options === "function")
8192
8192
  cb = options, options = null;
8193
- return go$writeFile(path15, data, options, cb);
8194
- function go$writeFile(path16, data2, options2, cb2, startTime) {
8195
- return fs$writeFile(path16, data2, options2, function(err) {
8193
+ return go$writeFile(path16, data, options, cb);
8194
+ function go$writeFile(path17, data2, options2, cb2, startTime) {
8195
+ return fs$writeFile(path17, data2, options2, function(err) {
8196
8196
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8197
- enqueue([go$writeFile, [path16, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8197
+ enqueue([go$writeFile, [path17, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8198
8198
  else {
8199
8199
  if (typeof cb2 === "function")
8200
8200
  cb2.apply(this, arguments);
@@ -8202,17 +8202,17 @@ var require_graceful_fs = __commonJS({
8202
8202
  });
8203
8203
  }
8204
8204
  }
8205
- var fs$appendFile = fs7.appendFile;
8205
+ var fs$appendFile = fs8.appendFile;
8206
8206
  if (fs$appendFile)
8207
- fs7.appendFile = appendFile;
8208
- function appendFile(path15, data, options, cb) {
8207
+ fs8.appendFile = appendFile;
8208
+ function appendFile(path16, data, options, cb) {
8209
8209
  if (typeof options === "function")
8210
8210
  cb = options, options = null;
8211
- return go$appendFile(path15, data, options, cb);
8212
- function go$appendFile(path16, data2, options2, cb2, startTime) {
8213
- return fs$appendFile(path16, data2, options2, function(err) {
8211
+ return go$appendFile(path16, data, options, cb);
8212
+ function go$appendFile(path17, data2, options2, cb2, startTime) {
8213
+ return fs$appendFile(path17, data2, options2, function(err) {
8214
8214
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8215
- enqueue([go$appendFile, [path16, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8215
+ enqueue([go$appendFile, [path17, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8216
8216
  else {
8217
8217
  if (typeof cb2 === "function")
8218
8218
  cb2.apply(this, arguments);
@@ -8220,9 +8220,9 @@ var require_graceful_fs = __commonJS({
8220
8220
  });
8221
8221
  }
8222
8222
  }
8223
- var fs$copyFile = fs7.copyFile;
8223
+ var fs$copyFile = fs8.copyFile;
8224
8224
  if (fs$copyFile)
8225
- fs7.copyFile = copyFile;
8225
+ fs8.copyFile = copyFile;
8226
8226
  function copyFile(src, dest, flags, cb) {
8227
8227
  if (typeof flags === "function") {
8228
8228
  cb = flags;
@@ -8240,34 +8240,34 @@ var require_graceful_fs = __commonJS({
8240
8240
  });
8241
8241
  }
8242
8242
  }
8243
- var fs$readdir = fs7.readdir;
8244
- fs7.readdir = readdir;
8243
+ var fs$readdir = fs8.readdir;
8244
+ fs8.readdir = readdir2;
8245
8245
  var noReaddirOptionVersions = /^v[0-5]\./;
8246
- function readdir(path15, options, cb) {
8246
+ function readdir2(path16, 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(path16, options2, cb2, startTime) {
8250
- return fs$readdir(path16, fs$readdirCallback(
8251
- path16,
8249
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path17, options2, cb2, startTime) {
8250
+ return fs$readdir(path17, fs$readdirCallback(
8251
+ path17,
8252
8252
  options2,
8253
8253
  cb2,
8254
8254
  startTime
8255
8255
  ));
8256
- } : function go$readdir2(path16, options2, cb2, startTime) {
8257
- return fs$readdir(path16, options2, fs$readdirCallback(
8258
- path16,
8256
+ } : function go$readdir2(path17, options2, cb2, startTime) {
8257
+ return fs$readdir(path17, options2, fs$readdirCallback(
8258
+ path17,
8259
8259
  options2,
8260
8260
  cb2,
8261
8261
  startTime
8262
8262
  ));
8263
8263
  };
8264
- return go$readdir(path15, options, cb);
8265
- function fs$readdirCallback(path16, options2, cb2, startTime) {
8264
+ return go$readdir(path16, options, cb);
8265
+ function fs$readdirCallback(path17, 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
- [path16, options2, cb2],
8270
+ [path17, options2, cb2],
8271
8271
  err,
8272
8272
  startTime || Date.now(),
8273
8273
  Date.now()
@@ -8282,21 +8282,21 @@ var require_graceful_fs = __commonJS({
8282
8282
  }
8283
8283
  }
8284
8284
  if (process.version.substr(0, 4) === "v0.8") {
8285
- var legStreams = legacy(fs7);
8285
+ var legStreams = legacy(fs8);
8286
8286
  ReadStream = legStreams.ReadStream;
8287
8287
  WriteStream = legStreams.WriteStream;
8288
8288
  }
8289
- var fs$ReadStream = fs7.ReadStream;
8289
+ var fs$ReadStream = fs8.ReadStream;
8290
8290
  if (fs$ReadStream) {
8291
8291
  ReadStream.prototype = Object.create(fs$ReadStream.prototype);
8292
8292
  ReadStream.prototype.open = ReadStream$open;
8293
8293
  }
8294
- var fs$WriteStream = fs7.WriteStream;
8294
+ var fs$WriteStream = fs8.WriteStream;
8295
8295
  if (fs$WriteStream) {
8296
8296
  WriteStream.prototype = Object.create(fs$WriteStream.prototype);
8297
8297
  WriteStream.prototype.open = WriteStream$open;
8298
8298
  }
8299
- Object.defineProperty(fs7, "ReadStream", {
8299
+ Object.defineProperty(fs8, "ReadStream", {
8300
8300
  get: function() {
8301
8301
  return ReadStream;
8302
8302
  },
@@ -8306,7 +8306,7 @@ var require_graceful_fs = __commonJS({
8306
8306
  enumerable: true,
8307
8307
  configurable: true
8308
8308
  });
8309
- Object.defineProperty(fs7, "WriteStream", {
8309
+ Object.defineProperty(fs8, "WriteStream", {
8310
8310
  get: function() {
8311
8311
  return WriteStream;
8312
8312
  },
@@ -8317,7 +8317,7 @@ var require_graceful_fs = __commonJS({
8317
8317
  configurable: true
8318
8318
  });
8319
8319
  var FileReadStream = ReadStream;
8320
- Object.defineProperty(fs7, "FileReadStream", {
8320
+ Object.defineProperty(fs8, "FileReadStream", {
8321
8321
  get: function() {
8322
8322
  return FileReadStream;
8323
8323
  },
@@ -8328,7 +8328,7 @@ var require_graceful_fs = __commonJS({
8328
8328
  configurable: true
8329
8329
  });
8330
8330
  var FileWriteStream = WriteStream;
8331
- Object.defineProperty(fs7, "FileWriteStream", {
8331
+ Object.defineProperty(fs8, "FileWriteStream", {
8332
8332
  get: function() {
8333
8333
  return FileWriteStream;
8334
8334
  },
@@ -8338,7 +8338,7 @@ var require_graceful_fs = __commonJS({
8338
8338
  enumerable: true,
8339
8339
  configurable: true
8340
8340
  });
8341
- function ReadStream(path15, options) {
8341
+ function ReadStream(path16, 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(path15, options) {
8361
+ function WriteStream(path16, 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(path15, options) {
8380
- return new fs7.ReadStream(path15, options);
8379
+ function createReadStream(path16, options) {
8380
+ return new fs8.ReadStream(path16, options);
8381
8381
  }
8382
- function createWriteStream(path15, options) {
8383
- return new fs7.WriteStream(path15, options);
8382
+ function createWriteStream(path16, options) {
8383
+ return new fs8.WriteStream(path16, options);
8384
8384
  }
8385
- var fs$open = fs7.open;
8386
- fs7.open = open;
8387
- function open(path15, flags, mode, cb) {
8385
+ var fs$open = fs8.open;
8386
+ fs8.open = open;
8387
+ function open(path16, flags, mode, cb) {
8388
8388
  if (typeof mode === "function")
8389
8389
  cb = mode, mode = null;
8390
- return go$open(path15, flags, mode, cb);
8391
- function go$open(path16, flags2, mode2, cb2, startTime) {
8392
- return fs$open(path16, flags2, mode2, function(err, fd) {
8390
+ return go$open(path16, flags, mode, cb);
8391
+ function go$open(path17, flags2, mode2, cb2, startTime) {
8392
+ return fs$open(path17, flags2, mode2, function(err, fd) {
8393
8393
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8394
- enqueue([go$open, [path16, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
8394
+ enqueue([go$open, [path17, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
8395
8395
  else {
8396
8396
  if (typeof cb2 === "function")
8397
8397
  cb2.apply(this, arguments);
@@ -8399,20 +8399,20 @@ var require_graceful_fs = __commonJS({
8399
8399
  });
8400
8400
  }
8401
8401
  }
8402
- return fs7;
8402
+ return fs8;
8403
8403
  }
8404
8404
  function enqueue(elem) {
8405
8405
  debug("ENQUEUE", elem[0].name, elem[1]);
8406
- fs6[gracefulQueue].push(elem);
8406
+ fs7[gracefulQueue].push(elem);
8407
8407
  retry();
8408
8408
  }
8409
8409
  var retryTimer;
8410
8410
  function resetQueue() {
8411
8411
  var now = Date.now();
8412
- for (var i = 0; i < fs6[gracefulQueue].length; ++i) {
8413
- if (fs6[gracefulQueue][i].length > 2) {
8414
- fs6[gracefulQueue][i][3] = now;
8415
- fs6[gracefulQueue][i][4] = now;
8412
+ for (var i = 0; i < fs7[gracefulQueue].length; ++i) {
8413
+ if (fs7[gracefulQueue][i].length > 2) {
8414
+ fs7[gracefulQueue][i][3] = now;
8415
+ fs7[gracefulQueue][i][4] = now;
8416
8416
  }
8417
8417
  }
8418
8418
  retry();
@@ -8420,9 +8420,9 @@ var require_graceful_fs = __commonJS({
8420
8420
  function retry() {
8421
8421
  clearTimeout(retryTimer);
8422
8422
  retryTimer = void 0;
8423
- if (fs6[gracefulQueue].length === 0)
8423
+ if (fs7[gracefulQueue].length === 0)
8424
8424
  return;
8425
- var elem = fs6[gracefulQueue].shift();
8425
+ var elem = fs7[gracefulQueue].shift();
8426
8426
  var fn = elem[0];
8427
8427
  var args = elem[1];
8428
8428
  var err = elem[2];
@@ -8444,7 +8444,7 @@ var require_graceful_fs = __commonJS({
8444
8444
  debug("RETRY", fn.name, args);
8445
8445
  fn.apply(null, args.concat([startTime]));
8446
8446
  } else {
8447
- fs6[gracefulQueue].push(elem);
8447
+ fs7[gracefulQueue].push(elem);
8448
8448
  }
8449
8449
  }
8450
8450
  if (retryTimer === void 0) {
@@ -8879,10 +8879,10 @@ var require_mtime_precision = __commonJS({
8879
8879
  "../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/mtime-precision.js"(exports2, module2) {
8880
8880
  "use strict";
8881
8881
  var cacheSymbol = Symbol();
8882
- function probe(file2, fs6, callback) {
8883
- const cachedPrecision = fs6[cacheSymbol];
8882
+ function probe(file2, fs7, callback) {
8883
+ const cachedPrecision = fs7[cacheSymbol];
8884
8884
  if (cachedPrecision) {
8885
- return fs6.stat(file2, (err, stat2) => {
8885
+ return fs7.stat(file2, (err, stat2) => {
8886
8886
  if (err) {
8887
8887
  return callback(err);
8888
8888
  }
@@ -8890,16 +8890,16 @@ var require_mtime_precision = __commonJS({
8890
8890
  });
8891
8891
  }
8892
8892
  const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
8893
- fs6.utimes(file2, mtime, mtime, (err) => {
8893
+ fs7.utimes(file2, mtime, mtime, (err) => {
8894
8894
  if (err) {
8895
8895
  return callback(err);
8896
8896
  }
8897
- fs6.stat(file2, (err2, stat2) => {
8897
+ fs7.stat(file2, (err2, stat2) => {
8898
8898
  if (err2) {
8899
8899
  return callback(err2);
8900
8900
  }
8901
8901
  const precision = stat2.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
8902
- Object.defineProperty(fs6, cacheSymbol, { value: precision });
8902
+ Object.defineProperty(fs7, cacheSymbol, { value: precision });
8903
8903
  callback(null, stat2.mtime, precision);
8904
8904
  });
8905
8905
  });
@@ -8920,8 +8920,8 @@ 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 path15 = require("path");
8924
- var fs6 = require_graceful_fs();
8923
+ var path16 = require("path");
8924
+ var fs7 = require_graceful_fs();
8925
8925
  var retry = require_retry2();
8926
8926
  var onExit = require_signal_exit();
8927
8927
  var mtimePrecision = require_mtime_precision();
@@ -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, path15.resolve(file2));
8934
+ return callback(null, path16.resolve(file2));
8935
8935
  }
8936
8936
  options.fs.realpath(file2, callback);
8937
8937
  }
@@ -9052,7 +9052,7 @@ var require_lockfile = __commonJS({
9052
9052
  update: null,
9053
9053
  realpath: true,
9054
9054
  retries: 0,
9055
- fs: fs6,
9055
+ fs: fs7,
9056
9056
  onCompromised: (err) => {
9057
9057
  throw err;
9058
9058
  },
@@ -9096,7 +9096,7 @@ var require_lockfile = __commonJS({
9096
9096
  }
9097
9097
  function unlock(file2, options, callback) {
9098
9098
  options = {
9099
- fs: fs6,
9099
+ fs: fs7,
9100
9100
  realpath: true,
9101
9101
  ...options
9102
9102
  };
@@ -9118,7 +9118,7 @@ var require_lockfile = __commonJS({
9118
9118
  options = {
9119
9119
  stale: 1e4,
9120
9120
  realpath: true,
9121
- fs: fs6,
9121
+ fs: fs7,
9122
9122
  ...options
9123
9123
  };
9124
9124
  options.stale = Math.max(options.stale || 0, 2e3);
@@ -9157,16 +9157,16 @@ var require_lockfile = __commonJS({
9157
9157
  var require_adapter = __commonJS({
9158
9158
  "../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/adapter.js"(exports2, module2) {
9159
9159
  "use strict";
9160
- var fs6 = require_graceful_fs();
9161
- function createSyncFs(fs7) {
9160
+ var fs7 = require_graceful_fs();
9161
+ function createSyncFs(fs8) {
9162
9162
  const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
9163
- const newFs = { ...fs7 };
9163
+ const newFs = { ...fs8 };
9164
9164
  methods.forEach((method) => {
9165
9165
  newFs[method] = (...args) => {
9166
9166
  const callback = args.pop();
9167
9167
  let ret;
9168
9168
  try {
9169
- ret = fs7[`${method}Sync`](...args);
9169
+ ret = fs8[`${method}Sync`](...args);
9170
9170
  } catch (err) {
9171
9171
  return callback(err);
9172
9172
  }
@@ -9204,7 +9204,7 @@ var require_adapter = __commonJS({
9204
9204
  }
9205
9205
  function toSyncOptions(options) {
9206
9206
  options = { ...options };
9207
- options.fs = createSyncFs(options.fs || fs6);
9207
+ options.fs = createSyncFs(options.fs || fs7);
9208
9208
  if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
9209
9209
  throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
9210
9210
  }
@@ -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 path15 = dijkstra.find_path(graph.map, "start", "end");
10798
+ const path16 = dijkstra.find_path(graph.map, "start", "end");
10799
10799
  const optimizedSegs = [];
10800
- for (let i = 1; i < path15.length - 1; i++) {
10801
- optimizedSegs.push(graph.table[path15[i]].node);
10800
+ for (let i = 1; i < path16.length - 1; i++) {
10801
+ optimizedSegs.push(graph.table[path16[i]].node);
10802
10802
  }
10803
10803
  return exports2.fromArray(mergeSegments(optimizedSegs));
10804
10804
  };
@@ -13234,7 +13234,7 @@ var require_utils2 = __commonJS({
13234
13234
  // ../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js
13235
13235
  var require_png2 = __commonJS({
13236
13236
  "../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js"(exports2) {
13237
- var fs6 = require("fs");
13237
+ var fs7 = require("fs");
13238
13238
  var PNG = require_png().PNG;
13239
13239
  var Utils = require_utils2();
13240
13240
  exports2.render = function render(qrData, options) {
@@ -13275,7 +13275,7 @@ var require_png2 = __commonJS({
13275
13275
  });
13276
13276
  png.pack();
13277
13277
  };
13278
- exports2.renderToFile = function renderToFile(path15, qrData, options, cb) {
13278
+ exports2.renderToFile = function renderToFile(path16, 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 = fs6.createWriteStream(path15);
13289
+ const stream = fs7.createWriteStream(path16);
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(path15, qrData, options, cb) {
13351
+ exports2.renderToFile = function renderToFile(path16, qrData, options, cb) {
13352
13352
  if (typeof cb === "undefined") {
13353
13353
  cb = options;
13354
13354
  options = void 0;
13355
13355
  }
13356
- const fs6 = require("fs");
13356
+ const fs7 = require("fs");
13357
13357
  const utf8 = exports2.render(qrData, options);
13358
- fs6.writeFile(path15, utf8, cb);
13358
+ fs7.writeFile(path16, 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 path15 = "";
13479
+ let path16 = "";
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
- path15 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
13490
+ path16 += 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
- path15 += svgCmd("h", lineLength);
13495
+ path16 += svgCmd("h", lineLength);
13496
13496
  lineLength = 0;
13497
13497
  }
13498
13498
  } else {
13499
13499
  moveBy++;
13500
13500
  }
13501
13501
  }
13502
- return path15;
13502
+ return path16;
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 path15 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
13510
+ const path16 = "<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 + path15 + "</svg>\n";
13513
+ const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path16 + "</svg>\n";
13514
13514
  if (typeof cb === "function") {
13515
13515
  cb(null, svgTag);
13516
13516
  }
@@ -13524,15 +13524,15 @@ 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(path15, qrData, options, cb) {
13527
+ exports2.renderToFile = function renderToFile(path16, qrData, options, cb) {
13528
13528
  if (typeof cb === "undefined") {
13529
13529
  cb = options;
13530
13530
  options = void 0;
13531
13531
  }
13532
- const fs6 = require("fs");
13532
+ const fs7 = 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
- fs6.writeFile(path15, xmlStr, cb);
13535
+ fs7.writeFile(path16, 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(path15) {
13694
- return path15.slice((path15.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
13693
+ function getTypeFromFilename(path16) {
13694
+ return path16.slice((path16.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(path15, text, opts, cb) {
13759
- if (typeof path15 !== "string" || !(typeof text === "string" || typeof text === "object")) {
13758
+ exports2.toFile = function toFile(path16, text, opts, cb) {
13759
+ if (typeof path16 !== "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(path15);
13766
+ const type = params.opts.type || getTypeFromFilename(path16);
13767
13767
  const renderer = getRendererFromType(type);
13768
- const renderToFile = renderer.renderToFile.bind(null, path15);
13768
+ const renderToFile = renderer.renderToFile.bind(null, path16);
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(path15) {
16987
- let input = path15;
16986
+ function removeDotSegments(path16) {
16987
+ let input = path16;
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 [path15, query] = wsComponent.resourceName.split("?");
17240
- wsComponent.path = path15 && path15 !== "/" ? path15 : void 0;
17239
+ const [path16, query] = wsComponent.resourceName.split("?");
17240
+ wsComponent.path = path16 && path16 !== "/" ? path16 : void 0;
17241
17241
  wsComponent.query = query;
17242
17242
  wsComponent.resourceName = void 0;
17243
17243
  }
@@ -20630,12 +20630,12 @@ var require_dist = __commonJS({
20630
20630
  throw new Error(`Unknown format "${name}"`);
20631
20631
  return f;
20632
20632
  };
20633
- function addFormats(ajv, list, fs6, exportName) {
20633
+ function addFormats(ajv, list, fs7, exportName) {
20634
20634
  var _a3;
20635
20635
  var _b;
20636
20636
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
20637
20637
  for (const f of list)
20638
- ajv.addFormat(f, fs6[f]);
20638
+ ajv.addFormat(f, fs7[f]);
20639
20639
  }
20640
20640
  module2.exports = exports2 = formatsPlugin;
20641
20641
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -20644,59 +20644,142 @@ var require_dist = __commonJS({
20644
20644
  });
20645
20645
 
20646
20646
  // src/bin.ts
20647
- var import_node_path20 = __toESM(require("node:path"), 1);
20648
- var import_node_child_process8 = require("node:child_process");
20649
- var import_node_fs16 = require("node:fs");
20650
- var import_node_os12 = require("node:os");
20651
20647
  var import_node_path21 = __toESM(require("node:path"), 1);
20648
+ var import_node_child_process9 = require("node:child_process");
20649
+ var import_node_fs16 = require("node:fs");
20650
+ var import_node_os13 = require("node:os");
20651
+ var import_node_path22 = __toESM(require("node:path"), 1);
20652
20652
 
20653
20653
  // src/install-codex.ts
20654
20654
  var import_promises = __toESM(require("node:fs/promises"), 1);
20655
+ var import_node_os2 = __toESM(require("node:os"), 1);
20656
+ var import_node_path2 = __toESM(require("node:path"), 1);
20657
+ var toml = __toESM(require_toml(), 1);
20658
+
20659
+ // src/browser-runtime.ts
20655
20660
  var import_node_os = __toESM(require("node:os"), 1);
20656
20661
  var import_node_path = __toESM(require("node:path"), 1);
20657
- var toml = __toESM(require_toml(), 1);
20662
+ var fs = __toESM(require("node:fs/promises"), 1);
20663
+ var import_node_child_process = require("node:child_process");
20664
+ var import_node_module = require("node:module");
20665
+ var import_node_url = require("node:url");
20666
+ var import_meta = {};
20667
+ function moduleRequire() {
20668
+ const base = typeof __dirname !== "undefined" ? import_node_path.default.join(__dirname, "browser-runtime.js") : (0, import_node_url.fileURLToPath)(import_meta.url);
20669
+ return (0, import_node_module.createRequire)(base);
20670
+ }
20671
+ function browserPaths(homeDir = import_node_os.default.homedir()) {
20672
+ const root = import_node_path.default.join(homeDir, ".mrrlin", "browser");
20673
+ return { root, browsersPath: import_node_path.default.join(root, "browsers"), profilePath: import_node_path.default.join(root, "profile") };
20674
+ }
20675
+ function resolvePackageBin(pkg) {
20676
+ const require2 = moduleRequire();
20677
+ const pkgJsonPath = require2.resolve(`${pkg}/package.json`);
20678
+ const pkgJson = require2(`${pkg}/package.json`);
20679
+ const bin = pkgJson.bin;
20680
+ const rel = typeof bin === "string" ? bin : bin ? Object.values(bin)[0] : void 0;
20681
+ if (!rel) throw new Error(`${pkg} has no bin entry to resolve a CLI from`);
20682
+ return import_node_path.default.join(import_node_path.default.dirname(pkgJsonPath), rel);
20683
+ }
20684
+ function browserServeArgs(homeDir = import_node_os.default.homedir()) {
20685
+ const { browsersPath, profilePath } = browserPaths(homeDir);
20686
+ const cli = resolvePackageBin("@playwright/mcp");
20687
+ return {
20688
+ command: process.execPath,
20689
+ // node
20690
+ args: [cli, "--browser", "chromium", "--user-data-dir", profilePath],
20691
+ env: { PLAYWRIGHT_BROWSERS_PATH: browsersPath }
20692
+ };
20693
+ }
20694
+ async function installBrowser(opts = {}) {
20695
+ const homeDir = opts.homeDir ?? import_node_os.default.homedir();
20696
+ const { browsersPath } = browserPaths(homeDir);
20697
+ const alreadyInstalled = opts.alreadyInstalled ?? (async (candidateBrowsersPath) => {
20698
+ try {
20699
+ const entries = await fs.readdir(candidateBrowsersPath);
20700
+ return entries.some((entry) => entry.startsWith("chromium"));
20701
+ } catch (error51) {
20702
+ if (error51.code === "ENOENT") {
20703
+ return false;
20704
+ }
20705
+ throw error51;
20706
+ }
20707
+ });
20708
+ if (await alreadyInstalled(browsersPath)) {
20709
+ return { action: "noop", browsersPath };
20710
+ }
20711
+ const run2 = opts.run ?? (async (cmd, args, env2) => {
20712
+ const r = (0, import_node_child_process.spawnSync)(cmd, args, { encoding: "utf8", env: env2, stdio: ["ignore", "inherit", "pipe"] });
20713
+ return { code: r.status ?? 1, stderr: r.stderr ?? "" };
20714
+ });
20715
+ const playwrightCli = resolvePackageBin("playwright-core");
20716
+ const env = { ...process.env, PLAYWRIGHT_BROWSERS_PATH: browsersPath };
20717
+ const result = await run2(process.execPath, [playwrightCli, "install", "chromium"], env);
20718
+ if (result.code !== 0) {
20719
+ throw new Error(
20720
+ `install-browser failed (exit ${result.code}). Fix the issue (often network/proxy), then re-run \`mrrlin-mcp install-browser\`: ${result.stderr.trim()}`
20721
+ );
20722
+ }
20723
+ return { action: "installed", browsersPath };
20724
+ }
20725
+
20726
+ // src/install-codex.ts
20658
20727
  function resolveCodexHome(options) {
20659
20728
  if (options.codexHome) return options.codexHome;
20660
20729
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
20661
- return import_node_path.default.join(options.homeDir ?? import_node_os.default.homedir(), ".codex");
20730
+ return import_node_path2.default.join(options.homeDir ?? import_node_os2.default.homedir(), ".codex");
20662
20731
  }
20663
- function expectedTable(binPath, distribution) {
20664
- if (distribution === "npm") {
20665
- return {
20666
- args: ["serve"],
20667
- command: "mrrlin-mcp",
20668
- startup_timeout_sec: 30
20669
- };
20670
- }
20671
- return {
20672
- args: [binPath, "serve"],
20673
- command: "node",
20674
- startup_timeout_sec: 30
20675
- };
20732
+ function mrrlinTable(binPath, distribution) {
20733
+ if (distribution === "npm") return { command: "mrrlin-mcp", args: ["serve"], startup_timeout_sec: 30 };
20734
+ return { command: "node", args: [binPath, "serve"], startup_timeout_sec: 30 };
20735
+ }
20736
+ function browserTable(binPath, distribution, homeDir) {
20737
+ const base = distribution === "npm" ? { command: "mrrlin-mcp", args: ["browser-serve"] } : { command: "node", args: [binPath, "browser-serve"] };
20738
+ return { ...base, startup_timeout_sec: 30, env: { PLAYWRIGHT_BROWSERS_PATH: browserPaths(homeDir).browsersPath } };
20739
+ }
20740
+ function blockRegex(id) {
20741
+ const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20742
+ return new RegExp(`(^|\\n)\\[mcp_servers\\.${escaped}\\][\\s\\S]*?(?=\\n\\[|$)`);
20743
+ }
20744
+ function managedBlocks(options, distribution) {
20745
+ const homeDir = options.homeDir ?? import_node_os2.default.homedir();
20746
+ return [
20747
+ { id: "mrrlin", expected: mrrlinTable(options.binPath, distribution), blockRe: blockRegex("mrrlin") },
20748
+ {
20749
+ id: "mrrlin-browser",
20750
+ expected: browserTable(options.binPath, distribution, homeDir),
20751
+ blockRe: blockRegex("mrrlin-browser")
20752
+ }
20753
+ ];
20676
20754
  }
20677
20755
  async function detectInstallDistribution(options) {
20678
20756
  if (options.distribution && options.distribution !== "auto") return options.distribution;
20679
- let current = import_node_path.default.dirname(options.binPath);
20757
+ let current = import_node_path2.default.dirname(options.binPath);
20680
20758
  while (true) {
20681
- if (await pathExists(import_node_path.default.join(current, "pnpm-workspace.yaml"))) {
20759
+ if (await pathExists(import_node_path2.default.join(current, "pnpm-workspace.yaml"))) {
20682
20760
  return "local";
20683
20761
  }
20684
- const parent = import_node_path.default.dirname(current);
20762
+ const parent = import_node_path2.default.dirname(current);
20685
20763
  if (parent === current) break;
20686
20764
  current = parent;
20687
20765
  }
20688
20766
  return "npm";
20689
20767
  }
20690
- function renderBlock(binPath, distribution) {
20691
- const expected = expectedTable(binPath, distribution);
20692
- return [
20768
+ function renderBlock(block) {
20769
+ const { id, expected } = block;
20770
+ const lines2 = [
20693
20771
  "",
20694
- "[mcp_servers.mrrlin]",
20695
- `command = "${expected.command}"`,
20772
+ `[mcp_servers.${id}]`,
20773
+ `command = ${JSON.stringify(expected.command)}`,
20696
20774
  `args = [${expected.args.map((value) => JSON.stringify(value)).join(", ")}]`,
20697
- `startup_timeout_sec = ${expected.startup_timeout_sec}`,
20698
- ""
20699
- ].join("\n");
20775
+ `startup_timeout_sec = ${expected.startup_timeout_sec}`
20776
+ ];
20777
+ if (expected.env && Object.keys(expected.env).length > 0) {
20778
+ const inline = Object.entries(expected.env).map(([key, value]) => `${key} = ${JSON.stringify(value)}`).join(", ");
20779
+ lines2.push(`env = { ${inline} }`);
20780
+ }
20781
+ lines2.push("");
20782
+ return lines2.join("\n");
20700
20783
  }
20701
20784
  function tablesEqual(actual, expected) {
20702
20785
  if (typeof actual !== "object" || actual === null) return false;
@@ -20710,6 +20793,13 @@ function tablesEqual(actual, expected) {
20710
20793
  if (candidate.startup_timeout_sec !== void 0 && candidate.startup_timeout_sec !== expected.startup_timeout_sec) {
20711
20794
  return false;
20712
20795
  }
20796
+ const expectedEnv = expected.env ?? {};
20797
+ const actualEnv = candidate.env && typeof candidate.env === "object" ? candidate.env : {};
20798
+ const expectedKeys = Object.keys(expectedEnv);
20799
+ if (expectedKeys.length !== Object.keys(actualEnv).length) return false;
20800
+ for (const key of expectedKeys) {
20801
+ if (actualEnv[key] !== expectedEnv[key]) return false;
20802
+ }
20713
20803
  return true;
20714
20804
  }
20715
20805
  async function pathExists(target) {
@@ -20729,19 +20819,21 @@ async function resolveRealConfigPath(configPath) {
20729
20819
  }
20730
20820
  async function installCodex(options) {
20731
20821
  const codexHome = resolveCodexHome(options);
20732
- const configPath = import_node_path.default.join(codexHome, "config.toml");
20822
+ const configPath = import_node_path2.default.join(codexHome, "config.toml");
20733
20823
  const distribution = await detectInstallDistribution(options);
20734
20824
  await import_promises.default.mkdir(codexHome, { recursive: true, mode: 448 });
20735
20825
  const writePrompts = async () => installPrompts(codexHome, options.prompts ?? [], options.forcePrompts === true);
20826
+ const blocks = managedBlocks(options, distribution);
20736
20827
  if (!await pathExists(configPath)) {
20737
- await import_promises.default.writeFile(configPath, renderBlock(options.binPath, distribution).replace(/^\n/, ""), { mode: 384 });
20828
+ const content2 = blocks.map(renderBlock).join("").replace(/^\n/, "");
20829
+ await import_promises.default.writeFile(configPath, content2, { mode: 384 });
20738
20830
  return { action: "created", configPath, prompts: await writePrompts() };
20739
20831
  }
20740
20832
  const realPath = await resolveRealConfigPath(configPath);
20741
- const existing = await import_promises.default.readFile(realPath, "utf8");
20833
+ let content = await import_promises.default.readFile(realPath, "utf8");
20742
20834
  let parsed = null;
20743
20835
  try {
20744
- parsed = toml.parse(existing);
20836
+ parsed = toml.parse(content);
20745
20837
  } catch (error51) {
20746
20838
  const detail = error51 instanceof Error ? error51.message : String(error51);
20747
20839
  const err = {
@@ -20751,34 +20843,38 @@ async function installCodex(options) {
20751
20843
  };
20752
20844
  throw Object.assign(new Error(err.detail), err);
20753
20845
  }
20754
- const existingTable = parsed?.mcp_servers?.["mrrlin"];
20755
- if (existingTable !== void 0) {
20756
- if (tablesEqual(existingTable, expectedTable(options.binPath, distribution))) {
20757
- return { action: "noop", configPath: realPath, prompts: await writePrompts() };
20758
- }
20759
- if (!options.force) {
20760
- const err = {
20761
- code: "CODEX_CONFIG_CONFLICT",
20762
- configPath: realPath,
20763
- detail: "An [mcp_servers.mrrlin] block already exists with different settings. Re-run with --force to replace it, or remove it manually."
20764
- };
20765
- throw Object.assign(new Error(err.detail), err);
20846
+ let action = "noop";
20847
+ for (const block of blocks) {
20848
+ const existingTable = parsed?.mcp_servers?.[block.id];
20849
+ if (existingTable !== void 0) {
20850
+ if (tablesEqual(existingTable, block.expected)) continue;
20851
+ if (!options.force) {
20852
+ const err = {
20853
+ code: "CODEX_CONFIG_CONFLICT",
20854
+ configPath: realPath,
20855
+ detail: `An [mcp_servers.${block.id}] block already exists with different settings. Re-run with --force to replace it, or remove it manually.`
20856
+ };
20857
+ throw Object.assign(new Error(err.detail), err);
20858
+ }
20859
+ content = replaceBlock(content, block.blockRe, renderBlock(block));
20860
+ action = "replaced";
20861
+ } else {
20862
+ content = appendBlock(content, renderBlock(block));
20863
+ if (action !== "replaced") action = "appended";
20766
20864
  }
20767
- const replaced = replaceMrrlinBlock(existing, renderBlock(options.binPath, distribution));
20768
- await import_promises.default.writeFile(realPath, replaced, { mode: 384 });
20769
- return { action: "replaced", configPath: realPath, prompts: await writePrompts() };
20770
20865
  }
20771
- const appended = appendMrrlinBlock(existing, renderBlock(options.binPath, distribution));
20772
- await import_promises.default.writeFile(realPath, appended, { mode: 384 });
20773
- return { action: "appended", configPath: realPath, prompts: await writePrompts() };
20866
+ if (action !== "noop") {
20867
+ await import_promises.default.writeFile(realPath, content, { mode: 384 });
20868
+ }
20869
+ return { action, configPath: realPath, prompts: await writePrompts() };
20774
20870
  }
20775
20871
  async function installPrompts(codexHome, prompts, forcePrompts) {
20776
20872
  if (prompts.length === 0) return [];
20777
- const promptsDir2 = import_node_path.default.join(codexHome, "prompts");
20873
+ const promptsDir2 = import_node_path2.default.join(codexHome, "prompts");
20778
20874
  await import_promises.default.mkdir(promptsDir2, { recursive: true, mode: 448 });
20779
20875
  const out = [];
20780
20876
  for (const prompt of prompts) {
20781
- const promptPath = import_node_path.default.join(promptsDir2, `${prompt.name}.md`);
20877
+ const promptPath = import_node_path2.default.join(promptsDir2, `${prompt.name}.md`);
20782
20878
  let existing = null;
20783
20879
  try {
20784
20880
  existing = await import_promises.default.readFile(promptPath, "utf8");
@@ -20803,17 +20899,16 @@ async function installPrompts(codexHome, prompts, forcePrompts) {
20803
20899
  }
20804
20900
  return out;
20805
20901
  }
20806
- function appendMrrlinBlock(existing, block) {
20902
+ function appendBlock(existing, block) {
20807
20903
  const trimmed = existing.replace(/\s+$/, "");
20808
20904
  return `${trimmed}
20809
20905
  ${block.startsWith("\n") ? block : `
20810
20906
  ${block}`}`.replace(/\n{3,}/g, "\n\n");
20811
20907
  }
20812
- var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.mrrlin\][\s\S]*?(?=\n\[|$)/;
20813
- function replaceMrrlinBlock(existing, block) {
20908
+ function replaceBlock(existing, blockRe, block) {
20814
20909
  const replacement = block.startsWith("\n") ? block : `
20815
20910
  ${block}`;
20816
- return existing.replace(MRRLIN_BLOCK_RE, (match) => {
20911
+ return existing.replace(blockRe, (match) => {
20817
20912
  const prefix = match.startsWith("\n") ? "\n" : "";
20818
20913
  return `${prefix}${replacement.replace(/^\n+/, "")}`;
20819
20914
  });
@@ -20822,11 +20917,203 @@ ${block}`;
20822
20917
  // src/director-bridge.ts
20823
20918
  var import_node_fs12 = __toESM(require("node:fs"), 1);
20824
20919
  var import_node_http = __toESM(require("node:http"), 1);
20825
- var import_node_os8 = __toESM(require("node:os"), 1);
20826
- var import_node_path12 = __toESM(require("node:path"), 1);
20827
- var import_node_child_process4 = require("node:child_process");
20920
+ var import_node_os9 = __toESM(require("node:os"), 1);
20921
+ var import_node_path13 = __toESM(require("node:path"), 1);
20922
+ var import_node_child_process5 = require("node:child_process");
20828
20923
  var import_node_crypto5 = __toESM(require("node:crypto"), 1);
20829
20924
 
20925
+ // src/turn-replay-buffer.ts
20926
+ var DEFAULT_GRACE_MS = 3e4;
20927
+ var DEFAULT_MAX_EVENTS = 2e3;
20928
+ var DEFAULT_MAX_BYTES = 4e6;
20929
+ var DEFAULT_POST_COMPLETION_TTL_MS = 1e4;
20930
+ function createReplayBuffer(opts) {
20931
+ return {
20932
+ turnId: opts.turnId,
20933
+ spanId: opts.spanId,
20934
+ bindEpoch: opts.bindEpoch ?? 0,
20935
+ events: [],
20936
+ lastSeq: 0,
20937
+ state: "live",
20938
+ terminalDelivered: false,
20939
+ replaying: false,
20940
+ outboundQueue: [],
20941
+ graceTimer: null,
20942
+ finishedAt: null,
20943
+ bytesUsed: 0,
20944
+ graceMs: opts.graceMs ?? DEFAULT_GRACE_MS,
20945
+ maxEvents: opts.maxEvents ?? DEFAULT_MAX_EVENTS,
20946
+ maxBytes: opts.maxBytes ?? DEFAULT_MAX_BYTES,
20947
+ postCompletionTtlMs: opts.postCompletionTtlMs ?? DEFAULT_POST_COMPLETION_TTL_MS,
20948
+ triggerGrace: null
20949
+ };
20950
+ }
20951
+ function recordOutgoing(buf, msg) {
20952
+ const seq = ++buf.lastSeq;
20953
+ const entry = { seq, msg };
20954
+ buf.events.push(entry);
20955
+ buf.bytesUsed += approxByteSize(msg);
20956
+ while ((buf.events.length > buf.maxEvents || buf.bytesUsed > buf.maxBytes) && buf.events.length > 0) {
20957
+ const dropped = buf.events.shift();
20958
+ if (!dropped) break;
20959
+ buf.bytesUsed -= approxByteSize(dropped.msg);
20960
+ }
20961
+ return entry;
20962
+ }
20963
+ function eventsAfter(buf, lastSeq) {
20964
+ const first = buf.events[0];
20965
+ if (first && lastSeq < first.seq - 1) return null;
20966
+ return buf.events.filter((e) => e.seq > lastSeq);
20967
+ }
20968
+ function enterGrace(buf, onExpire) {
20969
+ if (buf.graceTimer !== null) return;
20970
+ buf.state = "grace";
20971
+ buf.graceTimer = setTimeout(onExpire, buf.graceMs);
20972
+ }
20973
+ function cancelGrace(buf) {
20974
+ if (buf.graceTimer !== null) {
20975
+ clearTimeout(buf.graceTimer);
20976
+ buf.graceTimer = null;
20977
+ }
20978
+ if (buf.state === "grace") buf.state = "live";
20979
+ }
20980
+ function recordInterrupted(buf) {
20981
+ if (buf.terminalDelivered) return null;
20982
+ const msg = {
20983
+ type: "event",
20984
+ event: { type: "result", subtype: "interrupted" }
20985
+ };
20986
+ const entry = recordOutgoing(buf, msg);
20987
+ buf.terminalDelivered = true;
20988
+ return entry;
20989
+ }
20990
+ function markCompleted(buf, now) {
20991
+ buf.state = "completed";
20992
+ buf.finishedAt = now;
20993
+ }
20994
+ function shouldGc(buf, now) {
20995
+ if (buf.state !== "completed") return false;
20996
+ if (buf.finishedAt === null) return false;
20997
+ return now - buf.finishedAt > buf.postCompletionTtlMs;
20998
+ }
20999
+ function incrementBindEpoch(buf) {
21000
+ return ++buf.bindEpoch;
21001
+ }
21002
+ function isTerminalEvent(msg) {
21003
+ if (typeof msg !== "object" || msg === null) return false;
21004
+ const outer = msg;
21005
+ if (outer.type !== "event") return false;
21006
+ if (typeof outer.event !== "object" || outer.event === null) return false;
21007
+ const inner = outer.event;
21008
+ return inner.type === "result";
21009
+ }
21010
+ function approxByteSize(msg) {
21011
+ try {
21012
+ return JSON.stringify(msg).length;
21013
+ } catch {
21014
+ return 0;
21015
+ }
21016
+ }
21017
+
21018
+ // src/replay-state-machine.ts
21019
+ function transition(state, event) {
21020
+ if (event.kind === "resume" && !event.epochMatch) return { next: "invalid" };
21021
+ switch (state) {
21022
+ case "live":
21023
+ switch (event.kind) {
21024
+ case "socket_close":
21025
+ return { next: "grace", sideEffects: ["start_grace_timer"] };
21026
+ case "codex_terminal":
21027
+ return { next: "completed", sideEffects: ["mark_finished"] };
21028
+ case "stop":
21029
+ return {
21030
+ next: "interrupted",
21031
+ sideEffects: ["record_interrupted", "fire_turn_interrupt"]
21032
+ };
21033
+ default:
21034
+ return { next: "invalid" };
21035
+ }
21036
+ case "grace":
21037
+ switch (event.kind) {
21038
+ case "resume":
21039
+ return {
21040
+ next: "live",
21041
+ sideEffects: [
21042
+ "cancel_grace_timer",
21043
+ "rebind_sink_increment_epoch",
21044
+ "replay_drain"
21045
+ ]
21046
+ };
21047
+ case "grace_expire":
21048
+ return {
21049
+ next: "interrupted",
21050
+ sideEffects: ["record_interrupted", "fire_turn_interrupt"]
21051
+ };
21052
+ case "stop":
21053
+ return {
21054
+ next: "interrupted",
21055
+ sideEffects: [
21056
+ "cancel_grace_timer",
21057
+ "record_interrupted",
21058
+ "fire_turn_interrupt"
21059
+ ]
21060
+ };
21061
+ case "codex_terminal":
21062
+ return {
21063
+ next: "completed",
21064
+ sideEffects: ["cancel_grace_timer", "mark_finished"]
21065
+ };
21066
+ default:
21067
+ return { next: "invalid" };
21068
+ }
21069
+ case "interrupted":
21070
+ switch (event.kind) {
21071
+ case "resume":
21072
+ return {
21073
+ next: "interrupted",
21074
+ sideEffects: ["rebind_sink_increment_epoch", "replay_drain"]
21075
+ };
21076
+ case "codex_terminal":
21077
+ return { next: "interrupted", sideEffects: ["drop_with_warn"] };
21078
+ case "result_delivered_to_client":
21079
+ return { next: "completed", sideEffects: ["mark_finished"] };
21080
+ default:
21081
+ return { next: "invalid" };
21082
+ }
21083
+ case "completed":
21084
+ if (event.kind === "resume") {
21085
+ return {
21086
+ next: "completed",
21087
+ sideEffects: ["rebind_sink_increment_epoch", "replay_drain"]
21088
+ };
21089
+ }
21090
+ return { next: "completed", sideEffects: [] };
21091
+ }
21092
+ }
21093
+
21094
+ // src/bridge-tombstone.ts
21095
+ var DEFAULT_TOMBSTONE_TTL_MS = 36e5;
21096
+ function writeTombstone(tombstones, directorSessionId, buf, now) {
21097
+ tombstones.set(directorSessionId, {
21098
+ turnId: buf.turnId,
21099
+ lastSeq: buf.lastSeq,
21100
+ expiredAt: now
21101
+ });
21102
+ }
21103
+ function lookupTombstone(tombstones, directorSessionId) {
21104
+ return tombstones.get(directorSessionId) ?? null;
21105
+ }
21106
+ function sweepExpiredTombstones(tombstones, now, ttlMs = DEFAULT_TOMBSTONE_TTL_MS) {
21107
+ let removed = 0;
21108
+ for (const [sid, t] of tombstones) {
21109
+ if (now - t.expiredAt > ttlMs) {
21110
+ tombstones.delete(sid);
21111
+ removed += 1;
21112
+ }
21113
+ }
21114
+ return removed;
21115
+ }
21116
+
20830
21117
  // ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
20831
21118
  var import_stream = __toESM(require_stream(), 1);
20832
21119
  var import_extension = __toESM(require_extension(), 1);
@@ -20948,7 +21235,7 @@ var CodexJsonRpcClient = class {
20948
21235
  };
20949
21236
 
20950
21237
  // ../../packages/codex-client/dist/server-manager.js
20951
- var import_node_child_process = require("node:child_process");
21238
+ var import_node_child_process2 = require("node:child_process");
20952
21239
  var CodexServerManager = class {
20953
21240
  client = null;
20954
21241
  process = null;
@@ -20989,7 +21276,7 @@ var CodexServerManager = class {
20989
21276
  }
20990
21277
  async startServer(config2) {
20991
21278
  const executable = config2?.codexExecutable ?? "codex";
20992
- const spawnFn = config2?.spawn ?? import_node_child_process.spawn;
21279
+ const spawnFn = config2?.spawn ?? import_node_child_process2.spawn;
20993
21280
  const child = spawnFn(executable, ["app-server"], {
20994
21281
  stdio: ["pipe", "pipe", "pipe"],
20995
21282
  cwd: config2?.cwd,
@@ -22134,10 +22421,10 @@ function mergeDefs(...defs) {
22134
22421
  function cloneDef(schema) {
22135
22422
  return mergeDefs(schema._zod.def);
22136
22423
  }
22137
- function getElementAtPath(obj, path15) {
22138
- if (!path15)
22424
+ function getElementAtPath(obj, path16) {
22425
+ if (!path16)
22139
22426
  return obj;
22140
- return path15.reduce((acc, key) => acc?.[key], obj);
22427
+ return path16.reduce((acc, key) => acc?.[key], obj);
22141
22428
  }
22142
22429
  function promiseAllObject(promisesObj) {
22143
22430
  const keys = Object.keys(promisesObj);
@@ -22546,11 +22833,11 @@ function explicitlyAborted(x, startIndex = 0) {
22546
22833
  }
22547
22834
  return false;
22548
22835
  }
22549
- function prefixIssues(path15, issues) {
22836
+ function prefixIssues(path16, issues) {
22550
22837
  return issues.map((iss) => {
22551
22838
  var _a3;
22552
22839
  (_a3 = iss).path ?? (_a3.path = []);
22553
- iss.path.unshift(path15);
22840
+ iss.path.unshift(path16);
22554
22841
  return iss;
22555
22842
  });
22556
22843
  }
@@ -22697,16 +22984,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
22697
22984
  }
22698
22985
  function formatError(error51, mapper = (issue2) => issue2.message) {
22699
22986
  const fieldErrors = { _errors: [] };
22700
- const processError = (error52, path15 = []) => {
22987
+ const processError = (error52, path16 = []) => {
22701
22988
  for (const issue2 of error52.issues) {
22702
22989
  if (issue2.code === "invalid_union" && issue2.errors.length) {
22703
- issue2.errors.map((issues) => processError({ issues }, [...path15, ...issue2.path]));
22990
+ issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
22704
22991
  } else if (issue2.code === "invalid_key") {
22705
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
22992
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22706
22993
  } else if (issue2.code === "invalid_element") {
22707
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
22994
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22708
22995
  } else {
22709
- const fullpath = [...path15, ...issue2.path];
22996
+ const fullpath = [...path16, ...issue2.path];
22710
22997
  if (fullpath.length === 0) {
22711
22998
  fieldErrors._errors.push(mapper(issue2));
22712
22999
  } else {
@@ -22733,17 +23020,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
22733
23020
  }
22734
23021
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
22735
23022
  const result = { errors: [] };
22736
- const processError = (error52, path15 = []) => {
23023
+ const processError = (error52, path16 = []) => {
22737
23024
  var _a3, _b;
22738
23025
  for (const issue2 of error52.issues) {
22739
23026
  if (issue2.code === "invalid_union" && issue2.errors.length) {
22740
- issue2.errors.map((issues) => processError({ issues }, [...path15, ...issue2.path]));
23027
+ issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
22741
23028
  } else if (issue2.code === "invalid_key") {
22742
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
23029
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22743
23030
  } else if (issue2.code === "invalid_element") {
22744
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
23031
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22745
23032
  } else {
22746
- const fullpath = [...path15, ...issue2.path];
23033
+ const fullpath = [...path16, ...issue2.path];
22747
23034
  if (fullpath.length === 0) {
22748
23035
  result.errors.push(mapper(issue2));
22749
23036
  continue;
@@ -22775,8 +23062,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
22775
23062
  }
22776
23063
  function toDotPath(_path) {
22777
23064
  const segs = [];
22778
- const path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
22779
- for (const seg of path15) {
23065
+ const path16 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
23066
+ for (const seg of path16) {
22780
23067
  if (typeof seg === "number")
22781
23068
  segs.push(`[${seg}]`);
22782
23069
  else if (typeof seg === "symbol")
@@ -35468,13 +35755,13 @@ function resolveRef(ref, ctx) {
35468
35755
  if (!ref.startsWith("#")) {
35469
35756
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
35470
35757
  }
35471
- const path15 = ref.slice(1).split("/").filter(Boolean);
35472
- if (path15.length === 0) {
35758
+ const path16 = ref.slice(1).split("/").filter(Boolean);
35759
+ if (path16.length === 0) {
35473
35760
  return ctx.rootSchema;
35474
35761
  }
35475
35762
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
35476
- if (path15[0] === defsKey) {
35477
- const key = path15[1];
35763
+ if (path16[0] === defsKey) {
35764
+ const key = path16[1];
35478
35765
  if (!key || !ctx.defs[key]) {
35479
35766
  throw new Error(`Reference not found: ${ref}`);
35480
35767
  }
@@ -35888,6 +36175,7 @@ var openApiOperationIds = {
35888
36175
  archivePlan: "archivePlan",
35889
36176
  bindProjectGithubRepo: "bindProjectGithubRepo",
35890
36177
  createExecutionRun: "createExecutionRun",
36178
+ createExecutionRunHandoff: "createExecutionRunHandoff",
35891
36179
  createAsyncJob: "createAsyncJob",
35892
36180
  getAsyncJob: "getAsyncJob",
35893
36181
  getActiveAsyncJob: "getActiveAsyncJob",
@@ -35987,7 +36275,7 @@ var operatorSessionSchema = external_exports.object({
35987
36275
  issuedAt: external_exports.number().int().positive(),
35988
36276
  kind: external_exports.enum(["web", "agent"]).default("web"),
35989
36277
  login: external_exports.string().min(1),
35990
- projectSlug: external_exports.string().min(1),
36278
+ projectSlug: external_exports.string().min(1).optional(),
35991
36279
  provider: external_exports.literal("github"),
35992
36280
  repo: external_exports.string().min(1).nullable(),
35993
36281
  // ADR 0016: `scope` distinguishes project-pinned agent tokens (legacy, default) from
@@ -35996,7 +36284,7 @@ var operatorSessionSchema = external_exports.object({
35996
36284
  // cleanly into the project branch of the middleware (which mirrors today's behavior).
35997
36285
  scope: external_exports.enum(["project", "operator"]).default("project")
35998
36286
  });
35999
- var AGENT_SESSION_TTL_MS = 1e3 * 60 * 60;
36287
+ var AGENT_SESSION_TTL_MS = 1e3 * 60 * 15;
36000
36288
 
36001
36289
  // ../../packages/schemas/dist/github-state.js
36002
36290
  var TTL_MS = 10 * 6e4;
@@ -36114,6 +36402,7 @@ var mrrlinTaskTypeSchema = external_exports.enum(["task", "bug"]);
36114
36402
  var mrrlinTaskImpactSchema = external_exports.enum(["low", "medium", "high"]);
36115
36403
  var mrrlinAutonomyLevelSchema = external_exports.enum(["auto", "minimal_human", "human_only"]);
36116
36404
  var mrrlinAutoDeploySchema = external_exports.enum(["off", "dev", "prod"]);
36405
+ var mrrlinSpecApprovedSchema = external_exports.enum(["pending", "approved", "skipped", "skipped_legacy"]);
36117
36406
  var mrrlinTaskSourceSchema = external_exports.enum(["fixture-import", "api"]);
36118
36407
  var mrrlinPlanStatusSchema = external_exports.enum(["active", "paused", "done", "archived"]);
36119
36408
  var mrrlinTaskEventTypeSchema = external_exports.enum(["autonomy_set", "director_thread_reset", "note"]);
@@ -36204,7 +36493,13 @@ var mrrlinTaskSchema = external_exports.object({
36204
36493
  latestJudgementAt: external_exports.string().datetime().nullable().default(null),
36205
36494
  latestJudgementKind: external_exports.enum(["autonomy", "handoff"]).nullable().default(null),
36206
36495
  notes: external_exports.string().nullable().default(null),
36496
+ // Raw operator request captured at task creation (operator-authored ONLY, never Director-generated).
36497
+ // The intent-aware spec gate judges the spec against this; null/absent ⇒ the gate fail-closes.
36498
+ // Output-optional (not .default) so existing task fixtures need no churn; DB rows always resolve it
36499
+ // to `string | null` via taskRowToTask.
36500
+ operatorSeedRequest: external_exports.string().max(8e3).nullable().optional(),
36207
36501
  planId: mrrlinPlanIdSchema.nullable(),
36502
+ specApproved: mrrlinSpecApprovedSchema.optional(),
36208
36503
  specWikiPageId: mrrlinWikiPageIdSchema.nullable(),
36209
36504
  status: mrrlinTaskStatusSchema,
36210
36505
  subcategory: taxonomySubcategorySchema,
@@ -36220,6 +36515,7 @@ var mrrlinPlanSchema = external_exports.object({
36220
36515
  id: mrrlinPlanIdSchema,
36221
36516
  name: external_exports.string().min(1),
36222
36517
  progress: external_exports.number().min(0).max(1),
36518
+ specWikiPageId: external_exports.string().nullable().default(null),
36223
36519
  status: mrrlinPlanStatusSchema,
36224
36520
  taskCount: external_exports.number().int().nonnegative()
36225
36521
  });
@@ -36344,6 +36640,7 @@ var mrrlinTaskCreateSchema = external_exports.object({
36344
36640
  id: mrrlinTaskIdSchema,
36345
36641
  impact: mrrlinTaskImpactSchema.default("medium"),
36346
36642
  notes: external_exports.string().nullable().optional(),
36643
+ operatorSeedRequest: external_exports.string().max(8e3).nullable().optional(),
36347
36644
  planId: mrrlinPlanIdSchema.nullable().optional(),
36348
36645
  specWikiPageId: mrrlinWikiPageIdSchema.nullable().optional(),
36349
36646
  tags: mrrlinTaskTagsSchema.optional(),
@@ -36367,6 +36664,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
36367
36664
  impact: mrrlinTaskImpactSchema.optional(),
36368
36665
  notes: external_exports.string().nullable().optional(),
36369
36666
  planId: mrrlinPlanIdSchema.nullable().optional(),
36667
+ specApproved: mrrlinSpecApprovedSchema.optional(),
36370
36668
  specWikiPageId: mrrlinWikiPageIdSchema.nullable().optional(),
36371
36669
  status: mrrlinTaskStatusSchema.optional(),
36372
36670
  subcategory: taxonomySubcategorySchema.optional(),
@@ -36374,7 +36672,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
36374
36672
  type: mrrlinTaskTypeSchema.optional(),
36375
36673
  followUpAt: external_exports.string().datetime().nullable().optional(),
36376
36674
  verificationDueAt: external_exports.string().datetime().nullable().optional()
36377
- }).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
36675
+ }).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specApproved !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
36378
36676
  if (value.autonomyLevel !== void 0 && value.autonomyReason === void 0) {
36379
36677
  context.addIssue({
36380
36678
  code: external_exports.ZodIssueCode.custom,
@@ -36415,12 +36713,14 @@ var mrrlinPlanCreateSchema = external_exports.object({
36415
36713
  goal: external_exports.string().min(1),
36416
36714
  id: mrrlinPlanIdSchema,
36417
36715
  name: external_exports.string().min(1),
36716
+ specWikiPageId: external_exports.string().nullable().optional(),
36418
36717
  status: mrrlinPlanStatusSchema.default("active")
36419
36718
  });
36420
36719
  var mrrlinPlanUpdateSchema = external_exports.object({
36421
36720
  dueDate: external_exports.string().date().nullable().optional(),
36422
36721
  goal: external_exports.string().min(1).optional(),
36423
36722
  name: external_exports.string().min(1).optional(),
36723
+ specWikiPageId: external_exports.string().nullable().optional(),
36424
36724
  status: mrrlinPlanStatusSchema.optional()
36425
36725
  }).refine((value) => Object.keys(value).length > 0, { message: "PlanUpdate requires at least one field" });
36426
36726
  var mrrlinTaxonomyCreateSchema = mrrlinTaxonomyEntrySchema;
@@ -36643,6 +36943,10 @@ var markSpecReadyResponseSchema = external_exports.object({
36643
36943
  var wikiPageSpecReadyCasResponseSchema = external_exports.object({
36644
36944
  data: external_exports.object({ promoted: external_exports.literal(true) })
36645
36945
  });
36946
+ var mrrlinRunPrerequisiteSchema = external_exports.object({
36947
+ mcp: external_exports.string().min(1),
36948
+ reason: external_exports.string().min(1)
36949
+ });
36646
36950
  var mrrlinExecutionRunSchema = external_exports.object({
36647
36951
  actor: external_exports.string().min(1),
36648
36952
  baseSha: external_exports.string().min(1).nullable(),
@@ -36651,6 +36955,7 @@ var mrrlinExecutionRunSchema = external_exports.object({
36651
36955
  claimedAt: external_exports.string().datetime().nullable(),
36652
36956
  codeExecution: external_exports.boolean(),
36653
36957
  createdAt: external_exports.string().datetime(),
36958
+ devEnvUrl: external_exports.string().min(1).nullable(),
36654
36959
  devRunUrl: external_exports.string().min(1).nullable(),
36655
36960
  devWorkflowId: external_exports.number().int().positive().nullable(),
36656
36961
  directorSessionId: external_exports.string().min(1).nullable(),
@@ -36659,6 +36964,8 @@ var mrrlinExecutionRunSchema = external_exports.object({
36659
36964
  id: mrrlinExecutionRunIdSchema,
36660
36965
  lastActor: external_exports.string().min(1).nullable(),
36661
36966
  leaseId: external_exports.string().min(1).nullable(),
36967
+ prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema),
36968
+ prodEnvUrl: external_exports.string().min(1).nullable(),
36662
36969
  prodRunUrl: external_exports.string().min(1).nullable(),
36663
36970
  prodWorkflowId: external_exports.number().int().positive().nullable(),
36664
36971
  projectSlug: mrrlinProjectSlugSchema,
@@ -36677,6 +36984,7 @@ var mrrlinExecutionRunCreateSchema = external_exports.object({
36677
36984
  codeExecution: external_exports.boolean().optional().default(false),
36678
36985
  devWorkflowId: external_exports.number().int().positive().optional(),
36679
36986
  id: mrrlinExecutionRunIdSchema,
36987
+ prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema).default([]),
36680
36988
  prodWorkflowId: external_exports.number().int().positive().optional(),
36681
36989
  provider: external_exports.string().min(1),
36682
36990
  status: mrrlinExecutionRunStatusSchema.default("pending"),
@@ -36687,11 +36995,13 @@ var mrrlinExecutionRunUpdateSchema = external_exports.object({
36687
36995
  baseSha: external_exports.string().min(1).nullable().optional(),
36688
36996
  branch: external_exports.string().min(1).nullable().optional(),
36689
36997
  checkpointCursor: external_exports.string().min(1).nullable().optional(),
36998
+ devEnvUrl: external_exports.string().min(1).nullable().optional(),
36690
36999
  devRunUrl: external_exports.string().min(1).nullable().optional(),
36691
37000
  devWorkflowId: external_exports.number().int().positive().nullable().optional(),
36692
37001
  finishedAt: external_exports.string().datetime().nullable().optional(),
36693
37002
  headSha: external_exports.string().min(1).nullable().optional(),
36694
37003
  leaseId: external_exports.string().min(1).nullable().optional(),
37004
+ prodEnvUrl: external_exports.string().min(1).nullable().optional(),
36695
37005
  prodRunUrl: external_exports.string().min(1).nullable().optional(),
36696
37006
  prodWorkflowId: external_exports.number().int().positive().nullable().optional(),
36697
37007
  pullRequestUrl: external_exports.string().min(1).nullable().optional(),
@@ -36739,6 +37049,7 @@ var mrrlinResolveHandoffSchema = external_exports.object({
36739
37049
  }
36740
37050
  });
36741
37051
  var resolveHandoffResponseSchema = external_exports.object({ data: mrrlinExecutionRunSchema });
37052
+ var createExecutionRunHandoffSchema = external_exports.object({ reason: external_exports.string().min(1) });
36742
37053
  var mrrlinExecutionRunTouchSchema = external_exports.object({
36743
37054
  leaseId: external_exports.string().min(1)
36744
37055
  });
@@ -36804,7 +37115,9 @@ var exchangeAgentTokenRequestSchema = external_exports.object({
36804
37115
  var exchangeAgentTokenResponseSchema = external_exports.object({
36805
37116
  token: external_exports.string().min(1),
36806
37117
  expiresAt: external_exports.string().datetime(),
36807
- projectSlug: external_exports.string().min(1),
37118
+ // ADR 0016 §T7 amendment: operator-scope exchanges return no projectSlug (the token is
37119
+ // operator-wide); project-scope exchanges still return the pinned slug.
37120
+ projectSlug: external_exports.string().min(1).optional(),
36808
37121
  login: external_exports.string().min(1)
36809
37122
  });
36810
37123
  var MRRLIN_ARTIFACT_FILE_MAX_BYTES = 5 * 1024 * 1024;
@@ -36822,6 +37135,7 @@ var mrrlinArtifactFileMimeTypes = [
36822
37135
  ];
36823
37136
  var mrrlinArtifactFileClassSchema = external_exports.enum(["temp", "durable"]);
36824
37137
  var mrrlinArtifactFileStatusSchema = external_exports.enum(["pending", "uploaded", "expired"]);
37138
+ var mrrlinArtifactFileVisibilitySchema = external_exports.enum(["private", "public"]);
36825
37139
  var mrrlinArtifactFileSchema = external_exports.object({
36826
37140
  class: mrrlinArtifactFileClassSchema,
36827
37141
  contentType: external_exports.enum(mrrlinArtifactFileMimeTypes),
@@ -36836,7 +37150,9 @@ var mrrlinArtifactFileSchema = external_exports.object({
36836
37150
  // min(0): reads tolerate 0-byte rows; creation requires min(1) (see create schema).
36837
37151
  sizeBytes: external_exports.number().int().min(0).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
36838
37152
  status: mrrlinArtifactFileStatusSchema,
36839
- taskId: mrrlinTaskIdSchema.nullable()
37153
+ taskId: mrrlinTaskIdSchema.nullable(),
37154
+ // Defaulted (fail-safe → private) so legacy rows/fixtures predating the column read as private.
37155
+ visibility: mrrlinArtifactFileVisibilitySchema.default("private")
36840
37156
  });
36841
37157
  var mrrlinArtifactFileCreateSchema = external_exports.object({
36842
37158
  class: mrrlinArtifactFileClassSchema,
@@ -36844,7 +37160,9 @@ var mrrlinArtifactFileCreateSchema = external_exports.object({
36844
37160
  filename: external_exports.string().min(1).max(255),
36845
37161
  runId: mrrlinExecutionRunIdSchema.optional(),
36846
37162
  sizeBytes: external_exports.number().int().min(1).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
36847
- taskId: mrrlinTaskIdSchema.optional()
37163
+ taskId: mrrlinTaskIdSchema.optional(),
37164
+ // Optional + fail-safe: callers must opt in to 'public'; everything else stays private.
37165
+ visibility: mrrlinArtifactFileVisibilitySchema.optional().default("private")
36848
37166
  });
36849
37167
  var mrrlinArtifactFileUploadTargetSchema = external_exports.discriminatedUnion("kind", [
36850
37168
  external_exports.object({ kind: external_exports.literal("presigned-post"), url: external_exports.string().min(1), fields: external_exports.record(external_exports.string(), external_exports.string()) }),
@@ -36967,6 +37285,8 @@ var mrrlinInboxItemSchema = external_exports.object({
36967
37285
  directorSessionId: external_exports.string().min(1).nullable(),
36968
37286
  id: mrrlinInboxItemIdSchema,
36969
37287
  kind: mrrlinInboxItemKindSchema,
37288
+ origin: external_exports.string().nullable().optional(),
37289
+ planId: mrrlinPlanIdSchema.nullable().default(null),
36970
37290
  projectSlug: mrrlinProjectSlugSchema,
36971
37291
  readAt: external_exports.string().datetime().nullable(),
36972
37292
  status: mrrlinInboxItemStatusSchema,
@@ -36978,6 +37298,8 @@ var mrrlinInboxItemCreateSchema = external_exports.object({
36978
37298
  directorSessionId: external_exports.string().min(1).optional(),
36979
37299
  id: mrrlinInboxItemIdSchema,
36980
37300
  kind: mrrlinInboxItemKindSchema,
37301
+ origin: external_exports.string().min(1).optional(),
37302
+ planId: mrrlinPlanIdSchema.nullable().optional(),
36981
37303
  taskId: mrrlinTaskIdSchema.nullable().optional()
36982
37304
  });
36983
37305
  var mrrlinInboxItemDecideSchema = external_exports.object({
@@ -37108,18 +37430,18 @@ function createMrrlinClient(config2) {
37108
37430
  const customFetch = config2.fetch ?? globalThis.fetch;
37109
37431
  const baseUrl = config2.baseUrl.replace(/\/$/, "");
37110
37432
  const token = config2.token;
37111
- async function request(path15, init) {
37433
+ async function request(path16, init) {
37112
37434
  const method = init?.method ?? "GET";
37113
37435
  const headers = new Headers(init?.headers ?? {});
37114
37436
  if (token && !headers.has("authorization")) {
37115
37437
  headers.set("authorization", `Bearer ${token}`);
37116
37438
  }
37117
- const response = await customFetch(`${baseUrl}${path15}`, { ...init, headers });
37439
+ const response = await customFetch(`${baseUrl}${path16}`, { ...init, headers });
37118
37440
  if (!response.ok) {
37119
37441
  const body = await response.text();
37120
37442
  let code = `HTTP_${response.status}`;
37121
37443
  let violations = null;
37122
- let message = `Mrrlin API ${method} ${path15} failed: ${response.status}`;
37444
+ let message = `Mrrlin API ${method} ${path16} failed: ${response.status}`;
37123
37445
  try {
37124
37446
  const parsed = JSON.parse(body);
37125
37447
  const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
@@ -37139,7 +37461,7 @@ function createMrrlinClient(config2) {
37139
37461
  throw new MrrlinApiError({
37140
37462
  code,
37141
37463
  method,
37142
- path: path15,
37464
+ path: path16,
37143
37465
  responseBody: body,
37144
37466
  status: response.status,
37145
37467
  violations,
@@ -37386,7 +37708,7 @@ function createMrrlinClient(config2) {
37386
37708
  return taskEventListResponseSchema.parse(body).data;
37387
37709
  },
37388
37710
  async listTasks(projectSlug, filters = {}) {
37389
- const path15 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
37711
+ const path16 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
37390
37712
  assignee: filters.assignee,
37391
37713
  autonomyLevel: filters.autonomyLevel,
37392
37714
  blockedBy: filters.blockedBy,
@@ -37398,7 +37720,7 @@ function createMrrlinClient(config2) {
37398
37720
  subcategory: filters.subcategory,
37399
37721
  type: filters.type
37400
37722
  });
37401
- const body = await request(path15);
37723
+ const body = await request(path16);
37402
37724
  return taskListResponseSchema.parse(body).data;
37403
37725
  },
37404
37726
  async listTaxonomy(projectSlug) {
@@ -37406,22 +37728,22 @@ function createMrrlinClient(config2) {
37406
37728
  return taxonomyListResponseSchema.parse(body).data;
37407
37729
  },
37408
37730
  async listWikiPages(projectSlug, filters = {}) {
37409
- const path15 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
37731
+ const path16 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
37410
37732
  folder: filters.folder,
37411
37733
  q: filters.q,
37412
37734
  taskId: filters.taskId
37413
37735
  });
37414
- const body = await request(path15);
37736
+ const body = await request(path16);
37415
37737
  return wikiPageListResponseSchema.parse(body).data;
37416
37738
  },
37417
37739
  async searchWikiPages(projectSlug, query) {
37418
- const path15 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
37740
+ const path16 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
37419
37741
  folder: query.folder,
37420
37742
  limit: query.limit === void 0 ? void 0 : String(query.limit),
37421
37743
  pathPrefix: query.pathPrefix,
37422
37744
  q: query.q
37423
37745
  });
37424
- const body = await request(path15);
37746
+ const body = await request(path16);
37425
37747
  return wikiPageSearchResponseSchema.parse(body).data;
37426
37748
  },
37427
37749
  async updatePlan(projectSlug, planId, patch) {
@@ -37687,6 +38009,14 @@ function createMrrlinClient(config2) {
37687
38009
  });
37688
38010
  return executionRunResponseSchema.parse(body).data;
37689
38011
  },
38012
+ async createExecutionRunHandoff(projectSlug, runId, input) {
38013
+ const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/handoff`, {
38014
+ body: JSON.stringify(input),
38015
+ headers: { "content-type": "application/json" },
38016
+ method: "POST"
38017
+ });
38018
+ return executionRunResponseSchema.parse(body).data;
38019
+ },
37690
38020
  async listExecutionArtifacts(projectSlug, runId) {
37691
38021
  const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/artifacts`);
37692
38022
  return executionArtifactListResponseSchema.parse(body).data;
@@ -37962,13 +38292,13 @@ function startSelfUpdate(deps) {
37962
38292
  });
37963
38293
  return `[bridge:update] An update for @mrrlin-dev/mcp is available: ${pkgVersion} \u2192 ${latestVersion}.
37964
38294
 
37965
- This turn, at a natural pause, ASK the operator a yes/no question \u2014 e.g. "\u0411\u0430\u0447\u0443 \u0449\u043E bridge \u043D\u0430 ${pkgVersion}, \u043D\u0430 npm \u0443\u0436\u0435 ${latestVersion} \u2014 \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437? (\u0437\u0430\u043F\u0443\u0449\u0443 \`pnpm install -g @mrrlin-dev/mcp@latest\`)". Do NOT install without explicit confirmation.
38295
+ This turn, at a natural pause, ASK the operator a yes/no question \u2014 e.g. "\u0411\u0430\u0447\u0443 \u0449\u043E bridge \u043D\u0430 ${pkgVersion}, \u043D\u0430 npm \u0443\u0436\u0435 ${latestVersion} \u2014 \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437? (\u0437\u0430\u043F\u0443\u0449\u0443 \`npm install -g @mrrlin-dev/mcp@latest\`)". Do NOT install without explicit confirmation.
37966
38296
 
37967
- If the operator confirms (yes / \u0442\u0430\u043A / \u0430\u0433\u0430 / etc.): immediately run \`pnpm install -g @mrrlin-dev/mcp@latest\` via your shell tool and report the outcome in chat. After a successful install, the bridge auto-restarts via its self-update loop within a couple of minutes \u2014 you do NOT need to call pm2.
38297
+ If the operator confirms (yes / \u0442\u0430\u043A / \u0430\u0433\u0430 / etc.): immediately run \`npm install -g @mrrlin-dev/mcp@latest\` via your shell tool and report the outcome in chat. After a successful install, the bridge auto-restarts via its self-update loop within a couple of minutes \u2014 you do NOT need to call pm2.
37968
38298
 
37969
38299
  If the operator declines / says "later": acknowledge briefly and do not bring it up again this turn. The bridge has a cooldown and will re-offer in 48h.
37970
38300
 
37971
- If the install fails (permission denied, registry pinned, sudo required, network blocked): paste the error verbatim and show the operator the manual command \`pnpm install -g @mrrlin-dev/mcp@latest\` plus a one-line hint about likely cause.
38301
+ If the install fails (permission denied, registry pinned, sudo required, network blocked): paste the error verbatim and show the operator the manual command \`npm install -g @mrrlin-dev/mcp@latest\` plus a one-line hint about likely cause.
37972
38302
 
37973
38303
  Do NOT derail the current task \u2014 if the operator has an in-flight question, answer that first; the update offer is a brief aside, not the main subject.`;
37974
38304
  }
@@ -38130,7 +38460,7 @@ Do NOT derail the current task \u2014 if the operator has an in-flight question,
38130
38460
  }
38131
38461
 
38132
38462
  // src/_generated/version.ts
38133
- var PKG_VERSION = "0.3.2";
38463
+ var PKG_VERSION = "0.3.5";
38134
38464
 
38135
38465
  // src/api-base-url.ts
38136
38466
  var DEFAULT_API_BASE_URL = "http://127.0.0.1:8787";
@@ -38297,6 +38627,11 @@ async function runDeployGateTick(deps, projectSlug, run2, task) {
38297
38627
  await deps.handoff(projectSlug, task, run2, "no_environment_url");
38298
38628
  return { kind: "handoff", reason: "no_environment_url" };
38299
38629
  }
38630
+ await deps.client.updateExecutionRun(
38631
+ projectSlug,
38632
+ run2.id,
38633
+ env === "dev" ? { devEnvUrl: deployment.environmentUrl } : { prodEnvUrl: deployment.environmentUrl }
38634
+ );
38300
38635
  const section = await deps.loadVerificationSection(projectSlug, task);
38301
38636
  if (!section || section.trim().length === 0) {
38302
38637
  await deps.handoff(projectSlug, task, run2, "verification_steps_missing_at_verify");
@@ -38359,18 +38694,18 @@ async function awaitTurnWithDeadline(opts) {
38359
38694
  }
38360
38695
 
38361
38696
  // src/worktree.ts
38362
- var import_node_child_process2 = require("node:child_process");
38697
+ var import_node_child_process3 = require("node:child_process");
38363
38698
  var import_node_fs3 = require("node:fs");
38364
- var import_node_os2 = require("node:os");
38365
- var import_node_path3 = require("node:path");
38699
+ var import_node_os3 = require("node:os");
38700
+ var import_node_path4 = require("node:path");
38366
38701
 
38367
38702
  // src/checkout-lock.ts
38368
38703
  var import_node_fs2 = require("node:fs");
38369
- var import_node_path2 = require("node:path");
38704
+ var import_node_path3 = require("node:path");
38370
38705
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
38371
38706
  async function withCheckoutLock(locksDir, slug, fn) {
38372
38707
  (0, import_node_fs2.mkdirSync)(locksDir, { recursive: true });
38373
- const target = (0, import_node_path2.join)(locksDir, `${slug}.lock`);
38708
+ const target = (0, import_node_path3.join)(locksDir, `${slug}.lock`);
38374
38709
  if (!(0, import_node_fs2.existsSync)(target)) (0, import_node_fs2.writeFileSync)(target, "");
38375
38710
  const release = await import_proper_lockfile.default.lock(target, {
38376
38711
  retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
@@ -38387,16 +38722,16 @@ async function withCheckoutLock(locksDir, slug, fn) {
38387
38722
  function worktreeBranch(runId) {
38388
38723
  return `mrrlin/run-${runId}`;
38389
38724
  }
38390
- var defaultGitExec = (args, env) => (0, import_node_child_process2.execFileSync)("git", args, { encoding: "utf8", timeout: 3e4, env });
38725
+ var defaultGitExec = (args, env) => (0, import_node_child_process3.execFileSync)("git", args, { encoding: "utf8", timeout: 3e4, env });
38391
38726
  function git(checkout, args) {
38392
- return (0, import_node_child_process2.execFileSync)("git", ["-C", checkout, ...args], {
38727
+ return (0, import_node_child_process3.execFileSync)("git", ["-C", checkout, ...args], {
38393
38728
  encoding: "utf8",
38394
38729
  timeout: 3e4,
38395
38730
  env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
38396
38731
  });
38397
38732
  }
38398
38733
  async function createRunWorktree(opts) {
38399
- const worktreePath = (0, import_node_path3.join)(opts.worktreeRoot, opts.slug, opts.runId);
38734
+ const worktreePath = (0, import_node_path4.join)(opts.worktreeRoot, opts.slug, opts.runId);
38400
38735
  await withCheckoutLock(opts.locksDir, opts.slug, async () => {
38401
38736
  (0, import_node_fs3.mkdirSync)(opts.worktreeRoot, { recursive: true });
38402
38737
  try {
@@ -38459,8 +38794,8 @@ async function doPushRunBranch(opts, execGit) {
38459
38794
  if (localConfig.trim()) {
38460
38795
  throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
38461
38796
  }
38462
- const dir = (0, import_node_fs3.mkdtempSync)((0, import_node_path3.join)((0, import_node_os2.tmpdir)(), "mrrlin-push-"));
38463
- const askpass = (0, import_node_path3.join)(dir, "askpass");
38797
+ const dir = (0, import_node_fs3.mkdtempSync)((0, import_node_path4.join)((0, import_node_os3.tmpdir)(), "mrrlin-push-"));
38798
+ const askpass = (0, import_node_path4.join)(dir, "askpass");
38464
38799
  try {
38465
38800
  (0, import_node_fs3.writeFileSync)(
38466
38801
  askpass,
@@ -38946,16 +39281,12 @@ async function resetWedgedThread(deps, projectSlug, taskId, interruptFailed) {
38946
39281
  });
38947
39282
  }
38948
39283
  async function failRun(deps, projectSlug, task, runId, leaseId, reason) {
39284
+ if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
38949
39285
  try {
38950
- if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
38951
- await deps.client.updateExecutionRun(projectSlug, runId, {
38952
- status: "failed",
38953
- finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
38954
- leaseId
38955
- });
39286
+ await deps.client.createExecutionRunHandoff(projectSlug, runId, { reason });
38956
39287
  } catch {
39288
+ await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
38957
39289
  }
38958
- await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
38959
39290
  }
38960
39291
  async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
38961
39292
  try {
@@ -39261,14 +39592,14 @@ function codexIdleMs() {
39261
39592
 
39262
39593
  // src/operator-token.ts
39263
39594
  var import_node_fs4 = require("node:fs");
39264
- var import_node_os3 = __toESM(require("node:os"), 1);
39265
- var import_node_path4 = __toESM(require("node:path"), 1);
39595
+ var import_node_os4 = __toESM(require("node:os"), 1);
39596
+ var import_node_path5 = __toESM(require("node:path"), 1);
39266
39597
  function operatorDir() {
39267
- const base = process.env.CODEX_HOME ? import_node_path4.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path4.default.join(import_node_os3.default.homedir(), ".mrrlin");
39598
+ const base = process.env.CODEX_HOME ? import_node_path5.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path5.default.join(import_node_os4.default.homedir(), ".mrrlin");
39268
39599
  return base;
39269
39600
  }
39270
39601
  function operatorTokenPath() {
39271
- return import_node_path4.default.join(operatorDir(), "operator-token");
39602
+ return import_node_path5.default.join(operatorDir(), "operator-token");
39272
39603
  }
39273
39604
  function readOperatorToken() {
39274
39605
  try {
@@ -39285,7 +39616,7 @@ function persistOperatorToken(token) {
39285
39616
  `, { encoding: "utf8", mode: 384 });
39286
39617
  }
39287
39618
  function agentCredentialPath() {
39288
- return import_node_path4.default.join(operatorDir(), "agent-credential");
39619
+ return import_node_path5.default.join(operatorDir(), "agent-credential");
39289
39620
  }
39290
39621
  function persistAgentSecret(secret) {
39291
39622
  const dir = operatorDir();
@@ -39306,9 +39637,9 @@ function readAgentSecret() {
39306
39637
 
39307
39638
  // src/thread-index.ts
39308
39639
  var import_node_fs5 = require("node:fs");
39309
- var import_node_path5 = __toESM(require("node:path"), 1);
39640
+ var import_node_path6 = __toESM(require("node:path"), 1);
39310
39641
  function threadIndexPath(stateDir) {
39311
- return import_node_path5.default.join(stateDir, "threads.json");
39642
+ return import_node_path6.default.join(stateDir, "threads.json");
39312
39643
  }
39313
39644
  function loadThreadIndex(stateDir, ttlMs, now) {
39314
39645
  const result = /* @__PURE__ */ new Map();
@@ -39393,8 +39724,8 @@ function chatTurnMaxMs() {
39393
39724
  // src/worker-token.ts
39394
39725
  var import_node_crypto4 = require("node:crypto");
39395
39726
  var import_node_fs6 = require("node:fs");
39396
- var import_node_os4 = __toESM(require("node:os"), 1);
39397
- var import_node_path6 = __toESM(require("node:path"), 1);
39727
+ var import_node_os5 = __toESM(require("node:os"), 1);
39728
+ var import_node_path7 = __toESM(require("node:path"), 1);
39398
39729
  var DEFAULT_WORKER_PORT = 8792;
39399
39730
  function workerPort() {
39400
39731
  const raw = process.env.MRRLIN_WORKER_PORT;
@@ -39403,11 +39734,11 @@ function workerPort() {
39403
39734
  return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
39404
39735
  }
39405
39736
  function workerDir() {
39406
- const base = process.env.CODEX_HOME ? import_node_path6.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path6.default.join(import_node_os4.default.homedir(), ".mrrlin");
39407
- return import_node_path6.default.join(base, "worker");
39737
+ const base = process.env.CODEX_HOME ? import_node_path7.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path7.default.join(import_node_os5.default.homedir(), ".mrrlin");
39738
+ return import_node_path7.default.join(base, "worker");
39408
39739
  }
39409
39740
  function workerTokenPath() {
39410
- return import_node_path6.default.join(workerDir(), "token");
39741
+ return import_node_path7.default.join(workerDir(), "token");
39411
39742
  }
39412
39743
  function readWorkerToken() {
39413
39744
  try {
@@ -39431,8 +39762,8 @@ function readOrCreateWorkerToken() {
39431
39762
  // src/remote-phone-relay.ts
39432
39763
  var import_node_events2 = require("node:events");
39433
39764
  var import_node_fs7 = require("node:fs");
39434
- var import_node_os5 = require("node:os");
39435
- var import_node_path7 = require("node:path");
39765
+ var import_node_os6 = require("node:os");
39766
+ var import_node_path8 = require("node:path");
39436
39767
 
39437
39768
  // ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
39438
39769
  var nc = __toESM(require("node:crypto"), 1);
@@ -42207,7 +42538,10 @@ function parseFrame(bytes3) {
42207
42538
  };
42208
42539
  }
42209
42540
  case "inbox_read":
42210
- return { type: "inbox_read" };
42541
+ return {
42542
+ type: "inbox_read",
42543
+ ...isString(f.projectSlug) ? { projectSlug: f.projectSlug } : {}
42544
+ };
42211
42545
  case "inbox_decide":
42212
42546
  if (!isString(f.itemId) || !isString(f.idempotencyKey))
42213
42547
  throw new Error("frame inbox_decide: itemId + idempotencyKey required");
@@ -42220,7 +42554,8 @@ function parseFrame(bytes3) {
42220
42554
  itemId: f.itemId,
42221
42555
  decision: f.decision,
42222
42556
  idempotencyKey: f.idempotencyKey,
42223
- ...f.reason === void 0 ? {} : { reason: f.reason }
42557
+ ...f.reason === void 0 ? {} : { reason: f.reason },
42558
+ ...isString(f.projectSlug) ? { projectSlug: f.projectSlug } : {}
42224
42559
  };
42225
42560
  case "ack":
42226
42561
  if (!isString(f.refId))
@@ -42966,12 +43301,12 @@ var DirectorRelay = class {
42966
43301
  this.sendFrame(channelId, { type: "ack", refId: frame.idempotencyKey });
42967
43302
  return;
42968
43303
  }
42969
- await this.deps.onInboxDecide?.(frame.itemId, frame.decision, frame.idempotencyKey, frame.reason);
43304
+ await this.deps.onInboxDecide?.(frame.itemId, frame.decision, frame.idempotencyKey, frame.reason, frame.projectSlug);
42970
43305
  this.seenDecideKeys.add(frame.idempotencyKey);
42971
43306
  this.sendFrame(channelId, { type: "ack", refId: frame.idempotencyKey });
42972
43307
  return;
42973
43308
  case "inbox_read": {
42974
- const items = await this.deps.onInboxRead?.();
43309
+ const items = await this.deps.onInboxRead?.(frame.projectSlug);
42975
43310
  if (items !== void 0) this.sendDirectorEvent(channelId, { type: "inbox_items", items });
42976
43311
  this.sendFrame(channelId, { type: "ack", refId: "inbox_read" });
42977
43312
  return;
@@ -42999,9 +43334,9 @@ var DirectorRelay = class {
42999
43334
 
43000
43335
  // src/remote-phone-relay.ts
43001
43336
  function loadOrCreateAgentDeviceKey() {
43002
- const path15 = (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin", "agent-device-key");
43337
+ const path16 = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-device-key");
43003
43338
  try {
43004
- const raw = JSON.parse((0, import_node_fs7.readFileSync)(path15, "utf8"));
43339
+ const raw = JSON.parse((0, import_node_fs7.readFileSync)(path16, "utf8"));
43005
43340
  if (typeof raw.priv === "string" && typeof raw.pub === "string") {
43006
43341
  return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
43007
43342
  }
@@ -43009,9 +43344,9 @@ function loadOrCreateAgentDeviceKey() {
43009
43344
  }
43010
43345
  const kp = generateIdentityKeyPair();
43011
43346
  try {
43012
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin"), { recursive: true });
43347
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
43013
43348
  (0, import_node_fs7.writeFileSync)(
43014
- path15,
43349
+ path16,
43015
43350
  JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
43016
43351
  { mode: 384 }
43017
43352
  );
@@ -43019,7 +43354,7 @@ function loadOrCreateAgentDeviceKey() {
43019
43354
  }
43020
43355
  return kp;
43021
43356
  }
43022
- var AGENT_PAIRING_PATH = (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin", "agent-pairing.json");
43357
+ var AGENT_PAIRING_PATH = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-pairing.json");
43023
43358
  function loadAgentPairing() {
43024
43359
  try {
43025
43360
  const raw = JSON.parse((0, import_node_fs7.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
@@ -43037,7 +43372,7 @@ function loadAgentPairing() {
43037
43372
  }
43038
43373
  function saveAgentPairing(record2) {
43039
43374
  try {
43040
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin"), { recursive: true });
43375
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
43041
43376
  (0, import_node_fs7.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
43042
43377
  } catch {
43043
43378
  }
@@ -43116,30 +43451,38 @@ function decisionToVerdict(decision) {
43116
43451
  throw new Error(`remote-relay: unknown inbox decision "${decision}"`);
43117
43452
  }
43118
43453
  }
43119
- function startRemotePhoneRelay(deps) {
43120
- const log = deps.log ?? ((m) => process.stderr.write(`[mrrlin-mcp remote-relay] ${m}
43121
- `));
43122
- const provider = createAgentTokenProvider({ secret: deps.agentSecret, baseUrl: deps.apiBaseUrl });
43123
- const authed = async () => {
43454
+ function _makeRelayInboxCallbacks(provider, apiBaseUrl) {
43455
+ const authed = async (frameSlug) => {
43124
43456
  const session = await provider.getSession();
43457
+ const slug = frameSlug ?? session.projectSlug;
43458
+ if (!slug) {
43459
+ throw new Error("[mrrlin-mcp remote-relay] missing project context for inbox action");
43460
+ }
43125
43461
  return {
43126
- client: createMrrlinClient({ baseUrl: deps.apiBaseUrl, token: session.token }),
43127
- slug: session.projectSlug,
43462
+ client: createMrrlinClient({ baseUrl: apiBaseUrl, token: session.token }),
43463
+ slug,
43128
43464
  login: session.login
43129
43465
  };
43130
43466
  };
43131
- const onInboxRead = async () => {
43132
- const { client, slug } = await authed();
43467
+ const onInboxRead = async (projectSlug) => {
43468
+ const { client, slug } = await authed(projectSlug);
43133
43469
  return boundInboxItems(await client.listInboxItems(slug, { status: "pending" }));
43134
43470
  };
43135
- const onInboxDecide = async (itemId, decision, _key, reason) => {
43136
- const { client, slug, login } = await authed();
43471
+ const onInboxDecide = async (itemId, decision, _key, reason, projectSlug) => {
43472
+ const { client, slug, login } = await authed(projectSlug);
43137
43473
  await client.decideInboxItem(slug, itemId, {
43138
43474
  verdict: decisionToVerdict(decision),
43139
43475
  decidedBy: login,
43140
43476
  ...reason ? { reason } : {}
43141
43477
  });
43142
43478
  };
43479
+ return { onInboxRead, onInboxDecide };
43480
+ }
43481
+ function startRemotePhoneRelay(deps) {
43482
+ const log = deps.log ?? ((m) => process.stderr.write(`[mrrlin-mcp remote-relay] ${m}
43483
+ `));
43484
+ const provider = createAgentTokenProvider({ secret: deps.agentSecret, baseUrl: deps.apiBaseUrl });
43485
+ const { onInboxRead, onInboxDecide } = _makeRelayInboxCallbacks(provider, deps.apiBaseUrl);
43143
43486
  const relayClient = new RelayClient({
43144
43487
  relayUrl: deps.relayUrl,
43145
43488
  now: () => Date.now(),
@@ -43208,11 +43551,11 @@ async function renderPairingQrSvg(payload) {
43208
43551
 
43209
43552
  // src/checkout-registry.ts
43210
43553
  var import_node_fs8 = require("node:fs");
43211
- var import_node_path8 = require("node:path");
43554
+ var import_node_path9 = require("node:path");
43212
43555
  var CheckoutRegistry = class {
43213
43556
  file;
43214
43557
  constructor(stateDir) {
43215
- this.file = (0, import_node_path8.join)(stateDir, "checkouts.json");
43558
+ this.file = (0, import_node_path9.join)(stateDir, "checkouts.json");
43216
43559
  (0, import_node_fs8.mkdirSync)(stateDir, { recursive: true });
43217
43560
  }
43218
43561
  read() {
@@ -43226,17 +43569,17 @@ var CheckoutRegistry = class {
43226
43569
  get(slug) {
43227
43570
  return this.read()[slug] ?? null;
43228
43571
  }
43229
- confirm(slug, path15, now) {
43572
+ confirm(slug, path16, now) {
43230
43573
  const all = this.read();
43231
- all[slug] = { path: path15, confirmedAt: now };
43574
+ all[slug] = { path: path16, confirmedAt: now };
43232
43575
  (0, import_node_fs8.writeFileSync)(this.file, JSON.stringify(all, null, 2));
43233
43576
  }
43234
43577
  };
43235
43578
 
43236
43579
  // src/executor-server.ts
43237
43580
  var import_node_fs9 = require("node:fs");
43238
- var import_node_os6 = require("node:os");
43239
- var import_node_path9 = require("node:path");
43581
+ var import_node_os7 = require("node:os");
43582
+ var import_node_path10 = require("node:path");
43240
43583
  var DENY_READ_GLOBS = [
43241
43584
  "**/.ssh/**",
43242
43585
  "**/.aws/**",
@@ -43267,17 +43610,17 @@ function buildExecutorConfig(opts) {
43267
43610
  trustWorktreeConfig: false
43268
43611
  };
43269
43612
  }
43270
- function operatorSecretPaths(realHome = (0, import_node_os6.homedir)()) {
43613
+ function operatorSecretPaths(realHome = (0, import_node_os7.homedir)()) {
43271
43614
  return [
43272
- (0, import_node_path9.join)(realHome, ".ssh"),
43273
- (0, import_node_path9.join)(realHome, ".aws"),
43274
- (0, import_node_path9.join)(realHome, ".config", "gh"),
43275
- (0, import_node_path9.join)(realHome, ".npmrc"),
43276
- (0, import_node_path9.join)(realHome, ".netrc"),
43277
- (0, import_node_path9.join)(realHome, ".gnupg"),
43278
- (0, import_node_path9.join)(realHome, ".kube"),
43279
- (0, import_node_path9.join)(realHome, ".docker", "config.json"),
43280
- (0, import_node_path9.join)(realHome, ".config", "gcloud")
43615
+ (0, import_node_path10.join)(realHome, ".ssh"),
43616
+ (0, import_node_path10.join)(realHome, ".aws"),
43617
+ (0, import_node_path10.join)(realHome, ".config", "gh"),
43618
+ (0, import_node_path10.join)(realHome, ".npmrc"),
43619
+ (0, import_node_path10.join)(realHome, ".netrc"),
43620
+ (0, import_node_path10.join)(realHome, ".gnupg"),
43621
+ (0, import_node_path10.join)(realHome, ".kube"),
43622
+ (0, import_node_path10.join)(realHome, ".docker", "config.json"),
43623
+ (0, import_node_path10.join)(realHome, ".config", "gcloud")
43281
43624
  ];
43282
43625
  }
43283
43626
  var SECRET_DIRECTORY_BASENAMES = /* @__PURE__ */ new Set([".ssh", ".aws", "gh", ".gnupg", ".kube", "gcloud"]);
@@ -43286,7 +43629,7 @@ function isSecretDirectoryPath(p) {
43286
43629
  return SECRET_DIRECTORY_BASENAMES.has(base);
43287
43630
  }
43288
43631
  function writeExecutorCodexHome(scratchDir, opts) {
43289
- const codexHome = (0, import_node_path9.join)(scratchDir, ".codex");
43632
+ const codexHome = (0, import_node_path10.join)(scratchDir, ".codex");
43290
43633
  (0, import_node_fs9.mkdirSync)(codexHome, { recursive: true });
43291
43634
  const hasEgress = opts.egressDomains.length > 0;
43292
43635
  const networkSection = hasEgress ? [
@@ -43322,14 +43665,14 @@ function writeExecutorCodexHome(scratchDir, opts) {
43322
43665
  networkSection,
43323
43666
  ""
43324
43667
  ].join("\n");
43325
- (0, import_node_fs9.writeFileSync)((0, import_node_path9.join)(codexHome, "config.toml"), toml3, "utf8");
43668
+ (0, import_node_fs9.writeFileSync)((0, import_node_path10.join)(codexHome, "config.toml"), toml3, "utf8");
43326
43669
  return codexHome;
43327
43670
  }
43328
43671
  async function startExecutorServer(opts) {
43329
43672
  const egressDomains = opts.egressDomains ?? DEFAULT_EGRESS_DOMAINS;
43330
- const realHome = (0, import_node_os6.homedir)();
43673
+ const realHome = (0, import_node_os7.homedir)();
43331
43674
  const denySecretPaths = operatorSecretPaths(realHome);
43332
- const scratchDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path9.join)((0, import_node_os6.tmpdir)(), "mrrlin-executor-"));
43675
+ const scratchDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path10.join)((0, import_node_os7.tmpdir)(), "mrrlin-executor-"));
43333
43676
  const scratchHome = scratchDir;
43334
43677
  let scratchCleaned = false;
43335
43678
  const cleanScratch = () => {
@@ -43528,7 +43871,7 @@ function extractVerificationSection(markdown) {
43528
43871
 
43529
43872
  // src/bridge-log.ts
43530
43873
  var import_node_fs10 = require("node:fs");
43531
- var import_node_path10 = require("node:path");
43874
+ var import_node_path11 = require("node:path");
43532
43875
 
43533
43876
  // src/redact.ts
43534
43877
  var REDACTED = "[REDACTED]";
@@ -43613,14 +43956,14 @@ function resolvePromptsEnabled(env) {
43613
43956
  }
43614
43957
  function createBridgeLogger(stateDir, env = process.env) {
43615
43958
  if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
43616
- const logsDir = (0, import_node_path10.join)(stateDir, "logs");
43959
+ const logsDir = (0, import_node_path11.join)(stateDir, "logs");
43617
43960
  try {
43618
43961
  (0, import_node_fs10.mkdirSync)(logsDir, { recursive: true });
43619
43962
  } catch {
43620
43963
  return NOOP_LOGGER;
43621
43964
  }
43622
43965
  const includePrompts = resolvePromptsEnabled(env);
43623
- const fileFor = () => (0, import_node_path10.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
43966
+ const fileFor = () => (0, import_node_path11.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
43624
43967
  const write = (dir, rec) => {
43625
43968
  try {
43626
43969
  const line = JSON.stringify({
@@ -43646,9 +43989,9 @@ function createBridgeLogger(stateDir, env = process.env) {
43646
43989
 
43647
43990
  // src/issue-report.ts
43648
43991
  var import_node_fs11 = require("node:fs");
43649
- var import_node_os7 = require("node:os");
43650
- var import_node_path11 = __toESM(require("node:path"), 1);
43651
- var import_node_child_process3 = require("node:child_process");
43992
+ var import_node_os8 = require("node:os");
43993
+ var import_node_path12 = __toESM(require("node:path"), 1);
43994
+ var import_node_child_process4 = require("node:child_process");
43652
43995
  var TELEGRAM_BOT_TOKEN = "8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A";
43653
43996
  var TELEGRAM_CHAT_ID = "-5373779177";
43654
43997
  function summarizeTranscript(entries = []) {
@@ -43683,10 +44026,10 @@ function describePayload(payload) {
43683
44026
  function resolveLogDir() {
43684
44027
  const codexHome = process.env.CODEX_HOME?.trim();
43685
44028
  if (codexHome) {
43686
- const candidate = import_node_path11.default.join(codexHome, "mrrlin", "director-bridge", "logs");
44029
+ const candidate = import_node_path12.default.join(codexHome, "mrrlin", "director-bridge", "logs");
43687
44030
  if (existsDir(candidate)) return candidate;
43688
44031
  }
43689
- const fallback = import_node_path11.default.join((0, import_node_os7.homedir)(), ".mrrlin", "director-bridge", "logs");
44032
+ const fallback = import_node_path12.default.join((0, import_node_os8.homedir)(), ".mrrlin", "director-bridge", "logs");
43690
44033
  return fallback;
43691
44034
  }
43692
44035
  function existsDir(candidate) {
@@ -43698,7 +44041,7 @@ function existsDir(candidate) {
43698
44041
  }
43699
44042
  function listRecentLogFiles(logDir) {
43700
44043
  if (!existsDir(logDir)) return [];
43701
- return (0, import_node_fs11.readdirSync)(logDir).filter((name) => /^bridge-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name)).sort((a, b) => b.localeCompare(a)).slice(0, 3).map((name) => import_node_path11.default.join(logDir, name));
44044
+ return (0, import_node_fs11.readdirSync)(logDir).filter((name) => /^bridge-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name)).sort((a, b) => b.localeCompare(a)).slice(0, 3).map((name) => import_node_path12.default.join(logDir, name));
43702
44045
  }
43703
44046
  function parseLogFile(file2) {
43704
44047
  const lines2 = (0, import_node_fs11.readFileSync)(file2, "utf8").split(/\r?\n/).filter(Boolean);
@@ -43844,10 +44187,10 @@ function buildIssueDraft(request, logWindow) {
43844
44187
  `- Route: ${request.urlPath?.trim() || "(unknown)"}`,
43845
44188
  `- Director session: ${request.directorSessionId?.trim() || "(none)"}`,
43846
44189
  `- @mrrlin-dev/mcp: ${PKG_VERSION}`,
43847
- `- OS: ${(0, import_node_os7.platform)()}`,
44190
+ `- OS: ${(0, import_node_os8.platform)()}`,
43848
44191
  `- Node: ${process.version}`
43849
44192
  ].join("\n");
43850
- const logLabel = logWindow.file ? import_node_path11.default.basename(logWindow.file) : "(none)";
44193
+ const logLabel = logWindow.file ? import_node_path12.default.basename(logWindow.file) : "(none)";
43851
44194
  const body = [
43852
44195
  "## Summary",
43853
44196
  `${titlePrefix(request.source)} issue report generated from local Mrrlin evidence.`,
@@ -43883,7 +44226,7 @@ function buildTelegramAnnouncement(request, draft, issueUrl) {
43883
44226
  ${issueUrl}`;
43884
44227
  }
43885
44228
  function ensureGhReady() {
43886
- const auth = (0, import_node_child_process3.spawnSync)("gh", ["auth", "status", "-h", "github.com"], { encoding: "utf8" });
44229
+ const auth = (0, import_node_child_process4.spawnSync)("gh", ["auth", "status", "-h", "github.com"], { encoding: "utf8" });
43887
44230
  if (auth.status !== 0) {
43888
44231
  const detail = (auth.stderr || auth.stdout || "gh auth status failed").trim();
43889
44232
  throw new Error(`GitHub CLI is not ready: ${detail}`);
@@ -43891,13 +44234,13 @@ function ensureGhReady() {
43891
44234
  }
43892
44235
  function createGithubIssue(draft) {
43893
44236
  ensureGhReady();
43894
- const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path11.default.join((0, import_node_os7.tmpdir)(), "mrrlin-issue-"));
43895
- const bodyFile = import_node_path11.default.join(tmpDir, "issue-body.md");
44237
+ const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-"));
44238
+ const bodyFile = import_node_path12.default.join(tmpDir, "issue-body.md");
43896
44239
  try {
43897
44240
  (0, import_node_fs11.writeFileSync)(bodyFile, draft.body, "utf8");
43898
44241
  const args = ["issue", "create", "--repo", "fnnzzz/mrrlin", "--title", draft.title, "--body-file", bodyFile];
43899
44242
  for (const label of draft.labels) args.push("--label", label);
43900
- const result = (0, import_node_child_process3.spawnSync)("gh", args, { encoding: "utf8" });
44243
+ const result = (0, import_node_child_process4.spawnSync)("gh", args, { encoding: "utf8" });
43901
44244
  if (result.status !== 0) {
43902
44245
  const detail = (result.stderr || result.stdout || "gh issue create failed").trim();
43903
44246
  throw new Error(detail);
@@ -43913,8 +44256,8 @@ function createGithubIssue(draft) {
43913
44256
  }
43914
44257
  }
43915
44258
  function sendTelegramAnnouncement(text) {
43916
- const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path11.default.join((0, import_node_os7.tmpdir)(), "mrrlin-issue-telegram-"));
43917
- const bodyFile = import_node_path11.default.join(tmpDir, "telegram-body.json");
44259
+ const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-telegram-"));
44260
+ const bodyFile = import_node_path12.default.join(tmpDir, "telegram-body.json");
43918
44261
  try {
43919
44262
  (0, import_node_fs11.writeFileSync)(
43920
44263
  bodyFile,
@@ -43925,7 +44268,7 @@ function sendTelegramAnnouncement(text) {
43925
44268
  }),
43926
44269
  "utf8"
43927
44270
  );
43928
- const result = (0, import_node_child_process3.spawnSync)(
44271
+ const result = (0, import_node_child_process4.spawnSync)(
43929
44272
  "curl",
43930
44273
  [
43931
44274
  "-sS",
@@ -44032,7 +44375,7 @@ function normalizeIssueScreenshots(value) {
44032
44375
  return screenshots;
44033
44376
  }
44034
44377
  function neutralCheckoutCwd(stateDir) {
44035
- const dir = import_node_path12.default.join(stateDir, "no-checkout");
44378
+ const dir = import_node_path13.default.join(stateDir, "no-checkout");
44036
44379
  try {
44037
44380
  import_node_fs12.default.mkdirSync(dir, { recursive: true });
44038
44381
  } catch {
@@ -44043,12 +44386,19 @@ function buildThreadStartParams(msg, config2, desiredModel) {
44043
44386
  const baseInstructions = [
44044
44387
  "You are the Mrrlin Director assistant.",
44045
44388
  "You can call MCP tools to read and write project state.",
44046
- "Prefer calling tools over guessing. Be concise. Ask clarification questions only when needed.",
44389
+ "Prefer calling tools over guessing. Be concise.",
44390
+ "Autonomy level is NOT a reason to skip clarification. `auto` means only that no human gate is",
44391
+ "required before the result LANDS (merge/deploy); it does not authorize building on unvalidated",
44392
+ "assumptions. Judge clarification on requirement clarity, independently of autonomy_level.",
44047
44393
  "Never announce or pre-narrate that you are about to use tools, and never name the toolset in",
44048
44394
  `prose. Do NOT write openers like "I'll use the Mrrlin tools to\u2026", "\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u044E Mrrlin tools\u2026",`,
44049
44395
  'or "let me call the \u2026 tool" in ANY language. The operator already sees tool calls in the',
44050
44396
  "transcript. Just call the tools and reply with the outcome \u2014 start your reply with the result.",
44051
44397
  "When creating or updating tasks, always provide `autonomyLevel` and `autonomyReason`.",
44398
+ "When you create a task out of an operator request, set `operatorSeedRequest` to the operator's",
44399
+ "VERBATIM words (their request as they wrote it \u2014 NOT your paraphrase or synthesized notes). It is",
44400
+ "the spec gate's independent record of intent; omit it only when there is genuinely no operator",
44401
+ "request behind the task (pure system bookkeeping) \u2014 note that omitting it makes the gate fail-closed.",
44052
44402
  "",
44053
44403
  "Spec authoring contract \u2014 when creating or updating a `Specs/{id}` wiki page:",
44054
44404
  "- In `## Specification`, write each requirement as `### Requirement: <name>` followed by one",
@@ -44058,6 +44408,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
44058
44408
  "- Keep behavior contracts in the spec; implementation details belong in `## Implementation Plan`.",
44059
44409
  "- Apply this format ONLY to Specs/{id} pages; do not retro-fit it onto other wiki page types.",
44060
44410
  "- Spec consensus runs ASYNCHRONOUSLY. Call `run_spec_consensus` for a `Specs/{id}` page; it returns IMMEDIATELY. On `already_converged`, the spec is already marked ready \u2014 proceed straight to `create_execution_run`; do NOT call `mark_spec_ready` and do NOT re-run consensus. On `queued` or `already_running`, tell the user it was launched and END your turn \u2014 do NOT poll or call it again; the result arrives in the inbox (an `info` item on CONVERGED, a `handoff` item if it was blocked/failed). When a consensus `info` item says CONVERGED, proceed to `create_execution_run`. When a `handoff` says it was blocked, address the recorded issues in the spec (any edit re-arms the gate) and call `run_spec_consensus` once more.",
44411
+ '- When a task needs a browser (login flows, UI verification/clicks, scraping), pass `prerequisites:[{mcp:"mrrlin-browser",reason:"..."}]` to `create_execution_run`. If that run later fails into a handoff, the operator gets a one-click "Launch browser & resume" that brings up the dedicated browser as the turn starts.',
44061
44412
  "",
44062
44413
  'Research playbook \u2014 when the user asks about a topic, an area, or "what do we have on X":',
44063
44414
  "- Tasks are the source of truth. Start with `list_tasks` using `q=<keyword>`; the filter is a",
@@ -44119,12 +44470,20 @@ function buildThreadStartParams(msg, config2, desiredModel) {
44119
44470
  " call `list_inbox_items` (kind=question), fold any relevant `acknowledged` TASKLESS answer",
44120
44471
  " into the new task's Specs/{id} Clarifications, and `reject` (with a reason) any taskless",
44121
44472
  " question the new task makes moot \u2014 so taskless answers never linger unconsumed.",
44122
- "- When resuming a task, call `list_inbox_items` (kind=question) and incorporate any",
44123
- " `acknowledged` answer not yet reflected in the spec's Clarifications section.",
44473
+ "- Gate-origin questions (origin='gate', filed by the spec consensus gate) are auto-folded",
44474
+ " into the spec and re-gated by the system when the operator answers them in the inbox.",
44475
+ " Do NOT fold or `decide_inbox_item` them yourself \u2014 your fold-contract above applies only",
44476
+ " to YOUR OWN discretionary questions.",
44477
+ "- When resuming a task, call `list_inbox_items` (kind=question) and fold any `acknowledged`",
44478
+ " answer from YOUR questions (origin is null/absent) not yet reflected into the spec's",
44479
+ " Clarifications section \u2014 THEN re-run `run_spec_consensus` on the updated spec. Skip",
44480
+ " gate-origin items (origin='gate') as those are handled automatically.",
44124
44481
  "- If a question becomes moot (task cancelled, superseded, or no longer relevant), close it",
44125
44482
  ' with `decide_inbox_item` `verdict="rejected"` + a `reason`; never leave it pending.',
44126
- "- Questions are a chat-only mechanism. Do not create question items from non-interactive",
44127
- " runs; use the handoff contract above when there is no live operator.",
44483
+ "- YOUR discretionary questions are a chat-only mechanism: do not create question items yourself",
44484
+ " from non-interactive runs; use the handoff contract above when there is no live operator.",
44485
+ " The spec consensus GATE, however, may file its own clarification questions on non-interactive",
44486
+ " runs (that is gate-driven, not your discretion) \u2014 resume them via the rule above when answered.",
44128
44487
  "",
44129
44488
  "Onboarding contract \u2014 seed project context when there is none:",
44130
44489
  `- A project is un-onboarded when it has no \`${PROJECT_CONSTITUTION_PAGE.path}\` wiki page.`,
@@ -44226,7 +44585,7 @@ function resolveDefaultBranch(checkoutPath) {
44226
44585
  if (!checkoutPath) return "main";
44227
44586
  const runGit = (args) => {
44228
44587
  try {
44229
- return (0, import_node_child_process4.execFileSync)("git", ["-C", checkoutPath, ...args], {
44588
+ return (0, import_node_child_process5.execFileSync)("git", ["-C", checkoutPath, ...args], {
44230
44589
  encoding: "utf8",
44231
44590
  stdio: ["ignore", "pipe", "ignore"],
44232
44591
  timeout: 15e3,
@@ -44295,8 +44654,8 @@ async function runOrphanWorktreeSweep(client, opts) {
44295
44654
  }
44296
44655
  }
44297
44656
  function readStateDir() {
44298
- if (process.env.CODEX_HOME) return import_node_path12.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
44299
- return import_node_path12.default.join(import_node_os8.default.homedir(), ".mrrlin", "director-bridge");
44657
+ if (process.env.CODEX_HOME) return import_node_path13.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
44658
+ return import_node_path13.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
44300
44659
  }
44301
44660
  function readAllowedOrigins() {
44302
44661
  const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
@@ -44384,7 +44743,7 @@ function sessionIdOf(msg) {
44384
44743
  return typeof id === "string" ? id : null;
44385
44744
  }
44386
44745
  function attachBridgeWss(server, opts) {
44387
- const { token, allowedOrigins, onReady, logger, onPaired, selfUpdate } = opts;
44746
+ const { token, allowedOrigins, onReady, logger, onPaired, bridgeInstanceId, selfUpdate } = opts;
44388
44747
  const wss = new import_websocket_server.default({ server, path: "/ws" });
44389
44748
  wss.on("connection", (socket, request) => {
44390
44749
  const origin = request.headers.origin;
@@ -44426,6 +44785,7 @@ function attachBridgeWss(server, opts) {
44426
44785
  send({
44427
44786
  type: "ready",
44428
44787
  bridgeVersion: 1,
44788
+ ...bridgeInstanceId ? { bridgeInstanceId } : {},
44429
44789
  ...selfUpdate ? {
44430
44790
  version: selfUpdate.version,
44431
44791
  binSha: selfUpdate.binSha,
@@ -44439,13 +44799,118 @@ function attachBridgeWss(server, opts) {
44439
44799
  }
44440
44800
  var TurnInterruptedError = class extends Error {
44441
44801
  };
44802
+ function attachSeqMetadata(msg, seq, turnId) {
44803
+ if (msg.type === "event" || msg.type === "rateLimits" || msg.type === "error") {
44804
+ return { ...msg, seq, turnId };
44805
+ }
44806
+ return msg;
44807
+ }
44442
44808
  function createBridgeMessageHandler(deps) {
44809
+ const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
44443
44810
  return (socket, _request, send, logCtx) => {
44444
44811
  const boundSessions = /* @__PURE__ */ new Set();
44445
44812
  socket.on("close", () => {
44446
44813
  for (const id of boundSessions) deps.unbindSessionSink?.(id, send);
44447
44814
  boundSessions.clear();
44448
44815
  });
44816
+ function logResumeRejected(sessionId, reason) {
44817
+ logCtx?.logger.logOut({
44818
+ spanId: logCtx.span.id,
44819
+ sessionId,
44820
+ type: "<resume-rejected>",
44821
+ payload: { sessionId, reason }
44822
+ });
44823
+ }
44824
+ function handleResumeRequest(req, sendMsg) {
44825
+ if (req.lastSeenBridgeInstanceId !== deps.bridgeInstanceId) {
44826
+ sendMsg({ type: "resume", status: "no-buffer", reason: "bridge-restarted" });
44827
+ logResumeRejected(req.directorSessionId, "bridge-restarted");
44828
+ return;
44829
+ }
44830
+ const t = deps.threads.get(req.directorSessionId);
44831
+ const tombstone = lookupTombstone(tombstones, req.directorSessionId);
44832
+ if (!t && !tombstone) {
44833
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
44834
+ logResumeRejected(req.directorSessionId, "wrong-session");
44835
+ return;
44836
+ }
44837
+ if (!t && tombstone) {
44838
+ const reason = tombstone.turnId === req.turnId ? "expired" : "wrong-turn";
44839
+ sendMsg({ type: "resume", status: "no-buffer", reason });
44840
+ logResumeRejected(req.directorSessionId, reason);
44841
+ return;
44842
+ }
44843
+ const buf = t?.replay ?? null;
44844
+ if (!buf) {
44845
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
44846
+ logResumeRejected(req.directorSessionId, "wrong-session");
44847
+ return;
44848
+ }
44849
+ if (buf.turnId !== req.turnId) {
44850
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-turn" });
44851
+ logResumeRejected(req.directorSessionId, "wrong-turn");
44852
+ return;
44853
+ }
44854
+ const epochMatch = req.epoch === buf.bindEpoch || req.epoch === buf.bindEpoch - 1;
44855
+ if (!epochMatch) {
44856
+ sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
44857
+ logResumeRejected(req.directorSessionId, "superseded");
44858
+ return;
44859
+ }
44860
+ const tail2 = eventsAfter(buf, req.lastSeq);
44861
+ if (tail2 === null) {
44862
+ sendMsg({ type: "resume", status: "no-buffer", reason: "evicted" });
44863
+ logResumeRejected(req.directorSessionId, "evicted");
44864
+ return;
44865
+ }
44866
+ const result = transition(buf.state, { kind: "resume", epochMatch: true });
44867
+ if (result.next === "invalid") {
44868
+ sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
44869
+ return;
44870
+ }
44871
+ buf.state = result.next;
44872
+ incrementBindEpoch(buf);
44873
+ buf.replaying = true;
44874
+ deps.bindSessionSink?.(req.directorSessionId, send);
44875
+ boundSessions.add(req.directorSessionId);
44876
+ if (buf.triggerGrace) socket.once("close", buf.triggerGrace);
44877
+ const willStreamLive = result.next === "live";
44878
+ sendMsg({
44879
+ type: "resume",
44880
+ status: "replaying",
44881
+ turnId: buf.turnId,
44882
+ firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
44883
+ lastSeq: buf.lastSeq,
44884
+ spanId: buf.spanId,
44885
+ bindEpoch: buf.bindEpoch,
44886
+ eventCount: tail2.length,
44887
+ willStreamLive
44888
+ });
44889
+ for (const { msg: bufferedMsg } of tail2) sendMsg(bufferedMsg);
44890
+ for (const m of buf.outboundQueue) sendMsg(m);
44891
+ buf.outboundQueue.length = 0;
44892
+ buf.replaying = false;
44893
+ logCtx?.logger.logOut({
44894
+ spanId: logCtx.span.id,
44895
+ sessionId: req.directorSessionId,
44896
+ type: "<resume-replay>",
44897
+ payload: {
44898
+ sessionId: req.directorSessionId,
44899
+ turnId: buf.turnId,
44900
+ willStreamLive,
44901
+ firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
44902
+ lastSeq: buf.lastSeq,
44903
+ eventCount: tail2.length
44904
+ }
44905
+ });
44906
+ if (result.next === "interrupted") {
44907
+ const closed = transition("interrupted", { kind: "result_delivered_to_client" });
44908
+ if (closed.next !== "invalid") {
44909
+ buf.state = closed.next;
44910
+ buf.finishedAt = Date.now();
44911
+ }
44912
+ }
44913
+ }
44449
44914
  socket.on("message", async (data) => {
44450
44915
  const spanId = import_node_crypto5.default.randomUUID();
44451
44916
  if (logCtx) {
@@ -44532,7 +44997,11 @@ function createBridgeMessageHandler(deps) {
44532
44997
  } catch (error51) {
44533
44998
  bootstrapError = error51 instanceof Error ? error51.message : String(error51);
44534
44999
  }
44535
- sendForSpan({ type: "bootstrap", models, rateLimits, ...bootstrapError ? { error: bootstrapError } : {} });
45000
+ sendForSpan({ type: "bootstrap", models, rateLimits, ...deps.bridgeInstanceId ? { bridgeInstanceId: deps.bridgeInstanceId } : {}, ...bootstrapError ? { error: bootstrapError } : {} });
45001
+ return;
45002
+ }
45003
+ if (msg.type === "resume") {
45004
+ handleResumeRequest(msg, sendForSpan);
44536
45005
  return;
44537
45006
  }
44538
45007
  if (msg.type === "report_issue") {
@@ -44590,6 +45059,15 @@ function createBridgeMessageHandler(deps) {
44590
45059
  sendForSpan({ type: "error", directorSessionId: directorSessionId2, error: "No active Director session to interrupt." });
44591
45060
  return;
44592
45061
  }
45062
+ const interruptBuf = existing.replay;
45063
+ if (interruptBuf && interruptBuf.state === "grace") {
45064
+ const stopResult = transition("grace", { kind: "stop" });
45065
+ if (stopResult.next !== "invalid") {
45066
+ interruptBuf.state = stopResult.next;
45067
+ cancelGrace(interruptBuf);
45068
+ recordInterrupted(interruptBuf);
45069
+ }
45070
+ }
44593
45071
  const codexClient2 = await deps.acquireCodex();
44594
45072
  try {
44595
45073
  await codexClient2.turn.interrupt({ threadId: existing.threadId });
@@ -44660,7 +45138,8 @@ function createBridgeMessageHandler(deps) {
44660
45138
  lastUsedAt: Date.now(),
44661
45139
  inFlight: false,
44662
45140
  model: desiredModel,
44663
- reasoningEffort: desiredEffort
45141
+ reasoningEffort: desiredEffort,
45142
+ replay: null
44664
45143
  };
44665
45144
  await acquireThread(codexClient, {
44666
45145
  threadId: null,
@@ -44710,11 +45189,52 @@ function createBridgeMessageHandler(deps) {
44710
45189
  return;
44711
45190
  }
44712
45191
  thread.inFlight = true;
45192
+ thread.replay = createReplayBuffer({
45193
+ turnId: (0, import_node_crypto5.randomUUID)(),
45194
+ spanId,
45195
+ ...deps.turnGraceMs !== void 0 ? { graceMs: deps.turnGraceMs } : {}
45196
+ });
44713
45197
  thread.lastUsedAt = Date.now();
44714
45198
  const threadId = thread.threadId;
45199
+ sendForSpan({
45200
+ type: "turn-started",
45201
+ directorSessionId,
45202
+ turnId: thread.replay.turnId
45203
+ });
44715
45204
  const mapper = thread.mapper;
44716
45205
  mapper.reset();
44717
45206
  const contextPrefix = renderContextPrefix({ ...msg.context, directorSessionId });
45207
+ const sendInTurn = (msg2) => {
45208
+ const buf = thread.replay;
45209
+ if (!buf) {
45210
+ sendForSpan(msg2);
45211
+ return;
45212
+ }
45213
+ if (isTerminalEvent(msg2) && buf.terminalDelivered) {
45214
+ logCtx?.logger.logOut({
45215
+ spanId,
45216
+ sessionId: directorSessionId,
45217
+ type: "<terminal-event-dropped>",
45218
+ payload: { sessionId: directorSessionId, terminalAlreadyDelivered: true }
45219
+ });
45220
+ return;
45221
+ }
45222
+ const recorded = recordOutgoing(buf, msg2);
45223
+ if (isTerminalEvent(msg2)) buf.terminalDelivered = true;
45224
+ const tagged = attachSeqMetadata(recorded.msg, recorded.seq, buf.turnId);
45225
+ if (buf.replaying) {
45226
+ buf.outboundQueue.push(tagged);
45227
+ return;
45228
+ }
45229
+ const liveSink = deps.getSessionSink?.(directorSessionId);
45230
+ if (liveSink) {
45231
+ liveSink(tagged);
45232
+ return;
45233
+ }
45234
+ if (socket.readyState === socket.OPEN) {
45235
+ sendForSpan(tagged);
45236
+ }
45237
+ };
44718
45238
  try {
44719
45239
  await deps.runExclusive(async () => {
44720
45240
  let resolveTurn = null;
@@ -44734,13 +45254,13 @@ function createBridgeMessageHandler(deps) {
44734
45254
  return;
44735
45255
  }
44736
45256
  outputEvents += 1;
44737
- sendForSpan({ type: "event", directorSessionId, event });
45257
+ sendInTurn({ type: "event", directorSessionId, event });
44738
45258
  };
44739
45259
  const unsub = codexClient.onNotification((method, params) => {
44740
45260
  pokeActivity();
44741
45261
  if (method === "account/rateLimits/updated") {
44742
45262
  const snapshot = params?.rateLimits ?? null;
44743
- if (snapshot) sendForSpan({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
45263
+ if (snapshot) sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
44744
45264
  }
44745
45265
  const events = mapper.mapNotification({ method, params }, threadId);
44746
45266
  for (const event of events) {
@@ -44778,15 +45298,41 @@ function createBridgeMessageHandler(deps) {
44778
45298
  }
44779
45299
  });
44780
45300
  const onSocketClose = () => {
44781
- rejectWatchdog?.(new TurnInterruptedError());
44782
- void withTimeout(codexClient.turn.interrupt({ threadId }), DEFAULT_TURN_INTERRUPT_TIMEOUT_MS, "interrupt timed out").catch(
44783
- () => {
45301
+ const buf = thread.replay;
45302
+ if (!buf || buf.state !== "live") return;
45303
+ const r = transition("live", { kind: "socket_close" });
45304
+ if (r.next === "invalid") return;
45305
+ buf.state = r.next;
45306
+ logCtx?.logger.logOut({
45307
+ spanId,
45308
+ sessionId: directorSessionId,
45309
+ type: "<resume-grace-started>",
45310
+ payload: { sessionId: directorSessionId, turnId: buf.turnId, graceMs: buf.graceMs }
45311
+ });
45312
+ enterGrace(buf, () => {
45313
+ const expired = transition("grace", { kind: "grace_expire" });
45314
+ if (expired.next === "invalid") return;
45315
+ buf.state = expired.next;
45316
+ recordInterrupted(buf);
45317
+ logCtx?.logger.logOut({
45318
+ spanId,
45319
+ sessionId: directorSessionId,
45320
+ type: "<grace-expired>",
45321
+ payload: { sessionId: directorSessionId, turnId: buf.turnId, lastSeq: buf.lastSeq }
45322
+ });
45323
+ rejectWatchdog?.(new TurnInterruptedError());
45324
+ void withTimeout(
45325
+ codexClient.turn.interrupt({ threadId }),
45326
+ DEFAULT_TURN_INTERRUPT_TIMEOUT_MS,
45327
+ "interrupt timed out"
45328
+ ).catch(() => {
44784
45329
  deps.threads.delete(directorSessionId);
44785
45330
  deps.persistThreads();
44786
- }
44787
- );
45331
+ });
45332
+ });
44788
45333
  };
44789
45334
  socket.once("close", onSocketClose);
45335
+ if (thread.replay) thread.replay.triggerGrace = onSocketClose;
44790
45336
  pokeActivity = () => watchdog.poke();
44791
45337
  const runSequence = (async () => {
44792
45338
  const turnInput = [];
@@ -44821,16 +45367,19 @@ ${effectiveText}` : effectiveText;
44821
45367
  forward(event);
44822
45368
  }
44823
45369
  if (outputEvents === 0) {
44824
- sendForSpan({
45370
+ sendInTurn({
44825
45371
  type: "error",
44826
45372
  directorSessionId,
44827
45373
  error: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan."
44828
45374
  });
44829
45375
  }
44830
45376
  for (const event of deferredResults) {
44831
- sendForSpan({ type: "event", directorSessionId, event });
45377
+ sendInTurn({ type: "event", directorSessionId, event });
44832
45378
  }
44833
45379
  } finally {
45380
+ if (thread.replay && thread.replay.state === "live") {
45381
+ markCompleted(thread.replay, Date.now());
45382
+ }
44834
45383
  socket.off("close", onSocketClose);
44835
45384
  watchdog.cancel();
44836
45385
  unsub();
@@ -44839,7 +45388,7 @@ ${effectiveText}` : effectiveText;
44839
45388
  });
44840
45389
  } catch (error51) {
44841
45390
  if (!(error51 instanceof TurnInterruptedError)) {
44842
- sendForSpan({ type: "error", directorSessionId, error: error51 instanceof Error ? error51.message : String(error51) });
45391
+ sendInTurn({ type: "error", directorSessionId, error: error51 instanceof Error ? error51.message : String(error51) });
44843
45392
  const msg2 = error51 instanceof Error ? error51.message : String(error51);
44844
45393
  if (/unauthor|not logged in|login|401|auth/i.test(msg2)) {
44845
45394
  deps.setCodexAuth?.("expired");
@@ -44886,7 +45435,7 @@ function parseConfig() {
44886
45435
  }
44887
45436
  function scanForOtherBridges() {
44888
45437
  try {
44889
- const result = (0, import_node_child_process4.spawnSync)("pgrep", ["-f", "mrrlin-mcp director-bridge"], {
45438
+ const result = (0, import_node_child_process5.spawnSync)("pgrep", ["-f", "mrrlin-mcp director-bridge"], {
44890
45439
  encoding: "utf8"
44891
45440
  });
44892
45441
  if (result.status !== 0) return [];
@@ -45018,8 +45567,8 @@ async function startDirectorBridge() {
45018
45567
  codexCwd: config2.codexCwd,
45019
45568
  codexExecutable: config2.codexExecutable,
45020
45569
  checkoutRegistry,
45021
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
45022
- locksDir: import_node_path12.default.join(config2.stateDir, "locks"),
45570
+ worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
45571
+ locksDir: import_node_path13.default.join(config2.stateDir, "locks"),
45023
45572
  // Wire the profile-enforced executor server for code-execution runs. Each run gets its own
45024
45573
  // sandboxed Codex instance (scrubbed env, scratch CODEX_HOME, deny-read, egress allowlist).
45025
45574
  // The returned handle's dispose() shuts down the spawned app-server CHILD (manager.shutdown(),
@@ -45052,7 +45601,7 @@ async function startDirectorBridge() {
45052
45601
  },
45053
45602
  runVerificationTurn: createRunVerificationTurn({
45054
45603
  startSandbox: async (egressDomains) => {
45055
- const cwd = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os8.default.tmpdir(), "mrrlin-verify-"));
45604
+ const cwd = import_node_fs12.default.mkdtempSync(import_node_path13.default.join(import_node_os9.default.tmpdir(), "mrrlin-verify-"));
45056
45605
  let handle;
45057
45606
  try {
45058
45607
  handle = await startExecutorServer({ worktree: cwd, egressDomains });
@@ -45081,6 +45630,8 @@ async function startDirectorBridge() {
45081
45630
  }
45082
45631
  };
45083
45632
  const sessionSinks = createSessionSinkRegistry();
45633
+ const tombstones = /* @__PURE__ */ new Map();
45634
+ const bridgeInstanceId = (0, import_node_crypto5.randomUUID)();
45084
45635
  const asyncConsumerDeps = {
45085
45636
  client,
45086
45637
  runExclusive: wrappedTurnLock.runExclusive,
@@ -45140,7 +45691,8 @@ async function startDirectorBridge() {
45140
45691
  lastUsedAt: entry.lastUsedAt,
45141
45692
  inFlight: false,
45142
45693
  model: entry.model,
45143
- reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort)
45694
+ reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort),
45695
+ replay: null
45144
45696
  });
45145
45697
  }
45146
45698
  const persistThreads = () => {
@@ -45200,6 +45752,7 @@ async function startDirectorBridge() {
45200
45752
  unbindSessionSink: (directorSessionId, send) => {
45201
45753
  sessionSinks.unbind(directorSessionId, send);
45202
45754
  },
45755
+ getSessionSink: (directorSessionId) => sessionSinks.get(directorSessionId),
45203
45756
  maybeUpdateOffer: () => selfUpdateHandle.maybeUpdateOffer()
45204
45757
  };
45205
45758
  const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
@@ -45211,9 +45764,10 @@ async function startDirectorBridge() {
45211
45764
  attachBridgeWss(server, {
45212
45765
  token: config2.token,
45213
45766
  allowedOrigins: config2.allowedOrigins,
45214
- onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads }),
45767
+ onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads, bridgeInstanceId, tombstones }),
45215
45768
  logger: bridgeLogger,
45216
45769
  onPaired: () => health.setPaired(true),
45770
+ bridgeInstanceId,
45217
45771
  selfUpdate: {
45218
45772
  version: PKG_VERSION,
45219
45773
  binSha: bridgeBinShaShort,
@@ -45313,10 +45867,36 @@ async function startDirectorBridge() {
45313
45867
  enqueueRun(
45314
45868
  () => runOrphanWorktreeSweep(client, {
45315
45869
  checkoutRegistry,
45316
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
45317
- locksDir: import_node_path12.default.join(config2.stateDir, "locks")
45870
+ worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
45871
+ locksDir: import_node_path13.default.join(config2.stateDir, "locks")
45318
45872
  })
45319
45873
  );
45874
+ enqueueRun(async () => {
45875
+ const now = Date.now();
45876
+ for (const [sid, t] of threads) {
45877
+ if (t.replay && shouldGc(t.replay, now)) {
45878
+ const turnId = t.replay.turnId;
45879
+ const lastSeq = t.replay.lastSeq;
45880
+ writeTombstone(tombstones, sid, t.replay, now);
45881
+ bridgeLogger.logOut({
45882
+ spanId: "gc",
45883
+ sessionId: sid,
45884
+ type: "<tombstone-written>",
45885
+ payload: { sessionId: sid, turnId, lastSeq }
45886
+ });
45887
+ t.replay = null;
45888
+ }
45889
+ }
45890
+ const removed = sweepExpiredTombstones(tombstones, now);
45891
+ if (removed > 0) {
45892
+ bridgeLogger.logOut({
45893
+ spanId: "gc",
45894
+ sessionId: null,
45895
+ type: "<tombstone-expired>",
45896
+ payload: { removed }
45897
+ });
45898
+ }
45899
+ });
45320
45900
  scheduleClaimLoop();
45321
45901
  }, claimIntervalMs());
45322
45902
  claimTimer.unref?.();
@@ -45500,7 +46080,7 @@ function readDispatchBody(req) {
45500
46080
  function readOrCreateBridgeToken(stateDir) {
45501
46081
  const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
45502
46082
  if (explicit) return explicit;
45503
- const tokenPath = import_node_path12.default.join(stateDir, "token.txt");
46083
+ const tokenPath = import_node_path13.default.join(stateDir, "token.txt");
45504
46084
  try {
45505
46085
  const existing = import_node_fs12.default.readFileSync(tokenPath, "utf8").trim();
45506
46086
  if (existing) return existing;
@@ -48892,16 +49472,16 @@ var StdioServerTransport = class {
48892
49472
  // src/tools.ts
48893
49473
  var import_promises3 = require("node:fs/promises");
48894
49474
  var import_node_fs14 = require("node:fs");
48895
- var import_node_path15 = __toESM(require("node:path"), 1);
48896
- var import_node_os9 = __toESM(require("node:os"), 1);
48897
- var import_node_child_process7 = require("node:child_process");
49475
+ var import_node_path16 = __toESM(require("node:path"), 1);
49476
+ var import_node_os10 = __toESM(require("node:os"), 1);
49477
+ var import_node_child_process8 = require("node:child_process");
48898
49478
 
48899
49479
  // ../../packages/wiki/dist/index.js
48900
49480
  var import_promises2 = __toESM(require("node:fs/promises"), 1);
48901
- var import_node_path13 = __toESM(require("node:path"), 1);
49481
+ var import_node_path14 = __toESM(require("node:path"), 1);
48902
49482
  var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
48903
49483
  function toPosixPath(input) {
48904
- return input.split(import_node_path13.default.sep).join("/");
49484
+ return input.split(import_node_path14.default.sep).join("/");
48905
49485
  }
48906
49486
  function slugifyWikiSegment(input) {
48907
49487
  return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -48915,12 +49495,12 @@ async function pathExists2(input) {
48915
49495
  }
48916
49496
  }
48917
49497
  async function findWorkspaceRoot(start = process.cwd()) {
48918
- let current = import_node_path13.default.resolve(start);
49498
+ let current = import_node_path14.default.resolve(start);
48919
49499
  while (true) {
48920
- if (await pathExists2(import_node_path13.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path13.default.join(current, "docs"))) {
49500
+ if (await pathExists2(import_node_path14.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path14.default.join(current, "docs"))) {
48921
49501
  return current;
48922
49502
  }
48923
- const parent = import_node_path13.default.dirname(current);
49503
+ const parent = import_node_path14.default.dirname(current);
48924
49504
  if (parent === current) {
48925
49505
  throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
48926
49506
  }
@@ -48929,28 +49509,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
48929
49509
  }
48930
49510
  async function resolveDocsRoot(input) {
48931
49511
  if (input) {
48932
- return import_node_path13.default.resolve(input);
49512
+ return import_node_path14.default.resolve(input);
48933
49513
  }
48934
49514
  if (process.env.MRRLIN_DOCS_ROOT) {
48935
- return import_node_path13.default.resolve(process.env.MRRLIN_DOCS_ROOT);
49515
+ return import_node_path14.default.resolve(process.env.MRRLIN_DOCS_ROOT);
48936
49516
  }
48937
- return import_node_path13.default.join(await findWorkspaceRoot(), "docs");
49517
+ return import_node_path14.default.join(await findWorkspaceRoot(), "docs");
48938
49518
  }
48939
49519
  async function resolveIndexPath(input) {
48940
49520
  if (input) {
48941
- return import_node_path13.default.resolve(input);
49521
+ return import_node_path14.default.resolve(input);
48942
49522
  }
48943
49523
  if (process.env.MRRLIN_WIKI_INDEX_PATH) {
48944
- return import_node_path13.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
49524
+ return import_node_path14.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
48945
49525
  }
48946
49526
  const workspaceRoot = await findWorkspaceRoot();
48947
- return import_node_path13.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
49527
+ return import_node_path14.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
48948
49528
  }
48949
49529
  async function walkMarkdownFiles(root, dir = root) {
48950
49530
  const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
48951
49531
  const files = [];
48952
49532
  for (const entry of entries) {
48953
- const absolute = import_node_path13.default.join(dir, entry.name);
49533
+ const absolute = import_node_path14.default.join(dir, entry.name);
48954
49534
  if (entry.isDirectory()) {
48955
49535
  files.push(...await walkMarkdownFiles(root, absolute));
48956
49536
  continue;
@@ -48969,7 +49549,7 @@ function parseTitle(markdown, sourcePath) {
48969
49549
  return title;
48970
49550
  }
48971
49551
  function documentFromFile(docsRoot, absolutePath, markdown) {
48972
- const relativePath = toPosixPath(import_node_path13.default.relative(docsRoot, absolutePath));
49552
+ const relativePath = toPosixPath(import_node_path14.default.relative(docsRoot, absolutePath));
48973
49553
  const [section, fileName] = relativePath.split("/");
48974
49554
  if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
48975
49555
  return null;
@@ -49267,6 +49847,19 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
49267
49847
  var SPEC_HEADS = ["plan-reviewer", "architect", "security-analyst", "scope-analyst"];
49268
49848
  async function runSpecGate(_target, deps, opts) {
49269
49849
  if (!await deps.consensusEnabled()) return { outcome: "SKIPPED" };
49850
+ const intent = await deps.readIntent();
49851
+ if (intent.taskId !== null && (intent.seed === null || intent.seed.trim() === "")) {
49852
+ return {
49853
+ outcome: "CONSENSUS_BLOCKED",
49854
+ clarifications: [
49855
+ {
49856
+ question: "What are the requirements for this task? There is no operator request on record, so the spec cannot be validated against your intent \u2014 please state what this task must do.",
49857
+ whyBlocking: "operator_seed_request is empty",
49858
+ category: "scope"
49859
+ }
49860
+ ]
49861
+ };
49862
+ }
49270
49863
  const extraHeads = opts?.extraHeads ?? [];
49271
49864
  const heads = [...SPEC_HEADS, ...extraHeads.filter((h) => !SPEC_HEADS.includes(h))];
49272
49865
  const spec = await deps.readSpec();
@@ -49308,6 +49901,15 @@ async function runSpecGate(_target, deps, opts) {
49308
49901
  await deps.promoteSpecReady(currentHash);
49309
49902
  return { outcome: "CONVERGED" };
49310
49903
  }
49904
+ if (result.outcome === "CONSENSUS_BLOCKED") {
49905
+ const accepted = result.history.at(-1)?.accepted ?? [];
49906
+ const clarifications = accepted.filter((issue2) => issue2.category === "ambiguity" || issue2.category === "scope").map((issue2) => ({
49907
+ question: issue2.text,
49908
+ whyBlocking: `reviewer raised a ${issue2.category} issue`,
49909
+ category: issue2.category
49910
+ }));
49911
+ return clarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", clarifications } : { outcome: "CONSENSUS_BLOCKED" };
49912
+ }
49311
49913
  return { outcome: result.outcome };
49312
49914
  }
49313
49915
 
@@ -49384,7 +49986,7 @@ async function runCodeGate(_target, deps) {
49384
49986
  }
49385
49987
 
49386
49988
  // src/consensus/codex-exec.ts
49387
- var import_node_child_process5 = require("node:child_process");
49989
+ var import_node_child_process6 = require("node:child_process");
49388
49990
  function extractFinalMessage(stdout) {
49389
49991
  let last = null;
49390
49992
  for (const rawLine of stdout.split(/\r?\n/)) {
@@ -49429,7 +50031,7 @@ function firstString(...values) {
49429
50031
  return null;
49430
50032
  }
49431
50033
  function runCodexExec(input, deps) {
49432
- const spawn2 = deps?.spawn ?? import_node_child_process5.spawn;
50034
+ const spawn2 = deps?.spawn ?? import_node_child_process6.spawn;
49433
50035
  const executable = input.codexExecutable ?? "codex";
49434
50036
  const sandbox = input.sandbox ?? "read-only";
49435
50037
  const fullPrompt = input.developerInstructions.trim() ? `${input.developerInstructions.trim()}
@@ -49502,11 +50104,11 @@ function errMessage(err) {
49502
50104
 
49503
50105
  // src/consensus/wiring.ts
49504
50106
  var import_node_fs13 = __toESM(require("node:fs"), 1);
49505
- var import_node_path14 = __toESM(require("node:path"), 1);
49506
- var import_node_url = require("node:url");
50107
+ var import_node_path15 = __toESM(require("node:path"), 1);
50108
+ var import_node_url2 = require("node:url");
49507
50109
 
49508
50110
  // src/consensus/code-gate-git.ts
49509
- var import_node_child_process6 = require("node:child_process");
50111
+ var import_node_child_process7 = require("node:child_process");
49510
50112
  var DIFF_MAX_BYTES = 2e5;
49511
50113
  var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
49512
50114
  var GIT_TIMEOUT_MS = 6e4;
@@ -49522,7 +50124,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
49522
50124
  };
49523
50125
  let child;
49524
50126
  try {
49525
- child = (0, import_node_child_process6.spawn)(cmd, args, {
50127
+ child = (0, import_node_child_process7.spawn)(cmd, args, {
49526
50128
  cwd: opts.cwd,
49527
50129
  env: process.env,
49528
50130
  shell: false,
@@ -49734,18 +50336,18 @@ ${res.stdout}${res.stderr}`);
49734
50336
  }
49735
50337
 
49736
50338
  // src/consensus/wiring.ts
49737
- var import_meta = {};
50339
+ var import_meta2 = {};
49738
50340
  function getPersonasDir() {
49739
50341
  if (typeof __dirname !== "undefined") {
49740
- return import_node_path14.default.join(__dirname, "consensus", "personas");
50342
+ return import_node_path15.default.join(__dirname, "consensus", "personas");
49741
50343
  }
49742
- return import_node_path14.default.join(import_node_path14.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "personas");
50344
+ return import_node_path15.default.join(import_node_path15.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
49743
50345
  }
49744
50346
  var personaCache = /* @__PURE__ */ new Map();
49745
50347
  function loadPersona(name) {
49746
50348
  const cached2 = personaCache.get(name);
49747
50349
  if (cached2 !== void 0) return cached2;
49748
- const content = import_node_fs13.default.readFileSync(import_node_path14.default.join(getPersonasDir(), `${name}.md`), "utf8");
50350
+ const content = import_node_fs13.default.readFileSync(import_node_path15.default.join(getPersonasDir(), `${name}.md`), "utf8");
49749
50351
  personaCache.set(name, content);
49750
50352
  return content;
49751
50353
  }
@@ -49754,6 +50356,19 @@ function buildSpecGateDeps(args) {
49754
50356
  const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 3);
49755
50357
  const maxHeadCalls = rounds * (4 + extraHeadCount + 1);
49756
50358
  const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
50359
+ let intentPromise = null;
50360
+ function loadIntent() {
50361
+ if (!intentPromise) {
50362
+ intentPromise = (async () => {
50363
+ const page = await client.getWikiPage(projectSlug, specPageId);
50364
+ const taskId = page?.taskId ?? null;
50365
+ if (taskId === null) return { taskId: null, seed: null };
50366
+ const task = await client.getTask(projectSlug, taskId);
50367
+ return { taskId, seed: task?.operatorSeedRequest ?? null };
50368
+ })();
50369
+ }
50370
+ return intentPromise;
50371
+ }
49757
50372
  return {
49758
50373
  rounds,
49759
50374
  maxHeadCalls,
@@ -49769,15 +50384,23 @@ function buildSpecGateDeps(args) {
49769
50384
  contentHash: page.contentHash
49770
50385
  };
49771
50386
  },
50387
+ readIntent() {
50388
+ return loadIntent();
50389
+ },
49772
50390
  async runHead(personaName, artifact, dismissed) {
49773
50391
  const persona = loadPersona(personaName);
50392
+ const { seed } = await loadIntent();
50393
+ const intentBlock = seed ? `--- OPERATOR INTENT (the operator's own words \u2014 judge the spec against THIS) ---
50394
+ ${seed}
50395
+
50396
+ ` : "";
49774
50397
  return runCodexExec(
49775
50398
  {
49776
- prompt: `Review this spec.
50399
+ prompt: `Review this spec against the operator's intent.
49777
50400
 
49778
50401
  ${dismissed}
49779
50402
 
49780
- --- SPEC ---
50403
+ ${intentBlock}--- SPEC ---
49781
50404
  ${artifact}`,
49782
50405
  developerInstructions: persona,
49783
50406
  cwd,
@@ -49953,6 +50576,7 @@ ${artifact}`,
49953
50576
  }
49954
50577
 
49955
50578
  // src/async-tools/consensus.ts
50579
+ var import_node_crypto6 = require("node:crypto");
49956
50580
  async function cachedResult(client, input) {
49957
50581
  const page = await client.getWikiPage(input.projectSlug, input.pageId);
49958
50582
  if (!page) return null;
@@ -49979,16 +50603,58 @@ async function run(ctx, input) {
49979
50603
  deps,
49980
50604
  input.extraHeads && input.extraHeads.length > 0 ? { extraHeads: input.extraHeads } : void 0
49981
50605
  );
50606
+ if (result.outcome === "CONSENSUS_BLOCKED") {
50607
+ const clarifications = result.clarifications ?? [];
50608
+ if (clarifications.length > 0) {
50609
+ const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
50610
+ const taskId = page?.taskId ?? null;
50611
+ let planId = null;
50612
+ if (!taskId) {
50613
+ const plans = await ctx.client.listPlans(input.projectSlug);
50614
+ planId = plans.find((p) => p.specWikiPageId === input.pageId)?.id ?? null;
50615
+ }
50616
+ if (taskId) {
50617
+ for (const clarification of clarifications) {
50618
+ const scopeId = taskId;
50619
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto6.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
50620
+ try {
50621
+ await ctx.client.createInboxItem(input.projectSlug, {
50622
+ id,
50623
+ kind: "question",
50624
+ taskId: scopeId,
50625
+ body: clarification.question,
50626
+ origin: "gate"
50627
+ });
50628
+ } catch {
50629
+ }
50630
+ }
50631
+ } else if (planId) {
50632
+ for (const clarification of clarifications) {
50633
+ const scopeId = planId;
50634
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto6.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
50635
+ try {
50636
+ await ctx.client.createInboxItem(input.projectSlug, {
50637
+ id,
50638
+ kind: "question",
50639
+ planId: scopeId,
50640
+ body: clarification.question,
50641
+ origin: "gate"
50642
+ });
50643
+ } catch {
50644
+ }
50645
+ }
50646
+ }
50647
+ }
50648
+ return {
50649
+ kind: "failed",
50650
+ failureReason: "consensus_blocked",
50651
+ error: clarifications.length > 0 ? `Consensus blocked on ${clarifications.length} clarification(s); filed as operator question(s).` : "Consensus blocked: reviewers did not converge within budget."
50652
+ };
50653
+ }
49982
50654
  switch (result.outcome) {
49983
50655
  case "CONVERGED":
49984
50656
  case "SKIPPED":
49985
50657
  return { kind: "done", resultJson: JSON.stringify(result), finalReviewedHash: null };
49986
- case "CONSENSUS_BLOCKED":
49987
- return {
49988
- kind: "failed",
49989
- failureReason: "consensus_blocked",
49990
- error: "Consensus blocked: reviewers did not converge within budget."
49991
- };
49992
50658
  case "CONSENSUS_UNAVAILABLE":
49993
50659
  return { kind: "retry", failureReason: "provider_unavailable", error: "Consensus unavailable (provider/quota)." };
49994
50660
  case "SPEC_CHANGED_DURING_REVIEW":
@@ -50003,6 +50669,17 @@ async function run(ctx, input) {
50003
50669
  }
50004
50670
  function onComplete(outcome, input) {
50005
50671
  if (outcome.kind === "done") {
50672
+ let specOutcome = "CONVERGED";
50673
+ try {
50674
+ specOutcome = JSON.parse(outcome.resultJson).outcome ?? "CONVERGED";
50675
+ } catch {
50676
+ }
50677
+ if (specOutcome === "SKIPPED") {
50678
+ return {
50679
+ kind: "info",
50680
+ body: `Consensus is disabled for this project; Specs/${input.pageId} was not gated and spec_ready is unchanged.`
50681
+ };
50682
+ }
50006
50683
  return {
50007
50684
  kind: "info",
50008
50685
  body: `Consensus CONVERGED for Specs/${input.pageId}; spec_ready set. Ready to create an execution run.`
@@ -50023,7 +50700,7 @@ var consensusDescriptor = {
50023
50700
  };
50024
50701
 
50025
50702
  // src/async-tools/enqueue.ts
50026
- var import_node_crypto6 = __toESM(require("node:crypto"), 1);
50703
+ var import_node_crypto7 = __toESM(require("node:crypto"), 1);
50027
50704
  async function enqueueAsyncTool(client, descriptor2, input) {
50028
50705
  if (descriptor2.cachedResult) {
50029
50706
  const cached2 = await descriptor2.cachedResult(client, input);
@@ -50036,7 +50713,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
50036
50713
  if (active) {
50037
50714
  return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
50038
50715
  }
50039
- const jobId = `AJ-${import_node_crypto6.default.randomUUID()}`;
50716
+ const jobId = `AJ-${import_node_crypto7.default.randomUUID()}`;
50040
50717
  try {
50041
50718
  await client.createAsyncJob(input.projectSlug, {
50042
50719
  id: jobId,
@@ -50895,7 +51572,7 @@ var mcpToolDescriptions = {
50895
51572
  [mcpToolNames.runSpecConsensus]: 'Enqueue the consensus review gate over a Specs/{id} page. Returns IMMEDIATELY with one of: already_converged (a CONVERGED review already exists for the current content \u2014 proceed straight to create_execution_run, do NOT call mark_spec_ready, it is already set), already_reviewed (a terminal CONSENSUS_BLOCKED for this content), already_running (a consensus job is in flight), or queued (a new job was launched). The review runs in the background; its result/blocker arrives in the inbox (info on CONVERGED, handoff on failure) and is surfaced into the open chat. Do NOT call again for the same spec and do NOT poll. On queued/already_running, tell the user it was launched and end the turn. Pass extraHeads: ["researcher"] for specs referencing external libraries/APIs, or ["debugger"] for root-cause/investigation specs to add opt-in specialist reviewers on top of the fixed four.',
50896
51573
  [mcpToolNames.runCodeReviewerGate]: `Review the current branch's code diff (vs baseRef) with a Code Reviewer gate \u2014 independent reviewers iterate review\u2192fix\u2192re-check (checkpoint, scope-limited reviser edits, typecheck/build fast-gate, rollback) until the diff converges or is blocked. Run before opening a PR. Pass extraHeads: ["security-analyst"] for sensitive diffs (auth, secrets, input handling, new endpoints).`,
50897
51574
  [mcpToolNames.appendExecutionArtifact]: "Append a durable artifact (plan, checkpoint, command output, test result, diff summary, self-review, error, deploy attempt, or handoff judgement) to an execution run.",
50898
- [mcpToolNames.createExecutionRun]: "Create a durable Director execution run for a task. Persists status, branch/SHA, workflow ids, and checkpoint cursor outside the chat transcript.",
51575
+ [mcpToolNames.createExecutionRun]: 'Create a durable Director execution run for a task. Persists status, branch/SHA, workflow ids, and checkpoint cursor outside the chat transcript. For tasks that require a browser (login flows, UI verification, scraping), set prerequisites:[{mcp:"mrrlin-browser",reason:"<why a browser is needed>"}] so any resulting handoff offers a one-click "Launch browser & resume".',
50899
51576
  [mcpToolNames.getExecutionRun]: "Fetch a single execution run by id.",
50900
51577
  [mcpToolNames.listExecutionArtifacts]: "List artifacts captured during an execution run, in chronological order.",
50901
51578
  [mcpToolNames.listExecutionRuns]: "List execution runs for a project. Optional filters: taskId, status.",
@@ -51339,7 +52016,10 @@ function createMrrlinTools(options) {
51339
52016
  if (ready !== true) return await c.markSpecReady({ projectSlug, pageId, ready });
51340
52017
  const settings = await c.getOperatorSettings();
51341
52018
  if (!settings.consensusEnabled) {
51342
- return await c.markSpecReady({ projectSlug, pageId, ready });
52019
+ throw new McpToolCodedError(
52020
+ "SPEC_CONSENSUS_REQUIRED",
52021
+ `Spec ${pageId} cannot be marked ready by the Director while consensus is disabled for this project \u2014 an operator must approve it (web wiki / markSpecReady route). Autonomy is a landing gate, not a license to self-promote.`
52022
+ );
51343
52023
  }
51344
52024
  const page = await c.getWikiPage(projectSlug, pageId);
51345
52025
  if (!page || page.folder !== "Specs") {
@@ -51508,7 +52188,7 @@ function createMrrlinTools(options) {
51508
52188
  "ARTIFACT_FILE_UPLOAD_FAILED",
51509
52189
  "Unable to upload artifact file.",
51510
52190
  async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
51511
- const extension2 = import_node_path15.default.extname(filePath).toLowerCase();
52191
+ const extension2 = import_node_path16.default.extname(filePath).toLowerCase();
51512
52192
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
51513
52193
  if (!contentType) {
51514
52194
  throw new McpToolCodedError(
@@ -51536,7 +52216,7 @@ function createMrrlinTools(options) {
51536
52216
  "Artifact exceeds 5MB; split or summarize instead."
51537
52217
  );
51538
52218
  }
51539
- const filename = import_node_path15.default.basename(filePath);
52219
+ const filename = import_node_path16.default.basename(filePath);
51540
52220
  const created = await c.createArtifactFile(projectSlug, {
51541
52221
  class: artifactClass,
51542
52222
  contentType,
@@ -51619,7 +52299,7 @@ function createMrrlinTools(options) {
51619
52299
  "Unable to register local checkout.",
51620
52300
  async (_c, { projectSlug, path: checkoutPath, repo }) => {
51621
52301
  const trimmedPath = checkoutPath.trim();
51622
- if (!import_node_path15.default.isAbsolute(trimmedPath)) {
52302
+ if (!import_node_path16.default.isAbsolute(trimmedPath)) {
51623
52303
  throw new McpToolCodedError(
51624
52304
  "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
51625
52305
  `Path must be absolute, got: ${trimmedPath}`
@@ -51636,7 +52316,7 @@ function createMrrlinTools(options) {
51636
52316
  }
51637
52317
  let remoteUrl;
51638
52318
  try {
51639
- remoteUrl = (0, import_node_child_process7.execFileSync)("git", ["-C", resolvedPath, "remote", "get-url", "origin"], {
52319
+ remoteUrl = (0, import_node_child_process8.execFileSync)("git", ["-C", resolvedPath, "remote", "get-url", "origin"], {
51640
52320
  encoding: "utf8",
51641
52321
  stdio: ["ignore", "pipe", "ignore"],
51642
52322
  timeout: 15e3,
@@ -51654,7 +52334,7 @@ function createMrrlinTools(options) {
51654
52334
  `Origin remote ${remoteUrl} does not match repo ${repo}.`
51655
52335
  );
51656
52336
  }
51657
- const stateDir = process.env.CODEX_HOME ? import_node_path15.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path15.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
52337
+ const stateDir = process.env.CODEX_HOME ? import_node_path16.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path16.default.join(import_node_os10.default.homedir(), ".mrrlin", "director-bridge");
51658
52338
  const registry3 = new CheckoutRegistry(stateDir);
51659
52339
  const confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
51660
52340
  registry3.confirm(projectSlug, resolvedPath, confirmedAt);
@@ -51861,13 +52541,13 @@ function runSetCredential(args) {
51861
52541
  }
51862
52542
 
51863
52543
  // src/install-service.ts
51864
- var import_node_os10 = __toESM(require("node:os"), 1);
51865
- var import_node_path17 = __toESM(require("node:path"), 1);
52544
+ var import_node_os11 = __toESM(require("node:os"), 1);
52545
+ var import_node_path18 = __toESM(require("node:path"), 1);
51866
52546
 
51867
52547
  // src/service-paths.ts
51868
- var import_node_path16 = __toESM(require("node:path"), 1);
52548
+ var import_node_path17 = __toESM(require("node:path"), 1);
51869
52549
  function isWorktreePath(p) {
51870
- const norm = import_node_path16.default.normalize(p).split(import_node_path16.default.sep).join("/");
52550
+ const norm = import_node_path17.default.normalize(p).split(import_node_path17.default.sep).join("/");
51871
52551
  return norm.includes("/.claude/worktrees/");
51872
52552
  }
51873
52553
  function resolveServiceCwd(opts) {
@@ -51921,7 +52601,7 @@ function installService(deps) {
51921
52601
  deps.log(resolved.reason);
51922
52602
  return { ok: false };
51923
52603
  }
51924
- const home = deps.env.HOME ?? import_node_os10.default.homedir();
52604
+ const home = deps.env.HOME ?? import_node_os11.default.homedir();
51925
52605
  const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
51926
52606
  if (bins.some((b) => !b)) {
51927
52607
  deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
@@ -51932,7 +52612,7 @@ function installService(deps) {
51932
52612
  return { ok: false };
51933
52613
  }
51934
52614
  const resolvedBins = bins.filter((b) => b !== null);
51935
- const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path17.default.dirname(b)))).join(":");
52615
+ const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path18.default.dirname(b)))).join(":");
51936
52616
  const text = renderEcosystemConfig({
51937
52617
  cwd: resolved.cwd,
51938
52618
  home,
@@ -51941,7 +52621,7 @@ function installService(deps) {
51941
52621
  staging: deps.env.MRRLIN_STAGING === "1",
51942
52622
  apiBaseUrl: deps.env.MRRLIN_API_BASE_URL?.trim() || void 0
51943
52623
  });
51944
- const ecoPath = import_node_path17.default.join(home, ".mrrlin", "ecosystem.config.cjs");
52624
+ const ecoPath = import_node_path18.default.join(home, ".mrrlin", "ecosystem.config.cjs");
51945
52625
  deps.writeFile(ecoPath, text);
51946
52626
  const start = deps.runPm2(["startOrReload", ecoPath]);
51947
52627
  if (start.code !== 0) {
@@ -51972,13 +52652,13 @@ function uninstallService(deps) {
51972
52652
 
51973
52653
  // src/uninstall-codex.ts
51974
52654
  var import_promises4 = __toESM(require("node:fs/promises"), 1);
51975
- var import_node_os11 = __toESM(require("node:os"), 1);
51976
- var import_node_path18 = __toESM(require("node:path"), 1);
52655
+ var import_node_os12 = __toESM(require("node:os"), 1);
52656
+ var import_node_path19 = __toESM(require("node:path"), 1);
51977
52657
  var toml2 = __toESM(require_toml(), 1);
51978
52658
  function resolveCodexHome2(options) {
51979
52659
  if (options.codexHome) return options.codexHome;
51980
52660
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
51981
- return import_node_path18.default.join(options.homeDir ?? import_node_os11.default.homedir(), ".codex");
52661
+ return import_node_path19.default.join(options.homeDir ?? import_node_os12.default.homedir(), ".codex");
51982
52662
  }
51983
52663
  async function pathExists3(target) {
51984
52664
  try {
@@ -51988,10 +52668,10 @@ async function pathExists3(target) {
51988
52668
  return false;
51989
52669
  }
51990
52670
  }
51991
- var MRRLIN_BLOCK_RE2 = /(^|\n)\[mcp_servers\.mrrlin(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
52671
+ var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.mrrlin(?:-browser)?(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
51992
52672
  async function uninstallCodex(options = {}) {
51993
52673
  const codexHome = resolveCodexHome2(options);
51994
- const configPath = import_node_path18.default.join(codexHome, "config.toml");
52674
+ const configPath = import_node_path19.default.join(codexHome, "config.toml");
51995
52675
  const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
51996
52676
  if (!await pathExists3(configPath)) {
51997
52677
  return { action: "missing", configPath, prompts: await removePrompts() };
@@ -52010,19 +52690,19 @@ async function uninstallCodex(options = {}) {
52010
52690
  };
52011
52691
  throw Object.assign(new Error(err.detail), err);
52012
52692
  }
52013
- if (parsed?.mcp_servers?.["mrrlin"] === void 0) {
52693
+ if (parsed?.mcp_servers?.["mrrlin"] === void 0 && parsed?.mcp_servers?.["mrrlin-browser"] === void 0) {
52014
52694
  return { action: "noop", configPath: realPath, prompts: await removePrompts() };
52015
52695
  }
52016
- const stripped = existing.replace(MRRLIN_BLOCK_RE2, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
52696
+ const stripped = existing.replace(MRRLIN_BLOCK_RE, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
52017
52697
  await import_promises4.default.writeFile(realPath, stripped, { mode: 384 });
52018
52698
  return { action: "removed", configPath: realPath, prompts: await removePrompts() };
52019
52699
  }
52020
52700
  async function uninstallPrompts(codexHome, names) {
52021
52701
  if (names.length === 0) return [];
52022
- const promptsDir2 = import_node_path18.default.join(codexHome, "prompts");
52702
+ const promptsDir2 = import_node_path19.default.join(codexHome, "prompts");
52023
52703
  const out = [];
52024
52704
  for (const name of names) {
52025
- const promptPath = import_node_path18.default.join(promptsDir2, `${name}.md`);
52705
+ const promptPath = import_node_path19.default.join(promptsDir2, `${name}.md`);
52026
52706
  try {
52027
52707
  await import_promises4.default.unlink(promptPath);
52028
52708
  out.push({ name, action: "removed", promptPath });
@@ -52040,26 +52720,26 @@ async function uninstallPrompts(codexHome, names) {
52040
52720
 
52041
52721
  // src/report-issue-prompt.ts
52042
52722
  var import_node_fs15 = __toESM(require("node:fs"), 1);
52043
- var import_node_path19 = __toESM(require("node:path"), 1);
52044
- var import_node_url2 = require("node:url");
52045
- var import_meta2 = {};
52723
+ var import_node_path20 = __toESM(require("node:path"), 1);
52724
+ var import_node_url3 = require("node:url");
52725
+ var import_meta3 = {};
52046
52726
  function promptsDir() {
52047
- if (typeof __dirname !== "undefined") return import_node_path19.default.join(__dirname, "prompts");
52048
- return import_node_path19.default.join(import_node_path19.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "prompts");
52727
+ if (typeof __dirname !== "undefined") return import_node_path20.default.join(__dirname, "prompts");
52728
+ return import_node_path20.default.join(import_node_path20.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url)), "prompts");
52049
52729
  }
52050
52730
  function readReportIssuePrompt() {
52051
- return import_node_fs15.default.readFileSync(import_node_path19.default.join(promptsDir(), "report-issue.md"), "utf8");
52731
+ return import_node_fs15.default.readFileSync(import_node_path20.default.join(promptsDir(), "report-issue.md"), "utf8");
52052
52732
  }
52053
52733
 
52054
52734
  // src/bin.ts
52055
52735
  function pm2Runner(args) {
52056
- const r = (0, import_node_child_process8.spawnSync)("pm2", args, { encoding: "utf8" });
52736
+ const r = (0, import_node_child_process9.spawnSync)("pm2", args, { encoding: "utf8" });
52057
52737
  process.stderr.write(r.stdout ?? "");
52058
52738
  process.stderr.write(r.stderr ?? "");
52059
52739
  return { code: r.status ?? 1, stdout: r.stdout ?? "" };
52060
52740
  }
52061
52741
  function whichBin(bin) {
52062
- const r = (0, import_node_child_process8.spawnSync)("which", [bin], { encoding: "utf8" });
52742
+ const r = (0, import_node_child_process9.spawnSync)("which", [bin], { encoding: "utf8" });
52063
52743
  const out = (r.stdout ?? "").trim();
52064
52744
  return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
52065
52745
  }
@@ -52072,6 +52752,18 @@ Usage:
52072
52752
  MRRLIN_API_ALLOW_REMOTE=1, or use MRRLIN_STAGING=1
52073
52753
  to target the known staging API alias.
52074
52754
 
52755
+ mrrlin-mcp install-browser Idempotently install the dedicated, pinned
52756
+ Chromium into ~/.mrrlin/browser/browsers (its own
52757
+ copy, isolated from the operator's Chrome and
52758
+ codex-chrome). Run by install-codex; safe to
52759
+ re-run. Exits non-zero on download failure.
52760
+
52761
+ mrrlin-mcp browser-serve Launch the vendored @playwright/mcp against the
52762
+ dedicated persistent profile
52763
+ (~/.mrrlin/browser/profile, headed). This is the
52764
+ command install-codex wires for the
52765
+ [mcp_servers.mrrlin-browser] block.
52766
+
52075
52767
  mrrlin-mcp install-codex Idempotently register Mrrlin in
52076
52768
  [--force] ~/.codex/config.toml (or CODEX_HOME). Adds an
52077
52769
  [--force-prompts] [mcp_servers.mrrlin] block AND drops the bundled
@@ -52205,10 +52897,33 @@ async function main() {
52205
52897
  await startStdioServer();
52206
52898
  return;
52207
52899
  }
52900
+ case "install-browser": {
52901
+ const res = await installBrowser();
52902
+ process.stderr.write(`[mrrlin-mcp install-browser] ${res.action} ${res.browsersPath}
52903
+ `);
52904
+ return;
52905
+ }
52906
+ case "browser-serve": {
52907
+ const { command: command2, args, env } = browserServeArgs();
52908
+ const r = (0, import_node_child_process9.spawnSync)(command2, args, { stdio: "inherit", env: { ...process.env, ...env } });
52909
+ process.exitCode = r.status ?? 1;
52910
+ return;
52911
+ }
52208
52912
  case "install-codex": {
52209
52913
  const force = rest.includes("--force");
52210
52914
  const forcePrompts = rest.includes("--force-prompts");
52211
52915
  const binPath = resolveSelfBinPath();
52916
+ try {
52917
+ const b = await installBrowser();
52918
+ process.stderr.write(`[mrrlin-mcp install-codex] install-browser ${b.action} ${b.browsersPath}
52919
+ `);
52920
+ } catch (error51) {
52921
+ process.stderr.write(
52922
+ `[mrrlin-mcp install-codex] install-browser FAILED \u2014 config.toml left untouched: ${error51 instanceof Error ? error51.message : String(error51)}
52923
+ `
52924
+ );
52925
+ process.exit(2);
52926
+ }
52212
52927
  const result = await installCodex({
52213
52928
  binPath,
52214
52929
  force,
@@ -52258,7 +52973,7 @@ async function main() {
52258
52973
  env: process.env,
52259
52974
  cwd: process.cwd(),
52260
52975
  writeFile: (p, c) => {
52261
- (0, import_node_fs16.mkdirSync)(import_node_path21.default.dirname(p), { recursive: true, mode: 448 });
52976
+ (0, import_node_fs16.mkdirSync)(import_node_path22.default.dirname(p), { recursive: true, mode: 448 });
52262
52977
  (0, import_node_fs16.writeFileSync)(p, c, { mode: 384 });
52263
52978
  },
52264
52979
  runPm2: pm2Runner,
@@ -52283,14 +52998,14 @@ async function main() {
52283
52998
  purgeSecret: purge,
52284
52999
  secretPath: agentCredentialPath(),
52285
53000
  tokenPath: operatorTokenPath(),
52286
- ecoPath: import_node_path21.default.join(process.env.HOME ?? (0, import_node_os12.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
53001
+ ecoPath: import_node_path22.default.join(process.env.HOME ?? (0, import_node_os13.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
52287
53002
  log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
52288
53003
  `)
52289
53004
  });
52290
53005
  return;
52291
53006
  }
52292
53007
  case "uninstall": {
52293
- const home = process.env.HOME ?? (0, import_node_os12.homedir)();
53008
+ const home = process.env.HOME ?? (0, import_node_os13.homedir)();
52294
53009
  const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
52295
53010
  `);
52296
53011
  uninstallService({
@@ -52304,7 +53019,7 @@ async function main() {
52304
53019
  purgeSecret: true,
52305
53020
  secretPath: agentCredentialPath(),
52306
53021
  tokenPath: operatorTokenPath(),
52307
- ecoPath: import_node_path21.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
53022
+ ecoPath: import_node_path22.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
52308
53023
  log
52309
53024
  });
52310
53025
  let codexOk = true;
@@ -52324,7 +53039,7 @@ async function main() {
52324
53039
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
52325
53040
  }
52326
53041
  try {
52327
- (0, import_node_fs16.rmSync)(import_node_path21.default.join(home, ".mrrlin"), { recursive: true, force: true });
53042
+ (0, import_node_fs16.rmSync)(import_node_path22.default.join(home, ".mrrlin"), { recursive: true, force: true });
52328
53043
  } catch {
52329
53044
  }
52330
53045
  log("removed ~/.mrrlin");
@@ -52365,7 +53080,7 @@ ${HELP_TEXT}`);
52365
53080
  }
52366
53081
  }
52367
53082
  function resolveSelfBinPath() {
52368
- return import_node_path20.default.resolve(process.argv[1] ?? process.execPath);
53083
+ return import_node_path21.default.resolve(process.argv[1] ?? process.execPath);
52369
53084
  }
52370
53085
  main().catch((error51) => {
52371
53086
  process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}