@mrrlin-dev/mcp 0.3.52 → 0.3.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.cjs +1659 -548
  2. package/package.json +5 -5
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: randomBytes4, createHash: createHash4 } = require("crypto");
4276
+ var { randomBytes: randomBytes4, createHash: createHash5 } = 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 = createHash4("sha1").update(key + GUID).digest("base64");
4944
+ const digest = createHash5("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: createHash4 } = require("crypto");
5313
+ var { createHash: createHash5 } = 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 = createHash4("sha1").update(key + GUID).digest("base64");
5620
+ const digest = createHash5("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(fs8) {
7706
+ function patch(fs9) {
7707
7707
  if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
7708
- patchLchmod(fs8);
7709
- }
7710
- if (!fs8.lutimes) {
7711
- patchLutimes(fs8);
7712
- }
7713
- fs8.chown = chownFix(fs8.chown);
7714
- fs8.fchown = chownFix(fs8.fchown);
7715
- fs8.lchown = chownFix(fs8.lchown);
7716
- fs8.chmod = chmodFix(fs8.chmod);
7717
- fs8.fchmod = chmodFix(fs8.fchmod);
7718
- fs8.lchmod = chmodFix(fs8.lchmod);
7719
- fs8.chownSync = chownFixSync(fs8.chownSync);
7720
- fs8.fchownSync = chownFixSync(fs8.fchownSync);
7721
- fs8.lchownSync = chownFixSync(fs8.lchownSync);
7722
- fs8.chmodSync = chmodFixSync(fs8.chmodSync);
7723
- fs8.fchmodSync = chmodFixSync(fs8.fchmodSync);
7724
- fs8.lchmodSync = chmodFixSync(fs8.lchmodSync);
7725
- fs8.stat = statFix(fs8.stat);
7726
- fs8.fstat = statFix(fs8.fstat);
7727
- fs8.lstat = statFix(fs8.lstat);
7728
- fs8.statSync = statFixSync(fs8.statSync);
7729
- fs8.fstatSync = statFixSync(fs8.fstatSync);
7730
- fs8.lstatSync = statFixSync(fs8.lstatSync);
7731
- if (fs8.chmod && !fs8.lchmod) {
7732
- fs8.lchmod = function(path18, mode, cb) {
7708
+ patchLchmod(fs9);
7709
+ }
7710
+ if (!fs9.lutimes) {
7711
+ patchLutimes(fs9);
7712
+ }
7713
+ fs9.chown = chownFix(fs9.chown);
7714
+ fs9.fchown = chownFix(fs9.fchown);
7715
+ fs9.lchown = chownFix(fs9.lchown);
7716
+ fs9.chmod = chmodFix(fs9.chmod);
7717
+ fs9.fchmod = chmodFix(fs9.fchmod);
7718
+ fs9.lchmod = chmodFix(fs9.lchmod);
7719
+ fs9.chownSync = chownFixSync(fs9.chownSync);
7720
+ fs9.fchownSync = chownFixSync(fs9.fchownSync);
7721
+ fs9.lchownSync = chownFixSync(fs9.lchownSync);
7722
+ fs9.chmodSync = chmodFixSync(fs9.chmodSync);
7723
+ fs9.fchmodSync = chmodFixSync(fs9.fchmodSync);
7724
+ fs9.lchmodSync = chmodFixSync(fs9.lchmodSync);
7725
+ fs9.stat = statFix(fs9.stat);
7726
+ fs9.fstat = statFix(fs9.fstat);
7727
+ fs9.lstat = statFix(fs9.lstat);
7728
+ fs9.statSync = statFixSync(fs9.statSync);
7729
+ fs9.fstatSync = statFixSync(fs9.fstatSync);
7730
+ fs9.lstatSync = statFixSync(fs9.lstatSync);
7731
+ if (fs9.chmod && !fs9.lchmod) {
7732
+ fs9.lchmod = function(path19, mode, cb) {
7733
7733
  if (cb) process.nextTick(cb);
7734
7734
  };
7735
- fs8.lchmodSync = function() {
7735
+ fs9.lchmodSync = function() {
7736
7736
  };
7737
7737
  }
7738
- if (fs8.chown && !fs8.lchown) {
7739
- fs8.lchown = function(path18, uid, gid, cb) {
7738
+ if (fs9.chown && !fs9.lchown) {
7739
+ fs9.lchown = function(path19, uid, gid, cb) {
7740
7740
  if (cb) process.nextTick(cb);
7741
7741
  };
7742
- fs8.lchownSync = function() {
7742
+ fs9.lchownSync = function() {
7743
7743
  };
7744
7744
  }
7745
7745
  if (platform === "win32") {
7746
- fs8.rename = typeof fs8.rename !== "function" ? fs8.rename : function(fs$rename) {
7746
+ fs9.rename = typeof fs9.rename !== "function" ? fs9.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
- fs8.stat(to, function(stater, st) {
7753
+ fs9.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
- }(fs8.rename);
7769
+ }(fs9.rename);
7770
7770
  }
7771
- fs8.read = typeof fs8.read !== "function" ? fs8.read : function(fs$read) {
7771
+ fs9.read = typeof fs9.read !== "function" ? fs9.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(fs8, fd, buffer, offset, length, position, callback);
7779
+ return fs$read.call(fs9, fd, buffer, offset, length, position, callback);
7780
7780
  }
7781
7781
  callback_.apply(this, arguments);
7782
7782
  };
7783
7783
  }
7784
- return fs$read.call(fs8, fd, buffer, offset, length, position, callback);
7784
+ return fs$read.call(fs9, fd, buffer, offset, length, position, callback);
7785
7785
  }
7786
7786
  if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
7787
7787
  return read;
7788
- }(fs8.read);
7789
- fs8.readSync = typeof fs8.readSync !== "function" ? fs8.readSync : /* @__PURE__ */ function(fs$readSync) {
7788
+ }(fs9.read);
7789
+ fs9.readSync = typeof fs9.readSync !== "function" ? fs9.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(fs8, fd, buffer, offset, length, position);
7794
+ return fs$readSync.call(fs9, 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
- }(fs8.readSync);
7805
- function patchLchmod(fs9) {
7806
- fs9.lchmod = function(path18, mode, callback) {
7807
- fs9.open(
7808
- path18,
7804
+ }(fs9.readSync);
7805
+ function patchLchmod(fs10) {
7806
+ fs10.lchmod = function(path19, mode, callback) {
7807
+ fs10.open(
7808
+ path19,
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
- fs9.fchmod(fd, mode, function(err2) {
7817
- fs9.close(fd, function(err22) {
7816
+ fs10.fchmod(fd, mode, function(err2) {
7817
+ fs10.close(fd, function(err22) {
7818
7818
  if (callback) callback(err2 || err22);
7819
7819
  });
7820
7820
  });
7821
7821
  }
7822
7822
  );
7823
7823
  };
7824
- fs9.lchmodSync = function(path18, mode) {
7825
- var fd = fs9.openSync(path18, constants.O_WRONLY | constants.O_SYMLINK, mode);
7824
+ fs10.lchmodSync = function(path19, mode) {
7825
+ var fd = fs10.openSync(path19, constants.O_WRONLY | constants.O_SYMLINK, mode);
7826
7826
  var threw = true;
7827
7827
  var ret;
7828
7828
  try {
7829
- ret = fs9.fchmodSync(fd, mode);
7829
+ ret = fs10.fchmodSync(fd, mode);
7830
7830
  threw = false;
7831
7831
  } finally {
7832
7832
  if (threw) {
7833
7833
  try {
7834
- fs9.closeSync(fd);
7834
+ fs10.closeSync(fd);
7835
7835
  } catch (er) {
7836
7836
  }
7837
7837
  } else {
7838
- fs9.closeSync(fd);
7838
+ fs10.closeSync(fd);
7839
7839
  }
7840
7840
  }
7841
7841
  return ret;
7842
7842
  };
7843
7843
  }
7844
- function patchLutimes(fs9) {
7845
- if (constants.hasOwnProperty("O_SYMLINK") && fs9.futimes) {
7846
- fs9.lutimes = function(path18, at, mt, cb) {
7847
- fs9.open(path18, constants.O_SYMLINK, function(er, fd) {
7844
+ function patchLutimes(fs10) {
7845
+ if (constants.hasOwnProperty("O_SYMLINK") && fs10.futimes) {
7846
+ fs10.lutimes = function(path19, at, mt, cb) {
7847
+ fs10.open(path19, constants.O_SYMLINK, function(er, fd) {
7848
7848
  if (er) {
7849
7849
  if (cb) cb(er);
7850
7850
  return;
7851
7851
  }
7852
- fs9.futimes(fd, at, mt, function(er2) {
7853
- fs9.close(fd, function(er22) {
7852
+ fs10.futimes(fd, at, mt, function(er2) {
7853
+ fs10.close(fd, function(er22) {
7854
7854
  if (cb) cb(er2 || er22);
7855
7855
  });
7856
7856
  });
7857
7857
  });
7858
7858
  };
7859
- fs9.lutimesSync = function(path18, at, mt) {
7860
- var fd = fs9.openSync(path18, constants.O_SYMLINK);
7859
+ fs10.lutimesSync = function(path19, at, mt) {
7860
+ var fd = fs10.openSync(path19, constants.O_SYMLINK);
7861
7861
  var ret;
7862
7862
  var threw = true;
7863
7863
  try {
7864
- ret = fs9.futimesSync(fd, at, mt);
7864
+ ret = fs10.futimesSync(fd, at, mt);
7865
7865
  threw = false;
7866
7866
  } finally {
7867
7867
  if (threw) {
7868
7868
  try {
7869
- fs9.closeSync(fd);
7869
+ fs10.closeSync(fd);
7870
7870
  } catch (er) {
7871
7871
  }
7872
7872
  } else {
7873
- fs9.closeSync(fd);
7873
+ fs10.closeSync(fd);
7874
7874
  }
7875
7875
  }
7876
7876
  return ret;
7877
7877
  };
7878
- } else if (fs9.futimes) {
7879
- fs9.lutimes = function(_a3, _b, _c, cb) {
7878
+ } else if (fs10.futimes) {
7879
+ fs10.lutimes = function(_a3, _b, _c, cb) {
7880
7880
  if (cb) process.nextTick(cb);
7881
7881
  };
7882
- fs9.lutimesSync = function() {
7882
+ fs10.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(fs8, target, mode, function(er) {
7889
+ return orig.call(fs9, 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(fs8, target, mode);
7899
+ return orig.call(fs9, 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(fs8, target, uid, gid, function(er) {
7908
+ return orig.call(fs9, 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(fs8, target, uid, gid);
7918
+ return orig.call(fs9, 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(fs8, target, options, callback) : orig.call(fs8, target, callback);
7938
+ return options ? orig.call(fs9, target, options, callback) : orig.call(fs9, 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(fs8, target, options) : orig.call(fs8, target);
7944
+ var stats = options ? orig.call(fs9, target, options) : orig.call(fs9, 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(fs8) {
7973
+ function legacy(fs9) {
7974
7974
  return {
7975
7975
  ReadStream,
7976
7976
  WriteStream
7977
7977
  };
7978
- function ReadStream(path18, options) {
7979
- if (!(this instanceof ReadStream)) return new ReadStream(path18, options);
7978
+ function ReadStream(path19, options) {
7979
+ if (!(this instanceof ReadStream)) return new ReadStream(path19, options);
7980
7980
  Stream.call(this);
7981
7981
  var self = this;
7982
- this.path = path18;
7982
+ this.path = path19;
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
- fs8.open(this.path, this.flags, this.mode, function(err, fd) {
8016
+ fs9.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(path18, options) {
8028
- if (!(this instanceof WriteStream)) return new WriteStream(path18, options);
8027
+ function WriteStream(path19, options) {
8028
+ if (!(this instanceof WriteStream)) return new WriteStream(path19, options);
8029
8029
  Stream.call(this);
8030
- this.path = path18;
8030
+ this.path = path19;
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 = fs8.open;
8055
+ this._open = fs9.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 fs8 = require("fs");
8090
+ var fs9 = 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 (!fs8[gracefulQueue]) {
8122
+ if (!fs9[gracefulQueue]) {
8123
8123
  queue = global[gracefulQueue] || [];
8124
- publishQueue(fs8, queue);
8125
- fs8.close = function(fs$close) {
8124
+ publishQueue(fs9, queue);
8125
+ fs9.close = function(fs$close) {
8126
8126
  function close(fd, cb) {
8127
- return fs$close.call(fs8, fd, function(err) {
8127
+ return fs$close.call(fs9, 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
- }(fs8.close);
8140
- fs8.closeSync = function(fs$closeSync) {
8139
+ }(fs9.close);
8140
+ fs9.closeSync = function(fs$closeSync) {
8141
8141
  function closeSync(fd) {
8142
- fs$closeSync.apply(fs8, arguments);
8142
+ fs$closeSync.apply(fs9, arguments);
8143
8143
  resetQueue();
8144
8144
  }
8145
8145
  Object.defineProperty(closeSync, previousSymbol, {
8146
8146
  value: fs$closeSync
8147
8147
  });
8148
8148
  return closeSync;
8149
- }(fs8.closeSync);
8149
+ }(fs9.closeSync);
8150
8150
  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
8151
8151
  process.on("exit", function() {
8152
- debug(fs8[gracefulQueue]);
8153
- require("assert").equal(fs8[gracefulQueue].length, 0);
8152
+ debug(fs9[gracefulQueue]);
8153
+ require("assert").equal(fs9[gracefulQueue].length, 0);
8154
8154
  });
8155
8155
  }
8156
8156
  }
8157
8157
  var queue;
8158
8158
  if (!global[gracefulQueue]) {
8159
- publishQueue(global, fs8[gracefulQueue]);
8160
- }
8161
- module2.exports = patch(clone2(fs8));
8162
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs8.__patched) {
8163
- module2.exports = patch(fs8);
8164
- fs8.__patched = true;
8165
- }
8166
- function patch(fs9) {
8167
- polyfills(fs9);
8168
- fs9.gracefulify = patch;
8169
- fs9.createReadStream = createReadStream;
8170
- fs9.createWriteStream = createWriteStream;
8171
- var fs$readFile = fs9.readFile;
8172
- fs9.readFile = readFile2;
8173
- function readFile2(path18, options, cb) {
8159
+ publishQueue(global, fs9[gracefulQueue]);
8160
+ }
8161
+ module2.exports = patch(clone2(fs9));
8162
+ if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs9.__patched) {
8163
+ module2.exports = patch(fs9);
8164
+ fs9.__patched = true;
8165
+ }
8166
+ function patch(fs10) {
8167
+ polyfills(fs10);
8168
+ fs10.gracefulify = patch;
8169
+ fs10.createReadStream = createReadStream;
8170
+ fs10.createWriteStream = createWriteStream;
8171
+ var fs$readFile = fs10.readFile;
8172
+ fs10.readFile = readFile2;
8173
+ function readFile2(path19, options, cb) {
8174
8174
  if (typeof options === "function")
8175
8175
  cb = options, options = null;
8176
- return go$readFile(path18, options, cb);
8177
- function go$readFile(path19, options2, cb2, startTime) {
8178
- return fs$readFile(path19, options2, function(err) {
8176
+ return go$readFile(path19, options, cb);
8177
+ function go$readFile(path20, options2, cb2, startTime) {
8178
+ return fs$readFile(path20, options2, function(err) {
8179
8179
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8180
- enqueue([go$readFile, [path19, options2, cb2], err, startTime || Date.now(), Date.now()]);
8180
+ enqueue([go$readFile, [path20, 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 = fs9.writeFile;
8189
- fs9.writeFile = writeFile;
8190
- function writeFile(path18, data, options, cb) {
8188
+ var fs$writeFile = fs10.writeFile;
8189
+ fs10.writeFile = writeFile;
8190
+ function writeFile(path19, data, options, cb) {
8191
8191
  if (typeof options === "function")
8192
8192
  cb = options, options = null;
8193
- return go$writeFile(path18, data, options, cb);
8194
- function go$writeFile(path19, data2, options2, cb2, startTime) {
8195
- return fs$writeFile(path19, data2, options2, function(err) {
8193
+ return go$writeFile(path19, data, options, cb);
8194
+ function go$writeFile(path20, data2, options2, cb2, startTime) {
8195
+ return fs$writeFile(path20, data2, options2, function(err) {
8196
8196
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8197
- enqueue([go$writeFile, [path19, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8197
+ enqueue([go$writeFile, [path20, 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 = fs9.appendFile;
8205
+ var fs$appendFile = fs10.appendFile;
8206
8206
  if (fs$appendFile)
8207
- fs9.appendFile = appendFile;
8208
- function appendFile(path18, data, options, cb) {
8207
+ fs10.appendFile = appendFile;
8208
+ function appendFile(path19, data, options, cb) {
8209
8209
  if (typeof options === "function")
8210
8210
  cb = options, options = null;
8211
- return go$appendFile(path18, data, options, cb);
8212
- function go$appendFile(path19, data2, options2, cb2, startTime) {
8213
- return fs$appendFile(path19, data2, options2, function(err) {
8211
+ return go$appendFile(path19, data, options, cb);
8212
+ function go$appendFile(path20, data2, options2, cb2, startTime) {
8213
+ return fs$appendFile(path20, data2, options2, function(err) {
8214
8214
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8215
- enqueue([go$appendFile, [path19, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
8215
+ enqueue([go$appendFile, [path20, 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 = fs9.copyFile;
8223
+ var fs$copyFile = fs10.copyFile;
8224
8224
  if (fs$copyFile)
8225
- fs9.copyFile = copyFile;
8225
+ fs10.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 = fs9.readdir;
8244
- fs9.readdir = readdir2;
8243
+ var fs$readdir = fs10.readdir;
8244
+ fs10.readdir = readdir2;
8245
8245
  var noReaddirOptionVersions = /^v[0-5]\./;
8246
- function readdir2(path18, options, cb) {
8246
+ function readdir2(path19, 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(path19, options2, cb2, startTime) {
8250
- return fs$readdir(path19, fs$readdirCallback(
8251
- path19,
8249
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path20, options2, cb2, startTime) {
8250
+ return fs$readdir(path20, fs$readdirCallback(
8251
+ path20,
8252
8252
  options2,
8253
8253
  cb2,
8254
8254
  startTime
8255
8255
  ));
8256
- } : function go$readdir2(path19, options2, cb2, startTime) {
8257
- return fs$readdir(path19, options2, fs$readdirCallback(
8258
- path19,
8256
+ } : function go$readdir2(path20, options2, cb2, startTime) {
8257
+ return fs$readdir(path20, options2, fs$readdirCallback(
8258
+ path20,
8259
8259
  options2,
8260
8260
  cb2,
8261
8261
  startTime
8262
8262
  ));
8263
8263
  };
8264
- return go$readdir(path18, options, cb);
8265
- function fs$readdirCallback(path19, options2, cb2, startTime) {
8264
+ return go$readdir(path19, options, cb);
8265
+ function fs$readdirCallback(path20, 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
- [path19, options2, cb2],
8270
+ [path20, 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(fs9);
8285
+ var legStreams = legacy(fs10);
8286
8286
  ReadStream = legStreams.ReadStream;
8287
8287
  WriteStream = legStreams.WriteStream;
8288
8288
  }
8289
- var fs$ReadStream = fs9.ReadStream;
8289
+ var fs$ReadStream = fs10.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 = fs9.WriteStream;
8294
+ var fs$WriteStream = fs10.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(fs9, "ReadStream", {
8299
+ Object.defineProperty(fs10, "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(fs9, "WriteStream", {
8309
+ Object.defineProperty(fs10, "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(fs9, "FileReadStream", {
8320
+ Object.defineProperty(fs10, "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(fs9, "FileWriteStream", {
8331
+ Object.defineProperty(fs10, "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(path18, options) {
8341
+ function ReadStream(path19, 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(path18, options) {
8361
+ function WriteStream(path19, 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(path18, options) {
8380
- return new fs9.ReadStream(path18, options);
8379
+ function createReadStream(path19, options) {
8380
+ return new fs10.ReadStream(path19, options);
8381
8381
  }
8382
- function createWriteStream(path18, options) {
8383
- return new fs9.WriteStream(path18, options);
8382
+ function createWriteStream(path19, options) {
8383
+ return new fs10.WriteStream(path19, options);
8384
8384
  }
8385
- var fs$open = fs9.open;
8386
- fs9.open = open;
8387
- function open(path18, flags, mode, cb) {
8385
+ var fs$open = fs10.open;
8386
+ fs10.open = open;
8387
+ function open(path19, flags, mode, cb) {
8388
8388
  if (typeof mode === "function")
8389
8389
  cb = mode, mode = null;
8390
- return go$open(path18, flags, mode, cb);
8391
- function go$open(path19, flags2, mode2, cb2, startTime) {
8392
- return fs$open(path19, flags2, mode2, function(err, fd) {
8390
+ return go$open(path19, flags, mode, cb);
8391
+ function go$open(path20, flags2, mode2, cb2, startTime) {
8392
+ return fs$open(path20, flags2, mode2, function(err, fd) {
8393
8393
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
8394
- enqueue([go$open, [path19, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
8394
+ enqueue([go$open, [path20, 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 fs9;
8402
+ return fs10;
8403
8403
  }
8404
8404
  function enqueue(elem) {
8405
8405
  debug("ENQUEUE", elem[0].name, elem[1]);
8406
- fs8[gracefulQueue].push(elem);
8406
+ fs9[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 < fs8[gracefulQueue].length; ++i) {
8413
- if (fs8[gracefulQueue][i].length > 2) {
8414
- fs8[gracefulQueue][i][3] = now;
8415
- fs8[gracefulQueue][i][4] = now;
8412
+ for (var i = 0; i < fs9[gracefulQueue].length; ++i) {
8413
+ if (fs9[gracefulQueue][i].length > 2) {
8414
+ fs9[gracefulQueue][i][3] = now;
8415
+ fs9[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 (fs8[gracefulQueue].length === 0)
8423
+ if (fs9[gracefulQueue].length === 0)
8424
8424
  return;
8425
- var elem = fs8[gracefulQueue].shift();
8425
+ var elem = fs9[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
- fs8[gracefulQueue].push(elem);
8447
+ fs9[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, fs8, callback) {
8883
- const cachedPrecision = fs8[cacheSymbol];
8882
+ function probe(file2, fs9, callback) {
8883
+ const cachedPrecision = fs9[cacheSymbol];
8884
8884
  if (cachedPrecision) {
8885
- return fs8.stat(file2, (err, stat2) => {
8885
+ return fs9.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
- fs8.utimes(file2, mtime, mtime, (err) => {
8893
+ fs9.utimes(file2, mtime, mtime, (err) => {
8894
8894
  if (err) {
8895
8895
  return callback(err);
8896
8896
  }
8897
- fs8.stat(file2, (err2, stat2) => {
8897
+ fs9.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(fs8, cacheSymbol, { value: precision });
8902
+ Object.defineProperty(fs9, 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 path18 = require("path");
8924
- var fs8 = require_graceful_fs();
8923
+ var path19 = require("path");
8924
+ var fs9 = 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, path18.resolve(file2));
8934
+ return callback(null, path19.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: fs8,
9055
+ fs: fs9,
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: fs8,
9099
+ fs: fs9,
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: fs8,
9121
+ fs: fs9,
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 fs8 = require_graceful_fs();
9161
- function createSyncFs(fs9) {
9160
+ var fs9 = require_graceful_fs();
9161
+ function createSyncFs(fs10) {
9162
9162
  const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
9163
- const newFs = { ...fs9 };
9163
+ const newFs = { ...fs10 };
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 = fs9[`${method}Sync`](...args);
9169
+ ret = fs10[`${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 || fs8);
9207
+ options.fs = createSyncFs(options.fs || fs9);
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 path18 = dijkstra.find_path(graph.map, "start", "end");
10798
+ const path19 = dijkstra.find_path(graph.map, "start", "end");
10799
10799
  const optimizedSegs = [];
10800
- for (let i = 1; i < path18.length - 1; i++) {
10801
- optimizedSegs.push(graph.table[path18[i]].node);
10800
+ for (let i = 1; i < path19.length - 1; i++) {
10801
+ optimizedSegs.push(graph.table[path19[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 fs8 = require("fs");
13237
+ var fs9 = 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(path18, qrData, options, cb) {
13278
+ exports2.renderToFile = function renderToFile(path19, 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 = fs8.createWriteStream(path18);
13289
+ const stream = fs9.createWriteStream(path19);
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(path18, qrData, options, cb) {
13351
+ exports2.renderToFile = function renderToFile(path19, qrData, options, cb) {
13352
13352
  if (typeof cb === "undefined") {
13353
13353
  cb = options;
13354
13354
  options = void 0;
13355
13355
  }
13356
- const fs8 = require("fs");
13356
+ const fs9 = require("fs");
13357
13357
  const utf8 = exports2.render(qrData, options);
13358
- fs8.writeFile(path18, utf8, cb);
13358
+ fs9.writeFile(path19, 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 path18 = "";
13479
+ let path19 = "";
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
- path18 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
13490
+ path19 += 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
- path18 += svgCmd("h", lineLength);
13495
+ path19 += svgCmd("h", lineLength);
13496
13496
  lineLength = 0;
13497
13497
  }
13498
13498
  } else {
13499
13499
  moveBy++;
13500
13500
  }
13501
13501
  }
13502
- return path18;
13502
+ return path19;
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 path18 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
13510
+ const path19 = "<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 + path18 + "</svg>\n";
13513
+ const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path19 + "</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(path18, qrData, options, cb) {
13527
+ exports2.renderToFile = function renderToFile(path19, qrData, options, cb) {
13528
13528
  if (typeof cb === "undefined") {
13529
13529
  cb = options;
13530
13530
  options = void 0;
13531
13531
  }
13532
- const fs8 = require("fs");
13532
+ const fs9 = 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
- fs8.writeFile(path18, xmlStr, cb);
13535
+ fs9.writeFile(path19, 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(path18) {
13694
- return path18.slice((path18.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
13693
+ function getTypeFromFilename(path19) {
13694
+ return path19.slice((path19.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(path18, text, opts, cb) {
13759
- if (typeof path18 !== "string" || !(typeof text === "string" || typeof text === "object")) {
13758
+ exports2.toFile = function toFile(path19, text, opts, cb) {
13759
+ if (typeof path19 !== "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(path18);
13766
+ const type = params.opts.type || getTypeFromFilename(path19);
13767
13767
  const renderer = getRendererFromType(type);
13768
- const renderToFile = renderer.renderToFile.bind(null, path18);
13768
+ const renderToFile = renderer.renderToFile.bind(null, path19);
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(path18) {
16987
- let input = path18;
16986
+ function removeDotSegments(path19) {
16987
+ let input = path19;
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 [path18, query] = wsComponent.resourceName.split("?");
17240
- wsComponent.path = path18 && path18 !== "/" ? path18 : void 0;
17239
+ const [path19, query] = wsComponent.resourceName.split("?");
17240
+ wsComponent.path = path19 && path19 !== "/" ? path19 : 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, fs8, exportName) {
20633
+ function addFormats(ajv, list, fs9, 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, fs8[f]);
20638
+ ajv.addFormat(f, fs9[f]);
20639
20639
  }
20640
20640
  module2.exports = exports2 = formatsPlugin;
20641
20641
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -20644,11 +20644,11 @@ var require_dist = __commonJS({
20644
20644
  });
20645
20645
 
20646
20646
  // src/bin.ts
20647
- var import_node_path22 = __toESM(require("node:path"), 1);
20648
- var import_node_child_process13 = require("node:child_process");
20649
- var import_node_fs15 = require("node:fs");
20650
- var import_node_os12 = require("node:os");
20651
20647
  var import_node_path23 = __toESM(require("node:path"), 1);
20648
+ var import_node_child_process13 = require("node:child_process");
20649
+ var import_node_fs16 = require("node:fs");
20650
+ var import_node_os13 = require("node:os");
20651
+ var import_node_path24 = __toESM(require("node:path"), 1);
20652
20652
 
20653
20653
  // src/install-codex.ts
20654
20654
  var import_promises = __toESM(require("node:fs/promises"), 1);
@@ -21153,12 +21153,12 @@ ${block}`;
21153
21153
  }
21154
21154
 
21155
21155
  // src/director-bridge.ts
21156
- var import_node_fs13 = __toESM(require("node:fs"), 1);
21156
+ var import_node_fs14 = __toESM(require("node:fs"), 1);
21157
21157
  var import_node_http = __toESM(require("node:http"), 1);
21158
- var import_node_os8 = __toESM(require("node:os"), 1);
21159
- var import_node_path17 = __toESM(require("node:path"), 1);
21158
+ var import_node_os9 = __toESM(require("node:os"), 1);
21159
+ var import_node_path18 = __toESM(require("node:path"), 1);
21160
21160
  var import_node_child_process10 = require("node:child_process");
21161
- var import_node_crypto7 = __toESM(require("node:crypto"), 1);
21161
+ var import_node_crypto8 = __toESM(require("node:crypto"), 1);
21162
21162
 
21163
21163
  // src/turn-replay-buffer.ts
21164
21164
  var DEFAULT_MAX_EVENTS = 2e3;
@@ -22713,10 +22713,10 @@ function mergeDefs(...defs) {
22713
22713
  function cloneDef(schema) {
22714
22714
  return mergeDefs(schema._zod.def);
22715
22715
  }
22716
- function getElementAtPath(obj, path18) {
22717
- if (!path18)
22716
+ function getElementAtPath(obj, path19) {
22717
+ if (!path19)
22718
22718
  return obj;
22719
- return path18.reduce((acc, key) => acc?.[key], obj);
22719
+ return path19.reduce((acc, key) => acc?.[key], obj);
22720
22720
  }
22721
22721
  function promiseAllObject(promisesObj) {
22722
22722
  const keys = Object.keys(promisesObj);
@@ -23125,11 +23125,11 @@ function explicitlyAborted(x, startIndex = 0) {
23125
23125
  }
23126
23126
  return false;
23127
23127
  }
23128
- function prefixIssues(path18, issues) {
23128
+ function prefixIssues(path19, issues) {
23129
23129
  return issues.map((iss) => {
23130
23130
  var _a3;
23131
23131
  (_a3 = iss).path ?? (_a3.path = []);
23132
- iss.path.unshift(path18);
23132
+ iss.path.unshift(path19);
23133
23133
  return iss;
23134
23134
  });
23135
23135
  }
@@ -23276,16 +23276,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
23276
23276
  }
23277
23277
  function formatError(error51, mapper = (issue2) => issue2.message) {
23278
23278
  const fieldErrors = { _errors: [] };
23279
- const processError = (error52, path18 = []) => {
23279
+ const processError = (error52, path19 = []) => {
23280
23280
  for (const issue2 of error52.issues) {
23281
23281
  if (issue2.code === "invalid_union" && issue2.errors.length) {
23282
- issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
23282
+ issue2.errors.map((issues) => processError({ issues }, [...path19, ...issue2.path]));
23283
23283
  } else if (issue2.code === "invalid_key") {
23284
- processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
23284
+ processError({ issues: issue2.issues }, [...path19, ...issue2.path]);
23285
23285
  } else if (issue2.code === "invalid_element") {
23286
- processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
23286
+ processError({ issues: issue2.issues }, [...path19, ...issue2.path]);
23287
23287
  } else {
23288
- const fullpath = [...path18, ...issue2.path];
23288
+ const fullpath = [...path19, ...issue2.path];
23289
23289
  if (fullpath.length === 0) {
23290
23290
  fieldErrors._errors.push(mapper(issue2));
23291
23291
  } else {
@@ -23312,17 +23312,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
23312
23312
  }
23313
23313
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
23314
23314
  const result = { errors: [] };
23315
- const processError = (error52, path18 = []) => {
23315
+ const processError = (error52, path19 = []) => {
23316
23316
  var _a3, _b;
23317
23317
  for (const issue2 of error52.issues) {
23318
23318
  if (issue2.code === "invalid_union" && issue2.errors.length) {
23319
- issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
23319
+ issue2.errors.map((issues) => processError({ issues }, [...path19, ...issue2.path]));
23320
23320
  } else if (issue2.code === "invalid_key") {
23321
- processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
23321
+ processError({ issues: issue2.issues }, [...path19, ...issue2.path]);
23322
23322
  } else if (issue2.code === "invalid_element") {
23323
- processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
23323
+ processError({ issues: issue2.issues }, [...path19, ...issue2.path]);
23324
23324
  } else {
23325
- const fullpath = [...path18, ...issue2.path];
23325
+ const fullpath = [...path19, ...issue2.path];
23326
23326
  if (fullpath.length === 0) {
23327
23327
  result.errors.push(mapper(issue2));
23328
23328
  continue;
@@ -23354,8 +23354,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
23354
23354
  }
23355
23355
  function toDotPath(_path) {
23356
23356
  const segs = [];
23357
- const path18 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
23358
- for (const seg of path18) {
23357
+ const path19 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
23358
+ for (const seg of path19) {
23359
23359
  if (typeof seg === "number")
23360
23360
  segs.push(`[${seg}]`);
23361
23361
  else if (typeof seg === "symbol")
@@ -36047,13 +36047,13 @@ function resolveRef(ref, ctx) {
36047
36047
  if (!ref.startsWith("#")) {
36048
36048
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
36049
36049
  }
36050
- const path18 = ref.slice(1).split("/").filter(Boolean);
36051
- if (path18.length === 0) {
36050
+ const path19 = ref.slice(1).split("/").filter(Boolean);
36051
+ if (path19.length === 0) {
36052
36052
  return ctx.rootSchema;
36053
36053
  }
36054
36054
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
36055
- if (path18[0] === defsKey) {
36056
- const key = path18[1];
36055
+ if (path19[0] === defsKey) {
36056
+ const key = path19[1];
36057
36057
  if (!key || !ctx.defs[key]) {
36058
36058
  throw new Error(`Reference not found: ${ref}`);
36059
36059
  }
@@ -36499,12 +36499,15 @@ var openApiOperationIds = {
36499
36499
  deleteTaskDependency: "deleteTaskDependency",
36500
36500
  getExecutionRun: "getExecutionRun",
36501
36501
  getProjectSchedulerPolicy: "getProjectSchedulerPolicy",
36502
+ getProjectDeployWorkflow: "getProjectDeployWorkflow",
36502
36503
  getSchedulerPendingTasks: "getSchedulerPendingTasks",
36503
36504
  wakeDirector: "wakeDirector",
36504
36505
  getGithubInstallationRepositories: "getGithubInstallationRepositories",
36505
36506
  getProject: "getProject",
36506
36507
  getProjectSnapshot: "getProjectSnapshot",
36507
36508
  getTask: "getTask",
36509
+ archiveTask: "archiveTask",
36510
+ unarchiveTask: "unarchiveTask",
36508
36511
  getWikiPage: "getWikiPage",
36509
36512
  handleGithubInstallCallback: "handleGithubInstallCallback",
36510
36513
  listExecutionArtifacts: "listExecutionArtifacts",
@@ -36530,6 +36533,7 @@ var openApiOperationIds = {
36530
36533
  searchKnowledge: "searchKnowledge",
36531
36534
  updateExecutionRun: "updateExecutionRun",
36532
36535
  upsertProjectSchedulerPolicy: "upsertProjectSchedulerPolicy",
36536
+ upsertProjectDeployWorkflow: "upsertProjectDeployWorkflow",
36533
36537
  updatePlan: "updatePlan",
36534
36538
  updateTask: "updateTask",
36535
36539
  updateWikiPage: "updateWikiPage",
@@ -36554,6 +36558,7 @@ var openApiOperationIds = {
36554
36558
  listArtifactFiles: "listArtifactFiles",
36555
36559
  getOperatorSettings: "getOperatorSettings",
36556
36560
  updateOperatorSettings: "updateOperatorSettings",
36561
+ recordOperatorPresence: "recordOperatorPresence",
36557
36562
  getAgentPool: "getAgentPool",
36558
36563
  putAgentPool: "putAgentPool",
36559
36564
  getConsensusConfig: "getConsensusConfig",
@@ -36598,6 +36603,8 @@ var mrrlinOperatorSettingsSchema = external_exports.object({
36598
36603
  // to it (the web active-project selection is otherwise only a browser cookie). Null = not
36599
36604
  // selected yet.
36600
36605
  activeProjectSlug: external_exports.string().min(1).nullable(),
36606
+ // The last time an authenticated BROWSER operator session was observed. Null means never seen.
36607
+ lastPresenceAt: external_exports.string().datetime().nullable(),
36601
36608
  createdAt: external_exports.string().datetime(),
36602
36609
  updatedAt: external_exports.string().datetime()
36603
36610
  });
@@ -36609,6 +36616,7 @@ var mrrlinOperatorSettingsUpdateSchema = external_exports.object({
36609
36616
  message: "OperatorSettingsUpdate requires at least one field"
36610
36617
  });
36611
36618
  var operatorSettingsResponseSchema = external_exports.object({ data: mrrlinOperatorSettingsSchema });
36619
+ var operatorPresenceResponseSchema = external_exports.object({ data: external_exports.object({ lastPresenceAt: external_exports.string().datetime() }) });
36612
36620
  var mrrlinConsensusConfigSchema = external_exports.object({ consensusEnabled: external_exports.boolean() });
36613
36621
  var consensusConfigResponseSchema = external_exports.object({ data: mrrlinConsensusConfigSchema });
36614
36622
  var agentPoolSnapshotSchema = external_exports.object({
@@ -36746,7 +36754,13 @@ var mrrlinTaskDomainSchema = external_exports.enum(["code", "seo", "marketing",
36746
36754
  var mrrlinSpecApprovedSchema = external_exports.enum(["pending", "approved", "skipped", "skipped_legacy"]);
36747
36755
  var mrrlinTaskSourceSchema = external_exports.enum(["fixture-import", "api"]);
36748
36756
  var mrrlinPlanStatusSchema = external_exports.enum(["active", "paused", "done", "archived"]);
36749
- var mrrlinTaskEventTypeSchema = external_exports.enum(["autonomy_set", "director_thread_reset", "note"]);
36757
+ var mrrlinTaskEventTypeSchema = external_exports.enum([
36758
+ "autonomy_set",
36759
+ "director_thread_reset",
36760
+ "note",
36761
+ "archived",
36762
+ "restored"
36763
+ ]);
36750
36764
  var mrrlinTaskEventCreateKindSchema = external_exports.enum(["note"]);
36751
36765
  var githubRepositorySelectionSchema = external_exports.enum(["all", "selected"]);
36752
36766
  var mrrlinTaskIdSchema = external_exports.string().regex(/^GT-\d+$/);
@@ -36807,7 +36821,8 @@ var mrrlinExecutionRunStatusSchema = external_exports.enum([
36807
36821
  "done",
36808
36822
  "failed",
36809
36823
  "handoff_requested",
36810
- "handoff_queued"
36824
+ "handoff_queued",
36825
+ "cancelled"
36811
36826
  ]);
36812
36827
  var mrrlinExecutionArtifactKindSchema = external_exports.enum([
36813
36828
  "plan",
@@ -36859,6 +36874,9 @@ var taxonomyCategorySchema = external_exports.string().min(1).regex(/^[a-z][a-z0
36859
36874
  var taxonomySubcategorySchema = external_exports.string().min(1).regex(/^[a-z][a-z0-9-]*$/);
36860
36875
  var mrrlinTaskAssigneeSchema = external_exports.union([external_exports.string().regex(/^@/), external_exports.string().email()]).nullable();
36861
36876
  var mrrlinTaskSchema = external_exports.object({
36877
+ // Output-optional (not defaulted-required) so existing task fixtures/mocks across the
36878
+ // codebase need no churn; DB rows always resolve it to `string | null` via taskRowToTask.
36879
+ archivedAt: external_exports.string().datetime().nullable().optional(),
36862
36880
  assignee: mrrlinTaskAssigneeSchema,
36863
36881
  autoDeploy: mrrlinAutoDeploySchema,
36864
36882
  // ADR 0020. OUTPUT-optional (not defaulted-required) so hardcoded task fixtures/mocks across the
@@ -37045,7 +37063,11 @@ var mrrlinProjectSnapshotSchema = external_exports.object({
37045
37063
  wikiPages: external_exports.array(mrrlinWikiPageSchema).default([])
37046
37064
  });
37047
37065
  var mrrlinTaskCreateSchema = external_exports.object({
37048
- autoDeploy: mrrlinAutoDeploySchema.default("off"),
37066
+ // Auto-deploy design Part B: input-optional (NOT .default("off")) so createTask can tell
37067
+ // "caller omitted this" apart from "caller explicitly chose off" -- omitted falls through to
37068
+ // the project's default_auto_deploy; the tasks column itself still defaults to 'off' at the
37069
+ // SQL level for any direct-insert path that bypasses createTask entirely.
37070
+ autoDeploy: mrrlinAutoDeploySchema.optional(),
37049
37071
  // Input-optional so existing createTask call sites need no churn; createTask fills 'code' for the
37050
37072
  // INSERT (the pg column is NOT NULL, so a concrete value is required, not undefined→NULL).
37051
37073
  domain: mrrlinTaskDomainSchema.optional(),
@@ -37102,6 +37124,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
37102
37124
  }
37103
37125
  });
37104
37126
  var mrrlinTaskListFiltersSchema = external_exports.object({
37127
+ archived: external_exports.enum(["true", "false", "all"]).optional(),
37105
37128
  assignee: external_exports.string().startsWith("@").optional(),
37106
37129
  autoDeploy: mrrlinAutoDeploySchema.optional(),
37107
37130
  autonomyLevel: mrrlinAutonomyLevelSchema.optional(),
@@ -37639,6 +37662,10 @@ var mrrlinProjectSchedulerPolicySchema = external_exports.object({
37639
37662
  createdAt: external_exports.string().datetime(),
37640
37663
  // Slice 3 Part E: combined per-UTC-day cap on scheduler-enqueued draft/consensus jobs.
37641
37664
  dailyAutonomousJobBudget: external_exports.number().int().nonnegative(),
37665
+ // Auto-deploy design Part B: copied into tasks.autoDeploy at task-creation time when the
37666
+ // caller doesn't specify one. 'prod' is a legal value here (the DB CHECK allows it) but the
37667
+ // Settings UI never offers it as a project default -- only reachable per task.
37668
+ defaultAutoDeploy: mrrlinAutoDeploySchema,
37642
37669
  eligibleAutonomyLevels: external_exports.array(mrrlinAutonomyLevelSchema).min(1),
37643
37670
  // Slice 3 Part E: cap on concurrently active scheduler-created (ER-SCHED-*) runs.
37644
37671
  maxConcurrentAutonomousRuns: external_exports.number().int().nonnegative(),
@@ -37654,6 +37681,7 @@ var mrrlinProjectSchedulerPolicyUpsertSchema = external_exports.object({
37654
37681
  autoSpecApproval: mrrlinAutoSpecApprovalSchema.optional(),
37655
37682
  cadenceSeconds: external_exports.number().int().positive().nullable().optional(),
37656
37683
  dailyAutonomousJobBudget: external_exports.number().int().nonnegative().optional(),
37684
+ defaultAutoDeploy: mrrlinAutoDeploySchema.optional(),
37657
37685
  eligibleAutonomyLevels: external_exports.array(mrrlinAutonomyLevelSchema).min(1).optional(),
37658
37686
  maxConcurrentAutonomousRuns: external_exports.number().int().nonnegative().optional(),
37659
37687
  prodGraceSeconds: external_exports.number().int().nonnegative().optional(),
@@ -37665,6 +37693,38 @@ var mrrlinProjectSchedulerPolicyUpsertSchema = external_exports.object({
37665
37693
  var projectSchedulerPolicyResponseSchema = external_exports.object({
37666
37694
  data: mrrlinProjectSchedulerPolicySchema
37667
37695
  });
37696
+ var mrrlinDeployWorkflowEnvSchema = external_exports.enum(["dev", "prod"]);
37697
+ var mrrlinDeployWorkflowSourceSchema = external_exports.enum(["agent", "operator"]);
37698
+ var mrrlinDeployWorkflowStateSchema = external_exports.enum(["resolved", "ambiguous"]);
37699
+ var mrrlinProjectDeployWorkflowSchema = external_exports.object({
37700
+ projectSlug: mrrlinProjectSlugSchema,
37701
+ env: mrrlinDeployWorkflowEnvSchema,
37702
+ workflowId: external_exports.number().int().positive().nullable(),
37703
+ workflowPath: external_exports.string().nullable(),
37704
+ reason: external_exports.string().nullable(),
37705
+ source: mrrlinDeployWorkflowSourceSchema.nullable(),
37706
+ state: mrrlinDeployWorkflowStateSchema,
37707
+ activeSetFingerprint: external_exports.string().nullable(),
37708
+ reverifyRequested: external_exports.boolean(),
37709
+ resolvedAt: external_exports.string().datetime().nullable(),
37710
+ createdAt: external_exports.string().datetime(),
37711
+ updatedAt: external_exports.string().datetime()
37712
+ });
37713
+ var mrrlinProjectDeployWorkflowUpsertSchema = external_exports.object({
37714
+ workflowId: external_exports.number().int().positive().nullable(),
37715
+ workflowPath: external_exports.string().nullable().optional(),
37716
+ reason: external_exports.string().nullable().optional(),
37717
+ state: mrrlinDeployWorkflowStateSchema.optional(),
37718
+ activeSetFingerprint: external_exports.string().nullable().optional(),
37719
+ reverifyRequested: external_exports.boolean().optional()
37720
+ }).refine((value) => (value.state ?? "resolved") !== "resolved" || value.workflowId !== null, {
37721
+ message: "A resolved deploy-workflow row requires a non-null workflowId."
37722
+ }).refine((value) => (value.state ?? "resolved") !== "ambiguous" || value.workflowId === null, {
37723
+ message: "An ambiguous deploy-workflow row must not carry a workflowId."
37724
+ });
37725
+ var projectDeployWorkflowResponseSchema = external_exports.object({
37726
+ data: mrrlinProjectDeployWorkflowSchema
37727
+ });
37668
37728
  var mrrlinSchedulerPendingReasonSchema = external_exports.enum([
37669
37729
  "follow_up_due",
37670
37730
  "verification_due",
@@ -37785,7 +37845,11 @@ var schedulerPendingTasksResponseSchema = external_exports.object({
37785
37845
  // disclosure that some exist, so a misconfigured `github.operator` (e.g. it doesn't match the
37786
37846
  // person actually running the project) is visible as a large number instead of the autopilot
37787
37847
  // silently doing nothing.
37788
- excludedByOwnershipCount: external_exports.number().int().min(0)
37848
+ excludedByOwnershipCount: external_exports.number().int().min(0),
37849
+ // Additive: true when the operator-web-presence gate is the reason nothing new is starting
37850
+ // (autonomyPaused takes precedence when both apply). Computed by the same shared helper the
37851
+ // tick uses, so this page can never claim a task is starting when the tick would decline it.
37852
+ presenceGated: external_exports.boolean()
37789
37853
  })
37790
37854
  });
37791
37855
  var wakeDirectorRequestSchema = external_exports.object({
@@ -38055,18 +38119,18 @@ function createMrrlinClient(config2) {
38055
38119
  const customFetch = config2.fetch ?? globalThis.fetch;
38056
38120
  const baseUrl = config2.baseUrl.replace(/\/$/, "");
38057
38121
  const token = config2.token;
38058
- async function request(path18, init) {
38122
+ async function request(path19, init) {
38059
38123
  const method = init?.method ?? "GET";
38060
38124
  const headers = new Headers(init?.headers ?? {});
38061
38125
  if (token && !headers.has("authorization")) {
38062
38126
  headers.set("authorization", `Bearer ${token}`);
38063
38127
  }
38064
- const response = await customFetch(`${baseUrl}${path18}`, { ...init, headers });
38128
+ const response = await customFetch(`${baseUrl}${path19}`, { ...init, headers });
38065
38129
  if (!response.ok) {
38066
38130
  const body = await response.text();
38067
38131
  let code = `HTTP_${response.status}`;
38068
38132
  let violations = null;
38069
- let message = `Mrrlin API ${method} ${path18} failed: ${response.status}`;
38133
+ let message = `Mrrlin API ${method} ${path19} failed: ${response.status}`;
38070
38134
  try {
38071
38135
  const parsed = JSON.parse(body);
38072
38136
  const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
@@ -38086,7 +38150,7 @@ function createMrrlinClient(config2) {
38086
38150
  throw new MrrlinApiError({
38087
38151
  code,
38088
38152
  method,
38089
- path: path18,
38153
+ path: path19,
38090
38154
  responseBody: body,
38091
38155
  status: response.status,
38092
38156
  violations,
@@ -38341,7 +38405,8 @@ function createMrrlinClient(config2) {
38341
38405
  return taskEventListResponseSchema.parse(body).data;
38342
38406
  },
38343
38407
  async listTasks(projectSlug, filters = {}) {
38344
- const path18 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
38408
+ const path19 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
38409
+ archived: filters.archived,
38345
38410
  assignee: filters.assignee,
38346
38411
  autonomyLevel: filters.autonomyLevel,
38347
38412
  blockedBy: filters.blockedBy,
@@ -38353,7 +38418,7 @@ function createMrrlinClient(config2) {
38353
38418
  subcategory: filters.subcategory,
38354
38419
  type: filters.type
38355
38420
  });
38356
- const body = await request(path18);
38421
+ const body = await request(path19);
38357
38422
  return taskListResponseSchema.parse(body).data;
38358
38423
  },
38359
38424
  async listTaxonomy(projectSlug) {
@@ -38361,22 +38426,22 @@ function createMrrlinClient(config2) {
38361
38426
  return taxonomyListResponseSchema.parse(body).data;
38362
38427
  },
38363
38428
  async listWikiPages(projectSlug, filters = {}) {
38364
- const path18 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
38429
+ const path19 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
38365
38430
  folder: filters.folder,
38366
38431
  q: filters.q,
38367
38432
  taskId: filters.taskId
38368
38433
  });
38369
- const body = await request(path18);
38434
+ const body = await request(path19);
38370
38435
  return wikiPageListResponseSchema.parse(body).data;
38371
38436
  },
38372
38437
  async searchWikiPages(projectSlug, query) {
38373
- const path18 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
38438
+ const path19 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
38374
38439
  folder: query.folder,
38375
38440
  limit: query.limit === void 0 ? void 0 : String(query.limit),
38376
38441
  pathPrefix: query.pathPrefix,
38377
38442
  q: query.q
38378
38443
  });
38379
- const body = await request(path18);
38444
+ const body = await request(path19);
38380
38445
  return wikiPageSearchResponseSchema.parse(body).data;
38381
38446
  },
38382
38447
  async updatePlan(projectSlug, planId, patch) {
@@ -38399,6 +38464,18 @@ function createMrrlinClient(config2) {
38399
38464
  const body = await request(`${projectPath(projectSlug)}/tasks/${encodeURIComponent(taskId)}/director-thread/reset`, { method: "POST" });
38400
38465
  return taskResponseSchema.parse(body).data;
38401
38466
  },
38467
+ async archiveTask(projectSlug, taskId) {
38468
+ const body = await request(`${projectPath(projectSlug)}/tasks/${encodeURIComponent(taskId)}/archive`, {
38469
+ method: "POST"
38470
+ });
38471
+ return taskResponseSchema.parse(body).data;
38472
+ },
38473
+ async unarchiveTask(projectSlug, taskId) {
38474
+ const body = await request(`${projectPath(projectSlug)}/tasks/${encodeURIComponent(taskId)}/unarchive`, {
38475
+ method: "POST"
38476
+ });
38477
+ return taskResponseSchema.parse(body).data;
38478
+ },
38402
38479
  async updateWikiPage(projectSlug, pageId, patch) {
38403
38480
  const body = await request(`${projectPath(projectSlug)}/wiki/${encodeURIComponent(pageId)}`, {
38404
38481
  body: JSON.stringify(patch),
@@ -38721,6 +38798,25 @@ function createMrrlinClient(config2) {
38721
38798
  });
38722
38799
  return projectSchedulerPolicyResponseSchema.parse(body).data;
38723
38800
  },
38801
+ async getProjectDeployWorkflow(projectSlug, env) {
38802
+ try {
38803
+ const body = await request(`${projectPath(projectSlug)}/deploy-workflows/${env}`);
38804
+ return projectDeployWorkflowResponseSchema.parse(body).data;
38805
+ } catch (error51) {
38806
+ if (error51 instanceof MrrlinApiError && error51.status === 404 && error51.code === "DEPLOY_WORKFLOW_UNSET") {
38807
+ return null;
38808
+ }
38809
+ throw error51;
38810
+ }
38811
+ },
38812
+ async upsertProjectDeployWorkflow(projectSlug, env, input) {
38813
+ const body = await request(`${projectPath(projectSlug)}/deploy-workflows/${env}`, {
38814
+ body: JSON.stringify(input),
38815
+ headers: { "content-type": "application/json" },
38816
+ method: "PUT"
38817
+ });
38818
+ return projectDeployWorkflowResponseSchema.parse(body).data;
38819
+ },
38724
38820
  async getSchedulerPendingTasks(projectSlug) {
38725
38821
  const body = await request(`${projectPath(projectSlug)}/scheduler/pending`);
38726
38822
  return schedulerPendingTasksResponseSchema.parse(body).data;
@@ -38745,6 +38841,10 @@ function createMrrlinClient(config2) {
38745
38841
  });
38746
38842
  return operatorSettingsResponseSchema.parse(body).data;
38747
38843
  },
38844
+ async recordOperatorPresence() {
38845
+ const body = await request(`/operator/presence`, { method: "POST" });
38846
+ return operatorPresenceResponseSchema.parse(body).data;
38847
+ },
38748
38848
  async getOperatorAgentPool() {
38749
38849
  const body = await request(`/operator/agent-pool`);
38750
38850
  return agentPoolResponseSchema.parse(body).data;
@@ -39259,7 +39359,7 @@ function startCodexProbe(deps = {}) {
39259
39359
  }
39260
39360
 
39261
39361
  // src/_generated/version.ts
39262
- var PKG_VERSION = "0.3.52";
39362
+ var PKG_VERSION = "0.3.55";
39263
39363
 
39264
39364
  // src/api-base-url-migrate.ts
39265
39365
  var import_node_fs2 = __toESM(require("node:fs"), 1);
@@ -39789,9 +39889,6 @@ function startSchedulerTickLoop(deps) {
39789
39889
  };
39790
39890
  }
39791
39891
 
39792
- // src/agent-pool-loop.ts
39793
- var import_node_child_process5 = require("node:child_process");
39794
-
39795
39892
  // src/agent-pool-snapshot.ts
39796
39893
  function normalizeLastUsedAt(value) {
39797
39894
  if (value === void 0 || value === null) return null;
@@ -39904,6 +40001,9 @@ async function collectAgentPoolSnapshot(deps) {
39904
40001
  );
39905
40002
  }
39906
40003
 
40004
+ // src/external-agents-spawn.ts
40005
+ var import_node_child_process5 = require("node:child_process");
40006
+
39907
40007
  // src/external-agents-bin.ts
39908
40008
  function resolveExternalAgentsCliInvocation(override) {
39909
40009
  if (override && override.trim()) return { command: override, prefixArgs: [] };
@@ -39917,50 +40017,113 @@ function resolveExternalAgentsCliInvocation(override) {
39917
40017
  }
39918
40018
  }
39919
40019
 
39920
- // src/agent-pool-loop.ts
39921
- var DEFAULT_INTERVAL_MS2 = 6e4;
39922
- function agentPoolLoopDisabled(env = process.env) {
39923
- return env["MRRLIN_BRIDGE_AGENT_POOL_DISABLE"] === "1";
39924
- }
39925
- function defaultRunCli(args) {
39926
- const cli = process.env["EXTERNAL_AGENTS_CLI"];
39927
- const { command, prefixArgs } = cli ? { command: "node", prefixArgs: [cli] } : resolveExternalAgentsCliInvocation();
40020
+ // src/external-agents-spawn.ts
40021
+ function runExternalAgentsCli(args, opts) {
40022
+ let command;
40023
+ let prefixArgs;
40024
+ let source;
40025
+ let triedPath;
40026
+ if (opts.envCliPath && opts.envCliPath.trim()) {
40027
+ command = "node";
40028
+ prefixArgs = [opts.envCliPath];
40029
+ source = "env";
40030
+ triedPath = opts.envCliPath;
40031
+ } else {
40032
+ ({ command, prefixArgs } = resolveExternalAgentsCliInvocation());
40033
+ source = command === "node" && prefixArgs.length === 1 ? "bundled" : "path";
40034
+ triedPath = source === "bundled" ? prefixArgs[0] ?? "" : "external-agents (PATH)";
40035
+ }
40036
+ const useStdin = opts.stdinValue !== void 0;
40037
+ const stdioConfig = useStdin ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
39928
40038
  return new Promise((resolve) => {
39929
40039
  let stdout = "";
40040
+ let stderr = "";
39930
40041
  let settled = false;
40042
+ let timedOut = false;
39931
40043
  const done = (code) => {
39932
40044
  if (!settled) {
39933
40045
  settled = true;
39934
- resolve({ stdout, code });
40046
+ resolve({ stdout, stderr, code, timedOut, source, triedPath });
39935
40047
  }
39936
40048
  };
40049
+ let spawned;
39937
40050
  try {
39938
- const child = (0, import_node_child_process5.spawn)(command, [...prefixArgs, ...args], { stdio: ["ignore", "pipe", "ignore"] });
39939
- const timer = setTimeout(() => {
40051
+ spawned = (0, import_node_child_process5.spawn)(command, [...prefixArgs, ...args], { stdio: stdioConfig });
40052
+ } catch {
40053
+ done(1);
40054
+ return;
40055
+ }
40056
+ const child = spawned;
40057
+ let sigkillTimer = null;
40058
+ let budgetTimer = null;
40059
+ if (useStdin && child.stdin) {
40060
+ child.stdin.on("error", () => {
40061
+ });
40062
+ child.stdin.write(opts.stdinValue);
40063
+ child.stdin.end();
40064
+ }
40065
+ child.stdout?.on("data", (d) => {
40066
+ stdout += d.toString();
40067
+ if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
40068
+ });
40069
+ child.stderr?.on("data", (d) => {
40070
+ stderr += d.toString();
40071
+ if (stderr.length > 2e5) stderr = stderr.slice(-2e5);
40072
+ });
40073
+ budgetTimer = setTimeout(() => {
40074
+ budgetTimer = null;
40075
+ timedOut = true;
40076
+ try {
40077
+ child.kill("SIGTERM");
40078
+ } catch {
40079
+ }
40080
+ sigkillTimer = setTimeout(() => {
40081
+ sigkillTimer = null;
39940
40082
  try {
39941
40083
  child.kill("SIGKILL");
39942
40084
  } catch {
39943
40085
  }
39944
- done(1);
39945
- }, 5e3);
39946
- timer.unref?.();
39947
- child.stdout.on("data", (d) => {
39948
- stdout += d.toString();
39949
- if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
39950
- });
39951
- child.on("error", () => {
39952
- clearTimeout(timer);
39953
- done(1);
39954
- });
39955
- child.on("close", (code) => {
39956
- clearTimeout(timer);
39957
- done(code ?? 1);
39958
- });
39959
- } catch {
40086
+ }, 2e3);
40087
+ sigkillTimer.unref?.();
39960
40088
  done(1);
39961
- }
40089
+ }, opts.budgetMs);
40090
+ budgetTimer.unref?.();
40091
+ child.on("error", () => {
40092
+ if (budgetTimer) {
40093
+ clearTimeout(budgetTimer);
40094
+ budgetTimer = null;
40095
+ }
40096
+ if (sigkillTimer) {
40097
+ clearTimeout(sigkillTimer);
40098
+ sigkillTimer = null;
40099
+ }
40100
+ done(1);
40101
+ });
40102
+ child.on("close", (code) => {
40103
+ if (budgetTimer) {
40104
+ clearTimeout(budgetTimer);
40105
+ budgetTimer = null;
40106
+ }
40107
+ if (sigkillTimer) {
40108
+ clearTimeout(sigkillTimer);
40109
+ sigkillTimer = null;
40110
+ }
40111
+ done(code ?? 1);
40112
+ });
39962
40113
  });
39963
40114
  }
40115
+
40116
+ // src/agent-pool-loop.ts
40117
+ var DEFAULT_INTERVAL_MS2 = 6e4;
40118
+ function agentPoolLoopDisabled(env = process.env) {
40119
+ return env["MRRLIN_BRIDGE_AGENT_POOL_DISABLE"] === "1";
40120
+ }
40121
+ function defaultRunCli(args) {
40122
+ return runExternalAgentsCli(args, {
40123
+ budgetMs: 5e3,
40124
+ envCliPath: process.env["EXTERNAL_AGENTS_CLI"]
40125
+ }).then(({ stdout, code }) => ({ stdout, code }));
40126
+ }
39964
40127
  async function runAgentPoolCycle(deps) {
39965
40128
  try {
39966
40129
  const snapshot = await collectAgentPoolSnapshot({
@@ -39998,7 +40161,7 @@ function startAgentPoolLoop(deps) {
39998
40161
 
39999
40162
  // src/execution-consumer.ts
40000
40163
  var import_node_child_process9 = require("node:child_process");
40001
- var import_node_crypto4 = __toESM(require("node:crypto"), 1);
40164
+ var import_node_crypto5 = __toESM(require("node:crypto"), 1);
40002
40165
  var import_node_path10 = __toESM(require("node:path"), 1);
40003
40166
  var import_node_util = require("node:util");
40004
40167
 
@@ -40873,8 +41036,117 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
40873
41036
  };
40874
41037
  }
40875
41038
 
40876
- // src/async-tools/draft-spec.ts
41039
+ // src/consensus/deliverable-gate-outcome.ts
41040
+ function mapDeliverableGateResult(result) {
41041
+ switch (result.outcome) {
41042
+ case "DELIVERABLE_CHANGED_DURING_REVIEW":
41043
+ return {
41044
+ action: "retry",
41045
+ reason: "the deliverable's wiki page changed underneath an in-progress review (DELIVERABLE_CHANGED_DURING_REVIEW)"
41046
+ };
41047
+ case "CONSENSUS_UNAVAILABLE":
41048
+ return {
41049
+ action: "retry",
41050
+ reason: "reviewers were unavailable (provider/quota) during the deliverable review (CONSENSUS_UNAVAILABLE)"
41051
+ };
41052
+ case "CONSENSUS_BLOCKED": {
41053
+ const clarifications = result.clarifications ?? [];
41054
+ if (clarifications.length > 0) {
41055
+ return {
41056
+ action: "questions",
41057
+ clarifications,
41058
+ reason: "reviewers did not converge; unresolved scope/ambiguity/correctness issues were filed as operator questions (CONSENSUS_BLOCKED)"
41059
+ };
41060
+ }
41061
+ return {
41062
+ action: "handoff",
41063
+ reason: "reviewers did not converge and raised no clarification-eligible issues (CONSENSUS_BLOCKED)"
41064
+ };
41065
+ }
41066
+ case "MISSING_ACCEPTANCE_CRITERIA":
41067
+ return {
41068
+ action: "handoff",
41069
+ reason: "the linked spec has no parseable `## Acceptance criteria` checklist (MISSING_ACCEPTANCE_CRITERIA)"
41070
+ };
41071
+ // CONVERGED/SKIPPED (success paths) should never reach this function — both consumers
41072
+ // special-case them first. Degrade to a safe handoff rather than throwing so a future
41073
+ // caller mistake is visible to the operator instead of crashing the run.
41074
+ default:
41075
+ return {
41076
+ action: "handoff",
41077
+ reason: `unexpected outcome routed to mapDeliverableGateResult: ${result.outcome}`
41078
+ };
41079
+ }
41080
+ }
41081
+
41082
+ // src/consensus/deliverable-gate-questions.ts
40877
41083
  var import_node_crypto3 = require("node:crypto");
41084
+ function buildDeliverableQuestionOptions(category) {
41085
+ if (category === "correctness") {
41086
+ return [
41087
+ {
41088
+ label: "Deliverable is correct",
41089
+ description: "The flagged claim is accurate as written; no change needed.",
41090
+ answer: "Confirm the deliverable's content is correct as written; the reviewer's concern does not require a change."
41091
+ },
41092
+ {
41093
+ label: "Deliverable needs correction",
41094
+ description: "The flagged claim is wrong or unsupported; the deliverable needs revision.",
41095
+ answer: "The deliverable is incorrect here and must be revised to fix the flagged claim before it can be accepted."
41096
+ }
41097
+ ];
41098
+ }
41099
+ if (category === "scope") {
41100
+ return [
41101
+ {
41102
+ label: "Coverage is sufficient",
41103
+ description: "The deliverable's current coverage of the acceptance criteria is sufficient as written.",
41104
+ answer: "Accept the deliverable's current scope/coverage as sufficient against the acceptance criteria."
41105
+ },
41106
+ {
41107
+ label: "Coverage is missing",
41108
+ description: "The deliverable is missing required coverage and needs revision to address it.",
41109
+ answer: "The deliverable is missing required coverage and must be revised to address the flagged gap."
41110
+ }
41111
+ ];
41112
+ }
41113
+ return [
41114
+ {
41115
+ label: "Interpretation is fine",
41116
+ description: "The deliverable's current interpretation of the ambiguous point is acceptable as written.",
41117
+ answer: "Accept the deliverable's current interpretation of the ambiguous point as written."
41118
+ },
41119
+ {
41120
+ label: "Needs clarification",
41121
+ description: "The ambiguous point needs to be resolved and the deliverable revised accordingly.",
41122
+ answer: "The deliverable must be revised to resolve the flagged ambiguity explicitly."
41123
+ }
41124
+ ];
41125
+ }
41126
+ async function fileDeliverableGateQuestions(client, projectSlug, taskId, clarifications) {
41127
+ let filed = 0;
41128
+ for (const clarification of clarifications) {
41129
+ const id = `II-${taskId}-deliverable-gate-${(0, import_node_crypto3.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
41130
+ try {
41131
+ await client.createInboxItem(projectSlug, {
41132
+ id,
41133
+ kind: "question",
41134
+ taskId,
41135
+ body: clarification.question,
41136
+ origin: "gate",
41137
+ questionOptions: buildDeliverableQuestionOptions(clarification.category)
41138
+ });
41139
+ filed += 1;
41140
+ } catch (error51) {
41141
+ const message = error51 instanceof Error ? error51.message : String(error51);
41142
+ if (/inbox_items_pkey/.test(message)) filed += 1;
41143
+ }
41144
+ }
41145
+ return filed;
41146
+ }
41147
+
41148
+ // src/async-tools/draft-spec.ts
41149
+ var import_node_crypto4 = require("node:crypto");
40878
41150
  var DRAFT_SPEC_TOOL_NAME = "draft_task_spec";
40879
41151
  var SPECS_FOLDER = "Specs";
40880
41152
  var DRAFT_SPEC_TLDR_MAX_CHARS = 300;
@@ -41151,7 +41423,7 @@ function onComplete(outcome, input) {
41151
41423
  };
41152
41424
  }
41153
41425
  const summary = outcome.error;
41154
- const hash3 = (0, import_node_crypto3.createHash)("sha256").update(summary).digest("hex").slice(0, 10);
41426
+ const hash3 = (0, import_node_crypto4.createHash)("sha256").update(summary).digest("hex").slice(0, 10);
41155
41427
  return {
41156
41428
  kind: "info",
41157
41429
  id: `II-sched-draft-failed-${input.taskId}-${hash3}`,
@@ -41276,6 +41548,17 @@ function gateEnvSequence(autoDeploy) {
41276
41548
  if (autoDeploy === "prod") return ["dev", "prod"];
41277
41549
  return [];
41278
41550
  }
41551
+ function effectiveGateEnvSequence(autoDeploy, artifacts) {
41552
+ const policy = gateEnvSequence(autoDeploy);
41553
+ const envs = ["dev", "prod"];
41554
+ const union2 = new Set(policy);
41555
+ for (const env of envs) {
41556
+ if (latestByEnv(artifacts, "deploy_attempt", env, { realAttemptsOnly: true })) {
41557
+ union2.add(env);
41558
+ }
41559
+ }
41560
+ return envs.filter((env) => union2.has(env));
41561
+ }
41279
41562
  function deployApprovalItemId(runId, env) {
41280
41563
  return `II-deploy-approve-${env}-${runId}`;
41281
41564
  }
@@ -41343,7 +41626,7 @@ async function resolveProdGrace(deps, projectSlug, run3, task, artifacts) {
41343
41626
  const graceUntil = new Date(nowMs + seconds * 1e3);
41344
41627
  const cancelId = graceCancelItemId(run3.id);
41345
41628
  await deps.client.appendExecutionArtifact(projectSlug, run3.id, {
41346
- id: `deploy-grace-${run3.id}`,
41629
+ id: `EA-deploy-grace-${run3.id}`,
41347
41630
  kind: "deploy_attempt",
41348
41631
  payload: {
41349
41632
  env: "prod",
@@ -41403,7 +41686,7 @@ async function tryProdAutoRevert(deps, projectSlug, run3, task) {
41403
41686
  const lastGood = await findLastGoodProdAttempt(deps.client, projectSlug, task, run3.id);
41404
41687
  if (!lastGood) return null;
41405
41688
  await deps.client.appendExecutionArtifact(projectSlug, run3.id, {
41406
- id: `deploy-revert-${run3.id}`,
41689
+ id: `EA-deploy-revert-${run3.id}`,
41407
41690
  kind: "deploy_attempt",
41408
41691
  payload: {
41409
41692
  env: "prod",
@@ -41424,10 +41707,39 @@ async function tryProdAutoRevert(deps, projectSlug, run3, task) {
41424
41707
  return null;
41425
41708
  }
41426
41709
  }
41710
+ function computeActiveSetFingerprint(workflows) {
41711
+ return workflows.map((workflow) => `${workflow.id}:${workflow.path}`).sort().join(",");
41712
+ }
41713
+ async function resolveWorkflowId(deps, projectSlug, run3, env) {
41714
+ const pinned = env === "dev" ? run3.devWorkflowId : run3.prodWorkflowId;
41715
+ if (pinned) return { workflowId: pinned, source: null, resolvedFromStore: false };
41716
+ const row = await deps.client.getProjectDeployWorkflow(projectSlug, env);
41717
+ if (!row || row.state !== "resolved" || row.workflowId === null) {
41718
+ return { workflowId: null, source: null, resolvedFromStore: false };
41719
+ }
41720
+ if (row.source !== "operator") {
41721
+ const liveWorkflows = await deps.client.listGithubWorkflows(projectSlug);
41722
+ const activeWorkflows = liveWorkflows.filter((workflow) => workflow.state === "active");
41723
+ const isLive = activeWorkflows.some((workflow) => String(workflow.id) === String(row.workflowId));
41724
+ if (!isLive) return { workflowId: null, source: null, resolvedFromStore: false };
41725
+ const liveFingerprint = computeActiveSetFingerprint(activeWorkflows);
41726
+ if (!row.reverifyRequested && row.activeSetFingerprint !== null && liveFingerprint !== row.activeSetFingerprint) {
41727
+ await deps.client.upsertProjectDeployWorkflow(projectSlug, env, {
41728
+ workflowId: row.workflowId,
41729
+ workflowPath: row.workflowPath,
41730
+ reason: row.reason,
41731
+ state: row.state,
41732
+ activeSetFingerprint: row.activeSetFingerprint,
41733
+ reverifyRequested: true
41734
+ });
41735
+ }
41736
+ }
41737
+ return { workflowId: row.workflowId, source: row.source, resolvedFromStore: true };
41738
+ }
41427
41739
  async function runDeployGateTick(deps, projectSlug, run3, task) {
41428
- const sequence = gateEnvSequence(task.autoDeploy);
41429
- if (sequence.length === 0) return { kind: "noop", reason: "auto_deploy=off" };
41430
41740
  const artifacts = await deps.client.listExecutionArtifacts(projectSlug, run3.id);
41741
+ const sequence = effectiveGateEnvSequence(task.autoDeploy, artifacts);
41742
+ if (sequence.length === 0) return { kind: "noop", reason: "auto_deploy=off" };
41431
41743
  let activeEnv = null;
41432
41744
  for (const env2 of sequence) {
41433
41745
  const verification = latestByEnv(artifacts, "verification", env2);
@@ -41444,7 +41756,8 @@ async function runDeployGateTick(deps, projectSlug, run3, task) {
41444
41756
  return { kind: "done" };
41445
41757
  }
41446
41758
  const env = activeEnv;
41447
- const workflowId = env === "dev" ? run3.devWorkflowId : run3.prodWorkflowId;
41759
+ const resolution = await resolveWorkflowId(deps, projectSlug, run3, env);
41760
+ const workflowId = resolution.workflowId;
41448
41761
  const attempt = latestByEnv(artifacts, "deploy_attempt", env, { realAttemptsOnly: true });
41449
41762
  if (!attempt) {
41450
41763
  if (await autonomyPaused(deps.client)) {
@@ -41480,7 +41793,7 @@ async function runDeployGateTick(deps, projectSlug, run3, task) {
41480
41793
  }
41481
41794
  const dispatchedAt = deps.now().toISOString();
41482
41795
  await deps.client.appendExecutionArtifact(projectSlug, run3.id, {
41483
- id: `deploy-${env}-${attemptIndex(artifacts, env) + 1}`,
41796
+ id: `EA-deploy-${env}-${attemptIndex(artifacts, env) + 1}`,
41484
41797
  kind: "deploy_attempt",
41485
41798
  payload: { env, workflowId, branch: run3.branch ?? "", dispatchedAt }
41486
41799
  });
@@ -41490,9 +41803,23 @@ async function runDeployGateTick(deps, projectSlug, run3, task) {
41490
41803
  try {
41491
41804
  await deps.client.dispatchTaskDeploy(projectSlug, task.id, { env, ref: run3.branch, workflowId: String(workflowId) });
41492
41805
  } catch (error51) {
41806
+ if (resolution.source === "operator") {
41807
+ await deps.handoff(
41808
+ projectSlug,
41809
+ task,
41810
+ run3,
41811
+ `deploy_workflow_operator_choice_stale:${env}:${String(error51).slice(0, 120)}`
41812
+ );
41813
+ return { kind: "handoff", reason: `deploy_workflow_operator_choice_stale:${env}` };
41814
+ }
41493
41815
  await deps.handoff(projectSlug, task, run3, `workflow_dispatch_failed:${env}:${String(error51).slice(0, 120)}`);
41494
41816
  return { kind: "handoff", reason: `workflow_dispatch_failed:${env}` };
41495
41817
  }
41818
+ if (resolution.resolvedFromStore) {
41819
+ await deps.client.updateExecutionRun(projectSlug, run3.id, {
41820
+ [env === "dev" ? "devWorkflowId" : "prodWorkflowId"]: workflowId
41821
+ });
41822
+ }
41496
41823
  return { kind: "dispatched", env };
41497
41824
  }
41498
41825
  const runStatus = await deps.client.getGithubWorkflowRunLatest(projectSlug, {
@@ -41543,7 +41870,7 @@ async function runDeployGateTick(deps, projectSlug, run3, task) {
41543
41870
  run: run3
41544
41871
  });
41545
41872
  await deps.client.appendExecutionArtifact(projectSlug, run3.id, {
41546
- id: `verification-${env}-${attemptIndex(artifacts, env, "verification") + 1}`,
41873
+ id: `EA-verification-${env}-${attemptIndex(artifacts, env, "verification") + 1}`,
41547
41874
  kind: "verification",
41548
41875
  payload: { env, verdict: verdict.verdict, summary: verdict.summary, turnRef: verdict.turnRef }
41549
41876
  });
@@ -41726,6 +42053,20 @@ async function pushRunBranch(opts, execGit = defaultGitExec) {
41726
42053
  const run3 = () => doPushRunBranch(opts, execGit);
41727
42054
  return opts.alreadyLocked ? run3() : withCheckoutLock(opts.locksDir, opts.slug, run3);
41728
42055
  }
42056
+ async function hasCommitsToPush(opts, execGit = defaultGitExec) {
42057
+ const baseEnv = {
42058
+ PATH: process.env.PATH ?? "",
42059
+ GIT_TERMINAL_PROMPT: "0",
42060
+ GIT_CONFIG_GLOBAL: "/dev/null",
42061
+ GIT_CONFIG_SYSTEM: "/dev/null",
42062
+ GIT_CONFIG_NOSYSTEM: "1"
42063
+ };
42064
+ const count2 = execGit(
42065
+ ["-C", opts.worktreePath, "rev-list", "--count", `origin/${opts.defaultBranch}..HEAD`],
42066
+ baseEnv
42067
+ ).trim();
42068
+ return Number(count2) > 0;
42069
+ }
41729
42070
  async function doPushRunBranch(opts, execGit) {
41730
42071
  const branch = worktreeBranch(opts.runId);
41731
42072
  const baseEnv = {
@@ -41856,6 +42197,13 @@ var EXECUTION_TURN_BUDGET_PREFIX = "Execution turn exceeded the run wall-clock b
41856
42197
  var EXECUTION_TURN_TIMEOUT_RETRY_CODE = "execution_turn_timeout_retry";
41857
42198
  var EXECUTION_TURN_TIMEOUT_RETRY_SUMMARY = "Execution turn timed out; requeued for one automatic retry.";
41858
42199
  var EXECUTION_TURN_TIMEOUT_RETRY_CURSOR = "execution_turn_timeout_retry:1";
42200
+ var DELIVERABLE_GATE_RETRY_CODE = "deliverable_gate_retry";
42201
+ var DELIVERABLE_GATE_RETRY_CURSOR_PREFIX = "deliverable_gate_retry:";
42202
+ var DELIVERABLE_GATE_RETRY_MAX_ATTEMPTS = 3;
42203
+ var DELIVERABLE_GATE_RETRYABLE_REASON_PREFIXES = [
42204
+ "deliverable_gate_deliverable_changed_during_review",
42205
+ "deliverable_gate_consensus_unavailable"
42206
+ ];
41859
42207
  var AWAITING_MERGE_STATUS_RETRY_DELAYS_MS = [50, 100];
41860
42208
  function readPositiveIntEnv(name, fallback) {
41861
42209
  const raw = (process.env[name] ?? "").trim();
@@ -41887,6 +42235,17 @@ function executionTurnBudgetMessage(budgetMs) {
41887
42235
  function isExecutionTurnTimeoutReason(reason) {
41888
42236
  return reason.startsWith(EXECUTION_TURN_TIMEOUT_PREFIX) || reason.startsWith(EXECUTION_TURN_STALL_PREFIX);
41889
42237
  }
42238
+ function isDeliverableGateRetryableReason(reason) {
42239
+ return DELIVERABLE_GATE_RETRYABLE_REASON_PREFIXES.some((prefix) => reason.startsWith(prefix));
42240
+ }
42241
+ function deliverableGateRetryAttempt(checkpointCursor) {
42242
+ if (!checkpointCursor || !checkpointCursor.startsWith(DELIVERABLE_GATE_RETRY_CURSOR_PREFIX)) return 0;
42243
+ const parsed = Number.parseInt(checkpointCursor.slice(DELIVERABLE_GATE_RETRY_CURSOR_PREFIX.length), 10);
42244
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
42245
+ }
42246
+ function deliverableGateRetryCursor(attempt) {
42247
+ return `${DELIVERABLE_GATE_RETRY_CURSOR_PREFIX}${attempt}`;
42248
+ }
41890
42249
  function contextMaxArtifacts() {
41891
42250
  return readPositiveIntEnv("MRRLIN_DIRECTOR_BRIDGE_CONTEXT_MAX_ARTIFACTS", DEFAULT_CONTEXT_MAX_ARTIFACTS);
41892
42251
  }
@@ -41915,8 +42274,10 @@ function buildCompletionTurnPrompt(taskId, currentStatus) {
41915
42274
  " to the open run if you haven't already.",
41916
42275
  "",
41917
42276
  "If the work is NOT complete \u2014 be honest, do not close incomplete work:",
41918
- "1. Call update_task with the appropriate status (needs_human, awaiting_verification, etc.)",
41919
- " and explain what remains in the notes.",
42277
+ "1. Call update_task with the status that matches why it is not complete, and explain what remains",
42278
+ " in the notes:",
42279
+ " - if the code work itself is done and only a PR or merge remains, use status=awaiting_verification;",
42280
+ " - if you are blocked and need an operator decision before the work can continue, use status=needs_human.",
41920
42281
  "2. Append a handoff_judgement artifact explaining what the operator needs to do.",
41921
42282
  "",
41922
42283
  "You must pick one of these paths \u2014 do not leave the task in_progress."
@@ -41940,6 +42301,9 @@ var BASE_INSTRUCTIONS_PREFIX = [
41940
42301
  "- For a CODE task the run opens a draft PR for you after your turn; opening that PR is NOT",
41941
42302
  " completion. Do NOT set closed_done for code work \u2014 leave the task open; the run parks at",
41942
42303
  " `pull_request` (waiting for merge) and the operator merges. Closure happens after merge.",
42304
+ "- Pick the right open status when you stop a CODE task: if the code work itself is done and only a",
42305
+ " PR or merge remains, leave the task at `awaiting_verification`; if you are blocked and a human",
42306
+ " must decide before the work can continue, leave it at `needs_human`.",
41943
42307
  "",
41944
42308
  "File artifacts:",
41945
42309
  "- When your output is a file (markdown report, HTML, screenshot), upload it with",
@@ -42014,7 +42378,35 @@ var EXECUTOR_BASE_INSTRUCTIONS = [
42014
42378
  "You MUST verify every delegated result against the actual files and tests before it lands \u2014",
42015
42379
  "pool models are lower-reliability and a wrong delegated edit is YOUR responsibility; never",
42016
42380
  "commit unverified delegated output. If dispatch fails or the pool is unavailable, do the",
42017
- "work yourself \u2014 never block the run on the pool."
42381
+ "work yourself \u2014 never block the run on the pool.",
42382
+ "",
42383
+ // Auto-deploy design Part C (2026-08-04), C4: the workflow-resolution procedure. Only relevant
42384
+ // when the deploy gate has parked this run on a missing/stale workflow id for one environment —
42385
+ // most turns will never need this. This choice becomes durable project state (record_deploy_workflow
42386
+ // writes project_deploy_workflow), not a per-run decision, so resolve it AT MOST ONCE per
42387
+ // project+environment, only when actually needed (lazy, per env — do not speculatively resolve
42388
+ // prod when only dev was asked for).
42389
+ "If your context shows the deploy gate parked on a missing or stale workflow id for an",
42390
+ "environment, resolve it once with this fail-closed procedure \u2014 do this AT MOST ONCE per",
42391
+ "project+environment; it becomes durable project state, not a per-run choice:",
42392
+ '1. Call `list_github_workflows` and keep only candidates with state: "active". A workflow\'s',
42393
+ " name is NOT evidence it deploys anything \u2014 e.g. this repo also has `publish` (ships an npm",
42394
+ " package) and `bootstrap-changelog`; picking by name resemblance can dispatch the wrong thing.",
42395
+ "2. For each active candidate, read its file at `<worktree>/<path>` \u2014 the list API's `path` is",
42396
+ " already repo-root-relative (e.g. `.github/workflows/deploy.yml`), so do NOT prefix it again",
42397
+ " with `.github/workflows/`. Require an explicit `workflow_dispatch` trigger \u2014 a workflow you",
42398
+ " cannot confirm is dispatchable this way is not a candidate.",
42399
+ "3. Require positive evidence from the workflow's own steps that it deploys THIS project \u2014 not",
42400
+ " just a plausible-sounding name.",
42401
+ "4. Exactly one confirmed candidate \u2192 call `record_deploy_workflow` with that workflowId (state",
42402
+ ' defaults to "resolved") and a one-sentence reason. The server captures its own snapshot of',
42403
+ " the live active-workflow set at write time \u2014 you do not need to compute or pass one; hand-",
42404
+ " assembling it yourself would risk a format mismatch against what the deploy gate recomputes",
42405
+ " later, silently disabling the drift check. Append a `checkpoint` artifact with the same pick",
42406
+ " + reason so the decision stays auditable.",
42407
+ "5. Zero confirmed candidates, or more than one \u2192 call `record_deploy_workflow` with",
42408
+ ' workflowId: null and state: "ambiguous", and file a clarifying question through the normal',
42409
+ " inbox question path. Do NOT guess between multiple plausible candidates."
42018
42410
  ].join("\n");
42019
42411
  function artifactKindForEvent(event) {
42020
42412
  switch (event.type) {
@@ -42030,6 +42422,7 @@ function artifactKindForEvent(event) {
42030
42422
  }
42031
42423
  }
42032
42424
  var COMPLETED_TASK_STATUSES = /* @__PURE__ */ new Set(["closed_done"]);
42425
+ var CODE_PR_READY_TASK_STATUSES = /* @__PURE__ */ new Set(["closed_done", "awaiting_verification"]);
42033
42426
  var COMPLETION_EVIDENCE_KINDS = /* @__PURE__ */ new Set([
42034
42427
  "checkpoint",
42035
42428
  "test_result",
@@ -42047,11 +42440,11 @@ function isBridgeGeneratedArtifact(artifact) {
42047
42440
  return typeof payload === "object" && payload !== null && "event" in payload;
42048
42441
  }
42049
42442
  function newArtifactId() {
42050
- return `EA-${import_node_crypto4.default.randomUUID()}`;
42443
+ return `EA-${import_node_crypto5.default.randomUUID()}`;
42051
42444
  }
42052
42445
  var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
42053
- function isBlastRadiusFloorPath(path18) {
42054
- return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(path18));
42446
+ function isBlastRadiusFloorPath(path19) {
42447
+ return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(path19));
42055
42448
  }
42056
42449
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process9.execFile);
42057
42450
  async function defaultListRunDiffPaths(opts) {
@@ -42131,9 +42524,25 @@ async function gatherContext(client, projectSlug, task, openRunId) {
42131
42524
  autonomyEvents
42132
42525
  };
42133
42526
  }
42134
- async function assertRunCompletionReady(deps, projectSlug, taskId, runId) {
42527
+ async function deployWorkflowReverifyNotice(client, projectSlug) {
42528
+ const envs = ["dev", "prod"];
42529
+ const flagged = [];
42530
+ for (const env of envs) {
42531
+ try {
42532
+ const row = await client.getProjectDeployWorkflow(projectSlug, env);
42533
+ if (row?.reverifyRequested) flagged.push(env);
42534
+ } catch {
42535
+ }
42536
+ }
42537
+ if (flagged.length === 0) return "";
42538
+ return `
42539
+
42540
+ ## Deploy workflow re-verification needed
42541
+ The GitHub Actions workflow set changed since the deploy workflow was last confirmed for: ${flagged.join(", ")}. Re-run the workflow-resolution procedure (list_github_workflows -> confirm -> record_deploy_workflow) for ${flagged.length === 1 ? "this environment" : "these environments"} if you have a worktree this turn \u2014 this is a hint, not a blocker, so it is fine to skip if unrelated work is more urgent this turn.`;
42542
+ }
42543
+ async function assertRunCompletionReady(deps, projectSlug, taskId, runId, allowedStatuses) {
42135
42544
  const task = await deps.client.getTask(projectSlug, taskId);
42136
- if (!COMPLETED_TASK_STATUSES.has(task.status)) {
42545
+ if (!allowedStatuses.has(task.status)) {
42137
42546
  return {
42138
42547
  ok: false,
42139
42548
  reason: `Codex turn completed but task ${task.id} remained in status ${task.status}.`,
@@ -42264,7 +42673,7 @@ async function driveRun(deps, projectSlug, runId) {
42264
42673
  if (!claimed) return;
42265
42674
  if (!claimed.leaseId) {
42266
42675
  await deps.client.createInboxItem(projectSlug, {
42267
- id: `II-${import_node_crypto4.default.randomUUID()}`,
42676
+ id: `II-${import_node_crypto5.default.randomUUID()}`,
42268
42677
  kind: "handoff",
42269
42678
  taskId: claimed.taskId,
42270
42679
  body: `Execution run ${runId} was claimed but returned no leaseId. This indicates DB/API corruption and requires operator attention.`
@@ -42313,7 +42722,7 @@ async function driveRun(deps, projectSlug, runId) {
42313
42722
  }
42314
42723
  const compactEnabled = (process.env.MRRLIN_MCP_COMPACT_DISABLE ?? "").trim() !== "1";
42315
42724
  const context = await gatherContext(deps.client, projectSlug, task, runId);
42316
- const bundle = renderContextBundle(
42725
+ let bundle = renderContextBundle(
42317
42726
  compactEnabled ? {
42318
42727
  ...context,
42319
42728
  compact: {
@@ -42322,10 +42731,12 @@ async function driveRun(deps, projectSlug, runId) {
42322
42731
  }
42323
42732
  } : context
42324
42733
  );
42734
+ bundle += await deployWorkflowReverifyNotice(deps.client, projectSlug);
42325
42735
  const checkout = deps.checkoutRegistry?.get(projectSlug) ?? null;
42326
42736
  let sandbox = "read-only";
42327
42737
  let turnCwd = deps.codexCwd ?? null;
42328
42738
  let worktreePath = null;
42739
+ let resolvedDefaultBranch = null;
42329
42740
  let useExecutor = false;
42330
42741
  let codex;
42331
42742
  let disposeCodex = () => {
@@ -42343,13 +42754,14 @@ async function driveRun(deps, projectSlug, runId) {
42343
42754
  try {
42344
42755
  const createWt = deps.createRunWorktree ?? createRunWorktree;
42345
42756
  const getDefaultBranch = deps.getDefaultBranch ?? (async () => "main");
42757
+ resolvedDefaultBranch = await getDefaultBranch(projectSlug);
42346
42758
  worktreePath = await createWt({
42347
42759
  checkout: checkout.path,
42348
42760
  worktreeRoot: deps.worktreeRoot ?? "/tmp/mrrlin-worktrees",
42349
42761
  locksDir: deps.locksDir ?? "/tmp/mrrlin-locks",
42350
42762
  slug: projectSlug,
42351
42763
  runId,
42352
- defaultBranch: await getDefaultBranch(projectSlug)
42764
+ defaultBranch: resolvedDefaultBranch
42353
42765
  });
42354
42766
  if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
42355
42767
  await deps.client.updateExecutionRun(projectSlug, runId, {
@@ -42433,7 +42845,8 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
42433
42845
  await failRun(deps, projectSlug, task, runId, leaseId, outcome.error);
42434
42846
  return;
42435
42847
  }
42436
- let readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId);
42848
+ const prReadyStatuses = useExecutor ? CODE_PR_READY_TASK_STATUSES : COMPLETED_TASK_STATUSES;
42849
+ let readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses);
42437
42850
  if (!readiness.ok) {
42438
42851
  const completionBudget = Math.min(completionTurnBudgetMs(), remainingTurnBudgetMs());
42439
42852
  if (isCompletionTurnDisabled() || completionBudget < completionTurnMinBudgetMs()) {
@@ -42466,7 +42879,7 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
42466
42879
  await failRun(deps, projectSlug, readiness.task, runId, leaseId, completionOutcome.error);
42467
42880
  return;
42468
42881
  }
42469
- readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId);
42882
+ readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses);
42470
42883
  if (!readiness.ok) {
42471
42884
  await failRun(deps, projectSlug, readiness.task, runId, leaseId, readiness.reason);
42472
42885
  return;
@@ -42478,6 +42891,19 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
42478
42891
  return;
42479
42892
  }
42480
42893
  if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
42894
+ const hasCommitsFn = deps.hasCommitsToPush ?? hasCommitsToPush;
42895
+ const defaultBranchForPush = resolvedDefaultBranch ?? "main";
42896
+ if (!await hasCommitsFn({ worktreePath, defaultBranch: defaultBranchForPush })) {
42897
+ await failRun(
42898
+ deps,
42899
+ projectSlug,
42900
+ readiness.task,
42901
+ runId,
42902
+ leaseId,
42903
+ `no_commits_to_push: run ${runId} has no commits on ${worktreeBranch(runId)} ahead of origin/${defaultBranchForPush} \u2014 nothing to push.`
42904
+ );
42905
+ return;
42906
+ }
42481
42907
  let review = null;
42482
42908
  if (deps.selfReviewTurn) {
42483
42909
  review = await deps.selfReviewTurn(codex, worktreePath, readiness.task);
@@ -42788,9 +43214,9 @@ async function driveNonCodeRun(deps, projectSlug, runId, leaseId, task, domain2)
42788
43214
  );
42789
43215
  return;
42790
43216
  }
42791
- let gateOutcome;
43217
+ let gateResult;
42792
43218
  try {
42793
- gateOutcome = (await deps.runDeliverableGate({ projectSlug, taskId: task.id, runId, deliverablePageId: pageId })).outcome;
43219
+ gateResult = await deps.runDeliverableGate({ projectSlug, taskId: task.id, runId, deliverablePageId: pageId });
42794
43220
  } catch (error51) {
42795
43221
  await failRun(
42796
43222
  deps,
@@ -42802,14 +43228,19 @@ async function driveNonCodeRun(deps, projectSlug, runId, leaseId, task, domain2)
42802
43228
  );
42803
43229
  return;
42804
43230
  }
42805
- if (gateOutcome !== "CONVERGED") {
43231
+ if (gateResult.outcome !== "CONVERGED") {
43232
+ const mapped = mapDeliverableGateResult(gateResult);
43233
+ if (mapped.action === "questions") {
43234
+ await fileDeliverableGateQuestions(deps.client, projectSlug, task.id, mapped.clarifications).catch(() => {
43235
+ });
43236
+ }
42806
43237
  await failRun(
42807
43238
  deps,
42808
43239
  projectSlug,
42809
43240
  task,
42810
43241
  runId,
42811
43242
  leaseId,
42812
- `deliverable_gate_${gateOutcome.toLowerCase()}: the produced deliverable did not pass the acceptance-criteria review (${gateOutcome}).`
43243
+ `deliverable_gate_${gateResult.outcome.toLowerCase()}: ${mapped.reason}`
42813
43244
  );
42814
43245
  return;
42815
43246
  }
@@ -42858,6 +43289,33 @@ async function failRun(deps, projectSlug, task, runId, leaseId, reason) {
42858
43289
  } catch {
42859
43290
  }
42860
43291
  }
43292
+ if (isDeliverableGateRetryableReason(reason)) {
43293
+ const attempt = deliverableGateRetryAttempt(currentRun.checkpointCursor) + 1;
43294
+ if (attempt <= DELIVERABLE_GATE_RETRY_MAX_ATTEMPTS) {
43295
+ try {
43296
+ await deps.client.updateExecutionRun(projectSlug, runId, {
43297
+ status: "pending",
43298
+ leaseId: null,
43299
+ checkpointCursor: deliverableGateRetryCursor(attempt)
43300
+ });
43301
+ await deps.client.appendExecutionArtifact(projectSlug, runId, {
43302
+ id: newArtifactId(),
43303
+ kind: "error",
43304
+ payload: {
43305
+ code: DELIVERABLE_GATE_RETRY_CODE,
43306
+ source: "execution-consumer",
43307
+ attempt,
43308
+ maxAttempts: DELIVERABLE_GATE_RETRY_MAX_ATTEMPTS,
43309
+ reason,
43310
+ summary: `Deliverable review hit a transient outcome; requeued for automatic retry ${attempt}/${DELIVERABLE_GATE_RETRY_MAX_ATTEMPTS}.`
43311
+ }
43312
+ }).catch(() => {
43313
+ });
43314
+ return;
43315
+ } catch {
43316
+ }
43317
+ }
43318
+ }
42861
43319
  try {
42862
43320
  await deps.client.createExecutionRunHandoff(projectSlug, runId, { reason });
42863
43321
  } catch {
@@ -42897,7 +43355,7 @@ async function reconcileTaskAwaitingMerge(deps, projectSlug, task, runId, reason
42897
43355
  }
42898
43356
  try {
42899
43357
  await deps.client.createInboxItem(projectSlug, {
42900
- id: `II-${import_node_crypto4.default.randomUUID()}`,
43358
+ id: `II-${import_node_crypto5.default.randomUUID()}`,
42901
43359
  kind: "handoff",
42902
43360
  taskId: task.id,
42903
43361
  body: `Task ${task.id} (${task.title}) still needs operator follow-up: ${reason}. Mrrlin could not move the task back to Handoff needed automatically.`
@@ -42932,7 +43390,7 @@ async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
42932
43390
  }
42933
43391
  try {
42934
43392
  await deps.client.createInboxItem(projectSlug, {
42935
- id: `II-${import_node_crypto4.default.randomUUID()}`,
43393
+ id: `II-${import_node_crypto5.default.randomUUID()}`,
42936
43394
  kind: "handoff",
42937
43395
  taskId: task.id,
42938
43396
  body: `Execution run ${runId} for task ${task.id} (${task.title}) needs operator attention: ${reason}`
@@ -43021,7 +43479,7 @@ async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId
43021
43479
  }).catch(() => {
43022
43480
  });
43023
43481
  await deps.client.createInboxItem(projectSlug, {
43024
- id: `II-${import_node_crypto4.default.randomUUID()}`,
43482
+ id: `II-${import_node_crypto5.default.randomUUID()}`,
43025
43483
  kind: "handoff",
43026
43484
  taskId: task.id,
43027
43485
  body: `Deploy gate for run ${runId} (task ${task.id} \u2014 ${task.title}) needs operator attention: ${reason}`
@@ -43037,7 +43495,7 @@ function claimIntervalMs() {
43037
43495
  }
43038
43496
 
43039
43497
  // src/async-job-consumer.ts
43040
- var import_node_crypto5 = __toESM(require("node:crypto"), 1);
43498
+ var import_node_crypto6 = __toESM(require("node:crypto"), 1);
43041
43499
 
43042
43500
  // src/async-tools/registry.ts
43043
43501
  var registry2 = /* @__PURE__ */ new Map();
@@ -43121,7 +43579,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
43121
43579
  const delivery = descriptor2.onComplete(outcome, input);
43122
43580
  if (!delivery.suppressInbox) {
43123
43581
  await deps.client.createInboxItem(projectSlug, {
43124
- id: delivery.id ?? `II-${import_node_crypto5.default.randomUUID()}`,
43582
+ id: delivery.id ?? `II-${import_node_crypto6.default.randomUUID()}`,
43125
43583
  kind: delivery.kind,
43126
43584
  body: delivery.body,
43127
43585
  ...delivery.taskId ? { taskId: delivery.taskId } : {}
@@ -43134,13 +43592,13 @@ async function deriveRequestedHash(client, toolName, input) {
43134
43592
  if (input.requestedHash) return input.requestedHash;
43135
43593
  if (toolName === "run_spec_consensus" && input.pageId) {
43136
43594
  const page = await client.getWikiPage(input.projectSlug, input.pageId);
43137
- return page.contentHash ?? import_node_crypto5.default.createHash("sha256").update(page.markdownBody).digest("hex");
43595
+ return page.contentHash ?? import_node_crypto6.default.createHash("sha256").update(page.markdownBody).digest("hex");
43138
43596
  }
43139
43597
  if (toolName === "draft_task_spec" && input.taskId) {
43140
43598
  const task = await client.getTask(input.projectSlug, input.taskId);
43141
- return task.updatedAt ?? import_node_crypto5.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
43599
+ return task.updatedAt ?? import_node_crypto6.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
43142
43600
  }
43143
- return import_node_crypto5.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
43601
+ return import_node_crypto6.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
43144
43602
  }
43145
43603
  async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
43146
43604
  const projects = await deps.client.listProjects();
@@ -43381,6 +43839,15 @@ async function runDeliverableGate(_target, deps) {
43381
43839
  rounds: result.rounds,
43382
43840
  contentHash: currentHash
43383
43841
  });
43842
+ if (result.outcome === "CONSENSUS_BLOCKED") {
43843
+ const accepted = result.history.at(-1)?.accepted ?? [];
43844
+ const clarifications = accepted.filter((issue2) => issue2.category === "scope" || issue2.category === "ambiguity" || issue2.category === "correctness").map((issue2) => ({
43845
+ question: issue2.text,
43846
+ whyBlocking: `reviewer raised a ${issue2.category} issue`,
43847
+ category: issue2.category
43848
+ }));
43849
+ return clarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", rounds: result.rounds, clarifications } : { outcome: "CONSENSUS_BLOCKED", rounds: result.rounds };
43850
+ }
43384
43851
  return { outcome: result.outcome, rounds: result.rounds };
43385
43852
  }
43386
43853
 
@@ -43629,7 +44096,7 @@ function chatTurnMaxMs() {
43629
44096
  }
43630
44097
 
43631
44098
  // src/worker-token.ts
43632
- var import_node_crypto6 = require("node:crypto");
44099
+ var import_node_crypto7 = require("node:crypto");
43633
44100
  var import_node_fs9 = require("node:fs");
43634
44101
  var import_node_os6 = __toESM(require("node:os"), 1);
43635
44102
  var import_node_path13 = __toESM(require("node:path"), 1);
@@ -43660,7 +44127,7 @@ function readOrCreateWorkerToken() {
43660
44127
  if (existing) return existing;
43661
44128
  const dir = workerDir();
43662
44129
  (0, import_node_fs9.mkdirSync)(dir, { recursive: true, mode: 448 });
43663
- const token = (0, import_node_crypto6.randomBytes)(32).toString("hex");
44130
+ const token = (0, import_node_crypto7.randomBytes)(32).toString("hex");
43664
44131
  (0, import_node_fs9.writeFileSync)(workerTokenPath(), `${token}
43665
44132
  `, { encoding: "utf8", mode: 384 });
43666
44133
  return token;
@@ -47241,9 +47708,9 @@ var DirectorRelay = class {
47241
47708
 
47242
47709
  // src/remote-phone-relay.ts
47243
47710
  function loadOrCreateAgentDeviceKey() {
47244
- const path18 = (0, import_node_path14.join)((0, import_node_os7.homedir)(), ".mrrlin", "agent-device-key");
47711
+ const path19 = (0, import_node_path14.join)((0, import_node_os7.homedir)(), ".mrrlin", "agent-device-key");
47245
47712
  try {
47246
- const raw = JSON.parse((0, import_node_fs10.readFileSync)(path18, "utf8"));
47713
+ const raw = JSON.parse((0, import_node_fs10.readFileSync)(path19, "utf8"));
47247
47714
  if (typeof raw.priv === "string" && typeof raw.pub === "string") {
47248
47715
  return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
47249
47716
  }
@@ -47253,7 +47720,7 @@ function loadOrCreateAgentDeviceKey() {
47253
47720
  try {
47254
47721
  (0, import_node_fs10.mkdirSync)((0, import_node_path14.join)((0, import_node_os7.homedir)(), ".mrrlin"), { recursive: true });
47255
47722
  (0, import_node_fs10.writeFileSync)(
47256
- path18,
47723
+ path19,
47257
47724
  JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
47258
47725
  { mode: 384 }
47259
47726
  );
@@ -47476,9 +47943,9 @@ var CheckoutRegistry = class {
47476
47943
  get(slug) {
47477
47944
  return this.read()[slug] ?? null;
47478
47945
  }
47479
- confirm(slug, path18, now) {
47946
+ confirm(slug, path19, now) {
47480
47947
  const all = this.read();
47481
- all[slug] = { path: path18, confirmedAt: now };
47948
+ all[slug] = { path: path19, confirmedAt: now };
47482
47949
  (0, import_node_fs11.writeFileSync)(this.file, JSON.stringify(all, null, 2));
47483
47950
  }
47484
47951
  };
@@ -47807,6 +48274,362 @@ function createBridgeLogger(stateDir, env = process.env) {
47807
48274
  };
47808
48275
  }
47809
48276
 
48277
+ // src/external-agents-scrub.ts
48278
+ var import_node_fs13 = __toESM(require("node:fs"), 1);
48279
+ var import_node_os8 = __toESM(require("node:os"), 1);
48280
+ var import_node_path17 = __toESM(require("node:path"), 1);
48281
+ var REDACTION = "[REDACTED]";
48282
+ var SHORT_VALUE_THRESHOLD = 8;
48283
+ var KEYS_ENV_PATH = () => import_node_path17.default.join(import_node_os8.default.homedir(), ".local", "state", "external-agents", "keys.env");
48284
+ var keysEnvCache = null;
48285
+ function readKeysEnv() {
48286
+ const filePath = KEYS_ENV_PATH();
48287
+ let mtimeMs = 0;
48288
+ try {
48289
+ mtimeMs = import_node_fs13.default.statSync(filePath).mtimeMs;
48290
+ } catch {
48291
+ mtimeMs = 0;
48292
+ }
48293
+ if (keysEnvCache && keysEnvCache.mtimeMs === mtimeMs) {
48294
+ return keysEnvCache.map;
48295
+ }
48296
+ const map2 = /* @__PURE__ */ new Map();
48297
+ try {
48298
+ const content = import_node_fs13.default.readFileSync(filePath, "utf8");
48299
+ for (const rawLine of content.split(/\r?\n/)) {
48300
+ const line = rawLine.trim();
48301
+ if (line === "" || line.startsWith("#")) continue;
48302
+ const eq = line.indexOf("=");
48303
+ if (eq === -1) continue;
48304
+ const key = line.slice(0, eq).trim();
48305
+ const value = line.slice(eq + 1);
48306
+ if (key === "") continue;
48307
+ map2.set(key, value);
48308
+ }
48309
+ } catch {
48310
+ }
48311
+ keysEnvCache = { mtimeMs, map: map2 };
48312
+ return map2;
48313
+ }
48314
+ function buildScrubSet(opts) {
48315
+ const result = /* @__PURE__ */ new Set();
48316
+ const fileMap = readKeysEnv();
48317
+ for (const name of opts.registryEnvNames) {
48318
+ const fromFile = fileMap.get(name);
48319
+ if (fromFile !== void 0 && fromFile !== "") {
48320
+ result.add(fromFile);
48321
+ }
48322
+ const fromEnv = process.env[name];
48323
+ if (fromEnv !== void 0 && fromEnv !== "") {
48324
+ result.add(fromEnv);
48325
+ }
48326
+ }
48327
+ for (const value of opts.inFlightValues ?? []) {
48328
+ result.add(value);
48329
+ }
48330
+ return result;
48331
+ }
48332
+ function escapeRegExp(literal2) {
48333
+ return literal2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
48334
+ }
48335
+ function jsonEscapedVariant(value) {
48336
+ const json2 = JSON.stringify(value);
48337
+ return json2.slice(1, -1);
48338
+ }
48339
+ function percentEncodedVariant(value) {
48340
+ try {
48341
+ return encodeURIComponent(value);
48342
+ } catch {
48343
+ return null;
48344
+ }
48345
+ }
48346
+ function collectVariants(scrubSet) {
48347
+ const variants = /* @__PURE__ */ new Set();
48348
+ for (const value of scrubSet) {
48349
+ if (value === "") continue;
48350
+ variants.add(value);
48351
+ const jsonForm = jsonEscapedVariant(value);
48352
+ if (jsonForm !== "") variants.add(jsonForm);
48353
+ const percentForm = percentEncodedVariant(value);
48354
+ if (percentForm !== null && percentForm !== "") variants.add(percentForm);
48355
+ }
48356
+ return [...variants];
48357
+ }
48358
+ function buildScrubRegex(scrubSet) {
48359
+ const variants = collectVariants(scrubSet);
48360
+ if (variants.length === 0) return null;
48361
+ variants.sort((a, b) => b.length - a.length);
48362
+ const alternatives = variants.map((variant) => {
48363
+ const escaped = escapeRegExp(variant);
48364
+ if (variant.length >= SHORT_VALUE_THRESHOLD) {
48365
+ return escaped;
48366
+ }
48367
+ return `(?<![A-Za-z0-9_])${escaped}(?![A-Za-z0-9_])`;
48368
+ });
48369
+ return new RegExp(alternatives.join("|"), "g");
48370
+ }
48371
+ function scrubString(input, regex) {
48372
+ return input.replace(regex, REDACTION);
48373
+ }
48374
+ function isPlainObject3(value) {
48375
+ if (typeof value !== "object" || value === null) return false;
48376
+ const proto = Object.getPrototypeOf(value);
48377
+ return proto === Object.prototype || proto === null;
48378
+ }
48379
+ function scrubValue(value, regex) {
48380
+ if (typeof value === "string") {
48381
+ return regex === null ? value : scrubString(value, regex);
48382
+ }
48383
+ if (Array.isArray(value)) {
48384
+ return value.map((item) => scrubValue(item, regex));
48385
+ }
48386
+ if (isPlainObject3(value)) {
48387
+ const out = {};
48388
+ for (const [key, child] of Object.entries(value)) {
48389
+ out[key] = scrubValue(child, regex);
48390
+ }
48391
+ return out;
48392
+ }
48393
+ return value;
48394
+ }
48395
+ function scrubDeep(value, scrubSet) {
48396
+ const regex = buildScrubRegex(scrubSet);
48397
+ return scrubValue(value, regex);
48398
+ }
48399
+
48400
+ // src/external-agents-handlers.ts
48401
+ var BUDGET_STATE_MS = 1e4;
48402
+ var BUDGET_PROBE_MS = 6e4;
48403
+ var BUDGET_AUDIT_MS = 18e4;
48404
+ var BUDGET_TOGGLE_MS = 1e4;
48405
+ var BUDGET_ADD_MODEL_MS = 1e4;
48406
+ var BUDGET_SET_CREDENTIAL_MS = 1e4;
48407
+ var BUDGET_DISPATCH_MS = 3e5;
48408
+ var ENV_NAME_RE = /^[A-Z0-9_]+$/;
48409
+ var MAX_PROMPT_LEN = 8192;
48410
+ var TOGGLE_MIN_VERSION = "0.34.0";
48411
+ function invalidInput(field, reason) {
48412
+ return { ok: false, error: { code: "invalid_input", fields: { [field]: reason } } };
48413
+ }
48414
+ function tryParseJson(s) {
48415
+ try {
48416
+ return { ok: true, value: JSON.parse(s) };
48417
+ } catch {
48418
+ return { ok: false };
48419
+ }
48420
+ }
48421
+ function classifyCliFailure(result) {
48422
+ if (result.timedOut) return { code: "timeout" };
48423
+ const stderrLc = result.stderr.toLowerCase();
48424
+ const notFound = stderrLc.includes("command not found") || stderrLc.includes("enoent") || result.code === 1 && result.stdout === "" && result.stderr === "";
48425
+ const error51 = notFound ? { code: "cli_not_found", triedPaths: [result.triedPath] } : { code: "cli_broken" };
48426
+ if (result.stderr) error51.detail = result.stderr;
48427
+ return error51;
48428
+ }
48429
+ function finalizeReply(reply, scrubSet) {
48430
+ return scrubDeep(reply, scrubSet);
48431
+ }
48432
+ function defaultScrubSet(deps) {
48433
+ return buildScrubSet({ registryEnvNames: deps.registryEnvNames });
48434
+ }
48435
+ function extractRegistryEnvNames(agents) {
48436
+ const names = /* @__PURE__ */ new Set();
48437
+ for (const entry of agents) {
48438
+ if (typeof entry !== "object" || entry === null) continue;
48439
+ const auth = entry["auth"];
48440
+ if (typeof auth === "string" && auth.startsWith("env:")) {
48441
+ names.add(auth.slice("env:".length));
48442
+ }
48443
+ }
48444
+ return [...names];
48445
+ }
48446
+ async function handleAgentsState(deps, request) {
48447
+ if (request.since !== void 0) {
48448
+ if (Number.isNaN(new Date(request.since).getTime())) {
48449
+ return finalizeReply(invalidInput("since", "not a valid ISO timestamp"), defaultScrubSet(deps));
48450
+ }
48451
+ }
48452
+ const status = await deps.run(["status", "--json"], { budgetMs: BUDGET_STATE_MS });
48453
+ if (status.code !== 0) {
48454
+ return finalizeReply({ ok: false, error: classifyCliFailure(status) }, defaultScrubSet(deps));
48455
+ }
48456
+ const statusParsed = tryParseJson(status.stdout);
48457
+ if (!statusParsed.ok || !Array.isArray(statusParsed.value)) {
48458
+ return finalizeReply(
48459
+ { ok: false, error: { code: "cli_broken", detail: status.stderr || void 0 } },
48460
+ defaultScrubSet(deps)
48461
+ );
48462
+ }
48463
+ const agents = statusParsed.value;
48464
+ const stateScrubSet = buildScrubSet({
48465
+ registryEnvNames: [...deps.registryEnvNames, ...extractRegistryEnvNames(agents)]
48466
+ });
48467
+ const statsArgs = ["stats", "--json", ...request.since ? ["--since", request.since] : []];
48468
+ const stats = await deps.run(statsArgs, { budgetMs: BUDGET_STATE_MS });
48469
+ let totals = null;
48470
+ if (stats.code === 0) {
48471
+ const statsParsed = tryParseJson(stats.stdout);
48472
+ if (statsParsed.ok) totals = statsParsed.value;
48473
+ }
48474
+ return finalizeReply(
48475
+ { ok: true, data: { agents, totals, cli: { path: null, version: null, source: status.source } } },
48476
+ stateScrubSet
48477
+ );
48478
+ }
48479
+ async function handleAgentsProbe(deps, request) {
48480
+ const scrubSet = defaultScrubSet(deps);
48481
+ if (deps.lastKnownState === null || !deps.lastKnownState.agentIds.includes(request.id)) {
48482
+ return finalizeReply(invalidInput("id", "unknown agent id"), scrubSet);
48483
+ }
48484
+ const result = await deps.run(["probe", request.id], { budgetMs: BUDGET_PROBE_MS });
48485
+ if (result.code !== 0) {
48486
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48487
+ }
48488
+ const parsed = tryParseJson(result.stdout);
48489
+ if (!parsed.ok) {
48490
+ return finalizeReply({ ok: false, error: { code: "cli_broken", detail: result.stderr || void 0 } }, scrubSet);
48491
+ }
48492
+ return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
48493
+ }
48494
+ async function handleAgentsAudit(deps, request) {
48495
+ const scrubSet = defaultScrubSet(deps);
48496
+ if (deps.lastKnownState === null) {
48497
+ return finalizeReply(invalidInput("provider", "call agents-state before agents-audit"), scrubSet);
48498
+ }
48499
+ if (request.provider !== void 0 && !deps.lastKnownState.providers.includes(request.provider)) {
48500
+ return finalizeReply(invalidInput("provider", "unknown provider"), scrubSet);
48501
+ }
48502
+ const auditArgs = ["audit", "--json", ...request.provider ? ["--provider", request.provider] : []];
48503
+ const result = await deps.run(auditArgs, { budgetMs: BUDGET_AUDIT_MS });
48504
+ if (result.code !== 0) {
48505
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48506
+ }
48507
+ const parsed = tryParseJson(result.stdout);
48508
+ if (!parsed.ok) {
48509
+ return finalizeReply({ ok: false, error: { code: "cli_broken", detail: result.stderr || void 0 } }, scrubSet);
48510
+ }
48511
+ return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
48512
+ }
48513
+ async function handleAgentsToggle(deps, request) {
48514
+ const scrubSet = defaultScrubSet(deps);
48515
+ if (deps.lastKnownState === null || !deps.lastKnownState.agentIds.includes(request.id)) {
48516
+ return finalizeReply(invalidInput("id", "unknown agent id"), scrubSet);
48517
+ }
48518
+ const result = await deps.run(
48519
+ ["toggle", request.id, request.enabled ? "--enabled" : "--disabled"],
48520
+ { budgetMs: BUDGET_TOGGLE_MS }
48521
+ );
48522
+ if (result.code !== 0) {
48523
+ const stderrLc = result.stderr.toLowerCase();
48524
+ if (stderrLc.includes("unknown subcommand") || stderrLc.includes("unknown command")) {
48525
+ return finalizeReply(
48526
+ {
48527
+ ok: false,
48528
+ error: {
48529
+ code: "cli_outdated",
48530
+ detail: `the toggle control requires external-agents >= ${TOGGLE_MIN_VERSION}`
48531
+ }
48532
+ },
48533
+ scrubSet
48534
+ );
48535
+ }
48536
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48537
+ }
48538
+ return finalizeReply({ ok: true, data: { id: request.id, enabled: request.enabled } }, scrubSet);
48539
+ }
48540
+ async function handleAgentsAddModel(deps, request) {
48541
+ const scrubSet = defaultScrubSet(deps);
48542
+ if (!ENV_NAME_RE.test(request.env)) {
48543
+ return finalizeReply(invalidInput("env", "must match /^[A-Z0-9_]+$/"), scrubSet);
48544
+ }
48545
+ try {
48546
+ new URL(request.url);
48547
+ } catch {
48548
+ return finalizeReply(invalidInput("url", "not a valid URL"), scrubSet);
48549
+ }
48550
+ if (deps.lastKnownState === null) {
48551
+ return finalizeReply(invalidInput("id", "call agents-state before agents-add-model"), scrubSet);
48552
+ }
48553
+ if (deps.lastKnownState.agentIds.includes(request.id)) {
48554
+ return finalizeReply(invalidInput("id", "an agent with this id already exists"), scrubSet);
48555
+ }
48556
+ const args = [
48557
+ "add-model",
48558
+ "--id",
48559
+ request.id,
48560
+ "--provider",
48561
+ request.provider,
48562
+ "--url",
48563
+ request.url,
48564
+ "--model",
48565
+ request.model,
48566
+ "--env",
48567
+ request.env,
48568
+ ...request.tier ? ["--tier", request.tier] : [],
48569
+ ...request.tags?.length ? ["--tags", request.tags.join(",")] : []
48570
+ ];
48571
+ const result = await deps.run(args, { budgetMs: BUDGET_ADD_MODEL_MS });
48572
+ if (result.code !== 0) {
48573
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48574
+ }
48575
+ return finalizeReply({ ok: true, data: { id: request.id } }, scrubSet);
48576
+ }
48577
+ async function handleAgentsSetCredential(deps, request) {
48578
+ const scrubSet = buildScrubSet({
48579
+ registryEnvNames: deps.registryEnvNames,
48580
+ inFlightValues: [request.value]
48581
+ });
48582
+ if (deps.lastKnownState === null) {
48583
+ return finalizeReply(invalidInput("env", "call agents-state before agents-set-credential"), scrubSet);
48584
+ }
48585
+ if (!ENV_NAME_RE.test(request.env)) {
48586
+ return finalizeReply(invalidInput("env", "must match /^[A-Z0-9_]+$/"), scrubSet);
48587
+ }
48588
+ if (request.value === "") {
48589
+ return finalizeReply(invalidInput("value", "must not be empty"), scrubSet);
48590
+ }
48591
+ const result = await deps.run(["set-credential", request.env, "-"], {
48592
+ stdinValue: request.value,
48593
+ budgetMs: BUDGET_SET_CREDENTIAL_MS
48594
+ });
48595
+ if (result.code !== 0) {
48596
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48597
+ }
48598
+ return finalizeReply({ ok: true, data: { env: request.env } }, scrubSet);
48599
+ }
48600
+ var DISPATCH_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "prompt", "transport", "effort"]);
48601
+ async function handleAgentsDispatch(deps, request) {
48602
+ const scrubSet = defaultScrubSet(deps);
48603
+ for (const key of Object.keys(request)) {
48604
+ if (!DISPATCH_ALLOWED_KEYS.has(key)) {
48605
+ return finalizeReply(invalidInput(key, "unexpected field"), scrubSet);
48606
+ }
48607
+ }
48608
+ if (deps.lastKnownState === null || !deps.lastKnownState.agentIds.includes(request.id)) {
48609
+ return finalizeReply(invalidInput("id", "unknown agent id"), scrubSet);
48610
+ }
48611
+ if (request.prompt.length > MAX_PROMPT_LEN) {
48612
+ return finalizeReply(invalidInput("prompt", `must be at most ${MAX_PROMPT_LEN} characters`), scrubSet);
48613
+ }
48614
+ const args = [
48615
+ "dispatch",
48616
+ request.id,
48617
+ "--json",
48618
+ ...request.transport ? ["--transport", request.transport] : [],
48619
+ ...request.effort ? ["--effort", request.effort] : [],
48620
+ request.prompt
48621
+ ];
48622
+ const result = await deps.run(args, { budgetMs: BUDGET_DISPATCH_MS });
48623
+ if (result.code !== 0) {
48624
+ return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
48625
+ }
48626
+ const parsed = tryParseJson(result.stdout);
48627
+ if (!parsed.ok) {
48628
+ return finalizeReply({ ok: false, error: { code: "cli_broken", detail: result.stderr || void 0 } }, scrubSet);
48629
+ }
48630
+ return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
48631
+ }
48632
+
47810
48633
  // src/director-bridge.ts
47811
48634
  var JSON_GPT_MODEL_REF_RE = /"(?:slug|model)"\s*:\s*"(gpt-[a-z0-9.-]+)"/gi;
47812
48635
  var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
@@ -47864,7 +48687,7 @@ function addBridgeModel(target, model) {
47864
48687
  }
47865
48688
  function readTextIfExists(filePath) {
47866
48689
  try {
47867
- return import_node_fs13.default.readFileSync(filePath, "utf8");
48690
+ return import_node_fs14.default.readFileSync(filePath, "utf8");
47868
48691
  } catch {
47869
48692
  return null;
47870
48693
  }
@@ -47875,9 +48698,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
47875
48698
  return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
47876
48699
  }
47877
48700
  function readCodexFallbackModels() {
47878
- const codexHome = process.env.CODEX_HOME?.trim() || import_node_path17.default.join(import_node_os8.default.homedir(), ".codex");
48701
+ const codexHome = process.env.CODEX_HOME?.trim() || import_node_path18.default.join(import_node_os9.default.homedir(), ".codex");
47879
48702
  const models = /* @__PURE__ */ new Map();
47880
- const cachePath = import_node_path17.default.join(codexHome, "models_cache.json");
48703
+ const cachePath = import_node_path18.default.join(codexHome, "models_cache.json");
47881
48704
  const cacheRaw = readTextIfExists(cachePath);
47882
48705
  if (cacheRaw) {
47883
48706
  try {
@@ -47927,7 +48750,7 @@ function readCodexFallbackModels() {
47927
48750
  );
47928
48751
  }
47929
48752
  }
47930
- for (const slug of readKnownGptSlugsFromTomlFile(import_node_path17.default.join(codexHome, "config.toml"))) {
48753
+ for (const slug of readKnownGptSlugsFromTomlFile(import_node_path18.default.join(codexHome, "config.toml"))) {
47931
48754
  addBridgeModel(
47932
48755
  models,
47933
48756
  mapBridgeModel({
@@ -47941,11 +48764,11 @@ function readCodexFallbackModels() {
47941
48764
  })
47942
48765
  );
47943
48766
  }
47944
- const automationsDir = import_node_path17.default.join(codexHome, "automations");
48767
+ const automationsDir = import_node_path18.default.join(codexHome, "automations");
47945
48768
  try {
47946
- for (const entry of import_node_fs13.default.readdirSync(automationsDir, { withFileTypes: true })) {
48769
+ for (const entry of import_node_fs14.default.readdirSync(automationsDir, { withFileTypes: true })) {
47947
48770
  if (!entry.isDirectory()) continue;
47948
- for (const slug of readKnownGptSlugsFromTomlFile(import_node_path17.default.join(automationsDir, entry.name, "automation.toml"))) {
48771
+ for (const slug of readKnownGptSlugsFromTomlFile(import_node_path18.default.join(automationsDir, entry.name, "automation.toml"))) {
47949
48772
  addBridgeModel(
47950
48773
  models,
47951
48774
  mapBridgeModel({
@@ -47965,9 +48788,9 @@ function readCodexFallbackModels() {
47965
48788
  return [...models.values()];
47966
48789
  }
47967
48790
  function neutralCheckoutCwd(stateDir) {
47968
- const dir = import_node_path17.default.join(stateDir, "no-checkout");
48791
+ const dir = import_node_path18.default.join(stateDir, "no-checkout");
47969
48792
  try {
47970
- import_node_fs13.default.mkdirSync(dir, { recursive: true });
48793
+ import_node_fs14.default.mkdirSync(dir, { recursive: true });
47971
48794
  } catch {
47972
48795
  }
47973
48796
  return dir;
@@ -47986,6 +48809,21 @@ function buildThreadStartParams(msg, config2, desiredModel) {
47986
48809
  "transcript. Just call the tools and reply with the outcome \u2014 start your reply with the result.",
47987
48810
  "When creating or updating tasks, always provide `autonomyLevel` and `autonomyReason`.",
47988
48811
  "",
48812
+ "Tool-use contract \u2014 typed MCP tools are the ONLY channel for Mrrlin data:",
48813
+ "- Every read or write of Mrrlin data \u2014 tasks, plans, wiki pages, inbox items, execution runs,",
48814
+ " projects \u2014 must go through the corresponding typed MCP tool. Never use `commandExecution`,",
48815
+ " `curl`, `python`, or any direct HTTP call to the Mrrlin API.",
48816
+ "- A single `create_task` call creates a task completely; it accepts `title`, `notes`, `category`,",
48817
+ " `subcategory`, `impact`, `autonomyLevel`, `planId`, `parentTaskId`, and more in one call.",
48818
+ " Do not create then patch, and do not re-read the task afterwards unless the operator asked",
48819
+ " for confirmation.",
48820
+ "- `commandExecution` is for the operator's own machine and repositories \u2014 running builds, tests,",
48821
+ " `git`, inspecting local files \u2014 and for public third-party web checks. It is not a transport",
48822
+ " for this product's API.",
48823
+ "- If no typed tool exists for a needed operation, state that to the operator instead of reaching",
48824
+ " for the API by hand.",
48825
+ "- Do not spend turns re-reading state you just wrote.",
48826
+ "",
47989
48827
  "Turn lifecycle \u2014 what you can and cannot do between turns:",
47990
48828
  "- Your turn ends the moment you stop producing output. You CANNOT start a new turn yourself:",
47991
48829
  " no timer and no scheduler wakes you up. Only a new operator message starts the next turn.",
@@ -48059,9 +48897,10 @@ function buildThreadStartParams(msg, config2, desiredModel) {
48059
48897
  ' Never answer "nothing found" from plans alone.',
48060
48898
  '- Only report "nothing found" after the q-variants AND a full-list scan are empty, and then',
48061
48899
  " state exactly what you searched.",
48062
- "- For public HTTP/HTML verification through `commandExecution`, prefer built-in tooling such",
48063
- " as `curl`, `python3` stdlib `urllib.request`, and `html.parser`; do not assume third-party",
48064
- " Python packages such as `requests` or `bs4` are installed.",
48900
+ "- For public/third-party HTTP/HTML verification through `commandExecution`, prefer built-in",
48901
+ " tooling such as `curl`, `python3` stdlib `urllib.request`, and `html.parser`; do not assume",
48902
+ " third-party Python packages such as `requests` or `bs4` are installed. This permission covers",
48903
+ " third-party sites ONLY \u2014 never call the Mrrlin API from `commandExecution`.",
48065
48904
  "",
48066
48905
  "Handoff contract \u2014 durable operator action MUST NOT live only in chat:",
48067
48906
  "- If you conclude that a specific task needs human input, account access, manual evidence,",
@@ -48304,7 +49143,7 @@ async function runOrphanWorktreeSweep(client, opts) {
48304
49143
  const cutoff = Date.now() - worktreeRetentionMs();
48305
49144
  const isReapable = (worktreePath) => {
48306
49145
  try {
48307
- return import_node_fs13.default.statSync(worktreePath).mtimeMs < cutoff;
49146
+ return import_node_fs14.default.statSync(worktreePath).mtimeMs < cutoff;
48308
49147
  } catch {
48309
49148
  return false;
48310
49149
  }
@@ -48342,8 +49181,8 @@ async function runOrphanWorktreeSweep(client, opts) {
48342
49181
  }
48343
49182
  }
48344
49183
  function readStateDir() {
48345
- if (process.env.CODEX_HOME) return import_node_path17.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
48346
- return import_node_path17.default.join(import_node_os8.default.homedir(), ".mrrlin", "director-bridge");
49184
+ if (process.env.CODEX_HOME) return import_node_path18.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
49185
+ return import_node_path18.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
48347
49186
  }
48348
49187
  function readAllowedOrigins() {
48349
49188
  const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
@@ -48418,7 +49257,7 @@ function createBridgeRequestListener(opts) {
48418
49257
  res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
48419
49258
  return;
48420
49259
  }
48421
- const nonce = import_node_crypto7.default.randomBytes(16).toString("base64url");
49260
+ const nonce = import_node_crypto8.default.randomBytes(16).toString("base64url");
48422
49261
  res.writeHead(200, { "content-type": "application/json" });
48423
49262
  res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
48424
49263
  return;
@@ -48542,6 +49381,45 @@ function createBridgeMessageHandler(deps) {
48542
49381
  for (const id of boundSessions) deps.unbindSessionSink?.(id, send);
48543
49382
  boundSessions.clear();
48544
49383
  });
49384
+ let externalAgentsRegistryEnvNames = [];
49385
+ let externalAgentsLastKnownState = null;
49386
+ function deriveLastKnownState(agents) {
49387
+ const agentIds = [];
49388
+ const providers = /* @__PURE__ */ new Set();
49389
+ for (const entry of agents) {
49390
+ if (typeof entry !== "object" || entry === null) continue;
49391
+ const rec = entry;
49392
+ if (typeof rec.id === "string") agentIds.push(rec.id);
49393
+ if (typeof rec.provider === "string") providers.add(rec.provider);
49394
+ }
49395
+ return { agentIds, providers: [...providers] };
49396
+ }
49397
+ async function probeAgentsUsingEnvVar(handlerDeps, envVar) {
49398
+ try {
49399
+ const before = await handleAgentsState(handlerDeps, {});
49400
+ if (!before.ok) return;
49401
+ const matchingIds = before.data.agents.filter((entry) => typeof entry === "object" && entry !== null).filter((entry) => entry.auth === `env:${envVar}`).map((entry) => entry.id).filter((id) => typeof id === "string");
49402
+ const lastKnownState = deriveLastKnownState(before.data.agents);
49403
+ await Promise.all(
49404
+ matchingIds.map((id) => handleAgentsProbe({ ...handlerDeps, lastKnownState }, { id }))
49405
+ );
49406
+ } catch {
49407
+ }
49408
+ }
49409
+ async function withPoolStateReread(handlerDeps, reply) {
49410
+ if (!reply.ok) return reply;
49411
+ try {
49412
+ const reRead = await handleAgentsState(handlerDeps, {});
49413
+ if (reRead.ok) {
49414
+ externalAgentsRegistryEnvNames = extractRegistryEnvNames(reRead.data.agents);
49415
+ externalAgentsLastKnownState = deriveLastKnownState(reRead.data.agents);
49416
+ return { ...reply, poolState: reRead.data };
49417
+ }
49418
+ return { ...reply, poolState: null };
49419
+ } catch {
49420
+ return { ...reply, poolState: null };
49421
+ }
49422
+ }
48545
49423
  function logResumeRejected(sessionId, reason) {
48546
49424
  logCtx?.logger.logOut({
48547
49425
  spanId: logCtx.span.id,
@@ -48656,7 +49534,7 @@ function createBridgeMessageHandler(deps) {
48656
49534
  }
48657
49535
  }
48658
49536
  socket.on("message", async (data) => {
48659
- const spanId = import_node_crypto7.default.randomUUID();
49537
+ const spanId = import_node_crypto8.default.randomUUID();
48660
49538
  if (logCtx) {
48661
49539
  logCtx.span.id = spanId;
48662
49540
  logCtx.span.at = Date.now();
@@ -48693,7 +49571,10 @@ function createBridgeMessageHandler(deps) {
48693
49571
  spanId,
48694
49572
  sessionId: sid,
48695
49573
  type: typeof msg.type === "string" ? msg.type : "<unknown>",
48696
- payload: msg
49574
+ // Structural credential removal: the set-credential message carries a raw secret in
49575
+ // `value` that must never reach the structured log. Redact that one field for that one
49576
+ // message type only; every other message's payload is logged unchanged.
49577
+ payload: msg.type === "agents-set-credential" ? { ...msg, value: "[REDACTED]" } : msg
48697
49578
  });
48698
49579
  if (msg.type === "ping") {
48699
49580
  sendForSpan({ type: "pong" });
@@ -48704,6 +49585,142 @@ function createBridgeMessageHandler(deps) {
48704
49585
  sendForSpan({ type: "pairing-qr", ...result });
48705
49586
  return;
48706
49587
  }
49588
+ if (msg.type === "agents-state") {
49589
+ if (!deps.runExternalAgentsCli) {
49590
+ sendForSpan({ type: "agents-state", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49591
+ return;
49592
+ }
49593
+ const handlerDeps = {
49594
+ run: deps.runExternalAgentsCli,
49595
+ registryEnvNames: externalAgentsRegistryEnvNames,
49596
+ lastKnownState: externalAgentsLastKnownState
49597
+ };
49598
+ const req = msg;
49599
+ const reply = await handleAgentsState(handlerDeps, req.since !== void 0 ? { since: req.since } : {});
49600
+ if (reply.ok) {
49601
+ externalAgentsRegistryEnvNames = extractRegistryEnvNames(reply.data.agents);
49602
+ externalAgentsLastKnownState = deriveLastKnownState(reply.data.agents);
49603
+ }
49604
+ sendForSpan({ type: "agents-state", ...reply });
49605
+ return;
49606
+ }
49607
+ if (msg.type === "agents-probe") {
49608
+ if (!deps.runExternalAgentsCli) {
49609
+ sendForSpan({ type: "agents-probe", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49610
+ return;
49611
+ }
49612
+ const handlerDeps = {
49613
+ run: deps.runExternalAgentsCli,
49614
+ registryEnvNames: externalAgentsRegistryEnvNames,
49615
+ lastKnownState: externalAgentsLastKnownState
49616
+ };
49617
+ const req = msg;
49618
+ const reply = await withPoolStateReread(handlerDeps, await handleAgentsProbe(handlerDeps, { id: req.id }));
49619
+ sendForSpan({ type: "agents-probe", ...reply });
49620
+ return;
49621
+ }
49622
+ if (msg.type === "agents-audit") {
49623
+ if (!deps.runExternalAgentsCli) {
49624
+ sendForSpan({ type: "agents-audit", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49625
+ return;
49626
+ }
49627
+ const handlerDeps = {
49628
+ run: deps.runExternalAgentsCli,
49629
+ registryEnvNames: externalAgentsRegistryEnvNames,
49630
+ lastKnownState: externalAgentsLastKnownState
49631
+ };
49632
+ const req = msg;
49633
+ const reply = await withPoolStateReread(
49634
+ handlerDeps,
49635
+ await handleAgentsAudit(handlerDeps, req.provider !== void 0 ? { provider: req.provider } : {})
49636
+ );
49637
+ sendForSpan({ type: "agents-audit", ...reply });
49638
+ return;
49639
+ }
49640
+ if (msg.type === "agents-toggle") {
49641
+ if (!deps.runExternalAgentsCli) {
49642
+ sendForSpan({ type: "agents-toggle", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49643
+ return;
49644
+ }
49645
+ const handlerDeps = {
49646
+ run: deps.runExternalAgentsCli,
49647
+ registryEnvNames: externalAgentsRegistryEnvNames,
49648
+ lastKnownState: externalAgentsLastKnownState
49649
+ };
49650
+ const req = msg;
49651
+ const reply = await withPoolStateReread(
49652
+ handlerDeps,
49653
+ await handleAgentsToggle(handlerDeps, { id: req.id, enabled: req.enabled })
49654
+ );
49655
+ sendForSpan({ type: "agents-toggle", ...reply });
49656
+ return;
49657
+ }
49658
+ if (msg.type === "agents-add-model") {
49659
+ if (!deps.runExternalAgentsCli) {
49660
+ sendForSpan({ type: "agents-add-model", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49661
+ return;
49662
+ }
49663
+ const handlerDeps = {
49664
+ run: deps.runExternalAgentsCli,
49665
+ registryEnvNames: externalAgentsRegistryEnvNames,
49666
+ lastKnownState: externalAgentsLastKnownState
49667
+ };
49668
+ const req = msg;
49669
+ const reply = await withPoolStateReread(
49670
+ handlerDeps,
49671
+ await handleAgentsAddModel(handlerDeps, {
49672
+ id: req.id,
49673
+ provider: req.provider,
49674
+ model: req.model,
49675
+ url: req.url,
49676
+ env: req.env,
49677
+ ...req.tier !== void 0 ? { tier: req.tier } : {},
49678
+ ...req.tags !== void 0 ? { tags: req.tags } : {}
49679
+ })
49680
+ );
49681
+ sendForSpan({ type: "agents-add-model", ...reply });
49682
+ return;
49683
+ }
49684
+ if (msg.type === "agents-set-credential") {
49685
+ if (!deps.runExternalAgentsCli) {
49686
+ sendForSpan({ type: "agents-set-credential", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49687
+ return;
49688
+ }
49689
+ const handlerDeps = {
49690
+ run: deps.runExternalAgentsCli,
49691
+ registryEnvNames: externalAgentsRegistryEnvNames,
49692
+ lastKnownState: externalAgentsLastKnownState
49693
+ };
49694
+ const req = msg;
49695
+ const setCredResult = await handleAgentsSetCredential(handlerDeps, { env: req.env, value: req.value });
49696
+ if (setCredResult.ok) await probeAgentsUsingEnvVar(handlerDeps, req.env);
49697
+ const reply = await withPoolStateReread(handlerDeps, setCredResult);
49698
+ sendForSpan({ type: "agents-set-credential", ...reply });
49699
+ return;
49700
+ }
49701
+ if (msg.type === "agents-dispatch") {
49702
+ if (!deps.runExternalAgentsCli) {
49703
+ sendForSpan({ type: "agents-dispatch", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
49704
+ return;
49705
+ }
49706
+ const handlerDeps = {
49707
+ run: deps.runExternalAgentsCli,
49708
+ registryEnvNames: externalAgentsRegistryEnvNames,
49709
+ lastKnownState: externalAgentsLastKnownState
49710
+ };
49711
+ const req = msg;
49712
+ const reply = await withPoolStateReread(
49713
+ handlerDeps,
49714
+ await handleAgentsDispatch(handlerDeps, {
49715
+ id: req.id,
49716
+ prompt: req.prompt,
49717
+ ...req.transport !== void 0 ? { transport: req.transport } : {},
49718
+ ...req.effort !== void 0 ? { effort: req.effort } : {}
49719
+ })
49720
+ );
49721
+ sendForSpan({ type: "agents-dispatch", ...reply });
49722
+ return;
49723
+ }
48707
49724
  if (msg.type === "bootstrap") {
48708
49725
  let models = null;
48709
49726
  let rateLimits = null;
@@ -48969,7 +49986,7 @@ function createBridgeMessageHandler(deps) {
48969
49986
  thread.inFlight = true;
48970
49987
  pendingTurnSessions.delete(directorSessionId);
48971
49988
  thread.replay = createReplayBuffer({
48972
- turnId: (0, import_node_crypto7.randomUUID)(),
49989
+ turnId: (0, import_node_crypto8.randomUUID)(),
48973
49990
  spanId,
48974
49991
  ...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
48975
49992
  ...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
@@ -49374,8 +50391,8 @@ async function startDirectorBridge() {
49374
50391
  codexCwd: config2.codexCwd,
49375
50392
  codexExecutable: config2.codexExecutable,
49376
50393
  checkoutRegistry,
49377
- worktreeRoot: import_node_path17.default.join(config2.stateDir, "worktrees"),
49378
- locksDir: import_node_path17.default.join(config2.stateDir, "locks"),
50394
+ worktreeRoot: import_node_path18.default.join(config2.stateDir, "worktrees"),
50395
+ locksDir: import_node_path18.default.join(config2.stateDir, "locks"),
49379
50396
  // Wire the executor server for code-execution runs. Each run gets its own app-server
49380
50397
  // process at the run worktree, running UNRESTRICTED from the real ~/.codex (owner
49381
50398
  // no-sandbox decision — auth + mrrlin MCP come from the operator config).
@@ -49411,13 +50428,13 @@ async function startDirectorBridge() {
49411
50428
  // egressDomains is retained in the seam signature (verification-turn.ts still computes the
49412
50429
  // env host) but no longer constrains anything — the executor is unrestricted.
49413
50430
  startSandbox: async (_egressDomains) => {
49414
- const cwd = import_node_fs13.default.mkdtempSync(import_node_path17.default.join(import_node_os8.default.tmpdir(), "mrrlin-verify-"));
50431
+ const cwd = import_node_fs14.default.mkdtempSync(import_node_path18.default.join(import_node_os9.default.tmpdir(), "mrrlin-verify-"));
49415
50432
  let handle;
49416
50433
  try {
49417
50434
  handle = await startExecutorServer({ worktree: cwd });
49418
50435
  } catch (error51) {
49419
50436
  try {
49420
- import_node_fs13.default.rmSync(cwd, { recursive: true, force: true });
50437
+ import_node_fs14.default.rmSync(cwd, { recursive: true, force: true });
49421
50438
  } catch {
49422
50439
  }
49423
50440
  throw error51;
@@ -49428,7 +50445,7 @@ async function startDirectorBridge() {
49428
50445
  dispose: () => {
49429
50446
  handle.dispose();
49430
50447
  try {
49431
- import_node_fs13.default.rmSync(cwd, { recursive: true, force: true });
50448
+ import_node_fs14.default.rmSync(cwd, { recursive: true, force: true });
49432
50449
  } catch {
49433
50450
  }
49434
50451
  }
@@ -49456,7 +50473,7 @@ async function startDirectorBridge() {
49456
50473
  };
49457
50474
  const sessionSinks = createSessionSinkRegistry();
49458
50475
  const tombstones = /* @__PURE__ */ new Map();
49459
- const bridgeInstanceId = (0, import_node_crypto7.randomUUID)();
50476
+ const bridgeInstanceId = (0, import_node_crypto8.randomUUID)();
49460
50477
  const asyncConsumerDeps = {
49461
50478
  client,
49462
50479
  runExclusive: wrappedTurnLock.runExclusive,
@@ -49610,7 +50627,7 @@ async function startDirectorBridge() {
49610
50627
  fileUpdateInboxItem: async (projectSlug) => {
49611
50628
  const body = selfUpdateHandle.updateInboxBody();
49612
50629
  if (!body) return;
49613
- const id = `II-MCPUPD-${(0, import_node_crypto7.randomUUID)()}`;
50630
+ const id = `II-MCPUPD-${(0, import_node_crypto8.randomUUID)()}`;
49614
50631
  try {
49615
50632
  const row = await client.createInboxItem(projectSlug, { id, kind: "question", body });
49616
50633
  process.stderr.write(
@@ -49631,12 +50648,15 @@ async function startDirectorBridge() {
49631
50648
  `
49632
50649
  );
49633
50650
  }
49634
- }
50651
+ },
50652
+ // External-agents control plane: the real spawn runner, with the EXTERNAL_AGENTS_CLI operator
50653
+ // escape hatch bound here (the handlers stay spawn-free and this is the only production seam).
50654
+ runExternalAgentsCli: (args, opts) => runExternalAgentsCli(args, { ...opts, envCliPath: process.env["EXTERNAL_AGENTS_CLI"] })
49635
50655
  };
49636
50656
  const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
49637
50657
  let bridgeBinShaShort = "unknown00000";
49638
50658
  try {
49639
- bridgeBinShaShort = import_node_crypto7.default.createHash("sha256").update(import_node_fs13.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
50659
+ bridgeBinShaShort = import_node_crypto8.default.createHash("sha256").update(import_node_fs14.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
49640
50660
  } catch {
49641
50661
  }
49642
50662
  attachBridgeWss(server, {
@@ -49765,8 +50785,8 @@ async function startDirectorBridge() {
49765
50785
  enqueueRun(
49766
50786
  () => runOrphanWorktreeSweep(client, {
49767
50787
  checkoutRegistry,
49768
- worktreeRoot: import_node_path17.default.join(config2.stateDir, "worktrees"),
49769
- locksDir: import_node_path17.default.join(config2.stateDir, "locks")
50788
+ worktreeRoot: import_node_path18.default.join(config2.stateDir, "worktrees"),
50789
+ locksDir: import_node_path18.default.join(config2.stateDir, "locks")
49770
50790
  })
49771
50791
  );
49772
50792
  enqueueRun(async () => {
@@ -50006,7 +51026,7 @@ function timingSafeTokenEqual(provided, expected) {
50006
51026
  const a = Buffer.from(provided);
50007
51027
  const b = Buffer.from(expected);
50008
51028
  if (a.length !== b.length) return false;
50009
- return import_node_crypto7.default.timingSafeEqual(a, b);
51029
+ return import_node_crypto8.default.timingSafeEqual(a, b);
50010
51030
  }
50011
51031
  function readDispatchBody(req) {
50012
51032
  return new Promise((resolve, reject) => {
@@ -50028,15 +51048,15 @@ function readDispatchBody(req) {
50028
51048
  function readOrCreateBridgeToken(stateDir) {
50029
51049
  const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
50030
51050
  if (explicit) return explicit;
50031
- const tokenPath = import_node_path17.default.join(stateDir, "token.txt");
51051
+ const tokenPath = import_node_path18.default.join(stateDir, "token.txt");
50032
51052
  try {
50033
- const existing = import_node_fs13.default.readFileSync(tokenPath, "utf8").trim();
51053
+ const existing = import_node_fs14.default.readFileSync(tokenPath, "utf8").trim();
50034
51054
  if (existing) return existing;
50035
51055
  } catch {
50036
51056
  }
50037
- import_node_fs13.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
50038
- const token = import_node_crypto7.default.randomBytes(32).toString("base64url");
50039
- import_node_fs13.default.writeFileSync(tokenPath, `${token}
51057
+ import_node_fs14.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
51058
+ const token = import_node_crypto8.default.randomBytes(32).toString("base64url");
51059
+ import_node_fs14.default.writeFileSync(tokenPath, `${token}
50040
51060
  `, { mode: 384 });
50041
51061
  return token;
50042
51062
  }
@@ -52609,7 +53629,7 @@ var Protocol = class {
52609
53629
  };
52610
53630
  }
52611
53631
  };
52612
- function isPlainObject3(value) {
53632
+ function isPlainObject4(value) {
52613
53633
  return value !== null && typeof value === "object" && !Array.isArray(value);
52614
53634
  }
52615
53635
  function mergeCapabilities(base, additional) {
@@ -52620,7 +53640,7 @@ function mergeCapabilities(base, additional) {
52620
53640
  if (addValue === void 0)
52621
53641
  continue;
52622
53642
  const baseValue = result[k];
52623
- if (isPlainObject3(baseValue) && isPlainObject3(addValue)) {
53643
+ if (isPlainObject4(baseValue) && isPlainObject4(addValue)) {
52624
53644
  result[k] = { ...baseValue, ...addValue };
52625
53645
  } else {
52626
53646
  result[k] = addValue;
@@ -53418,19 +54438,19 @@ var StdioServerTransport = class {
53418
54438
  };
53419
54439
 
53420
54440
  // src/tools.ts
53421
- var import_node_crypto10 = require("node:crypto");
54441
+ var import_node_crypto11 = require("node:crypto");
53422
54442
  var import_promises3 = require("node:fs/promises");
53423
- var import_node_fs14 = require("node:fs");
53424
- var import_node_path19 = __toESM(require("node:path"), 1);
53425
- var import_node_os9 = __toESM(require("node:os"), 1);
54443
+ var import_node_fs15 = require("node:fs");
54444
+ var import_node_path20 = __toESM(require("node:path"), 1);
54445
+ var import_node_os10 = __toESM(require("node:os"), 1);
53426
54446
  var import_node_child_process12 = require("node:child_process");
53427
54447
 
53428
54448
  // ../../packages/wiki/dist/index.js
53429
54449
  var import_promises2 = __toESM(require("node:fs/promises"), 1);
53430
- var import_node_path18 = __toESM(require("node:path"), 1);
54450
+ var import_node_path19 = __toESM(require("node:path"), 1);
53431
54451
  var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
53432
54452
  function toPosixPath(input) {
53433
- return input.split(import_node_path18.default.sep).join("/");
54453
+ return input.split(import_node_path19.default.sep).join("/");
53434
54454
  }
53435
54455
  function slugifyWikiSegment(input) {
53436
54456
  return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -53444,12 +54464,12 @@ async function pathExists2(input) {
53444
54464
  }
53445
54465
  }
53446
54466
  async function findWorkspaceRoot(start = process.cwd()) {
53447
- let current = import_node_path18.default.resolve(start);
54467
+ let current = import_node_path19.default.resolve(start);
53448
54468
  while (true) {
53449
- if (await pathExists2(import_node_path18.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path18.default.join(current, "docs"))) {
54469
+ if (await pathExists2(import_node_path19.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path19.default.join(current, "docs"))) {
53450
54470
  return current;
53451
54471
  }
53452
- const parent = import_node_path18.default.dirname(current);
54472
+ const parent = import_node_path19.default.dirname(current);
53453
54473
  if (parent === current) {
53454
54474
  throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
53455
54475
  }
@@ -53458,28 +54478,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
53458
54478
  }
53459
54479
  async function resolveDocsRoot(input) {
53460
54480
  if (input) {
53461
- return import_node_path18.default.resolve(input);
54481
+ return import_node_path19.default.resolve(input);
53462
54482
  }
53463
54483
  if (process.env.MRRLIN_DOCS_ROOT) {
53464
- return import_node_path18.default.resolve(process.env.MRRLIN_DOCS_ROOT);
54484
+ return import_node_path19.default.resolve(process.env.MRRLIN_DOCS_ROOT);
53465
54485
  }
53466
- return import_node_path18.default.join(await findWorkspaceRoot(), "docs");
54486
+ return import_node_path19.default.join(await findWorkspaceRoot(), "docs");
53467
54487
  }
53468
54488
  async function resolveIndexPath(input) {
53469
54489
  if (input) {
53470
- return import_node_path18.default.resolve(input);
54490
+ return import_node_path19.default.resolve(input);
53471
54491
  }
53472
54492
  if (process.env.MRRLIN_WIKI_INDEX_PATH) {
53473
- return import_node_path18.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
54493
+ return import_node_path19.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
53474
54494
  }
53475
54495
  const workspaceRoot = await findWorkspaceRoot();
53476
- return import_node_path18.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
54496
+ return import_node_path19.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
53477
54497
  }
53478
54498
  async function walkMarkdownFiles(root, dir = root) {
53479
54499
  const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
53480
54500
  const files = [];
53481
54501
  for (const entry of entries) {
53482
- const absolute = import_node_path18.default.join(dir, entry.name);
54502
+ const absolute = import_node_path19.default.join(dir, entry.name);
53483
54503
  if (entry.isDirectory()) {
53484
54504
  files.push(...await walkMarkdownFiles(root, absolute));
53485
54505
  continue;
@@ -53498,7 +54518,7 @@ function parseTitle(markdown, sourcePath) {
53498
54518
  return title;
53499
54519
  }
53500
54520
  function documentFromFile(docsRoot, absolutePath, markdown) {
53501
- const relativePath = toPosixPath(import_node_path18.default.relative(docsRoot, absolutePath));
54521
+ const relativePath = toPosixPath(import_node_path19.default.relative(docsRoot, absolutePath));
53502
54522
  const [section, fileName] = relativePath.split("/");
53503
54523
  if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
53504
54524
  return null;
@@ -53682,15 +54702,35 @@ function firstTaskIdToken(text) {
53682
54702
  }
53683
54703
 
53684
54704
  // src/consensus/spec-gate.ts
54705
+ function mapAcceptedIssueToClarification(issue2) {
54706
+ const text = issue2.text.toLowerCase();
54707
+ let kind;
54708
+ if (issue2.category === "scope") {
54709
+ const directionCues = ["only", "or also", "narrower", "broader", "include", "exclude", "versus", "vs"];
54710
+ kind = directionCues.some((cue) => text.includes(cue)) ? "scope_direction" : "missing_requirement";
54711
+ } else {
54712
+ const acceptanceCues = ["acceptance", "done", "success", "criteria", "satisfy"];
54713
+ kind = acceptanceCues.some((cue) => text.includes(cue)) ? "acceptance_criteria_detail" : "default_choice";
54714
+ }
54715
+ return {
54716
+ kind,
54717
+ diagnostic: false,
54718
+ rawQuestion: issue2.text,
54719
+ whyBlocking: `reviewer raised a ${issue2.category} issue`,
54720
+ category: issue2.category
54721
+ };
54722
+ }
53685
54723
  async function runSpecGate(_target, deps, opts) {
53686
54724
  if (!await deps.consensusEnabled()) return { outcome: "SKIPPED" };
53687
54725
  const intent = await deps.readIntent();
53688
54726
  if (intent.taskId !== null && (intent.seed === null || intent.seed.trim() === "")) {
53689
54727
  return {
53690
54728
  outcome: "CONSENSUS_BLOCKED",
53691
- clarifications: [
54729
+ operatorClarifications: [
53692
54730
  {
53693
- 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.",
54731
+ kind: "missing_requirement",
54732
+ diagnostic: false,
54733
+ rawQuestion: "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.",
53694
54734
  whyBlocking: "operator_seed_request is empty",
53695
54735
  category: "scope"
53696
54736
  }
@@ -53704,9 +54744,11 @@ async function runSpecGate(_target, deps, opts) {
53704
54744
  if (normalizeDomain(intent.domain) !== "code" && parseAcceptanceCriteria(spec.markdownBody) === null) {
53705
54745
  return {
53706
54746
  outcome: "CONSENSUS_BLOCKED",
53707
- clarifications: [
54747
+ operatorClarifications: [
53708
54748
  {
53709
- question: "This spec has no machine-usable acceptance criteria. Add an `## Acceptance criteria` section written as a markdown checklist (`- [ ] \u2026` items) describing exactly what the finished deliverable must satisfy \u2014 the review of the produced work is scored against it.",
54749
+ kind: "acceptance_criteria_detail",
54750
+ diagnostic: false,
54751
+ rawQuestion: "This spec has no machine-usable acceptance criteria. Add an `## Acceptance criteria` section written as a markdown checklist (`- [ ] \u2026` items) describing exactly what the finished deliverable must satisfy \u2014 the review of the produced work is scored against it.",
53710
54752
  whyBlocking: "non-code spec is missing a parseable `## Acceptance criteria` checklist",
53711
54753
  category: "scope"
53712
54754
  }
@@ -53756,9 +54798,11 @@ async function runSpecGate(_target, deps, opts) {
53756
54798
  );
53757
54799
  return {
53758
54800
  outcome: "CONSENSUS_BLOCKED",
53759
- clarifications: [
54801
+ diagnostics: [
53760
54802
  {
53761
- question: `SPEC_IDENTITY_MISMATCH: this spec page gates ${intent.taskId}, but its heading identifies a different task \u2014 rewrite the spec heading and content for ${intent.taskId}, or re-link the task.`,
54803
+ kind: "spec_identity_mismatch",
54804
+ diagnostic: true,
54805
+ rawQuestion: `SPEC_IDENTITY_MISMATCH: this spec page gates ${intent.taskId}, but its heading identifies a different task \u2014 rewrite the spec heading and content for ${intent.taskId}, or re-link the task.`,
53762
54806
  whyBlocking: "converged spec content belongs to a different task than the one it gates",
53763
54807
  category: "scope"
53764
54808
  }
@@ -53778,12 +54822,8 @@ async function runSpecGate(_target, deps, opts) {
53778
54822
  }
53779
54823
  if (result.outcome === "CONSENSUS_BLOCKED") {
53780
54824
  const accepted = result.history.at(-1)?.accepted ?? [];
53781
- const clarifications = accepted.filter((issue2) => issue2.category === "ambiguity" || issue2.category === "scope").map((issue2) => ({
53782
- question: issue2.text,
53783
- whyBlocking: `reviewer raised a ${issue2.category} issue`,
53784
- category: issue2.category
53785
- }));
53786
- return clarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", clarifications } : { outcome: "CONSENSUS_BLOCKED" };
54825
+ const operatorClarifications = accepted.filter((issue2) => issue2.category === "ambiguity" || issue2.category === "scope").map((issue2) => mapAcceptedIssueToClarification(issue2));
54826
+ return operatorClarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", operatorClarifications } : { outcome: "CONSENSUS_BLOCKED" };
53787
54827
  }
53788
54828
  return { outcome: result.outcome };
53789
54829
  }
@@ -54133,7 +55173,7 @@ async function resolveActiveRunHead(input, deps) {
54133
55173
  }
54134
55174
 
54135
55175
  // src/async-tools/consensus.ts
54136
- var import_node_crypto8 = require("node:crypto");
55176
+ var import_node_crypto9 = require("node:crypto");
54137
55177
  function normalizeClarificationQuestion(question) {
54138
55178
  return question.replace(/\s+/g, " ").trim().replace(/[?.!]+$/, "").trim();
54139
55179
  }
@@ -54208,6 +55248,22 @@ function buildGateQuestionOptions(question, category) {
54208
55248
  }
54209
55249
  ];
54210
55250
  }
55251
+ var HUMANIZE_TEMPLATE_BY_KIND = {
55252
+ scope_direction: "The spec can be read in two different ways. Which direction should it follow?",
55253
+ default_choice: "One important detail is still ambiguous. Which interpretation should the spec use?",
55254
+ missing_requirement: "A required part of the task is still missing from the spec. What should it say?",
55255
+ acceptance_criteria_detail: "The direction is clear, but the spec still needs a sharper success check. What should count as done?"
55256
+ };
55257
+ var HUMANIZE_CONTEXT_CAP = 200;
55258
+ function humanizeClarificationBody(clarification) {
55259
+ const prefix = HUMANIZE_TEMPLATE_BY_KIND[clarification.kind];
55260
+ let context = clarification.rawQuestion.replace(/\b(?:parseable|SPEC_IDENTITY_MISMATCH|machine-usable)\b/gi, "").replace(/\s+/g, " ").trim();
55261
+ if (context.length > HUMANIZE_CONTEXT_CAP) {
55262
+ const cutIdx = context.lastIndexOf(" ", HUMANIZE_CONTEXT_CAP);
55263
+ context = context.slice(0, cutIdx > 0 ? cutIdx : HUMANIZE_CONTEXT_CAP).trim() + "\u2026";
55264
+ }
55265
+ return context ? `${prefix} ${context}` : prefix;
55266
+ }
54211
55267
  var defaultNativeSpecGateBuilders = { buildSpecGateDeps, runSpecGate };
54212
55268
  async function runNativeSpecGate(ctx, input, builders = defaultNativeSpecGateBuilders) {
54213
55269
  const deps = builders.buildSpecGateDeps({
@@ -54248,6 +55304,100 @@ async function cachedResult(client, input) {
54248
55304
  }
54249
55305
  return null;
54250
55306
  }
55307
+ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
55308
+ const operatorClarifications = result.operatorClarifications ?? [];
55309
+ const diagnostics = result.diagnostics ?? [];
55310
+ if (operatorClarifications.length > 0) {
55311
+ try {
55312
+ const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
55313
+ if (page) {
55314
+ const domain2 = await resolveSpecDomain(ctx.client, input.projectSlug, {
55315
+ id: page.id,
55316
+ taskId: page.taskId ?? null
55317
+ });
55318
+ await ctx.client.recordSpecConsensusReview(input.projectSlug, input.pageId, {
55319
+ contentHash: domainScopedReviewHash(page.contentHash, domain2),
55320
+ outcome: "CONSENSUS_BLOCKED_CLARIFICATION",
55321
+ rounds: 0
55322
+ });
55323
+ }
55324
+ } catch (error52) {
55325
+ process.stderr.write(
55326
+ `[mrrlin-mcp consensus] clarification verdict write failed for ${input.projectSlug}/${input.pageId}: ${error52 instanceof Error ? error52.message : String(error52)}
55327
+ `
55328
+ );
55329
+ }
55330
+ }
55331
+ let filedQuestionCount = 0;
55332
+ if (operatorClarifications.length > 0) {
55333
+ const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
55334
+ const taskId = page?.taskId ?? null;
55335
+ if (!resolvedTaskId && taskId) resolvedTaskId = taskId;
55336
+ let planId = null;
55337
+ if (!taskId) {
55338
+ const plans = await ctx.client.listPlans(input.projectSlug);
55339
+ planId = plans.find((p) => p.specWikiPageId === input.pageId)?.id ?? null;
55340
+ }
55341
+ if (taskId) {
55342
+ const scopeId = taskId;
55343
+ const groupId = operatorClarifications.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto9.createHash)("sha256").update(operatorClarifications.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
55344
+ for (const clarification of operatorClarifications) {
55345
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto9.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
55346
+ try {
55347
+ const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
55348
+ await ctx.client.createInboxItem(input.projectSlug, {
55349
+ id,
55350
+ kind: "question",
55351
+ taskId: scopeId,
55352
+ body: humanizeClarificationBody(clarification),
55353
+ origin: "gate",
55354
+ questionOptions,
55355
+ ...groupId ? { groupId } : {}
55356
+ });
55357
+ } catch {
55358
+ }
55359
+ }
55360
+ filedQuestionCount = operatorClarifications.length;
55361
+ } else if (planId) {
55362
+ const scopeId = planId;
55363
+ const groupId = operatorClarifications.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto9.createHash)("sha256").update(operatorClarifications.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
55364
+ for (const clarification of operatorClarifications) {
55365
+ const id = `II-${scopeId}-gate-${(0, import_node_crypto9.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
55366
+ try {
55367
+ const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
55368
+ await ctx.client.createInboxItem(input.projectSlug, {
55369
+ id,
55370
+ kind: "question",
55371
+ planId: scopeId,
55372
+ body: humanizeClarificationBody(clarification),
55373
+ origin: "gate",
55374
+ questionOptions,
55375
+ ...groupId ? { groupId } : {}
55376
+ });
55377
+ } catch {
55378
+ }
55379
+ }
55380
+ filedQuestionCount = operatorClarifications.length;
55381
+ }
55382
+ }
55383
+ let error51;
55384
+ if (filedQuestionCount > 0) {
55385
+ error51 = `Consensus blocked on ${filedQuestionCount} clarification(s); filed as operator question(s).`;
55386
+ } else if (diagnostics.length > 0 && operatorClarifications.length === 0) {
55387
+ error51 = "Consensus blocked: the spec content does not match its linked task. This requires fixing the spec/task relationship directly, not an inbox answer.";
55388
+ } else if (operatorClarifications.length > 0) {
55389
+ error51 = `Consensus blocked on ${operatorClarifications.length} clarification(s), but the spec page is not linked to a task or plan, so none could be filed as questions.`;
55390
+ } else {
55391
+ error51 = "Consensus blocked: reviewers did not converge within budget.";
55392
+ }
55393
+ return {
55394
+ kind: "failed",
55395
+ failureReason: "consensus_blocked",
55396
+ error: error51,
55397
+ filedQuestionCount,
55398
+ ...resolvedTaskId ? { taskId: resolvedTaskId } : {}
55399
+ };
55400
+ }
54251
55401
  async function run(ctx, input) {
54252
55402
  const result = await runNativeSpecGate(ctx, input);
54253
55403
  if (process.env[SHADOW_ENV_FLAG]) {
@@ -54276,95 +55426,7 @@ async function run(ctx, input) {
54276
55426
  } catch {
54277
55427
  }
54278
55428
  if (result.outcome === "CONSENSUS_BLOCKED") {
54279
- const clarifications = result.clarifications ?? [];
54280
- if (clarifications.length > 0) {
54281
- try {
54282
- const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
54283
- if (page) {
54284
- const domain2 = await resolveSpecDomain(ctx.client, input.projectSlug, {
54285
- id: page.id,
54286
- taskId: page.taskId ?? null
54287
- });
54288
- await ctx.client.recordSpecConsensusReview(input.projectSlug, input.pageId, {
54289
- contentHash: domainScopedReviewHash(page.contentHash, domain2),
54290
- outcome: "CONSENSUS_BLOCKED_CLARIFICATION",
54291
- rounds: 0
54292
- });
54293
- }
54294
- } catch (error52) {
54295
- process.stderr.write(
54296
- `[mrrlin-mcp consensus] clarification verdict write failed for ${input.projectSlug}/${input.pageId}: ${error52 instanceof Error ? error52.message : String(error52)}
54297
- `
54298
- );
54299
- }
54300
- }
54301
- let filedQuestionCount = 0;
54302
- if (clarifications.length > 0) {
54303
- const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
54304
- const taskId = page?.taskId ?? null;
54305
- if (!resolvedTaskId && taskId) resolvedTaskId = taskId;
54306
- let planId = null;
54307
- if (!taskId) {
54308
- const plans = await ctx.client.listPlans(input.projectSlug);
54309
- planId = plans.find((p) => p.specWikiPageId === input.pageId)?.id ?? null;
54310
- }
54311
- if (taskId) {
54312
- const scopeId = taskId;
54313
- const groupId = clarifications.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto8.createHash)("sha256").update(clarifications.map((c) => c.question).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
54314
- for (const clarification of clarifications) {
54315
- const id = `II-${scopeId}-gate-${(0, import_node_crypto8.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
54316
- try {
54317
- const questionOptions = buildGateQuestionOptions(clarification.question, clarification.category);
54318
- await ctx.client.createInboxItem(input.projectSlug, {
54319
- id,
54320
- kind: "question",
54321
- taskId: scopeId,
54322
- body: clarification.question,
54323
- origin: "gate",
54324
- questionOptions,
54325
- ...groupId ? { groupId } : {}
54326
- });
54327
- } catch {
54328
- }
54329
- }
54330
- filedQuestionCount = clarifications.length;
54331
- } else if (planId) {
54332
- const scopeId = planId;
54333
- const groupId = clarifications.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto8.createHash)("sha256").update(clarifications.map((c) => c.question).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
54334
- for (const clarification of clarifications) {
54335
- const id = `II-${scopeId}-gate-${(0, import_node_crypto8.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
54336
- try {
54337
- const questionOptions = buildGateQuestionOptions(clarification.question, clarification.category);
54338
- await ctx.client.createInboxItem(input.projectSlug, {
54339
- id,
54340
- kind: "question",
54341
- planId: scopeId,
54342
- body: clarification.question,
54343
- origin: "gate",
54344
- questionOptions,
54345
- ...groupId ? { groupId } : {}
54346
- });
54347
- } catch {
54348
- }
54349
- }
54350
- filedQuestionCount = clarifications.length;
54351
- }
54352
- }
54353
- let error51;
54354
- if (filedQuestionCount > 0) {
54355
- error51 = `Consensus blocked on ${filedQuestionCount} clarification(s); filed as operator question(s).`;
54356
- } else if (clarifications.length > 0) {
54357
- error51 = `Consensus blocked on ${clarifications.length} clarification(s), but the spec page is not linked to a task or plan, so none could be filed as questions.`;
54358
- } else {
54359
- error51 = "Consensus blocked: reviewers did not converge within budget.";
54360
- }
54361
- return {
54362
- kind: "failed",
54363
- failureReason: "consensus_blocked",
54364
- error: error51,
54365
- filedQuestionCount,
54366
- ...resolvedTaskId ? { taskId: resolvedTaskId } : {}
54367
- };
55429
+ return handleConsensusBlocked(result, ctx, input, resolvedTaskId);
54368
55430
  }
54369
55431
  switch (result.outcome) {
54370
55432
  case "CONVERGED":
@@ -54461,33 +55523,32 @@ async function run2(ctx, input) {
54461
55523
  { projectSlug: input.projectSlug, deliverablePageId: input.pageId },
54462
55524
  deps
54463
55525
  );
54464
- switch (result.outcome) {
54465
- case "CONVERGED":
54466
- case "SKIPPED":
54467
- return { kind: "done", resultJson: JSON.stringify(result), finalReviewedHash: null };
54468
- case "CONSENSUS_UNAVAILABLE":
54469
- return { kind: "retry", failureReason: "provider_unavailable", error: "Deliverable consensus unavailable (provider/quota)." };
54470
- case "DELIVERABLE_CHANGED_DURING_REVIEW":
54471
- return { kind: "retry", failureReason: "spec_changed", error: "Deliverable changed during review." };
54472
- case "MISSING_ACCEPTANCE_CRITERIA":
54473
- return {
54474
- kind: "failed",
54475
- failureReason: "consensus_blocked",
54476
- error: "Deliverable cannot be gated: the linked spec has no `## Acceptance criteria` checklist."
54477
- };
54478
- case "CONSENSUS_BLOCKED":
54479
- return {
54480
- kind: "failed",
54481
- failureReason: "consensus_blocked",
54482
- error: "Deliverable consensus blocked: reviewers did not converge against the acceptance criteria."
54483
- };
54484
- default:
54485
- return {
54486
- kind: "failed",
54487
- failureReason: "provider_unavailable",
54488
- error: `Unexpected deliverable consensus outcome: ${String(result.outcome)}`
54489
- };
55526
+ if (result.outcome === "CONVERGED" || result.outcome === "SKIPPED") {
55527
+ return { kind: "done", resultJson: JSON.stringify(result), finalReviewedHash: null };
55528
+ }
55529
+ const mapped = mapDeliverableGateResult(result);
55530
+ if (mapped.action === "retry") {
55531
+ return {
55532
+ kind: "retry",
55533
+ failureReason: result.outcome === "CONSENSUS_UNAVAILABLE" ? "provider_unavailable" : "spec_changed",
55534
+ error: mapped.reason
55535
+ };
55536
+ }
55537
+ let filedQuestionCount = 0;
55538
+ if (mapped.action === "questions") {
55539
+ const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
55540
+ const taskId = page?.taskId ?? null;
55541
+ if (taskId) {
55542
+ filedQuestionCount = await fileDeliverableGateQuestions(ctx.client, input.projectSlug, taskId, mapped.clarifications);
55543
+ }
54490
55544
  }
55545
+ const error51 = filedQuestionCount > 0 ? `Consensus blocked on ${filedQuestionCount} clarification(s); filed as operator question(s).` : mapped.reason;
55546
+ return {
55547
+ kind: "failed",
55548
+ failureReason: "consensus_blocked",
55549
+ error: error51,
55550
+ filedQuestionCount
55551
+ };
54491
55552
  }
54492
55553
  function onComplete3(outcome, input) {
54493
55554
  if (outcome.kind === "done") {
@@ -54507,6 +55568,14 @@ function onComplete3(outcome, input) {
54507
55568
  body: `Deliverable consensus CONVERGED for Deliverables/${input.pageId}; it meets the acceptance criteria.`
54508
55569
  };
54509
55570
  }
55571
+ if (outcome.kind === "failed" && (outcome.filedQuestionCount ?? 0) > 0) {
55572
+ const n = outcome.filedQuestionCount ?? 0;
55573
+ return {
55574
+ kind: "info",
55575
+ suppressInbox: true,
55576
+ body: `Deliverable consensus blocked on Deliverables/${input.pageId}; filed ${n} clarifying question${n === 1 ? "" : "s"} \u2014 answer to unblock the run.`
55577
+ };
55578
+ }
54510
55579
  return {
54511
55580
  kind: "handoff",
54512
55581
  body: `Deliverable consensus could not complete for Deliverables/${input.pageId}: ${outcome.error} Needs operator attention.`
@@ -54522,7 +55591,7 @@ var deliverableConsensusDescriptor = {
54522
55591
  };
54523
55592
 
54524
55593
  // src/async-tools/enqueue.ts
54525
- var import_node_crypto9 = __toESM(require("node:crypto"), 1);
55594
+ var import_node_crypto10 = __toESM(require("node:crypto"), 1);
54526
55595
  async function enqueueAsyncTool(client, descriptor2, input) {
54527
55596
  if (descriptor2.cachedResult) {
54528
55597
  const cached2 = await descriptor2.cachedResult(client, input);
@@ -54535,7 +55604,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
54535
55604
  if (active) {
54536
55605
  return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
54537
55606
  }
54538
- const jobId = `AJ-${import_node_crypto9.default.randomUUID()}`;
55607
+ const jobId = `AJ-${import_node_crypto10.default.randomUUID()}`;
54539
55608
  try {
54540
55609
  await client.createAsyncJob(input.projectSlug, {
54541
55610
  id: jobId,
@@ -54623,9 +55692,12 @@ var mcpToolNames = {
54623
55692
  searchKnowledge: "search_knowledge",
54624
55693
  updateExecutionRun: "update_execution_run",
54625
55694
  upsertProjectSchedulerPolicy: "upsert_project_scheduler_policy",
55695
+ recordDeployWorkflow: "record_deploy_workflow",
54626
55696
  updatePlan: "update_plan",
54627
55697
  updateTask: "update_task",
54628
55698
  resetDirectorThread: "reset_director_thread",
55699
+ archiveTask: "archive_task",
55700
+ unarchiveTask: "unarchive_task",
54629
55701
  updateWikiPage: "update_wiki_page",
54630
55702
  markSpecReady: "mark_spec_ready",
54631
55703
  runSpecConsensus: "run_spec_consensus",
@@ -55141,6 +56213,8 @@ var getTaskInputSchema = taskScopedSchema;
55141
56213
  var createTaskInputSchema = projectScopedSchema.merge(mrrlinTaskCreateSchema);
55142
56214
  var updateTaskInputSchema = taskScopedSchema.merge(mrrlinTaskUpdateSchema);
55143
56215
  var resetDirectorThreadInputSchema = taskScopedSchema;
56216
+ var archiveTaskInputSchema = taskScopedSchema;
56217
+ var unarchiveTaskInputSchema = taskScopedSchema;
55144
56218
  var listPlansInputSchema = projectScopedSchema;
55145
56219
  var createPlanInputSchema = projectScopedSchema.merge(mrrlinPlanCreateSchema);
55146
56220
  var updatePlanInputSchema = planScopedSchema.merge(mrrlinPlanUpdateSchema);
@@ -55200,6 +56274,13 @@ var appendExecutionArtifactInputSchema = runScopedSchema.merge(mrrlinExecutionAr
55200
56274
  var recordProducedUrlInputSchema = runScopedSchema.merge(mrrlinProducedUrlPayloadSchema);
55201
56275
  var getProjectSchedulerPolicyInputSchema = projectScopedSchema;
55202
56276
  var upsertProjectSchedulerPolicyInputSchema = projectScopedSchema.merge(mrrlinProjectSchedulerPolicyUpsertSchema);
56277
+ var recordDeployWorkflowInputSchema = projectScopedSchema.extend({
56278
+ env: mrrlinDeployWorkflowEnvSchema,
56279
+ workflowId: external_exports.number().int().positive().nullable(),
56280
+ workflowPath: external_exports.string().nullable().optional(),
56281
+ reason: external_exports.string().nullable().optional(),
56282
+ state: mrrlinDeployWorkflowStateSchema.optional()
56283
+ });
55203
56284
  var getSchedulerPendingTasksInputSchema = projectScopedSchema;
55204
56285
  var wakeDirectorInputSchema = projectScopedSchema.merge(wakeDirectorRequestSchema.partial());
55205
56286
  var uploadArtifactInputSchema = projectScopedSchema.merge(
@@ -55282,9 +56363,12 @@ var mcpToolInputSchemas = {
55282
56363
  [mcpToolNames.searchKnowledge]: searchKnowledgeInputSchema,
55283
56364
  [mcpToolNames.updateExecutionRun]: updateExecutionRunInputSchema,
55284
56365
  [mcpToolNames.upsertProjectSchedulerPolicy]: upsertProjectSchedulerPolicyInputSchema,
56366
+ [mcpToolNames.recordDeployWorkflow]: recordDeployWorkflowInputSchema,
55285
56367
  [mcpToolNames.updatePlan]: updatePlanInputSchema,
55286
56368
  [mcpToolNames.updateTask]: updateTaskInputSchema,
55287
56369
  [mcpToolNames.resetDirectorThread]: resetDirectorThreadInputSchema,
56370
+ [mcpToolNames.archiveTask]: archiveTaskInputSchema,
56371
+ [mcpToolNames.unarchiveTask]: unarchiveTaskInputSchema,
55288
56372
  [mcpToolNames.updateWikiPage]: updateWikiPageInputSchema,
55289
56373
  [mcpToolNames.markSpecReady]: markSpecReadyInputSchema,
55290
56374
  [mcpToolNames.runSpecConsensus]: runSpecConsensusInputSchema,
@@ -55344,9 +56428,12 @@ var mcpToolOperationIds = {
55344
56428
  [mcpToolNames.searchKnowledge]: openApiOperationIds.searchKnowledge,
55345
56429
  [mcpToolNames.updateExecutionRun]: openApiOperationIds.updateExecutionRun,
55346
56430
  [mcpToolNames.upsertProjectSchedulerPolicy]: openApiOperationIds.upsertProjectSchedulerPolicy,
56431
+ [mcpToolNames.recordDeployWorkflow]: openApiOperationIds.upsertProjectDeployWorkflow,
55347
56432
  [mcpToolNames.updatePlan]: openApiOperationIds.updatePlan,
55348
56433
  [mcpToolNames.updateTask]: openApiOperationIds.updateTask,
55349
56434
  [mcpToolNames.resetDirectorThread]: openApiOperationIds.resetDirectorThread,
56435
+ [mcpToolNames.archiveTask]: openApiOperationIds.archiveTask,
56436
+ [mcpToolNames.unarchiveTask]: openApiOperationIds.unarchiveTask,
55350
56437
  [mcpToolNames.updateWikiPage]: openApiOperationIds.updateWikiPage,
55351
56438
  [mcpToolNames.markSpecReady]: openApiOperationIds.markSpecReady,
55352
56439
  [mcpToolNames.listInboxItems]: openApiOperationIds.listInboxItems,
@@ -55394,6 +56481,8 @@ var mcpToolDescriptions = {
55394
56481
  [mcpToolNames.updatePlan]: "Update a plan/epic.",
55395
56482
  [mcpToolNames.updateTask]: "Update a task. Honors DB invariants: closed_no_result requires linked Evidence wiki pages. Set directorThreadId here to persist the worker's resumable provider thread handle.",
55396
56483
  [mcpToolNames.resetDirectorThread]: "Clear a task's persisted Director execution thread handle so the next execution run starts a fresh provider thread. Records a director_thread_reset task event.",
56484
+ [mcpToolNames.archiveTask]: "Archive a task: hides it from default reads, removes it from plan progress and scheduler consideration, cancels its non-terminal execution runs, and closes its open inbox items. Reversible \u2014 the project owner can restore it with unarchive_task. Records an 'archived' task event.",
56485
+ [mcpToolNames.unarchiveTask]: "Restore an archived task to its original status and visibility. Owner-only \u2014 refused with NOT_PROJECT_OWNER for any other caller. Does not resurrect the execution runs or inbox items that were cancelled/closed when the task was archived. Records a 'restored' task event.",
55397
56486
  [mcpToolNames.updateWikiPage]: "Update a markdown Wiki page.",
55398
56487
  [mcpToolNames.markSpecReady]: "Mark a wiki page (folder=Specs) as ready (or not) for execution-run gating. The Director sets this true after validating the spec; any edit to the page's markdown auto-resets it to false.",
55399
56488
  [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. For a NON-code task (domain seo/marketing/content, ADR 0020): the low-risk lanes `seo`, `marketing`, and `content` proceed to `create_execution_run` after consensus, using the same flow as code tasks. Report the spec\'s review outcome to the operator.',
@@ -55407,6 +56496,7 @@ var mcpToolDescriptions = {
55407
56496
  [mcpToolNames.updateExecutionRun]: "Update an execution run (status, branch, SHA, PR url, dev/prod workflow ids, checkpoint cursor). Transitioning to handoff_queued requires an approved handoff_judgement artifact.",
55408
56497
  [mcpToolNames.getProjectSchedulerPolicy]: "Fetch the project scheduler policy: cadence floor, eligible autonomy levels, and optional wake_floor. Returns defaults if unset.",
55409
56498
  [mcpToolNames.upsertProjectSchedulerPolicy]: "Upsert the project scheduler policy. Partial: only provided fields overwrite existing values.",
56499
+ [mcpToolNames.recordDeployWorkflow]: "Record which GitHub Actions workflow deploys this project for one environment (dev or prod), after confirming it via list_github_workflows + reading its file for a workflow_dispatch trigger. Call this AT MOST ONCE per environment per project, only when the deploy gate has parked on a missing/stale workflow id \u2014 this choice becomes durable project state, not a per-run decision. Pass workflowId=null and state='ambiguous' when zero or more than one candidate is confirmed dispatchable; otherwise pass the single confirmed workflowId with state='resolved' (the default). `source` is derived from your identity server-side \u2014 you cannot set it, and this call is always recorded as 'agent'.",
55410
56500
  [mcpToolNames.getSchedulerPendingTasks]: "Return tasks the scheduler should wake now: ones with follow_up_at or verification_due_at passed, or the policy wake_floor reached, filtered by eligible autonomy levels.",
55411
56501
  [mcpToolNames.wakeDirector]: "Wake Director once for a project: optionally dry-run scheduler evaluation or enqueue execution runs best-effort.",
55412
56502
  [mcpToolNames.listInboxItems]: "List operator-inbox items for a project. Optional filters: kind, status.",
@@ -55823,6 +56913,20 @@ function createMrrlinTools(options) {
55823
56913
  "Unable to reset director thread.",
55824
56914
  async (c, { projectSlug, taskId }) => await c.resetDirectorThread(projectSlug, taskId)
55825
56915
  ),
56916
+ [mcpToolNames.archiveTask]: makeTool(
56917
+ client,
56918
+ mcpToolNames.archiveTask,
56919
+ "TASK_ARCHIVE_FAILED",
56920
+ "Unable to archive task.",
56921
+ async (c, { projectSlug, taskId }) => await c.archiveTask(projectSlug, taskId)
56922
+ ),
56923
+ [mcpToolNames.unarchiveTask]: makeTool(
56924
+ client,
56925
+ mcpToolNames.unarchiveTask,
56926
+ "TASK_UNARCHIVE_FAILED",
56927
+ "Unable to unarchive task.",
56928
+ async (c, { projectSlug, taskId }) => await c.unarchiveTask(projectSlug, taskId)
56929
+ ),
55826
56930
  [mcpToolNames.updateWikiPage]: makeTool(
55827
56931
  client,
55828
56932
  mcpToolNames.updateWikiPage,
@@ -55986,7 +57090,7 @@ function createMrrlinTools(options) {
55986
57090
  "PRODUCED_URL_RECORD_FAILED",
55987
57091
  "Unable to record produced URL.",
55988
57092
  async (c, { projectSlug, runId, url: url2, label }) => {
55989
- const id = `EA-pu-${(0, import_node_crypto10.randomBytes)(4).toString("hex")}`;
57093
+ const id = `EA-pu-${(0, import_node_crypto11.randomBytes)(4).toString("hex")}`;
55990
57094
  const payload = label ? { url: url2, label } : { url: url2 };
55991
57095
  return await c.appendExecutionArtifact(projectSlug, runId, {
55992
57096
  id,
@@ -56009,6 +57113,13 @@ function createMrrlinTools(options) {
56009
57113
  "Unable to upsert project scheduler policy.",
56010
57114
  async (c, { projectSlug, ...input }) => await c.upsertProjectSchedulerPolicy(projectSlug, input)
56011
57115
  ),
57116
+ [mcpToolNames.recordDeployWorkflow]: makeTool(
57117
+ client,
57118
+ mcpToolNames.recordDeployWorkflow,
57119
+ "DEPLOY_WORKFLOW_RECORD_FAILED",
57120
+ "Unable to record the project's deploy workflow choice.",
57121
+ async (c, { projectSlug, env, ...input }) => await c.upsertProjectDeployWorkflow(projectSlug, env, input)
57122
+ ),
56012
57123
  [mcpToolNames.getSchedulerPendingTasks]: makeTool(
56013
57124
  client,
56014
57125
  mcpToolNames.getSchedulerPendingTasks,
@@ -56053,7 +57164,7 @@ function createMrrlinTools(options) {
56053
57164
  "ARTIFACT_FILE_UPLOAD_FAILED",
56054
57165
  "Unable to upload artifact file.",
56055
57166
  async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
56056
- const extension2 = import_node_path19.default.extname(filePath).toLowerCase();
57167
+ const extension2 = import_node_path20.default.extname(filePath).toLowerCase();
56057
57168
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
56058
57169
  if (!contentType) {
56059
57170
  throw new McpToolCodedError(
@@ -56081,7 +57192,7 @@ function createMrrlinTools(options) {
56081
57192
  "Artifact exceeds 5MB; split or summarize instead."
56082
57193
  );
56083
57194
  }
56084
- const filename = import_node_path19.default.basename(filePath);
57195
+ const filename = import_node_path20.default.basename(filePath);
56085
57196
  const created = await c.createArtifactFile(projectSlug, {
56086
57197
  class: artifactClass,
56087
57198
  contentType,
@@ -56164,7 +57275,7 @@ function createMrrlinTools(options) {
56164
57275
  "Unable to register local checkout.",
56165
57276
  async (_c, { projectSlug, path: checkoutPath, repo }) => {
56166
57277
  const trimmedPath = checkoutPath.trim();
56167
- if (!import_node_path19.default.isAbsolute(trimmedPath)) {
57278
+ if (!import_node_path20.default.isAbsolute(trimmedPath)) {
56168
57279
  throw new McpToolCodedError(
56169
57280
  "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
56170
57281
  `Path must be absolute, got: ${trimmedPath}`
@@ -56172,7 +57283,7 @@ function createMrrlinTools(options) {
56172
57283
  }
56173
57284
  let resolvedPath;
56174
57285
  try {
56175
- resolvedPath = (0, import_node_fs14.realpathSync)(trimmedPath);
57286
+ resolvedPath = (0, import_node_fs15.realpathSync)(trimmedPath);
56176
57287
  } catch {
56177
57288
  throw new McpToolCodedError(
56178
57289
  "LOCAL_CHECKOUT_PATH_NOT_FOUND",
@@ -56199,7 +57310,7 @@ function createMrrlinTools(options) {
56199
57310
  `Origin remote ${remoteUrl} does not match repo ${repo}.`
56200
57311
  );
56201
57312
  }
56202
- const stateDir = process.env.CODEX_HOME ? import_node_path19.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path19.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
57313
+ const stateDir = process.env.CODEX_HOME ? import_node_path20.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path20.default.join(import_node_os10.default.homedir(), ".mrrlin", "director-bridge");
56203
57314
  const registry3 = new CheckoutRegistry(stateDir);
56204
57315
  const confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
56205
57316
  registry3.confirm(projectSlug, resolvedPath, confirmedAt);
@@ -56421,8 +57532,8 @@ function runSetCredential(args) {
56421
57532
  }
56422
57533
 
56423
57534
  // src/install-service.ts
56424
- var import_node_os10 = __toESM(require("node:os"), 1);
56425
- var import_node_path20 = __toESM(require("node:path"), 1);
57535
+ var import_node_os11 = __toESM(require("node:os"), 1);
57536
+ var import_node_path21 = __toESM(require("node:path"), 1);
56426
57537
  function installService(deps) {
56427
57538
  if (!deps.hasSecret()) {
56428
57539
  deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
@@ -56433,7 +57544,7 @@ function installService(deps) {
56433
57544
  deps.log(resolved.reason);
56434
57545
  return { ok: false };
56435
57546
  }
56436
- const home = deps.env.HOME ?? import_node_os10.default.homedir();
57547
+ const home = deps.env.HOME ?? import_node_os11.default.homedir();
56437
57548
  const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
56438
57549
  if (bins.some((b) => !b)) {
56439
57550
  deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
@@ -56444,7 +57555,7 @@ function installService(deps) {
56444
57555
  return { ok: false };
56445
57556
  }
56446
57557
  const resolvedBins = bins.filter((b) => b !== null);
56447
- const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path20.default.dirname(b)))).join(":");
57558
+ const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path21.default.dirname(b)))).join(":");
56448
57559
  const text = renderEcosystemConfig({
56449
57560
  cwd: resolved.cwd,
56450
57561
  home,
@@ -56453,7 +57564,7 @@ function installService(deps) {
56453
57564
  staging: deps.env.MRRLIN_STAGING === "1",
56454
57565
  apiBaseUrl: deps.env.MRRLIN_API_BASE_URL?.trim() || void 0
56455
57566
  });
56456
- const ecoPath = import_node_path20.default.join(home, ".mrrlin", "ecosystem.config.cjs");
57567
+ const ecoPath = import_node_path21.default.join(home, ".mrrlin", "ecosystem.config.cjs");
56457
57568
  deps.writeFile(ecoPath, text);
56458
57569
  const start = deps.runPm2(["startOrReload", ecoPath]);
56459
57570
  if (start.code !== 0) {
@@ -56484,13 +57595,13 @@ function uninstallService(deps) {
56484
57595
 
56485
57596
  // src/uninstall-codex.ts
56486
57597
  var import_promises4 = __toESM(require("node:fs/promises"), 1);
56487
- var import_node_os11 = __toESM(require("node:os"), 1);
56488
- var import_node_path21 = __toESM(require("node:path"), 1);
57598
+ var import_node_os12 = __toESM(require("node:os"), 1);
57599
+ var import_node_path22 = __toESM(require("node:path"), 1);
56489
57600
  var toml2 = __toESM(require_toml(), 1);
56490
57601
  function resolveCodexHome2(options) {
56491
57602
  if (options.codexHome) return options.codexHome;
56492
57603
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
56493
- return import_node_path21.default.join(options.homeDir ?? import_node_os11.default.homedir(), ".codex");
57604
+ return import_node_path22.default.join(options.homeDir ?? import_node_os12.default.homedir(), ".codex");
56494
57605
  }
56495
57606
  async function pathExists3(target) {
56496
57607
  try {
@@ -56503,7 +57614,7 @@ async function pathExists3(target) {
56503
57614
  var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
56504
57615
  async function uninstallCodex(options = {}) {
56505
57616
  const codexHome = resolveCodexHome2(options);
56506
- const configPath = import_node_path21.default.join(codexHome, "config.toml");
57617
+ const configPath = import_node_path22.default.join(codexHome, "config.toml");
56507
57618
  const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
56508
57619
  if (!await pathExists3(configPath)) {
56509
57620
  return { action: "missing", configPath, prompts: await removePrompts() };
@@ -56531,10 +57642,10 @@ async function uninstallCodex(options = {}) {
56531
57642
  }
56532
57643
  async function uninstallPrompts(codexHome, names) {
56533
57644
  if (names.length === 0) return [];
56534
- const promptsDir = import_node_path21.default.join(codexHome, "prompts");
57645
+ const promptsDir = import_node_path22.default.join(codexHome, "prompts");
56535
57646
  const out = [];
56536
57647
  for (const name of names) {
56537
- const promptPath = import_node_path21.default.join(promptsDir, `${name}.md`);
57648
+ const promptPath = import_node_path22.default.join(promptsDir, `${name}.md`);
56538
57649
  try {
56539
57650
  await import_promises4.default.unlink(promptPath);
56540
57651
  out.push({ name, action: "removed", promptPath });
@@ -56787,8 +57898,8 @@ async function main() {
56787
57898
  }
56788
57899
  }
56789
57900
  try {
56790
- const codexHome = process.env.CODEX_HOME ?? import_node_path23.default.join(process.env.HOME ?? (0, import_node_os12.homedir)(), ".codex");
56791
- (0, import_node_fs15.rmSync)(import_node_path23.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
57901
+ const codexHome = process.env.CODEX_HOME ?? import_node_path24.default.join(process.env.HOME ?? (0, import_node_os13.homedir)(), ".codex");
57902
+ (0, import_node_fs16.rmSync)(import_node_path24.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
56792
57903
  } catch {
56793
57904
  }
56794
57905
  return;
@@ -56818,8 +57929,8 @@ async function main() {
56818
57929
  env: process.env,
56819
57930
  cwd: process.cwd(),
56820
57931
  writeFile: (p, c) => {
56821
- (0, import_node_fs15.mkdirSync)(import_node_path23.default.dirname(p), { recursive: true, mode: 448 });
56822
- (0, import_node_fs15.writeFileSync)(p, c, { mode: 384 });
57932
+ (0, import_node_fs16.mkdirSync)(import_node_path24.default.dirname(p), { recursive: true, mode: 448 });
57933
+ (0, import_node_fs16.writeFileSync)(p, c, { mode: 384 });
56823
57934
  },
56824
57935
  runPm2: pm2Runner,
56825
57936
  which: whichBin,
@@ -56836,35 +57947,35 @@ async function main() {
56836
57947
  runPm2: (a) => ({ code: pm2Runner(a).code }),
56837
57948
  removeFile: (p) => {
56838
57949
  try {
56839
- (0, import_node_fs15.rmSync)(p, { force: true });
57950
+ (0, import_node_fs16.rmSync)(p, { force: true });
56840
57951
  } catch {
56841
57952
  }
56842
57953
  },
56843
57954
  purgeSecret: purge,
56844
57955
  secretPath: agentCredentialPath(),
56845
57956
  tokenPath: operatorTokenPath(),
56846
- ecoPath: import_node_path23.default.join(process.env.HOME ?? (0, import_node_os12.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
57957
+ ecoPath: import_node_path24.default.join(process.env.HOME ?? (0, import_node_os13.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
56847
57958
  log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
56848
57959
  `)
56849
57960
  });
56850
57961
  return;
56851
57962
  }
56852
57963
  case "uninstall": {
56853
- const home = process.env.HOME ?? (0, import_node_os12.homedir)();
57964
+ const home = process.env.HOME ?? (0, import_node_os13.homedir)();
56854
57965
  const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
56855
57966
  `);
56856
57967
  uninstallService({
56857
57968
  runPm2: (a) => ({ code: pm2Runner(a).code }),
56858
57969
  removeFile: (p) => {
56859
57970
  try {
56860
- (0, import_node_fs15.rmSync)(p, { force: true });
57971
+ (0, import_node_fs16.rmSync)(p, { force: true });
56861
57972
  } catch {
56862
57973
  }
56863
57974
  },
56864
57975
  purgeSecret: true,
56865
57976
  secretPath: agentCredentialPath(),
56866
57977
  tokenPath: operatorTokenPath(),
56867
- ecoPath: import_node_path23.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
57978
+ ecoPath: import_node_path24.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
56868
57979
  log
56869
57980
  });
56870
57981
  let codexOk = true;
@@ -56884,7 +57995,7 @@ async function main() {
56884
57995
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
56885
57996
  }
56886
57997
  try {
56887
- (0, import_node_fs15.rmSync)(import_node_path23.default.join(home, ".mrrlin"), { recursive: true, force: true });
57998
+ (0, import_node_fs16.rmSync)(import_node_path24.default.join(home, ".mrrlin"), { recursive: true, force: true });
56888
57999
  } catch {
56889
58000
  }
56890
58001
  log("removed ~/.mrrlin");
@@ -56925,7 +58036,7 @@ ${HELP_TEXT}`);
56925
58036
  }
56926
58037
  }
56927
58038
  function resolveSelfBinPath() {
56928
- return import_node_path22.default.resolve(process.argv[1] ?? process.execPath);
58039
+ return import_node_path23.default.resolve(process.argv[1] ?? process.execPath);
56929
58040
  }
56930
58041
  main().catch((error51) => {
56931
58042
  process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}