@remixhq/claude-plugin 0.1.24 → 0.1.26

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.
@@ -38,7 +38,7 @@ var require_windows = __commonJS({
38
38
  module2.exports = isexe;
39
39
  isexe.sync = sync;
40
40
  var fs11 = require("fs");
41
- function checkPathExt(path17, options) {
41
+ function checkPathExt(path18, options) {
42
42
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
43
43
  if (!pathext) {
44
44
  return true;
@@ -49,25 +49,25 @@ var require_windows = __commonJS({
49
49
  }
50
50
  for (var i2 = 0; i2 < pathext.length; i2++) {
51
51
  var p = pathext[i2].toLowerCase();
52
- if (p && path17.substr(-p.length).toLowerCase() === p) {
52
+ if (p && path18.substr(-p.length).toLowerCase() === p) {
53
53
  return true;
54
54
  }
55
55
  }
56
56
  return false;
57
57
  }
58
- function checkStat(stat, path17, options) {
58
+ function checkStat(stat, path18, options) {
59
59
  if (!stat.isSymbolicLink() && !stat.isFile()) {
60
60
  return false;
61
61
  }
62
- return checkPathExt(path17, options);
62
+ return checkPathExt(path18, options);
63
63
  }
64
- function isexe(path17, options, cb) {
65
- fs11.stat(path17, function(er, stat) {
66
- cb(er, er ? false : checkStat(stat, path17, options));
64
+ function isexe(path18, options, cb) {
65
+ fs11.stat(path18, function(er, stat) {
66
+ cb(er, er ? false : checkStat(stat, path18, options));
67
67
  });
68
68
  }
69
- function sync(path17, options) {
70
- return checkStat(fs11.statSync(path17), path17, options);
69
+ function sync(path18, options) {
70
+ return checkStat(fs11.statSync(path18), path18, options);
71
71
  }
72
72
  }
73
73
  });
@@ -79,13 +79,13 @@ var require_mode = __commonJS({
79
79
  module2.exports = isexe;
80
80
  isexe.sync = sync;
81
81
  var fs11 = require("fs");
82
- function isexe(path17, options, cb) {
83
- fs11.stat(path17, function(er, stat) {
82
+ function isexe(path18, options, cb) {
83
+ fs11.stat(path18, function(er, stat) {
84
84
  cb(er, er ? false : checkStat(stat, options));
85
85
  });
86
86
  }
87
- function sync(path17, options) {
88
- return checkStat(fs11.statSync(path17), options);
87
+ function sync(path18, options) {
88
+ return checkStat(fs11.statSync(path18), options);
89
89
  }
90
90
  function checkStat(stat, options) {
91
91
  return stat.isFile() && checkMode(stat, options);
@@ -119,7 +119,7 @@ var require_isexe = __commonJS({
119
119
  }
120
120
  module2.exports = isexe;
121
121
  isexe.sync = sync;
122
- function isexe(path17, options, cb) {
122
+ function isexe(path18, options, cb) {
123
123
  if (typeof options === "function") {
124
124
  cb = options;
125
125
  options = {};
@@ -129,7 +129,7 @@ var require_isexe = __commonJS({
129
129
  throw new TypeError("callback not provided");
130
130
  }
131
131
  return new Promise(function(resolve, reject) {
132
- isexe(path17, options || {}, function(er, is) {
132
+ isexe(path18, options || {}, function(er, is) {
133
133
  if (er) {
134
134
  reject(er);
135
135
  } else {
@@ -138,7 +138,7 @@ var require_isexe = __commonJS({
138
138
  });
139
139
  });
140
140
  }
141
- core(path17, options || {}, function(er, is) {
141
+ core(path18, options || {}, function(er, is) {
142
142
  if (er) {
143
143
  if (er.code === "EACCES" || options && options.ignoreErrors) {
144
144
  er = null;
@@ -148,9 +148,9 @@ var require_isexe = __commonJS({
148
148
  cb(er, is);
149
149
  });
150
150
  }
151
- function sync(path17, options) {
151
+ function sync(path18, options) {
152
152
  try {
153
- return core.sync(path17, options || {});
153
+ return core.sync(path18, options || {});
154
154
  } catch (er) {
155
155
  if (options && options.ignoreErrors || er.code === "EACCES") {
156
156
  return false;
@@ -167,7 +167,7 @@ var require_which = __commonJS({
167
167
  "node_modules/which/which.js"(exports2, module2) {
168
168
  "use strict";
169
169
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
170
- var path17 = require("path");
170
+ var path18 = require("path");
171
171
  var COLON = isWindows ? ";" : ":";
172
172
  var isexe = require_isexe();
173
173
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -205,7 +205,7 @@ var require_which = __commonJS({
205
205
  return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
206
206
  const ppRaw = pathEnv[i2];
207
207
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
208
- const pCmd = path17.join(pathPart, cmd);
208
+ const pCmd = path18.join(pathPart, cmd);
209
209
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
210
210
  resolve(subStep(p, i2, 0));
211
211
  });
@@ -232,7 +232,7 @@ var require_which = __commonJS({
232
232
  for (let i2 = 0; i2 < pathEnv.length; i2++) {
233
233
  const ppRaw = pathEnv[i2];
234
234
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
235
- const pCmd = path17.join(pathPart, cmd);
235
+ const pCmd = path18.join(pathPart, cmd);
236
236
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
237
237
  for (let j = 0; j < pathExt.length; j++) {
238
238
  const cur = p + pathExt[j];
@@ -280,7 +280,7 @@ var require_path_key = __commonJS({
280
280
  var require_resolveCommand = __commonJS({
281
281
  "node_modules/cross-spawn/lib/util/resolveCommand.js"(exports2, module2) {
282
282
  "use strict";
283
- var path17 = require("path");
283
+ var path18 = require("path");
284
284
  var which = require_which();
285
285
  var getPathKey = require_path_key();
286
286
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -298,7 +298,7 @@ var require_resolveCommand = __commonJS({
298
298
  try {
299
299
  resolved = which.sync(parsed.command, {
300
300
  path: env[getPathKey({ env })],
301
- pathExt: withoutPathExt ? path17.delimiter : void 0
301
+ pathExt: withoutPathExt ? path18.delimiter : void 0
302
302
  });
303
303
  } catch (e) {
304
304
  } finally {
@@ -307,7 +307,7 @@ var require_resolveCommand = __commonJS({
307
307
  }
308
308
  }
309
309
  if (resolved) {
310
- resolved = path17.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
310
+ resolved = path18.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
311
311
  }
312
312
  return resolved;
313
313
  }
@@ -361,8 +361,8 @@ var require_shebang_command = __commonJS({
361
361
  if (!match) {
362
362
  return null;
363
363
  }
364
- const [path17, argument] = match[0].replace(/#! ?/, "").split(" ");
365
- const binary = path17.split("/").pop();
364
+ const [path18, argument] = match[0].replace(/#! ?/, "").split(" ");
365
+ const binary = path18.split("/").pop();
366
366
  if (binary === "env") {
367
367
  return argument;
368
368
  }
@@ -397,7 +397,7 @@ var require_readShebang = __commonJS({
397
397
  var require_parse = __commonJS({
398
398
  "node_modules/cross-spawn/lib/parse.js"(exports2, module2) {
399
399
  "use strict";
400
- var path17 = require("path");
400
+ var path18 = require("path");
401
401
  var resolveCommand = require_resolveCommand();
402
402
  var escape = require_escape();
403
403
  var readShebang = require_readShebang();
@@ -422,7 +422,7 @@ var require_parse = __commonJS({
422
422
  const needsShell = !isExecutableRegExp.test(commandFile);
423
423
  if (parsed.options.forceShell || needsShell) {
424
424
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
425
- parsed.command = path17.normalize(parsed.command);
425
+ parsed.command = path18.normalize(parsed.command);
426
426
  parsed.command = escape.command(parsed.command);
427
427
  parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
428
428
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -540,7 +540,7 @@ __export(hook_user_prompt_exports, {
540
540
  module.exports = __toCommonJS(hook_user_prompt_exports);
541
541
  var import_node_child_process8 = require("child_process");
542
542
  var import_node_fs7 = require("fs");
543
- var import_node_path13 = __toESM(require("path"), 1);
543
+ var import_node_path14 = __toESM(require("path"), 1);
544
544
 
545
545
  // node_modules/@remixhq/core/dist/chunk-7XJGOKEO.js
546
546
  var RemixError = class extends Error {
@@ -4943,13 +4943,13 @@ var logOutputSync = ({ serializedResult, fdNumber, state, verboseInfo, encoding,
4943
4943
  }
4944
4944
  };
4945
4945
  var writeToFiles = (serializedResult, stdioItems, outputFiles) => {
4946
- for (const { path: path17, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) {
4947
- const pathString = typeof path17 === "string" ? path17 : path17.toString();
4946
+ for (const { path: path18, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) {
4947
+ const pathString = typeof path18 === "string" ? path18 : path18.toString();
4948
4948
  if (append || outputFiles.has(pathString)) {
4949
- (0, import_node_fs4.appendFileSync)(path17, serializedResult);
4949
+ (0, import_node_fs4.appendFileSync)(path18, serializedResult);
4950
4950
  } else {
4951
4951
  outputFiles.add(pathString);
4952
- (0, import_node_fs4.writeFileSync)(path17, serializedResult);
4952
+ (0, import_node_fs4.writeFileSync)(path18, serializedResult);
4953
4953
  }
4954
4954
  }
4955
4955
  };
@@ -7668,6 +7668,21 @@ async function writeCollabBinding(repoRoot, binding) {
7668
7668
  return filePath;
7669
7669
  }
7670
7670
 
7671
+ // src/collab-init-spawn-lock.ts
7672
+ var import_node_crypto = require("crypto");
7673
+ var import_node_os4 = __toESM(require("os"), 1);
7674
+ var import_node_path6 = __toESM(require("path"), 1);
7675
+ function stateRoot() {
7676
+ const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();
7677
+ return configured || import_node_path6.default.join(import_node_os4.default.tmpdir(), "remix-claude-plugin-hooks");
7678
+ }
7679
+ function sha256Hex(value) {
7680
+ return (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
7681
+ }
7682
+ function collabInitSpawnLockPath(repoRoot) {
7683
+ return import_node_path6.default.join(stateRoot(), "collab-init-spawn-locks", `${sha256Hex(repoRoot)}.json`);
7684
+ }
7685
+
7671
7686
  // src/history-routing.ts
7672
7687
  var STRONG_MEMORY_FIRST_PATTERNS = [
7673
7688
  /\bwhy\b/i,
@@ -7773,25 +7788,25 @@ function buildPromptRoutingAdvisory(intent) {
7773
7788
 
7774
7789
  // src/deferred-turn-queue.ts
7775
7790
  var import_promises14 = __toESM(require("fs/promises"), 1);
7776
- var import_node_os4 = __toESM(require("os"), 1);
7777
- var import_node_path6 = __toESM(require("path"), 1);
7791
+ var import_node_os5 = __toESM(require("os"), 1);
7792
+ var import_node_path7 = __toESM(require("path"), 1);
7778
7793
  var DEFERRED_TURN_SCHEMA_VERSION = 1;
7779
7794
  var DEFERRED_TURN_MAX_ATTEMPTS = 10;
7780
7795
  var DEFERRED_TURN_TTL_MS = 24 * 60 * 60 * 1e3;
7781
7796
  var DEFERRED_TURN_DIR = "deferred-turns";
7782
- function stateRoot() {
7797
+ function stateRoot2() {
7783
7798
  const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();
7784
- return configured || import_node_path6.default.join(import_node_os4.default.tmpdir(), "remix-claude-plugin-hooks");
7799
+ return configured || import_node_path7.default.join(import_node_os5.default.tmpdir(), "remix-claude-plugin-hooks");
7785
7800
  }
7786
7801
  function getDeferredTurnDirPath() {
7787
- return import_node_path6.default.join(stateRoot(), DEFERRED_TURN_DIR);
7802
+ return import_node_path7.default.join(stateRoot2(), DEFERRED_TURN_DIR);
7788
7803
  }
7789
7804
  function deferredTurnFileName(sessionId, turnId) {
7790
7805
  const safe = (s) => s.replace(/[^A-Za-z0-9_-]/g, "_");
7791
7806
  return `${safe(sessionId)}-${safe(turnId)}.json`;
7792
7807
  }
7793
7808
  function getDeferredTurnFilePath(sessionId, turnId) {
7794
- return import_node_path6.default.join(getDeferredTurnDirPath(), deferredTurnFileName(sessionId, turnId));
7809
+ return import_node_path7.default.join(getDeferredTurnDirPath(), deferredTurnFileName(sessionId, turnId));
7795
7810
  }
7796
7811
  async function writeDeferredTurn(record) {
7797
7812
  if (record.schemaVersion !== DEFERRED_TURN_SCHEMA_VERSION) {
@@ -7852,7 +7867,7 @@ async function listDeferredTurnsForRepo(repoRoot) {
7852
7867
  const entries = [];
7853
7868
  for (const entry of dirEntries) {
7854
7869
  if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
7855
- const filePath = import_node_path6.default.join(dir, entry.name);
7870
+ const filePath = import_node_path7.default.join(dir, entry.name);
7856
7871
  const record = await readDeferredTurnFile(filePath);
7857
7872
  if (!record) continue;
7858
7873
  if (record.repoRoot !== repoRoot) continue;
@@ -7876,7 +7891,7 @@ async function pruneStaleDeferredTurns(maxAgeMs = DEFERRED_TURN_TTL_MS) {
7876
7891
  const now = Date.now();
7877
7892
  for (const entry of dirEntries) {
7878
7893
  if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
7879
- const filePath = import_node_path6.default.join(dir, entry.name);
7894
+ const filePath = import_node_path7.default.join(dir, entry.name);
7880
7895
  const record = await readDeferredTurnFile(filePath);
7881
7896
  if (!record) {
7882
7897
  const stat = await import_promises14.default.stat(filePath).catch(() => null);
@@ -7912,8 +7927,8 @@ async function recordDeferredTurnFailedAttempt(filePath) {
7912
7927
 
7913
7928
  // src/deferred-turn-drainer.ts
7914
7929
  var import_promises23 = __toESM(require("fs/promises"), 1);
7915
- var import_node_path11 = __toESM(require("path"), 1);
7916
- var import_node_crypto3 = require("crypto");
7930
+ var import_node_path12 = __toESM(require("path"), 1);
7931
+ var import_node_crypto5 = require("crypto");
7917
7932
 
7918
7933
  // node_modules/@remixhq/core/dist/collab.js
7919
7934
  var import_promises15 = __toESM(require("fs/promises"), 1);
@@ -8015,7 +8030,7 @@ function buildBranchMismatchHint(params) {
8015
8030
  `Switch to ${describeBranch(params.branchName)} or rerun with ${overrideFlag} if this is intentional.`
8016
8031
  ].join("\n");
8017
8032
  }
8018
- function sha256Hex(value) {
8033
+ function sha256Hex2(value) {
8019
8034
  return (0, import_crypto.createHash)("sha256").update(value).digest("hex");
8020
8035
  }
8021
8036
  function getCollabStateRoot() {
@@ -8029,7 +8044,7 @@ function buildLaneStateKey(params) {
8029
8044
  const stableSource = repoRoot || "unknown-repo-root";
8030
8045
  const fingerprintSource = fingerprint || "unknown-repo-fingerprint";
8031
8046
  const laneSource = laneId || "unknown-lane";
8032
- return sha256Hex(`${stableSource}::${fingerprintSource}::${laneSource}`);
8047
+ return sha256Hex2(`${stableSource}::${fingerprintSource}::${laneSource}`);
8033
8048
  }
8034
8049
  function getSnapshotsRoot() {
8035
8050
  return import_path3.default.join(getCollabStateRoot(), "snapshots");
@@ -8230,7 +8245,7 @@ async function writeLocalBaseline(baseline) {
8230
8245
  await writeJsonAtomic(getBaselinePath(baseline), normalized);
8231
8246
  return normalized;
8232
8247
  }
8233
- function sha256Hex2(value) {
8248
+ function sha256Hex22(value) {
8234
8249
  return (0, import_crypto2.createHash)("sha256").update(value).digest("hex");
8235
8250
  }
8236
8251
  function getSnapshotRecordPath(snapshotId) {
@@ -8281,7 +8296,7 @@ async function persistBlob(blobHash, content) {
8281
8296
  }
8282
8297
  function buildSnapshotHash(files) {
8283
8298
  const manifest = files.map((file) => `${file.path} ${file.mode} ${file.blobHash} ${file.size}`).join("\n");
8284
- return sha256Hex2(manifest);
8299
+ return sha256Hex22(manifest);
8285
8300
  }
8286
8301
  async function inspectLocalSnapshot(params) {
8287
8302
  const repoRoot = params.repoRoot;
@@ -8292,7 +8307,7 @@ async function inspectLocalSnapshot(params) {
8292
8307
  const stat = await import_promises17.default.lstat(absolutePath);
8293
8308
  if (stat.isSymbolicLink()) {
8294
8309
  const linkTarget = await import_promises17.default.readlink(absolutePath);
8295
- const blobHash2 = sha256Hex2(`symlink:${linkTarget}`);
8310
+ const blobHash2 = sha256Hex22(`symlink:${linkTarget}`);
8296
8311
  if (params.persistBlobs !== false) {
8297
8312
  await persistBlob(blobHash2, linkTarget);
8298
8313
  }
@@ -8305,7 +8320,7 @@ async function inspectLocalSnapshot(params) {
8305
8320
  continue;
8306
8321
  }
8307
8322
  const content = await import_promises17.default.readFile(absolutePath);
8308
- const blobHash = sha256Hex2(content);
8323
+ const blobHash = sha256Hex22(content);
8309
8324
  if (params.persistBlobs !== false) {
8310
8325
  await persistBlob(blobHash, content);
8311
8326
  }
@@ -8409,7 +8424,7 @@ async function diffLocalSnapshots(params) {
8409
8424
  baseSnapshotId: params.baseSnapshotId,
8410
8425
  targetSnapshotId: params.targetSnapshotId,
8411
8426
  diff,
8412
- diffSha256: diff ? sha256Hex2(diff) : null,
8427
+ diffSha256: diff ? sha256Hex22(diff) : null,
8413
8428
  changedPaths,
8414
8429
  stats: summarizeUnifiedDiff(diff)
8415
8430
  };
@@ -10420,15 +10435,17 @@ function isFinalizePreflightFailureCode(value) {
10420
10435
 
10421
10436
  // src/auto-fix-dispatcher.ts
10422
10437
  var import_node_child_process6 = require("child_process");
10438
+ var import_node_crypto4 = require("crypto");
10423
10439
  var import_node_fs6 = require("fs");
10424
- var import_node_path10 = __toESM(require("path"), 1);
10440
+ var import_node_os8 = __toESM(require("os"), 1);
10441
+ var import_node_path11 = __toESM(require("path"), 1);
10425
10442
 
10426
10443
  // src/finalize-failure-marker.ts
10427
10444
  var import_promises19 = __toESM(require("fs/promises"), 1);
10428
- var import_node_path7 = __toESM(require("path"), 1);
10429
- var FINALIZE_FAILURE_MARKER_REL = import_node_path7.default.join(".remix", ".last-finalize-failure.json");
10445
+ var import_node_path8 = __toESM(require("path"), 1);
10446
+ var FINALIZE_FAILURE_MARKER_REL = import_node_path8.default.join(".remix", ".last-finalize-failure.json");
10430
10447
  function markerPath(repoRoot) {
10431
- return import_node_path7.default.join(repoRoot, FINALIZE_FAILURE_MARKER_REL);
10448
+ return import_node_path8.default.join(repoRoot, FINALIZE_FAILURE_MARKER_REL);
10432
10449
  }
10433
10450
  async function readFinalizeFailureMarker(repoRoot) {
10434
10451
  const raw = await import_promises19.default.readFile(markerPath(repoRoot), "utf8").catch(() => null);
@@ -10445,7 +10462,7 @@ async function readFinalizeFailureMarker(repoRoot) {
10445
10462
  }
10446
10463
  async function writeFinalizeFailureMarker(marker) {
10447
10464
  const filePath = markerPath(marker.repoRoot);
10448
- await import_promises19.default.mkdir(import_node_path7.default.dirname(filePath), { recursive: true });
10465
+ await import_promises19.default.mkdir(import_node_path8.default.dirname(filePath), { recursive: true });
10449
10466
  const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
10450
10467
  await import_promises19.default.writeFile(tmpPath, JSON.stringify(marker, null, 2), "utf8");
10451
10468
  await import_promises19.default.rename(tmpPath, filePath);
@@ -10471,31 +10488,31 @@ function buildFreshFailureMarker(params) {
10471
10488
  }
10472
10489
 
10473
10490
  // src/hook-diagnostics.ts
10474
- var import_node_crypto2 = require("crypto");
10491
+ var import_node_crypto3 = require("crypto");
10475
10492
  var import_promises21 = __toESM(require("fs/promises"), 1);
10476
- var import_node_os6 = __toESM(require("os"), 1);
10477
- var import_node_path9 = __toESM(require("path"), 1);
10493
+ var import_node_os7 = __toESM(require("os"), 1);
10494
+ var import_node_path10 = __toESM(require("path"), 1);
10478
10495
 
10479
10496
  // src/hook-state.ts
10480
10497
  var import_promises20 = __toESM(require("fs/promises"), 1);
10481
- var import_node_os5 = __toESM(require("os"), 1);
10482
- var import_node_path8 = __toESM(require("path"), 1);
10483
- var import_node_crypto = require("crypto");
10484
- function stateRoot2() {
10498
+ var import_node_os6 = __toESM(require("os"), 1);
10499
+ var import_node_path9 = __toESM(require("path"), 1);
10500
+ var import_node_crypto2 = require("crypto");
10501
+ function stateRoot3() {
10485
10502
  const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();
10486
- return configured || import_node_path8.default.join(import_node_os5.default.tmpdir(), "remix-claude-plugin-hooks");
10503
+ return configured || import_node_path9.default.join(import_node_os6.default.tmpdir(), "remix-claude-plugin-hooks");
10487
10504
  }
10488
10505
  function statePath(sessionId) {
10489
- return import_node_path8.default.join(stateRoot2(), `${sessionId}.json`);
10506
+ return import_node_path9.default.join(stateRoot3(), `${sessionId}.json`);
10490
10507
  }
10491
10508
  function stateLockPath(sessionId) {
10492
- return import_node_path8.default.join(stateRoot2(), `${sessionId}.lock`);
10509
+ return import_node_path9.default.join(stateRoot3(), `${sessionId}.lock`);
10493
10510
  }
10494
10511
  function stateLockMetaPath(sessionId) {
10495
- return import_node_path8.default.join(stateLockPath(sessionId), "owner.json");
10512
+ return import_node_path9.default.join(stateLockPath(sessionId), "owner.json");
10496
10513
  }
10497
10514
  async function writeJsonAtomic2(filePath, value) {
10498
- await import_promises20.default.mkdir(import_node_path8.default.dirname(filePath), { recursive: true });
10515
+ await import_promises20.default.mkdir(import_node_path9.default.dirname(filePath), { recursive: true });
10499
10516
  const tmpPath = `${filePath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
10500
10517
  await import_promises20.default.writeFile(tmpPath, JSON.stringify(value, null, 2) + "\n", "utf8");
10501
10518
  await import_promises20.default.rename(tmpPath, filePath);
@@ -10548,11 +10565,11 @@ async function tryRemoveStaleStateLock(sessionId) {
10548
10565
  async function acquireStateLock(sessionId) {
10549
10566
  const lockPath = stateLockPath(sessionId);
10550
10567
  const deadline = Date.now() + STATE_LOCK_WAIT_MS;
10551
- await import_promises20.default.mkdir(stateRoot2(), { recursive: true });
10568
+ await import_promises20.default.mkdir(stateRoot3(), { recursive: true });
10552
10569
  while (true) {
10553
10570
  try {
10554
10571
  await import_promises20.default.mkdir(lockPath);
10555
- const ownerId = (0, import_node_crypto.randomUUID)();
10572
+ const ownerId = (0, import_node_crypto2.randomUUID)();
10556
10573
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
10557
10574
  const metadata = {
10558
10575
  ownerId,
@@ -10609,7 +10626,7 @@ async function createPendingTurnState(params) {
10609
10626
  return withStateLock(params.sessionId, async () => {
10610
10627
  const state = {
10611
10628
  sessionId: params.sessionId,
10612
- turnId: (0, import_node_crypto.randomUUID)(),
10629
+ turnId: (0, import_node_crypto2.randomUUID)(),
10613
10630
  prompt: params.prompt,
10614
10631
  initialCwd: params.initialCwd?.trim() || null,
10615
10632
  intent: params.intent,
@@ -10628,7 +10645,7 @@ async function createPendingTurnState(params) {
10628
10645
  // package.json
10629
10646
  var package_default = {
10630
10647
  name: "@remixhq/claude-plugin",
10631
- version: "0.1.24",
10648
+ version: "0.1.26",
10632
10649
  description: "Claude Code plugin for Remix collaboration workflows",
10633
10650
  homepage: "https://github.com/RemixDotOne/remix-claude-plugin",
10634
10651
  license: "MIT",
@@ -10666,8 +10683,8 @@ var package_default = {
10666
10683
  prepack: "npm run build"
10667
10684
  },
10668
10685
  dependencies: {
10669
- "@remixhq/core": "^0.1.19",
10670
- "@remixhq/mcp": "^0.1.19"
10686
+ "@remixhq/core": "^0.1.21",
10687
+ "@remixhq/mcp": "^0.1.21"
10671
10688
  },
10672
10689
  devDependencies: {
10673
10690
  "@types/node": "^25.4.0",
@@ -10690,17 +10707,17 @@ var pluginMetadata = {
10690
10707
  var MAX_LOG_BYTES = 512 * 1024;
10691
10708
  function resolveClaudeRoot() {
10692
10709
  const configured = process.env.CLAUDE_CONFIG_DIR?.trim();
10693
- return configured || import_node_path9.default.join(import_node_os6.default.homedir(), ".claude");
10710
+ return configured || import_node_path10.default.join(import_node_os7.default.homedir(), ".claude");
10694
10711
  }
10695
10712
  function resolvePluginDataDirName() {
10696
10713
  return `${pluginMetadata.pluginId}-${pluginMetadata.pluginId}`;
10697
10714
  }
10698
10715
  function getHookDiagnosticsDirPath() {
10699
10716
  const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_DIAGNOSTICS_DIR?.trim();
10700
- return configured || import_node_path9.default.join(resolveClaudeRoot(), "plugins", "data", resolvePluginDataDirName());
10717
+ return configured || import_node_path10.default.join(resolveClaudeRoot(), "plugins", "data", resolvePluginDataDirName());
10701
10718
  }
10702
10719
  function getHookDiagnosticsLogPath() {
10703
- return import_node_path9.default.join(getHookDiagnosticsDirPath(), "hooks.ndjson");
10720
+ return import_node_path10.default.join(getHookDiagnosticsDirPath(), "hooks.ndjson");
10704
10721
  }
10705
10722
  function toFieldValue(value) {
10706
10723
  if (value === null) return null;
@@ -10738,13 +10755,13 @@ function summarizeText(value) {
10738
10755
  return {
10739
10756
  present: true,
10740
10757
  length: trimmed.length,
10741
- sha256Prefix: (0, import_node_crypto2.createHash)("sha256").update(trimmed).digest("hex").slice(0, 12)
10758
+ sha256Prefix: (0, import_node_crypto3.createHash)("sha256").update(trimmed).digest("hex").slice(0, 12)
10742
10759
  };
10743
10760
  }
10744
10761
  async function appendHookDiagnosticsEvent(params) {
10745
10762
  try {
10746
10763
  const logPath = getHookDiagnosticsLogPath();
10747
- await import_promises21.default.mkdir(import_node_path9.default.dirname(logPath), { recursive: true });
10764
+ await import_promises21.default.mkdir(import_node_path10.default.dirname(logPath), { recursive: true });
10748
10765
  await rotateLogIfNeeded(logPath);
10749
10766
  const event = {
10750
10767
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -10791,18 +10808,27 @@ var RECOMMENDED_USER_COMMAND = {
10791
10808
  pull_required: "remix collab sync",
10792
10809
  baseline_missing: "remix collab init"
10793
10810
  };
10794
- var SPAWN_LOCK_REL = (cmdSlug) => import_node_path10.default.join(".remix", `.${cmdSlug}-spawning`);
10795
- var SPAWN_LOG_REL = (cmdSlug) => import_node_path10.default.join(".remix", `${cmdSlug}.log`);
10796
10811
  var SPAWN_THROTTLE_MS = 5 * 60 * 1e3;
10797
10812
  function commandSlug(args) {
10798
10813
  return args.join("-").replace(/[^a-zA-Z0-9_-]/g, "_");
10799
10814
  }
10815
+ function stateRoot4() {
10816
+ const configured = process.env.REMIX_CLAUDE_PLUGIN_HOOK_STATE_ROOT?.trim();
10817
+ return configured || import_node_path11.default.join(import_node_os8.default.tmpdir(), "remix-claude-plugin-hooks");
10818
+ }
10819
+ function sha256Hex3(value) {
10820
+ return (0, import_node_crypto4.createHash)("sha256").update(value).digest("hex");
10821
+ }
10822
+ function spawnLockPath(repoRoot, cmdSlug) {
10823
+ if (cmdSlug === "collab-init") {
10824
+ return collabInitSpawnLockPath(repoRoot);
10825
+ }
10826
+ return import_node_path11.default.join(stateRoot4(), "auto-fix-spawn-locks", sha256Hex3(repoRoot), `${cmdSlug}.lock`);
10827
+ }
10800
10828
  function spawnFixDetached(repoRoot, args) {
10801
10829
  const slug = commandSlug(args);
10802
10830
  const command = `remix ${args.join(" ")}`;
10803
- const remixDir = import_node_path10.default.join(repoRoot, ".remix");
10804
- const lockPath = import_node_path10.default.join(repoRoot, SPAWN_LOCK_REL(slug));
10805
- const logPath = import_node_path10.default.join(repoRoot, SPAWN_LOG_REL(slug));
10831
+ const lockPath = spawnLockPath(repoRoot, slug);
10806
10832
  try {
10807
10833
  if ((0, import_node_fs6.existsSync)(lockPath)) {
10808
10834
  const ageMs = Date.now() - (0, import_node_fs6.statSync)(lockPath).mtimeMs;
@@ -10813,27 +10839,14 @@ function spawnFixDetached(repoRoot, args) {
10813
10839
  } catch {
10814
10840
  }
10815
10841
  try {
10816
- (0, import_node_fs6.mkdirSync)(remixDir, { recursive: true });
10842
+ (0, import_node_fs6.mkdirSync)(import_node_path11.default.dirname(lockPath), { recursive: true });
10817
10843
  } catch {
10818
10844
  }
10819
- let out;
10820
- let err;
10821
- try {
10822
- out = (0, import_node_fs6.openSync)(logPath, "a");
10823
- err = (0, import_node_fs6.openSync)(logPath, "a");
10824
- } catch (logErr) {
10825
- return {
10826
- kind: "spawn_failed",
10827
- command,
10828
- reason: "log_open_failed",
10829
- message: logErr instanceof Error ? logErr.message : String(logErr)
10830
- };
10831
- }
10832
10845
  try {
10833
10846
  const child = (0, import_node_child_process6.spawn)("remix", [...args], {
10834
10847
  cwd: repoRoot,
10835
10848
  detached: true,
10836
- stdio: ["ignore", out, err],
10849
+ stdio: "ignore",
10837
10850
  env: { ...process.env, REMIX_AUTO_FIX_SPAWN: "1" }
10838
10851
  });
10839
10852
  child.unref();
@@ -10842,7 +10855,7 @@ function spawnFixDetached(repoRoot, args) {
10842
10855
  (0, import_node_fs6.utimesSync)(lockPath, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
10843
10856
  } catch {
10844
10857
  }
10845
- return { kind: "spawned", command, pid: child.pid, logPath };
10858
+ return { kind: "spawned", command, pid: child.pid };
10846
10859
  } catch (spawnErr) {
10847
10860
  return {
10848
10861
  kind: "spawn_failed",
@@ -10898,7 +10911,6 @@ async function dispatchFinalizeFailure(input) {
10898
10911
  preflightCode: input.preflightCode,
10899
10912
  command: "command" in outcome ? outcome.command : null,
10900
10913
  pid: outcome.kind === "spawned" ? outcome.pid ?? null : null,
10901
- logPath: outcome.kind === "spawned" ? outcome.logPath : null,
10902
10914
  recommendedCommand
10903
10915
  },
10904
10916
  message: outcome.kind === "spawn_failed" ? outcome.message : null
@@ -10911,7 +10923,7 @@ function mergeOutcomeIntoMarker(existing, outcome) {
10911
10923
  status: "in_progress",
10912
10924
  command: outcome.command,
10913
10925
  pid: outcome.pid ?? null,
10914
- logPath: outcome.logPath,
10926
+ logPath: null,
10915
10927
  attemptedAt: (/* @__PURE__ */ new Date()).toISOString(),
10916
10928
  failureMessage: null
10917
10929
  };
@@ -10939,7 +10951,7 @@ function mergeOutcomeIntoMarker(existing, outcome) {
10939
10951
  return existing;
10940
10952
  }
10941
10953
 
10942
- // node_modules/@remixhq/core/dist/chunk-C2FOZ3O7.js
10954
+ // node_modules/@remixhq/core/dist/chunk-YENZA6QR.js
10943
10955
  async function readJsonSafe(res) {
10944
10956
  const ct = res.headers.get("content-type") ?? "";
10945
10957
  if (!ct.toLowerCase().includes("application/json")) return null;
@@ -10958,7 +10970,7 @@ function createApiClient(config, opts) {
10958
10970
  const ms = typeof timeoutMs === "number" && timeoutMs > 0 ? timeoutMs : defaultTimeoutMs;
10959
10971
  return ms != null ? AbortSignal.timeout(ms) : void 0;
10960
10972
  }
10961
- async function request(path17, init, opts2) {
10973
+ async function request(path18, init, opts2) {
10962
10974
  if (!tokenProvider) {
10963
10975
  throw new RemixError("API client is missing a token provider.", {
10964
10976
  exitCode: 1,
@@ -10966,7 +10978,7 @@ function createApiClient(config, opts) {
10966
10978
  });
10967
10979
  }
10968
10980
  const auth = await tokenProvider();
10969
- const url = new URL(path17, config.apiUrl).toString();
10981
+ const url = new URL(path18, config.apiUrl).toString();
10970
10982
  const doFetch = async (bearer) => fetch(url, {
10971
10983
  ...init,
10972
10984
  signal: makeTimeoutSignal(opts2?.timeoutMs),
@@ -10995,7 +11007,7 @@ function createApiClient(config, opts) {
10995
11007
  const json = await readJsonSafe(res);
10996
11008
  return json ?? null;
10997
11009
  }
10998
- async function requestBinary(path17, init, opts2) {
11010
+ async function requestBinary(path18, init, opts2) {
10999
11011
  if (!tokenProvider) {
11000
11012
  throw new RemixError("API client is missing a token provider.", {
11001
11013
  exitCode: 1,
@@ -11003,7 +11015,7 @@ function createApiClient(config, opts) {
11003
11015
  });
11004
11016
  }
11005
11017
  const auth = await tokenProvider();
11006
- const url = new URL(path17, config.apiUrl).toString();
11018
+ const url = new URL(path18, config.apiUrl).toString();
11007
11019
  const doFetch = async (bearer) => fetch(url, {
11008
11020
  ...init,
11009
11021
  signal: makeTimeoutSignal(opts2?.timeoutMs),
@@ -11220,6 +11232,21 @@ function createApiClient(config, opts) {
11220
11232
  const suffix = qs.toString() ? `?${qs.toString()}` : "";
11221
11233
  return request(`/v1/merge-requests${suffix}`, { method: "GET" });
11222
11234
  },
11235
+ listMergeRequestInbox: (params) => {
11236
+ const qs = new URLSearchParams();
11237
+ if (Array.isArray(params?.status)) {
11238
+ for (const status of params.status) qs.append("status", status);
11239
+ } else if (typeof params?.status === "string") {
11240
+ qs.set("status", params.status);
11241
+ }
11242
+ if (params?.kind) qs.set("kind", params.kind);
11243
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
11244
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
11245
+ if (typeof params?.includeReview === "boolean") qs.set("includeReview", String(params.includeReview));
11246
+ if (typeof params?.includeDiffs === "boolean") qs.set("includeDiffs", String(params.includeDiffs));
11247
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
11248
+ return request(`/v1/merge-requests/inbox${suffix}`, { method: "GET" });
11249
+ },
11223
11250
  openMergeRequest: (sourceAppId) => request("/v1/merge-requests", { method: "POST", body: JSON.stringify({ sourceAppId }) }),
11224
11251
  getMergeRequestReview: (mrId) => request(`/v1/merge-requests/${encodeURIComponent(mrId)}/review`, { method: "GET" }),
11225
11252
  updateMergeRequest: (mrId, payload) => request(`/v1/merge-requests/${encodeURIComponent(mrId)}`, { method: "PATCH", body: JSON.stringify(payload) }),
@@ -11866,8 +11893,8 @@ function getErrorMap() {
11866
11893
 
11867
11894
  // node_modules/zod/v3/helpers/parseUtil.js
11868
11895
  var makeIssue = (params) => {
11869
- const { data, path: path17, errorMaps, issueData } = params;
11870
- const fullPath = [...path17, ...issueData.path || []];
11896
+ const { data, path: path18, errorMaps, issueData } = params;
11897
+ const fullPath = [...path18, ...issueData.path || []];
11871
11898
  const fullIssue = {
11872
11899
  ...issueData,
11873
11900
  path: fullPath
@@ -11983,11 +12010,11 @@ var errorUtil;
11983
12010
 
11984
12011
  // node_modules/zod/v3/types.js
11985
12012
  var ParseInputLazyPath = class {
11986
- constructor(parent, value, path17, key) {
12013
+ constructor(parent, value, path18, key) {
11987
12014
  this._cachedPath = [];
11988
12015
  this.parent = parent;
11989
12016
  this.data = value;
11990
- this._path = path17;
12017
+ this._path = path18;
11991
12018
  this._key = key;
11992
12019
  }
11993
12020
  get path() {
@@ -24535,8 +24562,8 @@ var IcebergError = class extends Error {
24535
24562
  return this.status === 419;
24536
24563
  }
24537
24564
  };
24538
- function buildUrl(baseUrl, path17, query) {
24539
- const url = new URL(path17, baseUrl);
24565
+ function buildUrl(baseUrl, path18, query) {
24566
+ const url = new URL(path18, baseUrl);
24540
24567
  if (query) {
24541
24568
  for (const [key, value] of Object.entries(query)) {
24542
24569
  if (value !== void 0) {
@@ -24566,12 +24593,12 @@ function createFetchClient(options) {
24566
24593
  return {
24567
24594
  async request({
24568
24595
  method,
24569
- path: path17,
24596
+ path: path18,
24570
24597
  query,
24571
24598
  body,
24572
24599
  headers
24573
24600
  }) {
24574
- const url = buildUrl(options.baseUrl, path17, query);
24601
+ const url = buildUrl(options.baseUrl, path18, query);
24575
24602
  const authHeaders = await buildAuthHeaders(options.auth);
24576
24603
  const res = await fetchFn(url, {
24577
24604
  method,
@@ -25409,7 +25436,7 @@ var StorageFileApi = class extends BaseApiClient {
25409
25436
  * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
25410
25437
  * @param fileBody The body of the file to be stored in the bucket.
25411
25438
  */
25412
- async uploadOrUpdate(method, path17, fileBody, fileOptions) {
25439
+ async uploadOrUpdate(method, path18, fileBody, fileOptions) {
25413
25440
  var _this = this;
25414
25441
  return _this.handleOperation(async () => {
25415
25442
  let body;
@@ -25433,7 +25460,7 @@ var StorageFileApi = class extends BaseApiClient {
25433
25460
  if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
25434
25461
  }
25435
25462
  if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
25436
- const cleanPath = _this._removeEmptyFolders(path17);
25463
+ const cleanPath = _this._removeEmptyFolders(path18);
25437
25464
  const _path = _this._getFinalPath(cleanPath);
25438
25465
  const data = await (method == "PUT" ? put : post)(_this.fetch, `${_this.url}/object/${_path}`, body, _objectSpread22({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}));
25439
25466
  return {
@@ -25494,8 +25521,8 @@ var StorageFileApi = class extends BaseApiClient {
25494
25521
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25495
25522
  * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
25496
25523
  */
25497
- async upload(path17, fileBody, fileOptions) {
25498
- return this.uploadOrUpdate("POST", path17, fileBody, fileOptions);
25524
+ async upload(path18, fileBody, fileOptions) {
25525
+ return this.uploadOrUpdate("POST", path18, fileBody, fileOptions);
25499
25526
  }
25500
25527
  /**
25501
25528
  * Upload a file with a token generated from `createSignedUploadUrl`.
@@ -25534,9 +25561,9 @@ var StorageFileApi = class extends BaseApiClient {
25534
25561
  * - `objects` table permissions: none
25535
25562
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25536
25563
  */
25537
- async uploadToSignedUrl(path17, token, fileBody, fileOptions) {
25564
+ async uploadToSignedUrl(path18, token, fileBody, fileOptions) {
25538
25565
  var _this3 = this;
25539
- const cleanPath = _this3._removeEmptyFolders(path17);
25566
+ const cleanPath = _this3._removeEmptyFolders(path18);
25540
25567
  const _path = _this3._getFinalPath(cleanPath);
25541
25568
  const url = new URL(_this3.url + `/object/upload/sign/${_path}`);
25542
25569
  url.searchParams.set("token", token);
@@ -25598,10 +25625,10 @@ var StorageFileApi = class extends BaseApiClient {
25598
25625
  * - `objects` table permissions: `insert`
25599
25626
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25600
25627
  */
25601
- async createSignedUploadUrl(path17, options) {
25628
+ async createSignedUploadUrl(path18, options) {
25602
25629
  var _this4 = this;
25603
25630
  return _this4.handleOperation(async () => {
25604
- let _path = _this4._getFinalPath(path17);
25631
+ let _path = _this4._getFinalPath(path18);
25605
25632
  const headers = _objectSpread22({}, _this4.headers);
25606
25633
  if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
25607
25634
  const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
@@ -25610,7 +25637,7 @@ var StorageFileApi = class extends BaseApiClient {
25610
25637
  if (!token) throw new StorageError("No token returned by API");
25611
25638
  return {
25612
25639
  signedUrl: url.toString(),
25613
- path: path17,
25640
+ path: path18,
25614
25641
  token
25615
25642
  };
25616
25643
  });
@@ -25666,8 +25693,8 @@ var StorageFileApi = class extends BaseApiClient {
25666
25693
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25667
25694
  * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
25668
25695
  */
25669
- async update(path17, fileBody, fileOptions) {
25670
- return this.uploadOrUpdate("PUT", path17, fileBody, fileOptions);
25696
+ async update(path18, fileBody, fileOptions) {
25697
+ return this.uploadOrUpdate("PUT", path18, fileBody, fileOptions);
25671
25698
  }
25672
25699
  /**
25673
25700
  * Moves an existing file to a new path in the same bucket.
@@ -25815,10 +25842,10 @@ var StorageFileApi = class extends BaseApiClient {
25815
25842
  * - `objects` table permissions: `select`
25816
25843
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25817
25844
  */
25818
- async createSignedUrl(path17, expiresIn, options) {
25845
+ async createSignedUrl(path18, expiresIn, options) {
25819
25846
  var _this8 = this;
25820
25847
  return _this8.handleOperation(async () => {
25821
- let _path = _this8._getFinalPath(path17);
25848
+ let _path = _this8._getFinalPath(path18);
25822
25849
  const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
25823
25850
  let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
25824
25851
  const query = new URLSearchParams();
@@ -25952,13 +25979,13 @@ var StorageFileApi = class extends BaseApiClient {
25952
25979
  * - `objects` table permissions: `select`
25953
25980
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
25954
25981
  */
25955
- download(path17, options, parameters) {
25982
+ download(path18, options, parameters) {
25956
25983
  const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image/authenticated" : "object";
25957
25984
  const query = new URLSearchParams();
25958
25985
  if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
25959
25986
  if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
25960
25987
  const queryString = query.toString();
25961
- const _path = this._getFinalPath(path17);
25988
+ const _path = this._getFinalPath(path18);
25962
25989
  const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
25963
25990
  headers: this.headers,
25964
25991
  noResolveJson: true
@@ -25988,9 +26015,9 @@ var StorageFileApi = class extends BaseApiClient {
25988
26015
  * }
25989
26016
  * ```
25990
26017
  */
25991
- async info(path17) {
26018
+ async info(path18) {
25992
26019
  var _this10 = this;
25993
- const _path = _this10._getFinalPath(path17);
26020
+ const _path = _this10._getFinalPath(path18);
25994
26021
  return _this10.handleOperation(async () => {
25995
26022
  return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
25996
26023
  });
@@ -26010,9 +26037,9 @@ var StorageFileApi = class extends BaseApiClient {
26010
26037
  * .exists('folder/avatar1.png')
26011
26038
  * ```
26012
26039
  */
26013
- async exists(path17) {
26040
+ async exists(path18) {
26014
26041
  var _this11 = this;
26015
- const _path = _this11._getFinalPath(path17);
26042
+ const _path = _this11._getFinalPath(path18);
26016
26043
  try {
26017
26044
  await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
26018
26045
  return {
@@ -26090,8 +26117,8 @@ var StorageFileApi = class extends BaseApiClient {
26090
26117
  * - `objects` table permissions: none
26091
26118
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
26092
26119
  */
26093
- getPublicUrl(path17, options) {
26094
- const _path = this._getFinalPath(path17);
26120
+ getPublicUrl(path18, options) {
26121
+ const _path = this._getFinalPath(path18);
26095
26122
  const query = new URLSearchParams();
26096
26123
  if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
26097
26124
  if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
@@ -26228,10 +26255,10 @@ var StorageFileApi = class extends BaseApiClient {
26228
26255
  * - `objects` table permissions: `select`
26229
26256
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
26230
26257
  */
26231
- async list(path17, options, parameters) {
26258
+ async list(path18, options, parameters) {
26232
26259
  var _this13 = this;
26233
26260
  return _this13.handleOperation(async () => {
26234
- const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path17 || "" });
26261
+ const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path18 || "" });
26235
26262
  return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
26236
26263
  });
26237
26264
  }
@@ -26295,11 +26322,11 @@ var StorageFileApi = class extends BaseApiClient {
26295
26322
  if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
26296
26323
  return btoa(data);
26297
26324
  }
26298
- _getFinalPath(path17) {
26299
- return `${this.bucketId}/${path17.replace(/^\/+/, "")}`;
26325
+ _getFinalPath(path18) {
26326
+ return `${this.bucketId}/${path18.replace(/^\/+/, "")}`;
26300
26327
  }
26301
- _removeEmptyFolders(path17) {
26302
- return path17.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
26328
+ _removeEmptyFolders(path18) {
26329
+ return path18.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
26303
26330
  }
26304
26331
  /** Modifies the `query`, appending values the from `transform` */
26305
26332
  applyTransformOptsToQuery(query, transform) {
@@ -35677,11 +35704,11 @@ function isPidAlive(pid) {
35677
35704
  }
35678
35705
  }
35679
35706
  function repoLockFileName(repoRoot) {
35680
- const hash = (0, import_node_crypto3.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 16);
35707
+ const hash = (0, import_node_crypto5.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 16);
35681
35708
  return `.drainer-${hash}.lock`;
35682
35709
  }
35683
35710
  function repoLockPath(repoRoot) {
35684
- return import_node_path11.default.join(getDeferredTurnDirPath(), repoLockFileName(repoRoot));
35711
+ return import_node_path12.default.join(getDeferredTurnDirPath(), repoLockFileName(repoRoot));
35685
35712
  }
35686
35713
  async function readDrainLockMetadata(lockPath) {
35687
35714
  const raw = await import_promises23.default.readFile(lockPath, "utf8").catch(() => null);
@@ -35703,7 +35730,7 @@ async function writeDrainLockMetadata(lockPath, metadata) {
35703
35730
  }
35704
35731
  async function tryAcquireDrainLock(repoRoot) {
35705
35732
  const lockPath = repoLockPath(repoRoot);
35706
- await import_promises23.default.mkdir(import_node_path11.default.dirname(lockPath), { recursive: true });
35733
+ await import_promises23.default.mkdir(import_node_path12.default.dirname(lockPath), { recursive: true });
35707
35734
  const existingMeta = await readDrainLockMetadata(lockPath);
35708
35735
  if (existingMeta) {
35709
35736
  const lockStat = await import_promises23.default.stat(lockPath).catch(() => null);
@@ -36100,7 +36127,7 @@ function spawnDeferredTurnDrainer(repoRoot) {
36100
36127
 
36101
36128
  // src/hook-utils.ts
36102
36129
  var import_promises24 = __toESM(require("fs/promises"), 1);
36103
- var import_node_path12 = __toESM(require("path"), 1);
36130
+ var import_node_path13 = __toESM(require("path"), 1);
36104
36131
  async function readJsonStdin() {
36105
36132
  const chunks = [];
36106
36133
  for await (const chunk of process.stdin) {
@@ -36126,16 +36153,16 @@ function extractString(input, keys) {
36126
36153
  }
36127
36154
  async function findBoundRepo(startPath) {
36128
36155
  if (!startPath) return null;
36129
- let current = import_node_path12.default.resolve(startPath);
36156
+ let current = import_node_path13.default.resolve(startPath);
36130
36157
  let stats = await import_promises24.default.stat(current).catch(() => null);
36131
36158
  if (stats?.isFile()) {
36132
- current = import_node_path12.default.dirname(current);
36159
+ current = import_node_path13.default.dirname(current);
36133
36160
  }
36134
36161
  while (true) {
36135
- const bindingPath = import_node_path12.default.join(current, ".remix", "config.json");
36162
+ const bindingPath = import_node_path13.default.join(current, ".remix", "config.json");
36136
36163
  const bindingStats = await import_promises24.default.stat(bindingPath).catch(() => null);
36137
36164
  if (bindingStats?.isFile()) return current;
36138
- const parent = import_node_path12.default.dirname(current);
36165
+ const parent = import_node_path13.default.dirname(current);
36139
36166
  if (parent === current) return null;
36140
36167
  current = parent;
36141
36168
  }
@@ -36159,8 +36186,6 @@ function buildRuntimeStatusOverride() {
36159
36186
  "Use `remix_collab_drain_finalize_queue` only for explicit recovery flows, such as status reporting `await_finalize` before a merge-related operation."
36160
36187
  ].join("\n");
36161
36188
  }
36162
- var COLLAB_INIT_LOG_REL = import_node_path13.default.join(".remix", "collab-init.log");
36163
- var COLLAB_INIT_SPAWN_LOCK_REL = import_node_path13.default.join(".remix", ".collab-init-spawning");
36164
36189
  var COLLAB_INIT_SPAWN_LOCK_STALE_MS = 90 * 1e3;
36165
36190
  function isPidAlive2(pid) {
36166
36191
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -36171,9 +36196,9 @@ function isPidAlive2(pid) {
36171
36196
  return false;
36172
36197
  }
36173
36198
  }
36174
- function readSpawnLock(spawnLockPath) {
36199
+ function readSpawnLock(spawnLockPath2) {
36175
36200
  try {
36176
- const raw = (0, import_node_fs7.readFileSync)(spawnLockPath, "utf8").trim();
36201
+ const raw = (0, import_node_fs7.readFileSync)(spawnLockPath2, "utf8").trim();
36177
36202
  if (!raw) return null;
36178
36203
  if (raw.startsWith("{")) {
36179
36204
  const parsed = JSON.parse(raw);
@@ -36193,22 +36218,20 @@ function readSpawnLock(spawnLockPath) {
36193
36218
  }
36194
36219
  }
36195
36220
  function maybeAutoSpawnBranchInit(repoRoot, branchName) {
36196
- const remixDir = import_node_path13.default.join(repoRoot, ".remix");
36197
- const spawnLockPath = import_node_path13.default.join(repoRoot, COLLAB_INIT_SPAWN_LOCK_REL);
36198
- const logPath = import_node_path13.default.join(repoRoot, COLLAB_INIT_LOG_REL);
36221
+ const spawnLockPath2 = collabInitSpawnLockPath(repoRoot);
36199
36222
  try {
36200
- if ((0, import_node_fs7.existsSync)(spawnLockPath)) {
36201
- const lock = readSpawnLock(spawnLockPath);
36223
+ if ((0, import_node_fs7.existsSync)(spawnLockPath2)) {
36224
+ const lock = readSpawnLock(spawnLockPath2);
36202
36225
  const lockPid = lock?.pid ?? null;
36203
36226
  const lockAlive = lockPid !== null && isPidAlive2(lockPid);
36204
36227
  const sameBranch = !lock?.branchName || !branchName || lock.branchName === branchName;
36205
- const ageMs = Date.now() - (0, import_node_fs7.statSync)(spawnLockPath).mtimeMs;
36228
+ const ageMs = Date.now() - (0, import_node_fs7.statSync)(spawnLockPath2).mtimeMs;
36206
36229
  if (lockAlive && sameBranch && ageMs < COLLAB_INIT_SPAWN_LOCK_STALE_MS) {
36207
36230
  return { spawned: false, reason: "spawn_lock_held" };
36208
36231
  }
36209
36232
  if (!lockAlive) {
36210
36233
  try {
36211
- (0, import_node_fs7.unlinkSync)(spawnLockPath);
36234
+ (0, import_node_fs7.unlinkSync)(spawnLockPath2);
36212
36235
  } catch {
36213
36236
  }
36214
36237
  }
@@ -36216,33 +36239,14 @@ function maybeAutoSpawnBranchInit(repoRoot, branchName) {
36216
36239
  } catch {
36217
36240
  }
36218
36241
  try {
36219
- (0, import_node_fs7.mkdirSync)(remixDir, { recursive: true });
36242
+ (0, import_node_fs7.mkdirSync)(import_node_path14.default.dirname(spawnLockPath2), { recursive: true });
36220
36243
  } catch {
36221
36244
  }
36222
- let out;
36223
- let err;
36224
36245
  try {
36225
- out = (0, import_node_fs7.openSync)(logPath, "a");
36226
- err = (0, import_node_fs7.openSync)(logPath, "a");
36227
- } catch (logErr) {
36228
- return {
36229
- spawned: false,
36230
- reason: "log_open_failed",
36231
- message: logErr instanceof Error ? logErr.message : String(logErr)
36232
- };
36233
- }
36234
- try {
36235
- (0, import_node_fs7.appendFileSync)(
36236
- logPath,
36237
- `
36238
- [${(/* @__PURE__ */ new Date()).toISOString()}] auto-spawning remix collab init for branch=${branchName ?? "(unknown)"} repo=${repoRoot}
36239
- `,
36240
- "utf8"
36241
- );
36242
36246
  const child = (0, import_node_child_process8.spawn)("remix", ["collab", "init"], {
36243
36247
  cwd: repoRoot,
36244
36248
  detached: true,
36245
- stdio: ["ignore", out, err],
36249
+ stdio: "ignore",
36246
36250
  env: { ...process.env, REMIX_COLLAB_INIT_AUTO_SPAWN: "1" }
36247
36251
  });
36248
36252
  child.unref();
@@ -36255,12 +36259,12 @@ function maybeAutoSpawnBranchInit(repoRoot, branchName) {
36255
36259
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
36256
36260
  command: "remix collab init"
36257
36261
  };
36258
- (0, import_node_fs7.writeFileSync)(spawnLockPath, `${JSON.stringify(lock, null, 2)}
36262
+ (0, import_node_fs7.writeFileSync)(spawnLockPath2, `${JSON.stringify(lock, null, 2)}
36259
36263
  `, "utf8");
36260
- (0, import_node_fs7.utimesSync)(spawnLockPath, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
36264
+ (0, import_node_fs7.utimesSync)(spawnLockPath2, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
36261
36265
  } catch {
36262
36266
  }
36263
- return { spawned: true, pid: child.pid, logPath };
36267
+ return { spawned: true, pid: child.pid };
36264
36268
  } catch (spawnErr) {
36265
36269
  return {
36266
36270
  spawned: false,
@@ -36269,14 +36273,13 @@ function maybeAutoSpawnBranchInit(repoRoot, branchName) {
36269
36273
  };
36270
36274
  }
36271
36275
  }
36272
- function buildBranchInitContextMessage(branch, repoRoot, logPath) {
36276
+ function buildBranchInitContextMessage(branch, repoRoot) {
36273
36277
  const branchLabel = branch ? `\`${branch}\`` : "the current branch";
36274
36278
  return [
36275
36279
  "[Remix recovery in progress]:",
36276
36280
  `Remix is initializing recording for ${branchLabel} in ${repoRoot} in the background.`,
36277
36281
  "This turn may be recorded retroactively once init finishes (it may appear in the timeline with a small delay).",
36278
- "Do NOT call any Remix MCP tool to initialize, repair, or sync this branch \u2014 the plugin is handling it automatically.",
36279
- `Init log: ${logPath}`
36282
+ "Do NOT call any Remix MCP tool to initialize, repair, or sync this branch \u2014 the plugin is handling it automatically."
36280
36283
  ].join("\n");
36281
36284
  }
36282
36285
  var STALE_MARKER_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
@@ -36477,7 +36480,7 @@ async function runHookUserPrompt(payload) {
36477
36480
  const currentBranch = bindingState?.currentBranch ?? null;
36478
36481
  const outcome = maybeAutoSpawnBranchInit(boundRepo, currentBranch);
36479
36482
  if (outcome.spawned) {
36480
- advisorySections.push(buildBranchInitContextMessage(currentBranch, boundRepo, outcome.logPath));
36483
+ advisorySections.push(buildBranchInitContextMessage(currentBranch, boundRepo));
36481
36484
  await appendHookDiagnosticsEvent({
36482
36485
  hook: "UserPromptSubmit",
36483
36486
  sessionId,
@@ -36488,8 +36491,7 @@ async function runHookUserPrompt(payload) {
36488
36491
  fields: {
36489
36492
  currentBranch,
36490
36493
  knownBoundBranchCount: knownBoundBranches.length,
36491
- pid: outcome.pid ?? null,
36492
- logPath: outcome.logPath
36494
+ pid: outcome.pid ?? null
36493
36495
  }
36494
36496
  });
36495
36497
  } else {