@ai-development-environment/control-agent 0.0.89 → 0.0.91

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/control-agent.js +1419 -304
  2. package/package.json +1 -1
@@ -2276,7 +2276,7 @@ var require_websocket = __commonJS({
2276
2276
  var http = __require("http");
2277
2277
  var net = __require("net");
2278
2278
  var tls = __require("tls");
2279
- var { randomBytes, createHash: createHash7 } = __require("crypto");
2279
+ var { randomBytes, createHash: createHash8 } = __require("crypto");
2280
2280
  var { Duplex, Readable: Readable2 } = __require("stream");
2281
2281
  var { URL: URL2 } = __require("url");
2282
2282
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -2944,7 +2944,7 @@ var require_websocket = __commonJS({
2944
2944
  abortHandshake(websocket, socket, "Invalid Upgrade header");
2945
2945
  return;
2946
2946
  }
2947
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
2947
+ const digest = createHash8("sha1").update(key + GUID).digest("base64");
2948
2948
  if (res.headers["sec-websocket-accept"] !== digest) {
2949
2949
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
2950
2950
  return;
@@ -3313,7 +3313,7 @@ var require_websocket_server = __commonJS({
3313
3313
  var EventEmitter = __require("events");
3314
3314
  var http = __require("http");
3315
3315
  var { Duplex } = __require("stream");
3316
- var { createHash: createHash7 } = __require("crypto");
3316
+ var { createHash: createHash8 } = __require("crypto");
3317
3317
  var extension2 = require_extension();
3318
3318
  var PerMessageDeflate2 = require_permessage_deflate();
3319
3319
  var subprotocol2 = require_subprotocol();
@@ -3620,7 +3620,7 @@ var require_websocket_server = __commonJS({
3620
3620
  );
3621
3621
  }
3622
3622
  if (this._state > RUNNING) return abortHandshake(socket, 503);
3623
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
3623
+ const digest = createHash8("sha1").update(key + GUID).digest("base64");
3624
3624
  const headers = [
3625
3625
  "HTTP/1.1 101 Switching Protocols",
3626
3626
  "Upgrade: websocket",
@@ -3801,12 +3801,12 @@ var require_isexe = __commonJS({
3801
3801
  if (typeof Promise !== "function") {
3802
3802
  throw new TypeError("callback not provided");
3803
3803
  }
3804
- return new Promise(function(resolve8, reject) {
3804
+ return new Promise(function(resolve9, reject) {
3805
3805
  isexe(path, options || {}, function(er2, is) {
3806
3806
  if (er2) {
3807
3807
  reject(er2);
3808
3808
  } else {
3809
- resolve8(is);
3809
+ resolve9(is);
3810
3810
  }
3811
3811
  });
3812
3812
  });
@@ -3872,27 +3872,27 @@ var require_which = __commonJS({
3872
3872
  opt = {};
3873
3873
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
3874
3874
  const found = [];
3875
- const step = (i) => new Promise((resolve8, reject) => {
3875
+ const step = (i) => new Promise((resolve9, reject) => {
3876
3876
  if (i === pathEnv.length)
3877
- return opt.all && found.length ? resolve8(found) : reject(getNotFoundError(cmd));
3877
+ return opt.all && found.length ? resolve9(found) : reject(getNotFoundError(cmd));
3878
3878
  const ppRaw = pathEnv[i];
3879
3879
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
3880
3880
  const pCmd = path.join(pathPart, cmd);
3881
3881
  const p4 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
3882
- resolve8(subStep(p4, i, 0));
3882
+ resolve9(subStep(p4, i, 0));
3883
3883
  });
3884
- const subStep = (p4, i, ii) => new Promise((resolve8, reject) => {
3884
+ const subStep = (p4, i, ii) => new Promise((resolve9, reject) => {
3885
3885
  if (ii === pathExt.length)
3886
- return resolve8(step(i + 1));
3886
+ return resolve9(step(i + 1));
3887
3887
  const ext = pathExt[ii];
3888
3888
  isexe(p4 + ext, { pathExt: pathExtExe }, (er2, is) => {
3889
3889
  if (!er2 && is) {
3890
3890
  if (opt.all)
3891
3891
  found.push(p4 + ext);
3892
3892
  else
3893
- return resolve8(p4 + ext);
3893
+ return resolve9(p4 + ext);
3894
3894
  }
3895
- return resolve8(subStep(p4, i, ii + 1));
3895
+ return resolve9(subStep(p4, i, ii + 1));
3896
3896
  });
3897
3897
  });
3898
3898
  return cb2 ? step(0).then((res) => cb2(null, res), cb2) : step(0);
@@ -4205,7 +4205,7 @@ var require_cross_spawn = __commonJS({
4205
4205
  });
4206
4206
 
4207
4207
  // src/index.ts
4208
- import { rm as rm14 } from "node:fs/promises";
4208
+ import { rm as rm15 } from "node:fs/promises";
4209
4209
 
4210
4210
  // src/config.ts
4211
4211
  import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
@@ -4498,8 +4498,8 @@ function createClient(options) {
4498
4498
  retryWait = async function randomisedExponentialBackoff(retries2) {
4499
4499
  const retryDelaySeconds = Math.pow(2, retries2);
4500
4500
  await new Promise(
4501
- (resolve8) => setTimeout(
4502
- resolve8,
4501
+ (resolve9) => setTimeout(
4502
+ resolve9,
4503
4503
  retryDelaySeconds * 1e3 + // add random timeout from 300ms to 3s
4504
4504
  Math.floor(Math.random() * (3e3 - 300) + 300)
4505
4505
  )
@@ -4735,7 +4735,7 @@ function createClient(options) {
4735
4735
  if (socket.readyState === WebSocketImpl.CLOSING) await throwOnClose;
4736
4736
  let release2 = () => {
4737
4737
  };
4738
- const released = new Promise((resolve8) => release2 = resolve8);
4738
+ const released = new Promise((resolve9) => release2 = resolve9);
4739
4739
  return [
4740
4740
  socket,
4741
4741
  release2,
@@ -4898,7 +4898,7 @@ function createClient(options) {
4898
4898
  const iterator = (async function* iterator2() {
4899
4899
  for (; ; ) {
4900
4900
  if (!pending.length) {
4901
- await new Promise((resolve8) => deferred.resolve = resolve8);
4901
+ await new Promise((resolve9) => deferred.resolve = resolve9);
4902
4902
  }
4903
4903
  while (pending.length) {
4904
4904
  yield pending.shift();
@@ -5480,7 +5480,7 @@ function createAgentSubscriptionClient(config) {
5480
5480
  shouldRetry: () => true,
5481
5481
  retryWait: async (retries) => {
5482
5482
  const delay = Math.min(3e4, 1e3 * 2 ** Math.min(retries, 5));
5483
- await new Promise((resolve8) => setTimeout(resolve8, delay));
5483
+ await new Promise((resolve9) => setTimeout(resolve9, delay));
5484
5484
  },
5485
5485
  on: {
5486
5486
  connected: () => console.log("Connected to control-plane WebSocket"),
@@ -6128,6 +6128,7 @@ var WORKTREE_INSPECT_JOB_KIND = "worktree.inspect";
6128
6128
  var WORKTREE_OPERATION_JOB_KIND = "worktree.operation";
6129
6129
  var WORKTREE_COMMIT_JOB_KIND = "worktree.commit";
6130
6130
  var WORKTREE_AUTO_SYNC_JOB_KIND = "worktree.auto-sync";
6131
+ var WORKTREE_PREPARATION_JOB_KIND = "worktree.prepare";
6131
6132
  var WORKTREE_GIT_INSPECT_JOB_KIND = "worktree.git.inspect";
6132
6133
  var WORKTREE_GIT_OPERATION_JOB_KIND = "worktree.git.operation";
6133
6134
  var WORKTREE_WATCH_JOB_KIND = "worktree.watch";
@@ -6142,6 +6143,7 @@ var WORKTREE_JOB_KINDS = [
6142
6143
  WORKTREE_OPERATION_JOB_KIND,
6143
6144
  WORKTREE_COMMIT_JOB_KIND,
6144
6145
  WORKTREE_AUTO_SYNC_JOB_KIND,
6146
+ WORKTREE_PREPARATION_JOB_KIND,
6145
6147
  WORKTREE_GIT_INSPECT_JOB_KIND,
6146
6148
  WORKTREE_GIT_OPERATION_JOB_KIND,
6147
6149
  WORKTREE_WATCH_JOB_KIND,
@@ -6170,10 +6172,21 @@ var WORKTREE_OPERATIONS = [
6170
6172
  "PULL",
6171
6173
  "PUSH",
6172
6174
  "RESET",
6175
+ "CLEAR_LOCK",
6173
6176
  "STASH_ALL",
6174
6177
  "STAGE_ALL",
6175
6178
  "UNSTAGE_ALL"
6176
6179
  ];
6180
+ var WORKTREE_PREPARATION_KINDS = [
6181
+ "WRITE",
6182
+ "DELETE",
6183
+ "ASSUME_UNCHANGED"
6184
+ ];
6185
+ var WORKTREE_PREPARATION_ACTIONS = [
6186
+ "INSPECT",
6187
+ "APPLY",
6188
+ "UNDO"
6189
+ ];
6177
6190
  function validGitBranchName(value) {
6178
6191
  if (!value || value.length > 255 || value === "@" || value.startsWith("-"))
6179
6192
  return false;
@@ -6214,11 +6227,74 @@ function stashOid2(value, name) {
6214
6227
  }
6215
6228
  function safeRelativePath(value, name) {
6216
6229
  const path = stringValue4(value, name).replaceAll("\\", "/");
6217
- if (path.startsWith("/") || /^[A-Za-z]:\//.test(path) || path.split("/").includes("..") || path.includes("\0")) {
6218
- throw new Error(`${name} must stay within the worktree`);
6230
+ const parts = path.split("/");
6231
+ if (!path || path === "." || path.startsWith("/") || /^[A-Za-z]:\//.test(path) || /[\0\r\n]/.test(path) || parts.some((part) => !part || part === "." || part === "..") || parts.some((part) => part.toLowerCase() === ".git")) {
6232
+ throw new Error(`${name} must be an exact file inside the worktree`);
6233
+ }
6234
+ return path;
6235
+ }
6236
+ function safePreparationPath(value, name) {
6237
+ const path = safeRelativePath(value, name);
6238
+ if (/[*?[\]]/.test(path)) {
6239
+ throw new Error(`${name} must be an exact file inside the worktree`);
6219
6240
  }
6220
6241
  return path;
6221
6242
  }
6243
+ function safeDiffPath(value, name) {
6244
+ try {
6245
+ return safeRelativePath(value, name);
6246
+ } catch {
6247
+ throw new Error(`${name} must stay within the worktree`);
6248
+ }
6249
+ }
6250
+ function preparationDefinitions(value, name) {
6251
+ if (!Array.isArray(value) || value.length > 500) {
6252
+ throw new Error(`${name} must be an array with at most 500 items`);
6253
+ }
6254
+ const definitions = value.map((entry, index) => {
6255
+ const item = objectValue4(entry, `${name}[${index}]`);
6256
+ const allowed = /* @__PURE__ */ new Set([
6257
+ "id",
6258
+ "kind",
6259
+ "path",
6260
+ "contentBase64",
6261
+ "definitionHash"
6262
+ ]);
6263
+ const unexpected = Object.keys(item).find((key) => !allowed.has(key));
6264
+ if (unexpected) {
6265
+ throw new Error(`Unexpected ${name}[${index}] field: ${unexpected}`);
6266
+ }
6267
+ if (typeof item.kind !== "string" || !WORKTREE_PREPARATION_KINDS.includes(item.kind)) {
6268
+ throw new Error(`${name}[${index}].kind is invalid`);
6269
+ }
6270
+ const contentBase64 = item.contentBase64 === null || item.contentBase64 === void 0 ? null : typeof item.contentBase64 === "string" ? item.contentBase64 : (() => {
6271
+ throw new Error(
6272
+ `${name}[${index}].contentBase64 must be a string`
6273
+ );
6274
+ })();
6275
+ if (item.kind === "WRITE" && contentBase64 === null) {
6276
+ throw new Error(`${name}[${index}].contentBase64 is required`);
6277
+ }
6278
+ if (item.kind !== "WRITE" && contentBase64 !== null) {
6279
+ throw new Error(`${name}[${index}].contentBase64 is not allowed`);
6280
+ }
6281
+ return {
6282
+ id: stringValue4(item.id, `${name}[${index}].id`),
6283
+ kind: item.kind,
6284
+ path: safePreparationPath(item.path, `${name}[${index}].path`),
6285
+ contentBase64,
6286
+ definitionHash: stringValue4(
6287
+ item.definitionHash,
6288
+ `${name}[${index}].definitionHash`
6289
+ )
6290
+ };
6291
+ });
6292
+ const paths = definitions.map((item) => item.path);
6293
+ if (new Set(paths).size !== paths.length) {
6294
+ throw new Error(`${name} paths must be unique`);
6295
+ }
6296
+ return definitions;
6297
+ }
6222
6298
  function worktreeBranchJobPayload(value) {
6223
6299
  const payload = objectValue4(value, "worktree branch payload");
6224
6300
  const allowed = /* @__PURE__ */ new Set([
@@ -6231,7 +6307,8 @@ function worktreeBranchJobPayload(value) {
6231
6307
  "action",
6232
6308
  "mode",
6233
6309
  "candidates",
6234
- "stashOnFailure"
6310
+ "stashOnFailure",
6311
+ "preparations"
6235
6312
  ]);
6236
6313
  const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6237
6314
  if (unexpected) {
@@ -6297,7 +6374,11 @@ function worktreeBranchJobPayload(value) {
6297
6374
  action: payload.action,
6298
6375
  mode: payload.mode,
6299
6376
  candidates,
6300
- stashOnFailure: payload.stashOnFailure
6377
+ stashOnFailure: payload.stashOnFailure,
6378
+ preparations: preparationDefinitions(
6379
+ payload.preparations ?? [],
6380
+ "worktree branch payload.preparations"
6381
+ )
6301
6382
  };
6302
6383
  }
6303
6384
  function worktreeMovePushJobPayload(value) {
@@ -6357,7 +6438,8 @@ function worktreeMoveCheckoutJobPayload(value) {
6357
6438
  "expectedHeadSha",
6358
6439
  "baseBranch",
6359
6440
  "mode",
6360
- "stashOnFailure"
6441
+ "stashOnFailure",
6442
+ "preparations"
6361
6443
  ]);
6362
6444
  const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6363
6445
  if (unexpected) {
@@ -6418,7 +6500,11 @@ function worktreeMoveCheckoutJobPayload(value) {
6418
6500
  "worktree move checkout payload.baseBranch"
6419
6501
  ),
6420
6502
  mode: payload.mode,
6421
- stashOnFailure: payload.stashOnFailure
6503
+ stashOnFailure: payload.stashOnFailure,
6504
+ preparations: preparationDefinitions(
6505
+ payload.preparations ?? [],
6506
+ "worktree move checkout payload.preparations"
6507
+ )
6422
6508
  };
6423
6509
  }
6424
6510
  function worktreeDeleteJobPayload(value) {
@@ -6560,7 +6646,9 @@ function worktreeJobPayload(value) {
6560
6646
  "expectedOrigin",
6561
6647
  "baseBranch",
6562
6648
  "operation",
6563
- "editorVariant"
6649
+ "editorVariant",
6650
+ "forcePreparations",
6651
+ "preparations"
6564
6652
  ]);
6565
6653
  const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6566
6654
  if (unexpected)
@@ -6573,6 +6661,9 @@ function worktreeJobPayload(value) {
6573
6661
  if (editorVariant !== void 0 && !["CODE", "CODE_INSIDERS", "NONE"].includes(String(editorVariant))) {
6574
6662
  throw new Error("worktree payload.editorVariant is invalid");
6575
6663
  }
6664
+ if (payload.forcePreparations !== void 0 && typeof payload.forcePreparations !== "boolean") {
6665
+ throw new Error("worktree payload.forcePreparations must be a boolean");
6666
+ }
6576
6667
  return {
6577
6668
  codebaseId: stringValue4(payload.codebaseId, "worktree payload.codebaseId"),
6578
6669
  folder: stringValue4(payload.folder, "worktree payload.folder"),
@@ -6589,7 +6680,12 @@ function worktreeJobPayload(value) {
6589
6680
  "worktree payload.baseBranch"
6590
6681
  ),
6591
6682
  ...operation === void 0 ? {} : { operation },
6592
- ...editorVariant === void 0 ? {} : { editorVariant }
6683
+ ...editorVariant === void 0 ? {} : { editorVariant },
6684
+ forcePreparations: payload.forcePreparations === true,
6685
+ preparations: preparationDefinitions(
6686
+ payload.preparations ?? [],
6687
+ "worktree payload.preparations"
6688
+ )
6593
6689
  };
6594
6690
  }
6595
6691
  function worktreeAutoSyncJobPayload(value) {
@@ -6601,7 +6697,9 @@ function worktreeAutoSyncJobPayload(value) {
6601
6697
  "expectedOrigin",
6602
6698
  "expectedBranch",
6603
6699
  "baseBranch",
6604
- "phase"
6700
+ "phase",
6701
+ "forcePreparations",
6702
+ "preparations"
6605
6703
  ]);
6606
6704
  const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6607
6705
  if (unexpected) {
@@ -6612,6 +6710,11 @@ function worktreeAutoSyncJobPayload(value) {
6612
6710
  if (payload.phase !== "SYNC" && payload.phase !== "FINALIZE") {
6613
6711
  throw new Error("worktree auto sync payload.phase is invalid");
6614
6712
  }
6713
+ if (payload.forcePreparations !== void 0 && typeof payload.forcePreparations !== "boolean") {
6714
+ throw new Error(
6715
+ "worktree auto sync payload.forcePreparations must be a boolean"
6716
+ );
6717
+ }
6615
6718
  return {
6616
6719
  codebaseId: stringValue4(
6617
6720
  payload.codebaseId,
@@ -6634,9 +6737,104 @@ function worktreeAutoSyncJobPayload(value) {
6634
6737
  payload.baseBranch,
6635
6738
  "worktree auto sync payload.baseBranch"
6636
6739
  ),
6637
- phase: payload.phase
6740
+ phase: payload.phase,
6741
+ forcePreparations: payload.forcePreparations === true,
6742
+ preparations: preparationDefinitions(
6743
+ payload.preparations ?? [],
6744
+ "worktree auto sync payload.preparations"
6745
+ )
6638
6746
  };
6639
6747
  }
6748
+ function worktreePreparationJobPayload(value) {
6749
+ const payload = objectValue4(value, "worktree preparation payload");
6750
+ const batched = payload.worktrees !== void 0;
6751
+ const allowed = new Set(
6752
+ batched ? ["codebaseId", "expectedOrigin", "action", "preparations", "worktrees"] : [
6753
+ "codebaseId",
6754
+ "folder",
6755
+ "gitDirectory",
6756
+ "expectedOrigin",
6757
+ "action",
6758
+ "preparations"
6759
+ ]
6760
+ );
6761
+ const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6762
+ if (unexpected) {
6763
+ throw new Error(
6764
+ `Unexpected worktree preparation payload field: ${unexpected}`
6765
+ );
6766
+ }
6767
+ if (typeof payload.action !== "string" || !WORKTREE_PREPARATION_ACTIONS.includes(
6768
+ payload.action
6769
+ )) {
6770
+ throw new Error("worktree preparation payload.action is invalid");
6771
+ }
6772
+ const common = {
6773
+ codebaseId: stringValue4(
6774
+ payload.codebaseId,
6775
+ "worktree preparation payload.codebaseId"
6776
+ ),
6777
+ expectedOrigin: stringValue4(
6778
+ payload.expectedOrigin,
6779
+ "worktree preparation payload.expectedOrigin"
6780
+ ),
6781
+ action: payload.action,
6782
+ preparations: preparationDefinitions(
6783
+ payload.preparations,
6784
+ "worktree preparation payload.preparations"
6785
+ )
6786
+ };
6787
+ if (!batched) {
6788
+ return {
6789
+ ...common,
6790
+ folder: stringValue4(
6791
+ payload.folder,
6792
+ "worktree preparation payload.folder"
6793
+ ),
6794
+ gitDirectory: stringValue4(
6795
+ payload.gitDirectory,
6796
+ "worktree preparation payload.gitDirectory"
6797
+ )
6798
+ };
6799
+ }
6800
+ if (!Array.isArray(payload.worktrees) || payload.worktrees.length > 500) {
6801
+ throw new Error(
6802
+ "worktree preparation payload.worktrees must be an array with at most 500 items"
6803
+ );
6804
+ }
6805
+ const worktrees = payload.worktrees.map((value2, index) => {
6806
+ const target2 = objectValue4(
6807
+ value2,
6808
+ `worktree preparation payload.worktrees[${index}]`
6809
+ );
6810
+ const unexpectedTarget = Object.keys(target2).find(
6811
+ (key) => !["worktreeId", "folder", "gitDirectory"].includes(key)
6812
+ );
6813
+ if (unexpectedTarget) {
6814
+ throw new Error(
6815
+ `Unexpected worktree preparation payload.worktrees[${index}] field: ${unexpectedTarget}`
6816
+ );
6817
+ }
6818
+ return {
6819
+ worktreeId: stringValue4(
6820
+ target2.worktreeId,
6821
+ `worktree preparation payload.worktrees[${index}].worktreeId`
6822
+ ),
6823
+ folder: stringValue4(
6824
+ target2.folder,
6825
+ `worktree preparation payload.worktrees[${index}].folder`
6826
+ ),
6827
+ gitDirectory: stringValue4(
6828
+ target2.gitDirectory,
6829
+ `worktree preparation payload.worktrees[${index}].gitDirectory`
6830
+ )
6831
+ };
6832
+ });
6833
+ if (new Set(worktrees.map(({ worktreeId }) => worktreeId)).size !== worktrees.length) {
6834
+ throw new Error("worktree preparation payload.worktreeIds must be unique");
6835
+ }
6836
+ return { ...common, worktrees };
6837
+ }
6640
6838
  function worktreeGitInspectPayload(value) {
6641
6839
  const payload = objectValue4(value, "worktree Git inspect payload");
6642
6840
  const allowed = /* @__PURE__ */ new Set([
@@ -6802,8 +7000,8 @@ function worktreeDiffPayload(value) {
6802
7000
  if (payload.side !== null && payload.side !== void 0 && payload.side !== "BEFORE" && payload.side !== "AFTER") {
6803
7001
  throw new Error("worktree diff payload.side is invalid");
6804
7002
  }
6805
- const path = payload.path === null || payload.path === void 0 ? null : safeRelativePath(payload.path, "worktree diff payload.path");
6806
- const previousPath = payload.previousPath === null || payload.previousPath === void 0 ? null : safeRelativePath(
7003
+ const path = payload.path === null || payload.path === void 0 ? null : safeDiffPath(payload.path, "worktree diff payload.path");
7004
+ const previousPath = payload.previousPath === null || payload.previousPath === void 0 ? null : safeDiffPath(
6807
7005
  payload.previousPath,
6808
7006
  "worktree diff payload.previousPath"
6809
7007
  );
@@ -8449,7 +8647,7 @@ function captureCommand(options) {
8449
8647
  outputTruncated: false
8450
8648
  });
8451
8649
  }
8452
- return new Promise((resolve8, reject) => {
8650
+ return new Promise((resolve9, reject) => {
8453
8651
  const stdoutChunks = [];
8454
8652
  const stderrChunks = [];
8455
8653
  let stdoutBytes = 0;
@@ -8545,7 +8743,7 @@ function captureCommand(options) {
8545
8743
  clearTimeout(timeout);
8546
8744
  if (killTimer) clearTimeout(killTimer);
8547
8745
  options.signal.removeEventListener("abort", abort);
8548
- resolve8({
8746
+ resolve9({
8549
8747
  exitCode,
8550
8748
  signal,
8551
8749
  timedOut,
@@ -8633,11 +8831,11 @@ async function reapOrphanedCommandProcesses(agentId, signal = new AbortControlle
8633
8831
  console.error(
8634
8832
  `Terminating ${signalled.length} command process(es) left by a previous agent run.`
8635
8833
  );
8636
- await new Promise((resolve8) => {
8637
- const timer = setTimeout(resolve8, TERMINATE_GRACE_MS);
8834
+ await new Promise((resolve9) => {
8835
+ const timer = setTimeout(resolve9, TERMINATE_GRACE_MS);
8638
8836
  timer.unref();
8639
- if (signal.aborted) resolve8();
8640
- else signal.addEventListener("abort", () => resolve8(), { once: true });
8837
+ if (signal.aborted) resolve9();
8838
+ else signal.addEventListener("abort", () => resolve9(), { once: true });
8641
8839
  });
8642
8840
  for (const orphan of signalled) signalGroup(orphan.processGroup, "SIGKILL");
8643
8841
  return signalled;
@@ -8693,14 +8891,14 @@ var runCommand = async (rawPayload, _timeoutMs, signal, _onLog, context) => {
8693
8891
  `Could not append command output; retrying in ${delay}ms:`,
8694
8892
  error instanceof Error ? error.message : error
8695
8893
  );
8696
- await new Promise((resolve8) => {
8894
+ await new Promise((resolve9) => {
8697
8895
  const onAbort = () => {
8698
8896
  clearTimeout(retryTimer);
8699
- resolve8();
8897
+ resolve9();
8700
8898
  };
8701
8899
  const retryTimer = setTimeout(() => {
8702
8900
  signal.removeEventListener("abort", onAbort);
8703
- resolve8();
8901
+ resolve9();
8704
8902
  }, delay);
8705
8903
  retryTimer.unref();
8706
8904
  signal.addEventListener("abort", onAbort, { once: true });
@@ -8738,7 +8936,7 @@ var runCommand = async (rawPayload, _timeoutMs, signal, _onLog, context) => {
8738
8936
  }
8739
8937
  };
8740
8938
  try {
8741
- return await new Promise((resolve8, reject) => {
8939
+ return await new Promise((resolve9, reject) => {
8742
8940
  let cancelled = false;
8743
8941
  let settled = false;
8744
8942
  const child = spawn2(process.env.SHELL || "/bin/sh", ["-l", scriptPath], {
@@ -8805,7 +9003,7 @@ var runCommand = async (rawPayload, _timeoutMs, signal, _onLog, context) => {
8805
9003
  signal.removeEventListener("abort", abort);
8806
9004
  flush();
8807
9005
  void uploadChain.then(
8808
- () => resolve8({
9006
+ () => resolve9({
8809
9007
  exitCode,
8810
9008
  signal: closeSignal,
8811
9009
  timedOut: false,
@@ -12624,7 +12822,7 @@ function prependPathDirectory(directory, env = process.env) {
12624
12822
  // src/process-runner.ts
12625
12823
  import { spawn as spawn5 } from "node:child_process";
12626
12824
  async function runProcess(options) {
12627
- return new Promise((resolve8, reject) => {
12825
+ return new Promise((resolve9, reject) => {
12628
12826
  let sequence = 0;
12629
12827
  let timedOut = false;
12630
12828
  let cancelled = false;
@@ -12719,7 +12917,7 @@ async function runProcess(options) {
12719
12917
  clearTimeout(timeout);
12720
12918
  options.signal.removeEventListener("abort", abort);
12721
12919
  void logChain.then(
12722
- () => resolve8({ exitCode, signal, timedOut, cancelled })
12920
+ () => resolve9({ exitCode, signal, timedOut, cancelled })
12723
12921
  );
12724
12922
  });
12725
12923
  });
@@ -14158,6 +14356,20 @@ function rootPath(location) {
14158
14356
  }
14159
14357
  return path;
14160
14358
  }
14359
+ function isContainedPath(base, candidate) {
14360
+ return candidate === base || candidate.startsWith(`${base}${sep6}`);
14361
+ }
14362
+ async function resolvedSkillRoot(location) {
14363
+ const root = rootPath(location);
14364
+ const resolvedRoot = await realpath6(root);
14365
+ if (location.scope === "PROJECT") {
14366
+ const resolvedProject = await realpath6(location.folder);
14367
+ if (!isContainedPath(resolvedProject, resolvedRoot)) {
14368
+ throw new Error("Project skill root resolves outside the project folder");
14369
+ }
14370
+ }
14371
+ return { root, resolvedRoot };
14372
+ }
14161
14373
  function targetForFolder(targets, folder) {
14162
14374
  return folder ? targets.find((target2) => resolve6(target2.folder) === resolve6(folder)) : void 0;
14163
14375
  }
@@ -14198,14 +14410,15 @@ async function listPackageFiles(skillDirectory) {
14198
14410
  await visit(skillDirectory);
14199
14411
  return files;
14200
14412
  }
14201
- async function readPackage(directory) {
14413
+ async function readPackage(directory, resolvedRoot) {
14202
14414
  const metadata = await lstat3(directory);
14203
- let resolvedDirectory = directory;
14204
- if (metadata.isSymbolicLink()) {
14205
- resolvedDirectory = await realpath6(directory);
14206
- } else if (!metadata.isDirectory()) {
14415
+ if (!metadata.isSymbolicLink() && !metadata.isDirectory()) {
14207
14416
  throw new Error("Skill path is not a directory");
14208
14417
  }
14418
+ const resolvedDirectory = await realpath6(directory);
14419
+ if (!isContainedPath(resolvedRoot, resolvedDirectory)) {
14420
+ throw new Error("Skill package resolves outside its configured root");
14421
+ }
14209
14422
  const files = await listPackageFiles(resolvedDirectory);
14210
14423
  const definition = files.find((file) => file.path === "SKILL.md");
14211
14424
  if (!definition) throw new Error("Skill does not contain SKILL.md");
@@ -14245,6 +14458,15 @@ function consumersForRoot(configured, rootKind, scope) {
14245
14458
  async function scanRoot2(location, configured, targets, warnings) {
14246
14459
  const root = rootPath(location);
14247
14460
  if (!await directoryExists(root)) return [];
14461
+ let resolvedRoot;
14462
+ try {
14463
+ resolvedRoot = (await resolvedSkillRoot(location)).resolvedRoot;
14464
+ } catch (error) {
14465
+ warnings.push(
14466
+ `${root}: ${error instanceof Error ? error.message : String(error)}`
14467
+ );
14468
+ return [];
14469
+ }
14248
14470
  const consumers = consumersForRoot(
14249
14471
  configured,
14250
14472
  location.rootKind,
@@ -14257,7 +14479,7 @@ async function scanRoot2(location, configured, targets, warnings) {
14257
14479
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
14258
14480
  const directory = join9(root, entry.name);
14259
14481
  try {
14260
- const skillPackage = await readPackage(directory);
14482
+ const skillPackage = await readPackage(directory, resolvedRoot);
14261
14483
  const relativeDirectory = location.folder ? relative6(location.folder, directory).split(sep6).join("/") : "";
14262
14484
  installations.push({
14263
14485
  ...location,
@@ -14332,9 +14554,10 @@ var readSkills = async (payload) => {
14332
14554
  if (!allowed.has(`${request.scope}:${root}`)) {
14333
14555
  throw new Error("Requested skill root is not enabled or configured");
14334
14556
  }
14557
+ const { resolvedRoot } = await resolvedSkillRoot(request);
14335
14558
  packages.push({
14336
14559
  ...request,
14337
- package: await readPackage(join9(root, request.skillName))
14560
+ package: await readPackage(join9(root, request.skillName), resolvedRoot)
14338
14561
  });
14339
14562
  }
14340
14563
  return { ...successfulProcess6, packages };
@@ -14588,7 +14811,7 @@ async function optionalGit(cwd, args) {
14588
14811
  }
14589
14812
  function cappedGit(cwd, args, limit) {
14590
14813
  const budget = limit - TRUNCATION_RESERVE;
14591
- return new Promise((resolve8, reject) => {
14814
+ return new Promise((resolve9, reject) => {
14592
14815
  const child = spawn6("git", args, {
14593
14816
  cwd,
14594
14817
  env: {
@@ -14638,7 +14861,7 @@ function cappedGit(cwd, args, limit) {
14638
14861
  return;
14639
14862
  }
14640
14863
  const output = Buffer.concat(chunks).toString("utf8");
14641
- resolve8(
14864
+ resolve9(
14642
14865
  truncated ? `${output.trimEnd()}
14643
14866
 
14644
14867
  [Truncated after ${budget} bytes]` : output.trim()
@@ -14948,10 +15171,494 @@ var runWorkflowGitCheckpoint = async (payloadValue, _timeoutMs, signal) => {
14948
15171
 
14949
15172
  // src/handlers/worktrees.ts
14950
15173
  import { createWriteStream as createWriteStream2, watch } from "node:fs";
14951
- import { mkdtemp as mkdtemp6, open as open2, readFile as readFile8, realpath as realpath8, rm as rm9, stat as stat10 } from "node:fs/promises";
15174
+ import { mkdtemp as mkdtemp6, open as open2, readFile as readFile9, realpath as realpath9, rm as rm10, stat as stat10 } from "node:fs/promises";
14952
15175
  import { tmpdir as tmpdir6 } from "node:os";
14953
- import { basename as basename5, dirname as dirname7, isAbsolute as isAbsolute6, join as join13, relative as relative7 } from "node:path";
15176
+ import { basename as basename5, dirname as dirname8, isAbsolute as isAbsolute7, join as join14, relative as relative8 } from "node:path";
14954
15177
  import { spawn as spawn7 } from "node:child_process";
15178
+
15179
+ // src/handlers/worktree-preparations.ts
15180
+ import { createHash as createHash7 } from "node:crypto";
15181
+ import {
15182
+ chmod as chmod4,
15183
+ lstat as lstat4,
15184
+ mkdir as mkdir5,
15185
+ readFile as readFile8,
15186
+ realpath as realpath8,
15187
+ rm as rm9,
15188
+ writeFile as writeFile7
15189
+ } from "node:fs/promises";
15190
+ import { dirname as dirname7, isAbsolute as isAbsolute6, join as join13, relative as relative7, resolve as resolve7 } from "node:path";
15191
+ var EXCLUDE_BEGIN = "# BEGIN AIDE PREPARATIONS";
15192
+ var EXCLUDE_END = "# END AIDE PREPARATIONS";
15193
+ function cleanError3(value) {
15194
+ return (value instanceof Error ? value.message : String(value)).replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+@/gi, "$1").slice(0, 2e3);
15195
+ }
15196
+ async function git3(folder, args, timeoutMs, signal) {
15197
+ return captureCommand({
15198
+ command: "git",
15199
+ args: ["-C", folder, ...args],
15200
+ timeoutMs,
15201
+ signal,
15202
+ env: {
15203
+ ...process.env,
15204
+ GIT_LITERAL_PATHSPECS: "1",
15205
+ GIT_OPTIONAL_LOCKS: "0",
15206
+ GIT_TERMINAL_PROMPT: "0"
15207
+ }
15208
+ });
15209
+ }
15210
+ function requireSuccess3(result, fallback) {
15211
+ if (result.cancelled) throw new Error("Preparation was cancelled");
15212
+ if (result.timedOut) throw new Error("Preparation timed out");
15213
+ if (result.exitCode !== 0) {
15214
+ throw new Error(cleanError3(result.stderr || fallback));
15215
+ }
15216
+ return result;
15217
+ }
15218
+ async function exists(path) {
15219
+ try {
15220
+ await lstat4(path);
15221
+ return true;
15222
+ } catch (error) {
15223
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
15224
+ return false;
15225
+ }
15226
+ throw error;
15227
+ }
15228
+ }
15229
+ async function safeTarget(folder, path) {
15230
+ const root = await realpath8(folder);
15231
+ const target2 = resolve7(root, path);
15232
+ const fromRoot = relative7(root, target2);
15233
+ if (!fromRoot || fromRoot.startsWith("..") || isAbsolute6(fromRoot) || path.includes("\0")) {
15234
+ throw new Error(
15235
+ "Preparation path must be an exact file inside the worktree"
15236
+ );
15237
+ }
15238
+ let current = root;
15239
+ const segments = fromRoot.split(/[\\/]/);
15240
+ for (const segment of segments.slice(0, -1)) {
15241
+ current = join13(current, segment);
15242
+ try {
15243
+ const info = await lstat4(current);
15244
+ if (info.isSymbolicLink()) {
15245
+ throw new Error(`Preparation path crosses symbolic link: ${path}`);
15246
+ }
15247
+ if (!info.isDirectory()) {
15248
+ throw new Error(`Preparation parent is not a directory: ${path}`);
15249
+ }
15250
+ } catch (error) {
15251
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
15252
+ break;
15253
+ }
15254
+ throw error;
15255
+ }
15256
+ }
15257
+ return target2;
15258
+ }
15259
+ async function isTracked(folder, path, timeoutMs, signal) {
15260
+ const result = await git3(
15261
+ folder,
15262
+ ["ls-files", "--error-unmatch", "--", path],
15263
+ timeoutMs,
15264
+ signal
15265
+ );
15266
+ if (result.exitCode === 0) return true;
15267
+ if (result.exitCode === 1) return false;
15268
+ requireSuccess3(result, `Could not inspect tracked path ${path}`);
15269
+ return false;
15270
+ }
15271
+ async function isAssumeUnchanged(folder, path, timeoutMs, signal) {
15272
+ const result = requireSuccess3(
15273
+ await git3(folder, ["ls-files", "-v", "--", path], timeoutMs, signal),
15274
+ `Could not inspect assume-unchanged state for ${path}`
15275
+ );
15276
+ const marker = result.stdout[0];
15277
+ return Boolean(marker && /[a-z]/.test(marker));
15278
+ }
15279
+ async function setAssumeUnchanged(folder, path, assumed, timeoutMs, signal) {
15280
+ requireSuccess3(
15281
+ await git3(
15282
+ folder,
15283
+ [
15284
+ "update-index",
15285
+ assumed ? "--assume-unchanged" : "--no-assume-unchanged",
15286
+ "--",
15287
+ path
15288
+ ],
15289
+ timeoutMs,
15290
+ signal
15291
+ ),
15292
+ `Could not ${assumed ? "mark" : "unmark"} ${path} as assume unchanged`
15293
+ );
15294
+ }
15295
+ function excludeEntry(path) {
15296
+ return `/${path}`;
15297
+ }
15298
+ function withoutAideExcludeBlock(value) {
15299
+ const lines = value.split(/\r?\n/);
15300
+ const output = [];
15301
+ let inBlock = false;
15302
+ for (const line of lines) {
15303
+ if (line === EXCLUDE_BEGIN) {
15304
+ inBlock = true;
15305
+ continue;
15306
+ }
15307
+ if (line === EXCLUDE_END) {
15308
+ inBlock = false;
15309
+ continue;
15310
+ }
15311
+ if (!inBlock) output.push(line);
15312
+ }
15313
+ return output.join("\n").replace(/\n+$/, "");
15314
+ }
15315
+ async function excludeFile(folder, timeoutMs, signal) {
15316
+ const result = requireSuccess3(
15317
+ await git3(
15318
+ folder,
15319
+ ["rev-parse", "--git-path", "info/exclude"],
15320
+ timeoutMs,
15321
+ signal
15322
+ ),
15323
+ "Could not locate the repository exclude file"
15324
+ );
15325
+ const candidate = result.stdout.trim();
15326
+ return isAbsolute6(candidate) ? candidate : resolve7(folder, candidate);
15327
+ }
15328
+ async function readExcludeEntries(folder, timeoutMs, signal) {
15329
+ const path = await excludeFile(folder, timeoutMs, signal);
15330
+ let value = "";
15331
+ try {
15332
+ value = await readFile8(path, "utf8");
15333
+ } catch (error) {
15334
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
15335
+ throw error;
15336
+ }
15337
+ }
15338
+ const start = value.split(/\r?\n/).indexOf(EXCLUDE_BEGIN);
15339
+ const end = value.split(/\r?\n/).indexOf(EXCLUDE_END);
15340
+ if (start < 0 || end <= start) return /* @__PURE__ */ new Set();
15341
+ return new Set(value.split(/\r?\n/).slice(start + 1, end));
15342
+ }
15343
+ async function reconcileExcludeFile(folder, definitions, timeoutMs, signal) {
15344
+ const path = await excludeFile(folder, timeoutMs, signal);
15345
+ let existing = "";
15346
+ try {
15347
+ existing = await readFile8(path, "utf8");
15348
+ } catch (error) {
15349
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
15350
+ throw error;
15351
+ }
15352
+ }
15353
+ const base = withoutAideExcludeBlock(existing);
15354
+ const entries = definitions.filter((definition) => definition.kind === "WRITE").map((definition) => excludeEntry(definition.path)).sort((left, right) => left.localeCompare(right));
15355
+ const block = entries.length ? [EXCLUDE_BEGIN, ...entries, EXCLUDE_END].join("\n") : "";
15356
+ const next = [base, block].filter(Boolean).join("\n\n");
15357
+ await mkdir5(dirname7(path), { recursive: true });
15358
+ await writeFile7(path, next ? `${next}
15359
+ ` : "", "utf8");
15360
+ }
15361
+ function decodeContents(definition) {
15362
+ if (definition.contentBase64 === null) {
15363
+ throw new Error(`Write preparation ${definition.path} has no contents`);
15364
+ }
15365
+ const contents = Buffer.from(definition.contentBase64, "base64");
15366
+ const canonicalInput = definition.contentBase64.replace(/=+$/, "");
15367
+ if (contents.toString("base64").replace(/=+$/, "") !== canonicalInput) {
15368
+ throw new Error(
15369
+ `Write preparation ${definition.path} has invalid base64 contents`
15370
+ );
15371
+ }
15372
+ return contents;
15373
+ }
15374
+ async function removeTarget(target2, path) {
15375
+ try {
15376
+ const info = await lstat4(target2);
15377
+ if (info.isDirectory() && !info.isSymbolicLink()) {
15378
+ throw new Error(`Preparation path is a directory: ${path}`);
15379
+ }
15380
+ await rm9(target2, { force: true });
15381
+ } catch (error) {
15382
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
15383
+ return;
15384
+ }
15385
+ throw error;
15386
+ }
15387
+ }
15388
+ async function restoreFromHead(folder, definition, timeoutMs, signal) {
15389
+ const target2 = await safeTarget(folder, definition.path);
15390
+ if (await isTracked(folder, definition.path, timeoutMs, signal)) {
15391
+ await setAssumeUnchanged(folder, definition.path, false, timeoutMs, signal);
15392
+ const atHead = await git3(
15393
+ folder,
15394
+ ["cat-file", "-e", `HEAD:${definition.path}`],
15395
+ timeoutMs,
15396
+ signal
15397
+ );
15398
+ if (atHead.exitCode === 0) {
15399
+ requireSuccess3(
15400
+ await git3(
15401
+ folder,
15402
+ ["restore", "--source=HEAD", "--worktree", "--", definition.path],
15403
+ timeoutMs,
15404
+ signal
15405
+ ),
15406
+ `Could not restore ${definition.path} from HEAD`
15407
+ );
15408
+ return;
15409
+ }
15410
+ if (atHead.exitCode !== 1 && atHead.exitCode !== 128) {
15411
+ requireSuccess3(atHead, `Could not inspect ${definition.path} in HEAD`);
15412
+ }
15413
+ }
15414
+ await removeTarget(target2, definition.path);
15415
+ }
15416
+ async function applyOne(folder, definition, timeoutMs, signal) {
15417
+ const target2 = await safeTarget(folder, definition.path);
15418
+ const tracked = await isTracked(folder, definition.path, timeoutMs, signal);
15419
+ if (definition.kind === "ASSUME_UNCHANGED") {
15420
+ if (!tracked) return "NOT_APPLICABLE";
15421
+ await setAssumeUnchanged(folder, definition.path, true, timeoutMs, signal);
15422
+ return "APPLIED";
15423
+ }
15424
+ if (definition.kind === "DELETE") {
15425
+ await removeTarget(target2, definition.path);
15426
+ } else {
15427
+ const contents = decodeContents(definition);
15428
+ let executable = false;
15429
+ try {
15430
+ const info = await lstat4(target2);
15431
+ if (info.isDirectory() && !info.isSymbolicLink()) {
15432
+ throw new Error(`Preparation path is a directory: ${definition.path}`);
15433
+ }
15434
+ executable = info.isFile() && (info.mode & 73) !== 0;
15435
+ if (info.isSymbolicLink()) await rm9(target2, { force: true });
15436
+ } catch (error) {
15437
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
15438
+ throw error;
15439
+ }
15440
+ }
15441
+ await mkdir5(dirname7(target2), { recursive: true, mode: 493 });
15442
+ await safeTarget(folder, definition.path);
15443
+ await writeFile7(target2, contents, { mode: executable ? 493 : 420 });
15444
+ if (executable) await chmod4(target2, 493);
15445
+ }
15446
+ if (tracked) {
15447
+ await setAssumeUnchanged(folder, definition.path, true, timeoutMs, signal);
15448
+ }
15449
+ return "APPLIED";
15450
+ }
15451
+ async function undoOne(folder, definition, timeoutMs, signal) {
15452
+ if (definition.kind === "ASSUME_UNCHANGED") {
15453
+ if (!await isTracked(folder, definition.path, timeoutMs, signal)) {
15454
+ return "NOT_APPLICABLE";
15455
+ }
15456
+ await setAssumeUnchanged(folder, definition.path, false, timeoutMs, signal);
15457
+ return "UNDONE";
15458
+ }
15459
+ await restoreFromHead(folder, definition, timeoutMs, signal);
15460
+ return "UNDONE";
15461
+ }
15462
+ async function inspectOne(folder, definition, excludeEntries, timeoutMs, signal) {
15463
+ const target2 = await safeTarget(folder, definition.path);
15464
+ const tracked = await isTracked(folder, definition.path, timeoutMs, signal);
15465
+ const assumed = tracked ? await isAssumeUnchanged(folder, definition.path, timeoutMs, signal) : false;
15466
+ if (definition.kind === "ASSUME_UNCHANGED") {
15467
+ return tracked ? assumed ? "APPLIED" : "DRIFTED" : "NOT_APPLICABLE";
15468
+ }
15469
+ if (definition.kind === "DELETE") {
15470
+ return !await exists(target2) && (!tracked || assumed) ? "APPLIED" : "DRIFTED";
15471
+ }
15472
+ let matches = false;
15473
+ try {
15474
+ const info = await lstat4(target2);
15475
+ if (info.isFile()) {
15476
+ const expected = createHash7("sha256").update(decodeContents(definition)).digest("hex");
15477
+ const actual = createHash7("sha256").update(await readFile8(target2)).digest("hex");
15478
+ matches = actual === expected;
15479
+ }
15480
+ } catch (error) {
15481
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
15482
+ throw error;
15483
+ }
15484
+ }
15485
+ const hidden = tracked ? assumed : excludeEntries.has(excludeEntry(definition.path));
15486
+ return matches && hidden ? "APPLIED" : "DRIFTED";
15487
+ }
15488
+ async function executeWorktreePreparations(folder, definitions, action, timeoutMs, signal) {
15489
+ let excludeError = null;
15490
+ if (action !== "INSPECT") {
15491
+ try {
15492
+ await reconcileExcludeFile(folder, definitions, timeoutMs, signal);
15493
+ } catch (error) {
15494
+ excludeError = cleanError3(error);
15495
+ }
15496
+ }
15497
+ let excludeEntries = /* @__PURE__ */ new Set();
15498
+ try {
15499
+ excludeEntries = await readExcludeEntries(folder, timeoutMs, signal);
15500
+ } catch (error) {
15501
+ excludeError ??= cleanError3(error);
15502
+ }
15503
+ const results = [];
15504
+ for (const definition of definitions) {
15505
+ if (definition.kind === "WRITE" && excludeError) {
15506
+ results.push({
15507
+ id: definition.id,
15508
+ definitionHash: definition.definitionHash,
15509
+ state: "ERROR",
15510
+ message: excludeError
15511
+ });
15512
+ continue;
15513
+ }
15514
+ try {
15515
+ const state = action === "APPLY" ? await applyOne(folder, definition, timeoutMs, signal) : action === "UNDO" ? await undoOne(folder, definition, timeoutMs, signal) : await inspectOne(
15516
+ folder,
15517
+ definition,
15518
+ excludeEntries,
15519
+ timeoutMs,
15520
+ signal
15521
+ );
15522
+ results.push({
15523
+ id: definition.id,
15524
+ definitionHash: definition.definitionHash,
15525
+ state
15526
+ });
15527
+ } catch (error) {
15528
+ results.push({
15529
+ id: definition.id,
15530
+ definitionHash: definition.definitionHash,
15531
+ state: "ERROR",
15532
+ message: cleanError3(error)
15533
+ });
15534
+ }
15535
+ }
15536
+ return results;
15537
+ }
15538
+ async function suspendWorktreePreparations(folder, definitions, timeoutMs, signal, preserveAssumeUnchangedContents = false) {
15539
+ let excludeError = null;
15540
+ try {
15541
+ await reconcileExcludeFile(folder, definitions, timeoutMs, signal);
15542
+ } catch (error) {
15543
+ excludeError = cleanError3(error);
15544
+ }
15545
+ const results = [];
15546
+ for (const definition of definitions) {
15547
+ if (definition.kind === "WRITE" && excludeError) {
15548
+ results.push({
15549
+ id: definition.id,
15550
+ definitionHash: definition.definitionHash,
15551
+ state: "ERROR",
15552
+ message: excludeError
15553
+ });
15554
+ continue;
15555
+ }
15556
+ try {
15557
+ if (definition.kind === "ASSUME_UNCHANGED") {
15558
+ if (await isTracked(folder, definition.path, timeoutMs, signal)) {
15559
+ if (preserveAssumeUnchangedContents) {
15560
+ await setAssumeUnchanged(
15561
+ folder,
15562
+ definition.path,
15563
+ false,
15564
+ timeoutMs,
15565
+ signal
15566
+ );
15567
+ } else {
15568
+ await restoreFromHead(folder, definition, timeoutMs, signal);
15569
+ }
15570
+ results.push({
15571
+ id: definition.id,
15572
+ definitionHash: definition.definitionHash,
15573
+ state: "SUSPENDED"
15574
+ });
15575
+ } else {
15576
+ results.push({
15577
+ id: definition.id,
15578
+ definitionHash: definition.definitionHash,
15579
+ state: "NOT_APPLICABLE"
15580
+ });
15581
+ }
15582
+ } else {
15583
+ await restoreFromHead(folder, definition, timeoutMs, signal);
15584
+ results.push({
15585
+ id: definition.id,
15586
+ definitionHash: definition.definitionHash,
15587
+ state: "SUSPENDED"
15588
+ });
15589
+ }
15590
+ } catch (error) {
15591
+ results.push({
15592
+ id: definition.id,
15593
+ definitionHash: definition.definitionHash,
15594
+ state: "ERROR",
15595
+ message: cleanError3(error)
15596
+ });
15597
+ }
15598
+ }
15599
+ return results;
15600
+ }
15601
+ async function preparationConflictPaths(folder, definitions, remoteBase, timeoutMs, signal) {
15602
+ const paths = [];
15603
+ for (const definition of definitions) {
15604
+ const changedByBase = await git3(
15605
+ folder,
15606
+ ["diff", "--quiet", `HEAD...${remoteBase}`, "--", definition.path],
15607
+ timeoutMs,
15608
+ signal
15609
+ );
15610
+ if (changedByBase.exitCode === 1) {
15611
+ const tracked = await isTracked(
15612
+ folder,
15613
+ definition.path,
15614
+ timeoutMs,
15615
+ signal
15616
+ );
15617
+ let managedChange = false;
15618
+ if (tracked) {
15619
+ const head = await git3(
15620
+ folder,
15621
+ ["rev-parse", `HEAD:${definition.path}`],
15622
+ timeoutMs,
15623
+ signal
15624
+ );
15625
+ const working = await git3(
15626
+ folder,
15627
+ ["hash-object", "--", definition.path],
15628
+ timeoutMs,
15629
+ signal
15630
+ );
15631
+ managedChange = head.exitCode !== 0 || working.exitCode !== 0 || head.stdout.trim() !== working.stdout.trim();
15632
+ } else if (definition.kind === "WRITE") {
15633
+ managedChange = await exists(await safeTarget(folder, definition.path));
15634
+ } else {
15635
+ const presentOnBase = await git3(
15636
+ folder,
15637
+ ["cat-file", "-e", `${remoteBase}:${definition.path}`],
15638
+ timeoutMs,
15639
+ signal
15640
+ );
15641
+ if (presentOnBase.exitCode === 0) {
15642
+ managedChange = true;
15643
+ } else if (presentOnBase.exitCode !== 1 && presentOnBase.exitCode !== 128) {
15644
+ requireSuccess3(
15645
+ presentOnBase,
15646
+ `Could not inspect ${definition.path} on the base branch`
15647
+ );
15648
+ }
15649
+ }
15650
+ if (managedChange) paths.push(definition.path);
15651
+ continue;
15652
+ }
15653
+ requireSuccess3(
15654
+ changedByBase,
15655
+ `Could not inspect preparation conflict for ${definition.path}`
15656
+ );
15657
+ }
15658
+ return paths;
15659
+ }
15660
+
15661
+ // src/handlers/worktrees.ts
14955
15662
  var successfulProcess8 = {
14956
15663
  exitCode: 0,
14957
15664
  signal: null,
@@ -14995,7 +15702,7 @@ function statusChangeState(value) {
14995
15702
  }
14996
15703
  async function rebaseInProgress(folder, timeoutMs, signal) {
14997
15704
  for (const name of ["rebase-merge", "rebase-apply"]) {
14998
- const pathResult = await git3(
15705
+ const pathResult = await git4(
14999
15706
  folder,
15000
15707
  ["rev-parse", "--git-path", name],
15001
15708
  timeoutMs,
@@ -15005,7 +15712,7 @@ async function rebaseInProgress(folder, timeoutMs, signal) {
15005
15712
  const candidate = pathResult.stdout.trim();
15006
15713
  if (!candidate) continue;
15007
15714
  try {
15008
- await stat10(isAbsolute6(candidate) ? candidate : join13(folder, candidate));
15715
+ await stat10(isAbsolute7(candidate) ? candidate : join14(folder, candidate));
15009
15716
  return true;
15010
15717
  } catch {
15011
15718
  }
@@ -15014,7 +15721,7 @@ async function rebaseInProgress(folder, timeoutMs, signal) {
15014
15721
  }
15015
15722
  async function rebaseBranch(folder, timeoutMs, signal) {
15016
15723
  for (const name of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
15017
- const pathResult = await git3(
15724
+ const pathResult = await git4(
15018
15725
  folder,
15019
15726
  ["rev-parse", "--git-path", name],
15020
15727
  timeoutMs,
@@ -15024,8 +15731,8 @@ async function rebaseBranch(folder, timeoutMs, signal) {
15024
15731
  const candidate = pathResult.stdout.trim();
15025
15732
  if (!candidate) continue;
15026
15733
  try {
15027
- const headName = (await readFile8(
15028
- isAbsolute6(candidate) ? candidate : join13(folder, candidate),
15734
+ const headName = (await readFile9(
15735
+ isAbsolute7(candidate) ? candidate : join14(folder, candidate),
15029
15736
  "utf8"
15030
15737
  )).trim();
15031
15738
  if (headName.startsWith("refs/heads/")) {
@@ -15059,7 +15766,7 @@ async function flushWorktreeActivity(entry) {
15059
15766
  try {
15060
15767
  const signal = new AbortController().signal;
15061
15768
  const [status2, branchResult, headResult, codeStateHash, rebasing] = await Promise.all([
15062
- git3(
15769
+ git4(
15063
15770
  entry.folder,
15064
15771
  [
15065
15772
  "--no-optional-locks",
@@ -15071,13 +15778,13 @@ async function flushWorktreeActivity(entry) {
15071
15778
  entry.timeoutMs,
15072
15779
  signal
15073
15780
  ),
15074
- git3(
15781
+ git4(
15075
15782
  entry.folder,
15076
15783
  ["symbolic-ref", "--short", "-q", "HEAD"],
15077
15784
  entry.timeoutMs,
15078
15785
  signal
15079
15786
  ),
15080
- git3(entry.folder, ["rev-parse", "HEAD"], entry.timeoutMs, signal),
15787
+ git4(entry.folder, ["rev-parse", "HEAD"], entry.timeoutMs, signal),
15081
15788
  worktreeCodeStateHash(entry.folder, entry.timeoutMs, signal),
15082
15789
  rebaseInProgress(entry.folder, entry.timeoutMs, signal)
15083
15790
  ]);
@@ -15106,7 +15813,7 @@ async function flushWorktreeActivity(entry) {
15106
15813
  observedAt: (/* @__PURE__ */ new Date()).toISOString()
15107
15814
  };
15108
15815
  if (headIdentity && headIdentity !== entry.headIdentity) {
15109
- const upstreamResult = branch ? await git3(
15816
+ const upstreamResult = branch ? await git4(
15110
15817
  entry.folder,
15111
15818
  [
15112
15819
  "rev-parse",
@@ -15164,24 +15871,24 @@ function scheduleWorktreeActivity(entry) {
15164
15871
  }, WATCH_DEBOUNCE_MS);
15165
15872
  entry.timer.unref();
15166
15873
  }
15167
- function cleanError3(value) {
15874
+ function cleanError4(value) {
15168
15875
  return (value instanceof Error ? value.message : String(value)).replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+@/gi, "$1").slice(0, 2e3);
15169
15876
  }
15170
15877
  async function command2(executable, args, timeoutMs, signal, env = process.env) {
15171
15878
  return captureCommand({ command: executable, args, timeoutMs, signal, env });
15172
15879
  }
15173
- async function git3(folder, args, timeoutMs, signal) {
15880
+ async function git4(folder, args, timeoutMs, signal) {
15174
15881
  return command2("git", ["-C", folder, ...args], timeoutMs, signal, {
15175
15882
  ...process.env,
15176
15883
  GIT_TERMINAL_PROMPT: "0",
15177
15884
  GIT_OPTIONAL_LOCKS: "0"
15178
15885
  });
15179
15886
  }
15180
- function requireSuccess3(result, fallback) {
15887
+ function requireSuccess4(result, fallback) {
15181
15888
  if (result.cancelled) throw new Error("Worktree operation was cancelled");
15182
15889
  if (result.timedOut) throw new Error("Worktree operation timed out");
15183
15890
  if (result.exitCode !== 0)
15184
- throw new Error(cleanError3(result.stderr || fallback));
15891
+ throw new Error(cleanError4(result.stderr || fallback));
15185
15892
  return result;
15186
15893
  }
15187
15894
  function parseWorktreeList(value) {
@@ -15199,8 +15906,8 @@ function parseWorktreeList(value) {
15199
15906
  }).filter((entry) => Boolean(entry.folder));
15200
15907
  }
15201
15908
  async function gitDirectory(folder, timeoutMs, signal) {
15202
- const result = requireSuccess3(
15203
- await git3(
15909
+ const result = requireSuccess4(
15910
+ await git4(
15204
15911
  folder,
15205
15912
  ["rev-parse", "--path-format=absolute", "--git-dir"],
15206
15913
  timeoutMs,
@@ -15208,17 +15915,17 @@ async function gitDirectory(folder, timeoutMs, signal) {
15208
15915
  ),
15209
15916
  "Could not resolve the worktree Git directory"
15210
15917
  );
15211
- return realpath8(result.stdout.trim());
15918
+ return realpath9(result.stdout.trim());
15212
15919
  }
15213
15920
  async function origin(folder, timeoutMs, signal) {
15214
- const result = requireSuccess3(
15215
- await git3(folder, ["remote", "get-url", "origin"], timeoutMs, signal),
15921
+ const result = requireSuccess4(
15922
+ await git4(folder, ["remote", "get-url", "origin"], timeoutMs, signal),
15216
15923
  "Repository does not have an origin remote"
15217
15924
  );
15218
15925
  return normalizeGitOrigin(result.stdout.trim()).canonicalOrigin;
15219
15926
  }
15220
15927
  async function validateWorktree2(input, timeoutMs, signal) {
15221
- const folder = await realpath8(input.folder);
15928
+ const folder = await realpath9(input.folder);
15222
15929
  if (!(await stat10(folder)).isDirectory())
15223
15930
  throw new Error("Worktree is missing");
15224
15931
  const observedGitDirectory = await gitDirectory(folder, timeoutMs, signal);
@@ -15231,7 +15938,7 @@ async function validateWorktree2(input, timeoutMs, signal) {
15231
15938
  return folder;
15232
15939
  }
15233
15940
  async function counts(folder, range, timeoutMs, signal) {
15234
- const result = await git3(
15941
+ const result = await git4(
15235
15942
  folder,
15236
15943
  ["rev-list", "--left-right", "--count", range],
15237
15944
  timeoutMs,
@@ -15265,17 +15972,17 @@ async function worktreePushStatus(folder, branch, changes, timeoutMs, signal) {
15265
15972
  async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary, timeoutMs, signal) {
15266
15973
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
15267
15974
  try {
15268
- const folder = await realpath8(folderValue2);
15975
+ const folder = await realpath9(folderValue2);
15269
15976
  const [gitDir, branchResult, headResult, statusResult, rebasing] = await Promise.all([
15270
15977
  gitDirectory(folder, timeoutMs, signal),
15271
- git3(
15978
+ git4(
15272
15979
  folder,
15273
15980
  ["symbolic-ref", "--short", "-q", "HEAD"],
15274
15981
  timeoutMs,
15275
15982
  signal
15276
15983
  ),
15277
- git3(folder, ["rev-parse", "HEAD"], timeoutMs, signal),
15278
- git3(
15984
+ git4(folder, ["rev-parse", "HEAD"], timeoutMs, signal),
15985
+ git4(
15279
15986
  folder,
15280
15987
  [
15281
15988
  "--no-optional-locks",
@@ -15291,7 +15998,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
15291
15998
  ]);
15292
15999
  const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
15293
16000
  const branch = symbolicBranch ?? (rebasing ? await rebaseBranch(folder, timeoutMs, signal) : null);
15294
- const upstreamResult = branch ? await git3(
16001
+ const upstreamResult = branch ? await git4(
15295
16002
  folder,
15296
16003
  ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
15297
16004
  timeoutMs,
@@ -15314,7 +16021,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
15314
16021
  return {
15315
16022
  gitDirectory: gitDir,
15316
16023
  folder,
15317
- relativePath: relative7(rootFolder, folder) || ".",
16024
+ relativePath: relative8(rootFolder, folder) || ".",
15318
16025
  primary,
15319
16026
  branch,
15320
16027
  headSha: headResult.exitCode === 0 ? headResult.stdout.trim() : null,
@@ -15342,7 +16049,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
15342
16049
  return {
15343
16050
  gitDirectory: folderValue2,
15344
16051
  folder: folderValue2,
15345
- relativePath: relative7(rootFolder, folderValue2) || ".",
16052
+ relativePath: relative8(rootFolder, folderValue2) || ".",
15346
16053
  primary,
15347
16054
  branch: null,
15348
16055
  headSha: null,
@@ -15359,15 +16066,15 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
15359
16066
  hasConflicts: false,
15360
16067
  pushStatus: "UNKNOWN",
15361
16068
  availability: "ERROR",
15362
- error: cleanError3(error),
16069
+ error: cleanError4(error),
15363
16070
  checkedAt
15364
16071
  };
15365
16072
  }
15366
16073
  }
15367
16074
  async function discoverWorktrees(rootFolderValue, baseOverrides, knownDefaultBranch, timeoutMs, signal) {
15368
- const rootFolder = await realpath8(rootFolderValue);
15369
- const list = requireSuccess3(
15370
- await git3(
16075
+ const rootFolder = await realpath9(rootFolderValue);
16076
+ const list = requireSuccess4(
16077
+ await git4(
15371
16078
  rootFolder,
15372
16079
  ["worktree", "list", "--porcelain"],
15373
16080
  timeoutMs,
@@ -15375,14 +16082,14 @@ async function discoverWorktrees(rootFolderValue, baseOverrides, knownDefaultBra
15375
16082
  ),
15376
16083
  "Could not list Git worktrees"
15377
16084
  );
15378
- const remoteHead = await git3(
16085
+ const remoteHead = await git4(
15379
16086
  rootFolder,
15380
16087
  ["ls-remote", "--symref", "origin", "HEAD"],
15381
16088
  timeoutMs,
15382
16089
  signal
15383
16090
  );
15384
16091
  let defaultBranch = remoteHead.stdout.match(/^ref:\s+refs\/heads\/([^\s]+)\s+HEAD/m)?.[1] ?? null;
15385
- const defaultResult = await git3(
16092
+ const defaultResult = await git4(
15386
16093
  rootFolder,
15387
16094
  ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"],
15388
16095
  timeoutMs,
@@ -15393,13 +16100,13 @@ async function discoverWorktrees(rootFolderValue, baseOverrides, knownDefaultBra
15393
16100
  defaultBranch = localDefaultBranch || knownDefaultBranch;
15394
16101
  }
15395
16102
  const [localBranchesResult, remoteBranchesResult] = await Promise.all([
15396
- git3(
16103
+ git4(
15397
16104
  rootFolder,
15398
16105
  ["for-each-ref", "--format=%(refname:strip=2)", "refs/heads"],
15399
16106
  timeoutMs,
15400
16107
  signal
15401
16108
  ),
15402
- git3(
16109
+ git4(
15403
16110
  rootFolder,
15404
16111
  ["for-each-ref", "--format=%(refname:strip=3)", "refs/remotes/origin"],
15405
16112
  timeoutMs,
@@ -15462,7 +16169,7 @@ async function untrackedLines(folder, path) {
15462
16169
  try {
15463
16170
  const file = await stat10(`${folder}/${path}`);
15464
16171
  if (!file.isFile() || file.size > 1024 * 1024) return null;
15465
- const contents = await readFile8(`${folder}/${path}`);
16172
+ const contents = await readFile9(`${folder}/${path}`);
15466
16173
  if (contents.includes(0)) return null;
15467
16174
  const text2 = contents.toString("utf8");
15468
16175
  return text2 ? text2.split("\n").length - (text2.endsWith("\n") ? 1 : 0) : 0;
@@ -15472,16 +16179,16 @@ async function untrackedLines(folder, path) {
15472
16179
  }
15473
16180
  async function inspectChanges(folder, timeoutMs, signal) {
15474
16181
  const [statusResult, stagedResult, unstagedResult] = await Promise.all([
15475
- git3(
16182
+ git4(
15476
16183
  folder,
15477
16184
  ["status", "--porcelain=v1", "-z", "--untracked-files=all"],
15478
16185
  timeoutMs,
15479
16186
  signal
15480
16187
  ),
15481
- git3(folder, ["diff", "--cached", "--numstat", "-z"], timeoutMs, signal),
15482
- git3(folder, ["diff", "--numstat", "-z"], timeoutMs, signal)
16188
+ git4(folder, ["diff", "--cached", "--numstat", "-z"], timeoutMs, signal),
16189
+ git4(folder, ["diff", "--numstat", "-z"], timeoutMs, signal)
15483
16190
  ]);
15484
- requireSuccess3(statusResult, "Could not inspect worktree changes");
16191
+ requireSuccess4(statusResult, "Could not inspect worktree changes");
15485
16192
  const stagedCounts = parseNumstat(stagedResult.stdout);
15486
16193
  const unstagedCounts = parseNumstat(unstagedResult.stdout);
15487
16194
  const values = statusResult.stdout.split("\0").filter(Boolean);
@@ -15541,11 +16248,11 @@ function parseNameStatus(value) {
15541
16248
  }
15542
16249
  async function diffFiles(folder, range, timeoutMs, signal) {
15543
16250
  const [status2, counts2] = await Promise.all([
15544
- git3(folder, ["diff", "--name-status", "-z", range], timeoutMs, signal),
15545
- git3(folder, ["diff", "--numstat", "-z", range], timeoutMs, signal)
16251
+ git4(folder, ["diff", "--name-status", "-z", range], timeoutMs, signal),
16252
+ git4(folder, ["diff", "--numstat", "-z", range], timeoutMs, signal)
15546
16253
  ]);
15547
- requireSuccess3(status2, "Could not inspect changed files");
15548
- requireSuccess3(counts2, "Could not inspect changed line counts");
16254
+ requireSuccess4(status2, "Could not inspect changed files");
16255
+ requireSuccess4(counts2, "Could not inspect changed line counts");
15549
16256
  const numstat = parseNumstat(counts2.stdout);
15550
16257
  return parseNameStatus(status2.stdout).map((file) => {
15551
16258
  const [additions, deletions] = numstat.get(file.path) ?? [null, null];
@@ -15559,8 +16266,8 @@ async function diffFiles(folder, range, timeoutMs, signal) {
15559
16266
  });
15560
16267
  }
15561
16268
  async function inspectBranchChanges(folder, baseBranch, timeoutMs, signal) {
15562
- const mergeBase = requireSuccess3(
15563
- await git3(
16269
+ const mergeBase = requireSuccess4(
16270
+ await git4(
15564
16271
  folder,
15565
16272
  ["merge-base", `refs/remotes/origin/${baseBranch}`, "HEAD"],
15566
16273
  timeoutMs,
@@ -15577,8 +16284,8 @@ async function inspectBranchChanges(folder, baseBranch, timeoutMs, signal) {
15577
16284
  return { changes: files.slice(0, 500), truncated: files.length > 500 };
15578
16285
  }
15579
16286
  async function inspectCommits(folder, baseBranch, timeoutMs, signal) {
15580
- const result = requireSuccess3(
15581
- await git3(
16287
+ const result = requireSuccess4(
16288
+ await git4(
15582
16289
  folder,
15583
16290
  [
15584
16291
  "log",
@@ -15611,7 +16318,7 @@ async function inspectWorktreeDetail(folder, baseBranch, timeoutMs, signal) {
15611
16318
  inspectCommits(folder, baseBranch, timeoutMs, signal),
15612
16319
  inspectChanges(folder, timeoutMs, signal),
15613
16320
  inspectBranchChanges(folder, baseBranch, timeoutMs, signal),
15614
- git3(
16321
+ git4(
15615
16322
  folder,
15616
16323
  ["config", "--bool", "--get", "commit.gpgsign"],
15617
16324
  timeoutMs,
@@ -15629,8 +16336,8 @@ async function inspectWorktreeDetail(folder, baseBranch, timeoutMs, signal) {
15629
16336
  };
15630
16337
  }
15631
16338
  async function baseMergeCommit(folder, baseBranch, timeoutMs, signal) {
15632
- return requireSuccess3(
15633
- await git3(
16339
+ return requireSuccess4(
16340
+ await git4(
15634
16341
  folder,
15635
16342
  ["merge-base", `refs/remotes/origin/${baseBranch}`, "HEAD"],
15636
16343
  timeoutMs,
@@ -15645,13 +16352,13 @@ async function validateDisplayedCommit(folder, baseBranch, commitSha, timeoutMs,
15645
16352
  }
15646
16353
  const base = await baseMergeCommit(folder, baseBranch, timeoutMs, signal);
15647
16354
  const [afterBase, beforeHead] = await Promise.all([
15648
- git3(
16355
+ git4(
15649
16356
  folder,
15650
16357
  ["merge-base", "--is-ancestor", base, commitSha],
15651
16358
  timeoutMs,
15652
16359
  signal
15653
16360
  ),
15654
- git3(
16361
+ git4(
15655
16362
  folder,
15656
16363
  ["merge-base", "--is-ancestor", commitSha, "HEAD"],
15657
16364
  timeoutMs,
@@ -15663,7 +16370,7 @@ async function validateDisplayedCommit(folder, baseBranch, commitSha, timeoutMs,
15663
16370
  }
15664
16371
  }
15665
16372
  async function parentCommit(folder, commitSha, timeoutMs, signal) {
15666
- const result = await git3(
16373
+ const result = await git4(
15667
16374
  folder,
15668
16375
  ["rev-parse", `${commitSha}^`],
15669
16376
  timeoutMs,
@@ -15672,13 +16379,13 @@ async function parentCommit(folder, commitSha, timeoutMs, signal) {
15672
16379
  return result.exitCode === 0 ? result.stdout.trim() : null;
15673
16380
  }
15674
16381
  async function gitObjectExists(folder, specification, timeoutMs, signal) {
15675
- return (await git3(folder, ["cat-file", "-e", specification], timeoutMs, signal)).exitCode === 0;
16382
+ return (await git4(folder, ["cat-file", "-e", specification], timeoutMs, signal)).exitCode === 0;
15676
16383
  }
15677
16384
  async function comparisonSides(input, folder, timeoutMs, signal) {
15678
16385
  if (!input.path) return { before: null, after: null };
15679
16386
  const path = input.path;
15680
16387
  const previousPath = input.previousPath ?? path;
15681
- const currentPath = join13(folder, path);
16388
+ const currentPath = join14(folder, path);
15682
16389
  if (input.scope === "UNTRACKED") {
15683
16390
  return { before: null, after: { kind: "FILE", path: currentPath } };
15684
16391
  }
@@ -15780,8 +16487,8 @@ async function availableSide(side, folder, timeoutMs, signal) {
15780
16487
  return gitObjectExists(folder, side.specification, timeoutMs, signal);
15781
16488
  }
15782
16489
  try {
15783
- const resolved = await realpath8(side.path);
15784
- const difference = relative7(folder, resolved);
16490
+ const resolved = await realpath9(side.path);
16491
+ const difference = relative8(folder, resolved);
15785
16492
  return difference !== ".." && !difference.startsWith("../") && (await stat10(resolved)).isFile();
15786
16493
  } catch {
15787
16494
  return false;
@@ -15853,7 +16560,7 @@ async function inspectRequestedDiff(input, folder, timeoutMs, signal) {
15853
16560
  let patch;
15854
16561
  if (input.scope === "UNTRACKED") {
15855
16562
  const bounded = await readBoundedFile(
15856
- join13(folder, input.path),
16563
+ join14(folder, input.path),
15857
16564
  MAX_DIFF_BYTES
15858
16565
  );
15859
16566
  const contents = bounded.contents;
@@ -15864,8 +16571,8 @@ async function inspectRequestedDiff(input, folder, timeoutMs, signal) {
15864
16571
  patch = untrackedTextPatch(input.path, contents);
15865
16572
  }
15866
16573
  } else {
15867
- patch = requireSuccess3(
15868
- await git3(folder, args, timeoutMs, signal),
16574
+ patch = requireSuccess4(
16575
+ await git4(folder, args, timeoutMs, signal),
15869
16576
  "Could not load the file diff"
15870
16577
  ).stdout;
15871
16578
  }
@@ -15888,7 +16595,7 @@ async function validateChangedPath(input, folder, timeoutMs, signal) {
15888
16595
  if (!input.path) throw new Error("A changed file path is required");
15889
16596
  let result;
15890
16597
  if (input.scope === "UNTRACKED") {
15891
- result = await git3(
16598
+ result = await git4(
15892
16599
  folder,
15893
16600
  ["ls-files", "--others", "--exclude-standard", "-z", "--", input.path],
15894
16601
  timeoutMs,
@@ -15919,9 +16626,9 @@ async function validateChangedPath(input, folder, timeoutMs, signal) {
15919
16626
  );
15920
16627
  }
15921
16628
  args.push("--", ...requestedDiffPaths(input));
15922
- result = await git3(folder, args, timeoutMs, signal);
16629
+ result = await git4(folder, args, timeoutMs, signal);
15923
16630
  }
15924
- requireSuccess3(result, "Could not validate the changed file");
16631
+ requireSuccess4(result, "Could not validate the changed file");
15925
16632
  const requested = input.scope === "UNTRACKED" ? result.stdout.split("\0").filter(Boolean).includes(input.path) : parseNameStatus(result.stdout).some(
15926
16633
  (file) => file.path === input.path && (!input.previousPath || file.previousPath === input.previousPath)
15927
16634
  );
@@ -15986,7 +16693,7 @@ async function writeGitObject(folder, specification, destination, timeoutMs, sig
15986
16693
  signal.removeEventListener("abort", abort);
15987
16694
  if (settled) return;
15988
16695
  if (code !== 0) {
15989
- fail(new Error(cleanError3(stderr || "Could not extract image")));
16696
+ fail(new Error(cleanError4(stderr || "Could not extract image")));
15990
16697
  return;
15991
16698
  }
15992
16699
  output.end(() => {
@@ -16017,14 +16724,14 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
16017
16724
  let temporaryDirectory = null;
16018
16725
  try {
16019
16726
  if (selected.kind === "FILE") {
16020
- uploadPath = await realpath8(selected.path);
16021
- const difference = relative7(folder, uploadPath);
16727
+ uploadPath = await realpath9(selected.path);
16728
+ const difference = relative8(folder, uploadPath);
16022
16729
  if (difference === ".." || difference.startsWith("../")) {
16023
16730
  throw new Error("Diff image resolves outside the worktree");
16024
16731
  }
16025
16732
  } else {
16026
- const size = requireSuccess3(
16027
- await git3(
16733
+ const size = requireSuccess4(
16734
+ await git4(
16028
16735
  folder,
16029
16736
  ["cat-file", "-s", selected.specification],
16030
16737
  timeoutMs,
@@ -16035,8 +16742,8 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
16035
16742
  if (!/^\d+$/.test(size) || Number(size) > 20 * 1024 * 1024) {
16036
16743
  throw new Error("Diff image exceeds the 20 MiB limit");
16037
16744
  }
16038
- temporaryDirectory = await mkdtemp6(join13(tmpdir6(), "ade-diff-image-"));
16039
- uploadPath = join13(temporaryDirectory, basename5(input.path));
16745
+ temporaryDirectory = await mkdtemp6(join14(tmpdir6(), "ade-diff-image-"));
16746
+ uploadPath = join14(temporaryDirectory, basename5(input.path));
16040
16747
  await writeGitObject(
16041
16748
  folder,
16042
16749
  selected.specification,
@@ -16058,7 +16765,7 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
16058
16765
  return successfulProcess8;
16059
16766
  } finally {
16060
16767
  if (temporaryDirectory) {
16061
- await rm9(temporaryDirectory, { recursive: true, force: true });
16768
+ await rm10(temporaryDirectory, { recursive: true, force: true });
16062
16769
  }
16063
16770
  }
16064
16771
  };
@@ -16154,7 +16861,7 @@ var inspectWorktreeGit = async (payload, timeoutMs, signal) => {
16154
16861
  var commitWorktree = async (payload, timeoutMs, signal) => {
16155
16862
  const input = worktreeCommitJobPayload(payload);
16156
16863
  const folder = await validateWorktree2(input, timeoutMs, signal);
16157
- const runGit = async (args, fallback) => requireSuccess3(await git3(folder, args, timeoutMs, signal), fallback);
16864
+ const runGit = async (args, fallback) => requireSuccess4(await git4(folder, args, timeoutMs, signal), fallback);
16158
16865
  if (input.stageAll) {
16159
16866
  await runGit(["add", "--all"], "Could not stage worktree changes");
16160
16867
  } else {
@@ -16167,7 +16874,7 @@ var commitWorktree = async (payload, timeoutMs, signal) => {
16167
16874
  if (!change) throw new Error(`Worktree change no longer exists: ${path}`);
16168
16875
  return change;
16169
16876
  });
16170
- const head = await git3(
16877
+ const head = await git4(
16171
16878
  folder,
16172
16879
  ["rev-parse", "--verify", "HEAD"],
16173
16880
  timeoutMs,
@@ -16196,7 +16903,7 @@ var commitWorktree = async (payload, timeoutMs, signal) => {
16196
16903
  "Could not stage selected worktree changes"
16197
16904
  );
16198
16905
  }
16199
- const staged = await git3(
16906
+ const staged = await git4(
16200
16907
  folder,
16201
16908
  ["diff", "--cached", "--quiet", "--exit-code"],
16202
16909
  timeoutMs,
@@ -16204,10 +16911,10 @@ var commitWorktree = async (payload, timeoutMs, signal) => {
16204
16911
  );
16205
16912
  if (staged.exitCode === 0) throw new Error("No staged changes to commit");
16206
16913
  if (staged.exitCode !== 1)
16207
- requireSuccess3(staged, "Could not inspect staged changes");
16914
+ requireSuccess4(staged, "Could not inspect staged changes");
16208
16915
  let signed = input.signed;
16209
16916
  if (signed === null) {
16210
- const configured = await git3(
16917
+ const configured = await git4(
16211
16918
  folder,
16212
16919
  ["config", "--bool", "--get", "commit.gpgsign"],
16213
16920
  timeoutMs,
@@ -16264,7 +16971,7 @@ var operateWorktreeGit = async (payload, timeoutMs, signal) => {
16264
16971
  };
16265
16972
  };
16266
16973
  async function refExists(folder, ref, timeoutMs, signal) {
16267
- const result = await git3(
16974
+ const result = await git4(
16268
16975
  folder,
16269
16976
  ["show-ref", "--verify", "--quiet", ref],
16270
16977
  timeoutMs,
@@ -16273,13 +16980,13 @@ async function refExists(folder, ref, timeoutMs, signal) {
16273
16980
  return result.exitCode === 0;
16274
16981
  }
16275
16982
  async function resolveHead(folder, ref, timeoutMs, signal) {
16276
- return requireSuccess3(
16277
- await git3(folder, ["rev-parse", ref], timeoutMs, signal),
16983
+ return requireSuccess4(
16984
+ await git4(folder, ["rev-parse", ref], timeoutMs, signal),
16278
16985
  `Could not resolve ${ref}`
16279
16986
  ).stdout.trim();
16280
16987
  }
16281
16988
  async function isAncestor(folder, ancestor, descendant, timeoutMs, signal) {
16282
- const result = await git3(
16989
+ const result = await git4(
16283
16990
  folder,
16284
16991
  ["merge-base", "--is-ancestor", ancestor, descendant],
16285
16992
  timeoutMs,
@@ -16287,12 +16994,12 @@ async function isAncestor(folder, ancestor, descendant, timeoutMs, signal) {
16287
16994
  );
16288
16995
  if (result.exitCode === 0) return true;
16289
16996
  if (result.exitCode === 1) return false;
16290
- requireSuccess3(result, "Could not compare Git history");
16997
+ requireSuccess4(result, "Could not compare Git history");
16291
16998
  return false;
16292
16999
  }
16293
17000
  async function statusState(folder, timeoutMs, signal) {
16294
- const result = requireSuccess3(
16295
- await git3(
17001
+ const result = requireSuccess4(
17002
+ await git4(
16296
17003
  folder,
16297
17004
  ["status", "--porcelain=v1", "-z", "--untracked-files=all"],
16298
17005
  timeoutMs,
@@ -16306,7 +17013,7 @@ function hasChanges(changes) {
16306
17013
  return changes.hasStagedChanges || changes.hasUnstagedChanges;
16307
17014
  }
16308
17015
  async function currentBranch(folder, timeoutMs, signal) {
16309
- const result = await git3(
17016
+ const result = await git4(
16310
17017
  folder,
16311
17018
  ["symbolic-ref", "--short", "-q", "HEAD"],
16312
17019
  timeoutMs,
@@ -16326,7 +17033,7 @@ async function chooseNewBranch(folder, candidates, allowedCurrentBranch, timeout
16326
17033
  throw new Error("Every generated ticket branch name is already taken");
16327
17034
  }
16328
17035
  async function validateBranchRoot(input, timeoutMs, signal) {
16329
- const rootFolder = await realpath8(input.rootFolder);
17036
+ const rootFolder = await realpath9(input.rootFolder);
16330
17037
  if (!(await stat10(rootFolder)).isDirectory()) {
16331
17038
  throw new Error("Base repository is missing");
16332
17039
  }
@@ -16390,8 +17097,8 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
16390
17097
  timeoutMs,
16391
17098
  signal
16392
17099
  ) : input.candidates[0];
16393
- const targetFolder = input.action === "CREATE" ? join13(
16394
- dirname7(rootFolder),
17100
+ const targetFolder = input.action === "CREATE" ? join14(
17101
+ dirname8(rootFolder),
16395
17102
  `${basename5(rootFolder)}-${branch.replaceAll("/", "-")}`
16396
17103
  ) : changeFolder;
16397
17104
  if (input.action === "CREATE") {
@@ -16436,40 +17143,89 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
16436
17143
  ];
16437
17144
  }
16438
17145
  let stashed = false;
16439
- if (args.length > 0) {
16440
- let switched = await git3(
16441
- input.action === "CREATE" ? rootFolder : targetFolder,
16442
- args,
17146
+ let preparationsSuspended = false;
17147
+ const reapplyPreparations = () => executeWorktreePreparations(
17148
+ targetFolder,
17149
+ input.preparations,
17150
+ "APPLY",
17151
+ timeoutMs,
17152
+ signal
17153
+ );
17154
+ if (args.length > 0 && input.action === "CHANGE" && input.preparations.length > 0) {
17155
+ const suspended = await suspendWorktreePreparations(
17156
+ targetFolder,
17157
+ input.preparations,
16443
17158
  timeoutMs,
16444
- signal
17159
+ signal,
17160
+ true
16445
17161
  );
16446
- if (switched.exitCode !== 0 && input.action === "CHANGE" && input.stashOnFailure) {
16447
- const stash = requireSuccess3(
16448
- await git3(
16449
- targetFolder,
16450
- [
16451
- "stash",
16452
- "push",
16453
- "--include-untracked",
16454
- "-m",
16455
- `Automatic stash before switching to ${branch}`
16456
- ],
16457
- timeoutMs,
16458
- signal
16459
- ),
16460
- "Could not stash worktree changes"
17162
+ preparationsSuspended = true;
17163
+ const failed = suspended.filter((item) => item.state === "ERROR");
17164
+ if (failed.length > 0) {
17165
+ await reapplyPreparations();
17166
+ throw new Error(
17167
+ failed.map((item) => item.message ?? "Preparation failed").join("; ")
16461
17168
  );
16462
- stashed = !stash.stdout.toLowerCase().includes("no local changes");
16463
- switched = await git3(targetFolder, args, timeoutMs, signal);
16464
- if (switched.exitCode !== 0) {
16465
- throw new Error(
16466
- `${cleanError3(switched.stderr || "Branch switch failed after stashing")}. The stash was preserved.`
17169
+ }
17170
+ }
17171
+ if (args.length > 0) {
17172
+ try {
17173
+ let switched = await git4(
17174
+ input.action === "CREATE" ? rootFolder : targetFolder,
17175
+ args,
17176
+ timeoutMs,
17177
+ signal
17178
+ );
17179
+ if (switched.exitCode !== 0 && input.action === "CHANGE" && input.stashOnFailure) {
17180
+ const stash = requireSuccess4(
17181
+ await git4(
17182
+ targetFolder,
17183
+ [
17184
+ "stash",
17185
+ "push",
17186
+ "--include-untracked",
17187
+ "-m",
17188
+ `Automatic stash before switching to ${branch}`
17189
+ ],
17190
+ timeoutMs,
17191
+ signal
17192
+ ),
17193
+ "Could not stash worktree changes"
17194
+ );
17195
+ stashed = !stash.stdout.toLowerCase().includes("no local changes");
17196
+ switched = await git4(targetFolder, args, timeoutMs, signal);
17197
+ if (switched.exitCode !== 0) {
17198
+ throw new Error(
17199
+ `${cleanError4(switched.stderr || "Branch switch failed after stashing")}. The stash was preserved.`
17200
+ );
17201
+ }
17202
+ } else {
17203
+ requireSuccess4(
17204
+ switched,
17205
+ input.action === "CREATE" ? "Could not create the worktree" : "Could not change the worktree branch"
16467
17206
  );
16468
17207
  }
16469
- } else {
16470
- requireSuccess3(
16471
- switched,
16472
- input.action === "CREATE" ? "Could not create the worktree" : "Could not change the worktree branch"
17208
+ } catch (error) {
17209
+ if (preparationsSuspended) await reapplyPreparations();
17210
+ throw error;
17211
+ }
17212
+ }
17213
+ let preparations = [];
17214
+ if (input.preparations.length > 0) {
17215
+ preparations = await reapplyPreparations();
17216
+ const failed = preparations.filter((item) => item.state === "ERROR");
17217
+ if (failed.length > 0 && input.action === "CREATE") {
17218
+ await git4(
17219
+ rootFolder,
17220
+ ["worktree", "remove", "--force", targetFolder],
17221
+ timeoutMs,
17222
+ signal
17223
+ );
17224
+ if (input.mode === "NEW") {
17225
+ await git4(rootFolder, ["branch", "-D", branch], timeoutMs, signal);
17226
+ }
17227
+ throw new Error(
17228
+ failed.map((item) => item.message ?? "Preparation failed").join("; ")
16473
17229
  );
16474
17230
  }
16475
17231
  }
@@ -16489,7 +17245,9 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
16489
17245
  worktree,
16490
17246
  branch,
16491
17247
  baseBranch: input.baseBranch,
16492
- stashed
17248
+ stashed,
17249
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17250
+ preparations
16493
17251
  };
16494
17252
  };
16495
17253
  var pushMovedWorktree = async (payload, timeoutMs, signal) => {
@@ -16516,8 +17274,8 @@ var pushMovedWorktree = async (payload, timeoutMs, signal) => {
16516
17274
  if (hasChanges(changes)) {
16517
17275
  throw new Error("Commit or discard source changes before moving");
16518
17276
  }
16519
- requireSuccess3(
16520
- await git3(folder, ["fetch", "origin"], timeoutMs, signal),
17277
+ requireSuccess4(
17278
+ await git4(folder, ["fetch", "origin"], timeoutMs, signal),
16521
17279
  "Could not fetch origin before moving"
16522
17280
  );
16523
17281
  const remoteRef = `refs/remotes/origin/${branch}`;
@@ -16526,8 +17284,8 @@ var pushMovedWorktree = async (payload, timeoutMs, signal) => {
16526
17284
  "The origin branch contains commits that must be pulled before moving"
16527
17285
  );
16528
17286
  }
16529
- requireSuccess3(
16530
- await git3(
17287
+ requireSuccess4(
17288
+ await git4(
16531
17289
  folder,
16532
17290
  ["push", "--set-upstream", "origin", `HEAD:refs/heads/${branch}`],
16533
17291
  timeoutMs,
@@ -16562,8 +17320,8 @@ async function updateLocalBranchForMove(rootFolder, branch, expectedHeadSha, tim
16562
17320
  `Local branch ${branch} has commits that are not on origin; move them before retrying`
16563
17321
  );
16564
17322
  }
16565
- requireSuccess3(
16566
- await git3(
17323
+ requireSuccess4(
17324
+ await git4(
16567
17325
  rootFolder,
16568
17326
  ["branch", "-f", branch, expectedHeadSha],
16569
17327
  timeoutMs,
@@ -16574,8 +17332,8 @@ async function updateLocalBranchForMove(rootFolder, branch, expectedHeadSha, tim
16574
17332
  return true;
16575
17333
  }
16576
17334
  async function checkedOutBranchFolder(rootFolder, branch, timeoutMs, signal) {
16577
- const result = requireSuccess3(
16578
- await git3(
17335
+ const result = requireSuccess4(
17336
+ await git4(
16579
17337
  rootFolder,
16580
17338
  ["worktree", "list", "--porcelain"],
16581
17339
  timeoutMs,
@@ -16591,8 +17349,8 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16591
17349
  const input = worktreeMoveCheckoutJobPayload(payload);
16592
17350
  const rootFolder = await validateBranchRoot(input, timeoutMs, signal);
16593
17351
  const remoteRef = `refs/remotes/origin/${input.branch}`;
16594
- requireSuccess3(
16595
- await git3(
17352
+ requireSuccess4(
17353
+ await git4(
16596
17354
  rootFolder,
16597
17355
  [
16598
17356
  "fetch",
@@ -16617,6 +17375,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16617
17375
  );
16618
17376
  }
16619
17377
  let targetFolder;
17378
+ let createdLocalBranch = false;
16620
17379
  let stashed = false;
16621
17380
  const occupiedFolder = await checkedOutBranchFolder(
16622
17381
  rootFolder,
@@ -16630,8 +17389,8 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16630
17389
  `Branch ${input.branch} is already checked out in ${occupiedFolder}`
16631
17390
  );
16632
17391
  }
16633
- targetFolder = join13(
16634
- dirname7(rootFolder),
17392
+ targetFolder = join14(
17393
+ dirname8(rootFolder),
16635
17394
  `${basename5(rootFolder)}-${input.branch.replaceAll("/", "-")}`
16636
17395
  );
16637
17396
  try {
@@ -16649,8 +17408,9 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16649
17408
  timeoutMs,
16650
17409
  signal
16651
17410
  );
16652
- requireSuccess3(
16653
- await git3(
17411
+ createdLocalBranch = !local;
17412
+ requireSuccess4(
17413
+ await git4(
16654
17414
  rootFolder,
16655
17415
  local ? ["worktree", "add", targetFolder, input.branch] : [
16656
17416
  "worktree",
@@ -16681,7 +17441,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16681
17441
  const targetBranch = await currentBranch(targetFolder, timeoutMs, signal);
16682
17442
  const targetChanges = await statusState(targetFolder, timeoutMs, signal);
16683
17443
  if (occupiedFolder) {
16684
- const occupied = await realpath8(occupiedFolder);
17444
+ const occupied = await realpath9(occupiedFolder);
16685
17445
  if (occupied !== targetFolder) {
16686
17446
  throw new Error(
16687
17447
  `Branch ${input.branch} is checked out in another destination worktree`
@@ -16719,8 +17479,8 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16719
17479
  switchArgs = local ? ["switch", input.branch] : ["switch", "--track", "-c", input.branch, remoteRef];
16720
17480
  }
16721
17481
  if (input.stashOnFailure && hasChanges(targetChanges)) {
16722
- const stash = requireSuccess3(
16723
- await git3(
17482
+ const stash = requireSuccess4(
17483
+ await git4(
16724
17484
  targetFolder,
16725
17485
  [
16726
17486
  "stash",
@@ -16736,25 +17496,25 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16736
17496
  );
16737
17497
  stashed = !stash.stdout.toLowerCase().includes("no local changes");
16738
17498
  }
16739
- const switched = await git3(targetFolder, switchArgs, timeoutMs, signal);
17499
+ const switched = await git4(targetFolder, switchArgs, timeoutMs, signal);
16740
17500
  if (switched.exitCode !== 0) {
16741
17501
  if (!input.stashOnFailure && hasChanges(targetChanges)) {
16742
17502
  return {
16743
17503
  ...successfulProcess8,
16744
17504
  moveId: input.moveId,
16745
17505
  outcome: "NEEDS_STASH",
16746
- message: cleanError3(
17506
+ message: cleanError4(
16747
17507
  switched.stderr || "Destination changes block the branch switch"
16748
17508
  )
16749
17509
  };
16750
17510
  }
16751
17511
  throw new Error(
16752
- `${cleanError3(switched.stderr || "Could not check out the moved branch")}${stashed ? ". The destination stash was preserved." : ""}`
17512
+ `${cleanError4(switched.stderr || "Could not check out the moved branch")}${stashed ? ". The destination stash was preserved." : ""}`
16753
17513
  );
16754
17514
  }
16755
17515
  }
16756
- requireSuccess3(
16757
- await git3(
17516
+ requireSuccess4(
17517
+ await git4(
16758
17518
  targetFolder,
16759
17519
  ["branch", "--set-upstream-to", `origin/${input.branch}`, input.branch],
16760
17520
  timeoutMs,
@@ -16771,6 +17531,30 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16771
17531
  if (checkedOutHead !== input.expectedHeadSha) {
16772
17532
  throw new Error("The destination did not check out the pushed commit");
16773
17533
  }
17534
+ const preparations = await executeWorktreePreparations(
17535
+ targetFolder,
17536
+ input.preparations,
17537
+ "APPLY",
17538
+ timeoutMs,
17539
+ signal
17540
+ );
17541
+ const preparationErrors = preparations.filter(
17542
+ (item) => item.state === "ERROR"
17543
+ );
17544
+ if (preparationErrors.length > 0 && input.mode === "NEW") {
17545
+ await git4(
17546
+ rootFolder,
17547
+ ["worktree", "remove", "--force", targetFolder],
17548
+ timeoutMs,
17549
+ signal
17550
+ );
17551
+ if (createdLocalBranch) {
17552
+ await git4(rootFolder, ["branch", "-D", input.branch], timeoutMs, signal);
17553
+ }
17554
+ throw new Error(
17555
+ preparationErrors.map((item) => item.message ?? "Preparation failed").join("; ")
17556
+ );
17557
+ }
16774
17558
  const worktree = await inspectWorktreeItem(
16775
17559
  targetFolder,
16776
17560
  rootFolder,
@@ -16790,12 +17574,72 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
16790
17574
  outcome: "CHECKED_OUT",
16791
17575
  worktree,
16792
17576
  baseBranch: input.baseBranch,
16793
- stashed
17577
+ stashed,
17578
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17579
+ preparations
17580
+ };
17581
+ };
17582
+ var prepareWorktree = async (payload, timeoutMs, signal) => {
17583
+ const input = worktreePreparationJobPayload(payload);
17584
+ if ("worktrees" in input) {
17585
+ const worktrees = [];
17586
+ for (const target2 of input.worktrees) {
17587
+ try {
17588
+ const folder2 = await validateWorktree2(
17589
+ {
17590
+ codebaseId: input.codebaseId,
17591
+ folder: target2.folder,
17592
+ gitDirectory: target2.gitDirectory,
17593
+ expectedOrigin: input.expectedOrigin,
17594
+ baseBranch: null
17595
+ },
17596
+ timeoutMs,
17597
+ signal
17598
+ );
17599
+ const preparations2 = await executeWorktreePreparations(
17600
+ folder2,
17601
+ input.preparations,
17602
+ input.action,
17603
+ timeoutMs,
17604
+ signal
17605
+ );
17606
+ worktrees.push({
17607
+ worktreeId: target2.worktreeId,
17608
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17609
+ preparations: preparations2
17610
+ });
17611
+ } catch (error) {
17612
+ worktrees.push({
17613
+ worktreeId: target2.worktreeId,
17614
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17615
+ preparations: input.preparations.map((definition) => ({
17616
+ id: definition.id,
17617
+ definitionHash: definition.definitionHash,
17618
+ state: "ERROR",
17619
+ message: cleanError4(error)
17620
+ }))
17621
+ });
17622
+ }
17623
+ }
17624
+ return { ...successfulProcess8, worktrees };
17625
+ }
17626
+ const folder = await validateWorktree2(input, timeoutMs, signal);
17627
+ const preparations = await executeWorktreePreparations(
17628
+ folder,
17629
+ input.preparations,
17630
+ input.action,
17631
+ timeoutMs,
17632
+ signal
17633
+ );
17634
+ return {
17635
+ ...successfulProcess8,
17636
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17637
+ preparations
16794
17638
  };
16795
17639
  };
16796
17640
  var deleteWorktree = async (payload, timeoutMs, signal) => {
16797
17641
  const input = worktreeDeleteJobPayload(payload);
16798
- const rootFolder = await realpath8(input.rootFolder);
17642
+ const rootFolder = await realpath9(input.rootFolder);
16799
17643
  if (!(await stat10(rootFolder)).isDirectory()) {
16800
17644
  throw new Error("Base repository is missing");
16801
17645
  }
@@ -16816,8 +17660,8 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
16816
17660
  if (folder === rootFolder)
16817
17661
  throw new Error("The primary worktree cannot be deleted");
16818
17662
  const listed = parseWorktreeList(
16819
- requireSuccess3(
16820
- await git3(
17663
+ requireSuccess4(
17664
+ await git4(
16821
17665
  rootFolder,
16822
17666
  ["worktree", "list", "--porcelain"],
16823
17667
  timeoutMs,
@@ -16847,15 +17691,15 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
16847
17691
  if (branch === input.defaultBranch) {
16848
17692
  throw new Error("The default remote branch cannot be deleted");
16849
17693
  }
16850
- const remote = await git3(
17694
+ const remote = await git4(
16851
17695
  rootFolder,
16852
17696
  ["ls-remote", "--exit-code", "--heads", "origin", `refs/heads/${branch}`],
16853
17697
  timeoutMs,
16854
17698
  signal
16855
17699
  );
16856
17700
  if (remote.exitCode === 0) {
16857
- requireSuccess3(
16858
- await git3(
17701
+ requireSuccess4(
17702
+ await git4(
16859
17703
  rootFolder,
16860
17704
  ["push", "origin", "--delete", branch],
16861
17705
  timeoutMs,
@@ -16864,11 +17708,11 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
16864
17708
  `Could not delete origin/${branch}`
16865
17709
  );
16866
17710
  } else if (remote.exitCode !== 2) {
16867
- requireSuccess3(remote, `Could not inspect origin/${branch}`);
17711
+ requireSuccess4(remote, `Could not inspect origin/${branch}`);
16868
17712
  }
16869
17713
  }
16870
- requireSuccess3(
16871
- await git3(
17714
+ requireSuccess4(
17715
+ await git4(
16872
17716
  rootFolder,
16873
17717
  ["worktree", "remove", "--force", folder],
16874
17718
  timeoutMs,
@@ -16877,8 +17721,8 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
16877
17721
  "Could not remove the worktree"
16878
17722
  );
16879
17723
  if (branch && await refExists(rootFolder, `refs/heads/${branch}`, timeoutMs, signal)) {
16880
- requireSuccess3(
16881
- await git3(rootFolder, ["branch", "-D", branch], timeoutMs, signal),
17724
+ requireSuccess4(
17725
+ await git4(rootFolder, ["branch", "-D", branch], timeoutMs, signal),
16882
17726
  `Worktree removed, but local branch ${branch} could not be deleted`
16883
17727
  );
16884
17728
  }
@@ -16894,28 +17738,53 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
16894
17738
  const input = worktreeJobPayload(payload);
16895
17739
  const folder = await validateWorktree2(input, timeoutMs, signal);
16896
17740
  if (!input.operation) throw new Error("A worktree operation is required");
16897
- const branchResult = await git3(
17741
+ const branchResult = await git4(
16898
17742
  folder,
16899
17743
  ["symbolic-ref", "--short", "-q", "HEAD"],
16900
17744
  timeoutMs,
16901
17745
  signal
16902
17746
  );
16903
17747
  const branch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
16904
- const upstreamResult = branch ? await git3(
17748
+ const upstreamResult = branch ? await git4(
16905
17749
  folder,
16906
17750
  ["rev-parse", "--abbrev-ref", "@{upstream}"],
16907
17751
  timeoutMs,
16908
17752
  signal
16909
17753
  ) : null;
16910
17754
  const upstream = upstreamResult?.exitCode === 0 ? upstreamResult.stdout.trim() : null;
16911
- const runGit = async (args, fallback) => requireSuccess3(await git3(folder, args, timeoutMs, signal), fallback);
17755
+ const runGit = async (args, fallback) => requireSuccess4(await git4(folder, args, timeoutMs, signal), fallback);
17756
+ let operationOutcome = "COMPLETED";
17757
+ let preparationConflictPathList = [];
17758
+ let preparationResults = [];
17759
+ const inspectPreparations = () => executeWorktreePreparations(
17760
+ folder,
17761
+ input.preparations,
17762
+ "INSPECT",
17763
+ timeoutMs,
17764
+ signal
17765
+ );
17766
+ const reapplyPreparations = () => executeWorktreePreparations(
17767
+ folder,
17768
+ input.preparations,
17769
+ "APPLY",
17770
+ timeoutMs,
17771
+ signal
17772
+ );
17773
+ const worktreeResult = async () => inspectWorktreeItem(
17774
+ folder,
17775
+ folder,
17776
+ input.baseBranch,
17777
+ false,
17778
+ Math.min(timeoutMs, 3e4),
17779
+ signal
17780
+ );
16912
17781
  switch (input.operation) {
16913
17782
  case "OPEN_EDITOR": {
16914
17783
  if (input.editorVariant === "NONE" || !input.editorVariant) {
16915
17784
  throw new Error("VS Code is disabled in Settings");
16916
17785
  }
16917
17786
  const app = input.editorVariant === "CODE_INSIDERS" ? "Visual Studio Code - Insiders" : "Visual Studio Code";
16918
- requireSuccess3(
17787
+ requireSuccess4(
16919
17788
  await command2("open", ["-a", app, folder], timeoutMs, signal),
16920
17789
  `${app} could not be opened`
16921
17790
  );
@@ -16937,26 +17806,105 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
16937
17806
  if (statusResult.stdout.trim())
16938
17807
  throw new Error("Stash or commit changes before syncing");
16939
17808
  await runGit(["fetch", "origin"], "Could not fetch origin");
16940
- const rebase = await git3(
17809
+ const remoteBase = `refs/remotes/origin/${input.baseBranch}`;
17810
+ const isCurrent = await git4(
16941
17811
  folder,
16942
- ["rebase", `refs/remotes/origin/${input.baseBranch}`],
17812
+ ["merge-base", "--is-ancestor", remoteBase, "HEAD"],
16943
17813
  timeoutMs,
16944
17814
  signal
16945
17815
  );
16946
- if (rebase.exitCode !== 0) {
16947
- const status2 = await git3(
17816
+ if (isCurrent.exitCode !== 0 && isCurrent.exitCode !== 1) {
17817
+ requireSuccess4(isCurrent, "Could not compare the base branch");
17818
+ }
17819
+ if (isCurrent.exitCode === 1) {
17820
+ preparationConflictPathList = await preparationConflictPaths(
17821
+ folder,
17822
+ input.preparations,
17823
+ remoteBase,
17824
+ timeoutMs,
17825
+ signal
17826
+ );
17827
+ if (preparationConflictPathList.length > 0 && !input.forcePreparations) {
17828
+ operationOutcome = "PREPARATION_CONFLICT";
17829
+ preparationResults = await inspectPreparations();
17830
+ return {
17831
+ ...successfulProcess8,
17832
+ outcome: operationOutcome,
17833
+ preparationConflictPaths: preparationConflictPathList,
17834
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17835
+ preparations: preparationResults,
17836
+ worktree: await worktreeResult()
17837
+ };
17838
+ }
17839
+ if (input.forcePreparations) {
17840
+ preparationResults = await suspendWorktreePreparations(
17841
+ folder,
17842
+ input.preparations,
17843
+ timeoutMs,
17844
+ signal
17845
+ );
17846
+ if (preparationResults.some((item) => item.state === "ERROR")) {
17847
+ return {
17848
+ ...successfulProcess8,
17849
+ exitCode: 1,
17850
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17851
+ preparations: preparationResults
17852
+ };
17853
+ }
17854
+ }
17855
+ }
17856
+ const rebase = isCurrent.exitCode === 0 ? null : await git4(folder, ["rebase", remoteBase], timeoutMs, signal);
17857
+ if (rebase && rebase.exitCode !== 0) {
17858
+ const status2 = await git4(
16948
17859
  folder,
16949
17860
  ["status", "--porcelain=v1", "-z"],
16950
17861
  timeoutMs,
16951
17862
  signal
16952
17863
  );
16953
17864
  const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
16954
- if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
16955
- await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
17865
+ if (conflicts && await rebaseInProgress(folder, timeoutMs, signal)) {
17866
+ operationOutcome = "REBASE_CONFLICT";
17867
+ const conflictsResult = await git4(
17868
+ folder,
17869
+ ["diff", "--name-only", "--diff-filter=U"],
17870
+ timeoutMs,
17871
+ signal
17872
+ );
17873
+ preparationConflictPathList = conflictsResult.exitCode === 0 ? conflictsResult.stdout.split("\n").filter(Boolean) : [];
17874
+ preparationResults = input.preparations.map((definition) => ({
17875
+ id: definition.id,
17876
+ definitionHash: definition.definitionHash,
17877
+ state: "SUSPENDED"
17878
+ }));
17879
+ return {
17880
+ ...successfulProcess8,
17881
+ outcome: operationOutcome,
17882
+ preparationConflictPaths: preparationConflictPathList,
17883
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17884
+ preparations: preparationResults,
17885
+ worktree: await worktreeResult()
17886
+ };
17887
+ } else {
17888
+ await git4(folder, ["rebase", "--abort"], timeoutMs, signal);
17889
+ }
17890
+ if (input.forcePreparations) {
17891
+ preparationResults = await reapplyPreparations();
16956
17892
  }
16957
- throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
17893
+ throw new Error(cleanError4(rebase.stderr || "Rebase failed"));
16958
17894
  }
16959
- await runGit(["push", "--force-with-lease"], "Sync push failed");
17895
+ const push = await git4(
17896
+ folder,
17897
+ ["push", "--force-with-lease"],
17898
+ timeoutMs,
17899
+ signal
17900
+ );
17901
+ if (push.exitCode !== 0) {
17902
+ if (input.forcePreparations) {
17903
+ preparationResults = await reapplyPreparations();
17904
+ }
17905
+ requireSuccess4(push, "Sync push failed");
17906
+ }
17907
+ preparationResults = input.forcePreparations ? await reapplyPreparations() : await inspectPreparations();
16960
17908
  break;
16961
17909
  }
16962
17910
  case "REBASE": {
@@ -16969,25 +17917,93 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
16969
17917
  if (statusResult.stdout.trim())
16970
17918
  throw new Error("Stash or commit changes before rebasing");
16971
17919
  await runGit(["fetch", "origin"], "Could not fetch origin");
16972
- const rebase = await git3(
17920
+ const remoteBase = `refs/remotes/origin/${input.baseBranch}`;
17921
+ const isCurrent = await git4(
16973
17922
  folder,
16974
- ["rebase", `refs/remotes/origin/${input.baseBranch}`],
17923
+ ["merge-base", "--is-ancestor", remoteBase, "HEAD"],
16975
17924
  timeoutMs,
16976
17925
  signal
16977
17926
  );
16978
- if (rebase.exitCode !== 0) {
16979
- const status2 = await git3(
17927
+ if (isCurrent.exitCode !== 0 && isCurrent.exitCode !== 1) {
17928
+ requireSuccess4(isCurrent, "Could not compare the base branch");
17929
+ }
17930
+ if (isCurrent.exitCode === 1) {
17931
+ preparationConflictPathList = await preparationConflictPaths(
17932
+ folder,
17933
+ input.preparations,
17934
+ remoteBase,
17935
+ timeoutMs,
17936
+ signal
17937
+ );
17938
+ if (preparationConflictPathList.length > 0 && !input.forcePreparations) {
17939
+ operationOutcome = "PREPARATION_CONFLICT";
17940
+ preparationResults = await inspectPreparations();
17941
+ return {
17942
+ ...successfulProcess8,
17943
+ outcome: operationOutcome,
17944
+ preparationConflictPaths: preparationConflictPathList,
17945
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17946
+ preparations: preparationResults,
17947
+ worktree: await worktreeResult()
17948
+ };
17949
+ }
17950
+ if (input.forcePreparations) {
17951
+ preparationResults = await suspendWorktreePreparations(
17952
+ folder,
17953
+ input.preparations,
17954
+ timeoutMs,
17955
+ signal
17956
+ );
17957
+ if (preparationResults.some((item) => item.state === "ERROR")) {
17958
+ return {
17959
+ ...successfulProcess8,
17960
+ exitCode: 1,
17961
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17962
+ preparations: preparationResults
17963
+ };
17964
+ }
17965
+ }
17966
+ }
17967
+ const rebase = isCurrent.exitCode === 0 ? null : await git4(folder, ["rebase", remoteBase], timeoutMs, signal);
17968
+ if (rebase && rebase.exitCode !== 0) {
17969
+ const status2 = await git4(
16980
17970
  folder,
16981
17971
  ["status", "--porcelain=v1", "-z"],
16982
17972
  timeoutMs,
16983
17973
  signal
16984
17974
  );
16985
17975
  const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
16986
- if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
16987
- await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
17976
+ if (conflicts && await rebaseInProgress(folder, timeoutMs, signal)) {
17977
+ operationOutcome = "REBASE_CONFLICT";
17978
+ const conflictsResult = await git4(
17979
+ folder,
17980
+ ["diff", "--name-only", "--diff-filter=U"],
17981
+ timeoutMs,
17982
+ signal
17983
+ );
17984
+ preparationConflictPathList = conflictsResult.exitCode === 0 ? conflictsResult.stdout.split("\n").filter(Boolean) : [];
17985
+ preparationResults = input.preparations.map((definition) => ({
17986
+ id: definition.id,
17987
+ definitionHash: definition.definitionHash,
17988
+ state: "SUSPENDED"
17989
+ }));
17990
+ return {
17991
+ ...successfulProcess8,
17992
+ outcome: operationOutcome,
17993
+ preparationConflictPaths: preparationConflictPathList,
17994
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
17995
+ preparations: preparationResults,
17996
+ worktree: await worktreeResult()
17997
+ };
17998
+ } else {
17999
+ await git4(folder, ["rebase", "--abort"], timeoutMs, signal);
16988
18000
  }
16989
- throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
18001
+ if (input.forcePreparations) {
18002
+ preparationResults = await reapplyPreparations();
18003
+ }
18004
+ throw new Error(cleanError4(rebase.stderr || "Rebase failed"));
16990
18005
  }
18006
+ preparationResults = input.forcePreparations ? await reapplyPreparations() : await inspectPreparations();
16991
18007
  break;
16992
18008
  }
16993
18009
  case "CANCEL_REBASE": {
@@ -16995,6 +18011,7 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
16995
18011
  throw new Error("No rebase is in progress");
16996
18012
  }
16997
18013
  await runGit(["rebase", "--abort"], "Could not cancel rebase");
18014
+ preparationResults = await reapplyPreparations();
16998
18015
  break;
16999
18016
  }
17000
18017
  case "PULL": {
@@ -17021,6 +18038,9 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
17021
18038
  await runGit(["clean", "-fd"], "Could not remove untracked files");
17022
18039
  break;
17023
18040
  }
18041
+ case "CLEAR_LOCK":
18042
+ await rm10(join14(input.gitDirectory, "index.lock"), { force: true });
18043
+ break;
17024
18044
  case "STASH_ALL":
17025
18045
  await runGit(["stash", "push", "--include-untracked"], "Stash failed");
17026
18046
  break;
@@ -17033,21 +18053,37 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
17033
18053
  }
17034
18054
  return {
17035
18055
  ...successfulProcess8,
17036
- worktree: await inspectWorktreeItem(
17037
- folder,
17038
- folder,
17039
- input.baseBranch,
17040
- false,
17041
- Math.min(timeoutMs, 3e4),
17042
- signal
17043
- )
18056
+ outcome: operationOutcome,
18057
+ preparationConflictPaths: preparationConflictPathList,
18058
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18059
+ preparations: preparationResults,
18060
+ worktree: await worktreeResult()
17044
18061
  };
17045
18062
  };
17046
18063
  var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17047
18064
  const input = worktreeAutoSyncJobPayload(payload);
17048
18065
  const folder = await validateWorktree2(input, timeoutMs, signal);
17049
- const runGit = async (args, fallback) => requireSuccess3(await git3(folder, args, timeoutMs, signal), fallback);
17050
- const branchResult = await git3(
18066
+ const runGit = async (args, fallback) => requireSuccess4(await git4(folder, args, timeoutMs, signal), fallback);
18067
+ const inspectPreparations = () => executeWorktreePreparations(
18068
+ folder,
18069
+ input.preparations,
18070
+ "INSPECT",
18071
+ timeoutMs,
18072
+ signal
18073
+ );
18074
+ const reapplyPreparations = () => executeWorktreePreparations(
18075
+ folder,
18076
+ input.preparations,
18077
+ "APPLY",
18078
+ timeoutMs,
18079
+ signal
18080
+ );
18081
+ const suspendedPreparations = () => input.preparations.map((definition) => ({
18082
+ id: definition.id,
18083
+ definitionHash: definition.definitionHash,
18084
+ state: "SUSPENDED"
18085
+ }));
18086
+ const branchResult = await git4(
17051
18087
  folder,
17052
18088
  ["symbolic-ref", "--short", "-q", "HEAD"],
17053
18089
  timeoutMs,
@@ -17060,7 +18096,7 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17060
18096
  `Auto Sync expected branch ${input.expectedBranch}, but found ${branch ?? "detached HEAD"}`
17061
18097
  );
17062
18098
  }
17063
- const upstreamResult = branch ? await git3(
18099
+ const upstreamResult = branch ? await git4(
17064
18100
  folder,
17065
18101
  ["rev-parse", "--abbrev-ref", "@{upstream}"],
17066
18102
  timeoutMs,
@@ -17081,6 +18117,8 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17081
18117
  return {
17082
18118
  ...successfulProcess8,
17083
18119
  outcome: "UNRESOLVED",
18120
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18121
+ preparations: suspendedPreparations(),
17084
18122
  worktree: await inspectWorktreeItem(
17085
18123
  folder,
17086
18124
  folder,
@@ -17109,6 +18147,8 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17109
18147
  return {
17110
18148
  ...successfulProcess8,
17111
18149
  outcome: "UNRESOLVED",
18150
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18151
+ preparations: suspendedPreparations(),
17112
18152
  worktree: await inspectWorktreeItem(
17113
18153
  folder,
17114
18154
  folder,
@@ -17129,6 +18169,8 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17129
18169
  return {
17130
18170
  ...successfulProcess8,
17131
18171
  outcome: "UNRESOLVED",
18172
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18173
+ preparations: suspendedPreparations(),
17132
18174
  worktree: await inspectWorktreeItem(
17133
18175
  folder,
17134
18176
  folder,
@@ -17139,13 +18181,13 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17139
18181
  )
17140
18182
  };
17141
18183
  }
17142
- const finalBranch = await git3(
18184
+ const finalBranch = await git4(
17143
18185
  folder,
17144
18186
  ["symbolic-ref", "--short", "-q", "HEAD"],
17145
18187
  timeoutMs,
17146
18188
  signal
17147
18189
  );
17148
- const finalUpstream = finalBranch.exitCode === 0 ? await git3(
18190
+ const finalUpstream = finalBranch.exitCode === 0 ? await git4(
17149
18191
  folder,
17150
18192
  ["rev-parse", "--abbrev-ref", "@{upstream}"],
17151
18193
  timeoutMs,
@@ -17156,10 +18198,22 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17156
18198
  `Auto Sync expected branch ${input.expectedBranch} with an upstream`
17157
18199
  );
17158
18200
  }
17159
- await runGit(["push", "--force-with-lease"], "Auto Sync push failed");
18201
+ const push2 = await git4(
18202
+ folder,
18203
+ ["push", "--force-with-lease"],
18204
+ timeoutMs,
18205
+ signal
18206
+ );
18207
+ if (push2.exitCode !== 0) {
18208
+ await reapplyPreparations();
18209
+ requireSuccess4(push2, "Auto Sync push failed");
18210
+ }
18211
+ const preparations = await reapplyPreparations();
17160
18212
  return {
17161
18213
  ...successfulProcess8,
17162
18214
  outcome: "SYNCED",
18215
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18216
+ preparations,
17163
18217
  worktree: await inspectWorktreeItem(
17164
18218
  folder,
17165
18219
  folder,
@@ -17179,14 +18233,14 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17179
18233
  }
17180
18234
  await runGit(["fetch", "origin"], "Could not fetch origin");
17181
18235
  const remoteBase = `refs/remotes/origin/${input.baseBranch}`;
17182
- const isCurrent = await git3(
18236
+ const isCurrent = await git4(
17183
18237
  folder,
17184
18238
  ["merge-base", "--is-ancestor", remoteBase, "HEAD"],
17185
18239
  timeoutMs,
17186
18240
  signal
17187
18241
  );
17188
18242
  if (isCurrent.exitCode === 0) {
17189
- const upstreamContainsHead = await git3(
18243
+ const upstreamContainsHead = await git4(
17190
18244
  folder,
17191
18245
  ["merge-base", "--is-ancestor", "HEAD", "@{upstream}"],
17192
18246
  timeoutMs,
@@ -17194,7 +18248,7 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17194
18248
  );
17195
18249
  if (upstreamContainsHead.exitCode !== 0 && upstreamContainsHead.exitCode !== 1) {
17196
18250
  throw new Error(
17197
- cleanError3(
18251
+ cleanError4(
17198
18252
  upstreamContainsHead.stderr || "Could not compare the upstream branch"
17199
18253
  )
17200
18254
  );
@@ -17204,6 +18258,8 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17204
18258
  return {
17205
18259
  ...successfulProcess8,
17206
18260
  outcome: "SYNCED",
18261
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18262
+ preparations: await inspectPreparations(),
17207
18263
  worktree: await inspectWorktreeItem(
17208
18264
  folder,
17209
18265
  folder,
@@ -17217,6 +18273,32 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17217
18273
  return {
17218
18274
  ...successfulProcess8,
17219
18275
  outcome: "NO_CHANGE",
18276
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18277
+ preparations: await inspectPreparations(),
18278
+ worktree: await inspectWorktreeItem(
18279
+ folder,
18280
+ folder,
18281
+ input.baseBranch,
18282
+ false,
18283
+ Math.min(timeoutMs, 3e4),
18284
+ signal
18285
+ )
18286
+ };
18287
+ }
18288
+ const preparationConflictPathList = await preparationConflictPaths(
18289
+ folder,
18290
+ input.preparations,
18291
+ remoteBase,
18292
+ timeoutMs,
18293
+ signal
18294
+ );
18295
+ if (preparationConflictPathList.length > 0 && !input.forcePreparations) {
18296
+ return {
18297
+ ...successfulProcess8,
18298
+ outcome: "PREPARATION_CONFLICT",
18299
+ preparationConflictPaths: preparationConflictPathList,
18300
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18301
+ preparations: await inspectPreparations(),
17220
18302
  worktree: await inspectWorktreeItem(
17221
18303
  folder,
17222
18304
  folder,
@@ -17227,9 +18309,26 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17227
18309
  )
17228
18310
  };
17229
18311
  }
17230
- const rebase = await git3(folder, ["rebase", remoteBase], timeoutMs, signal);
18312
+ let preparationResults = [];
18313
+ if (input.forcePreparations) {
18314
+ preparationResults = await suspendWorktreePreparations(
18315
+ folder,
18316
+ input.preparations,
18317
+ timeoutMs,
18318
+ signal
18319
+ );
18320
+ if (preparationResults.some((item) => item.state === "ERROR")) {
18321
+ return {
18322
+ ...successfulProcess8,
18323
+ exitCode: 1,
18324
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18325
+ preparations: preparationResults
18326
+ };
18327
+ }
18328
+ }
18329
+ const rebase = await git4(folder, ["rebase", remoteBase], timeoutMs, signal);
17231
18330
  if (rebase.exitCode !== 0) {
17232
- const conflictStatus = await git3(
18331
+ const conflictStatus = await git4(
17233
18332
  folder,
17234
18333
  ["status", "--porcelain=v1", "-z"],
17235
18334
  timeoutMs,
@@ -17240,6 +18339,8 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17240
18339
  return {
17241
18340
  ...successfulProcess8,
17242
18341
  outcome: "CONFLICT",
18342
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18343
+ preparations: suspendedPreparations(),
17243
18344
  worktree: await inspectWorktreeItem(
17244
18345
  folder,
17245
18346
  folder,
@@ -17250,13 +18351,26 @@ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
17250
18351
  )
17251
18352
  };
17252
18353
  }
17253
- await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
17254
- throw new Error(cleanError3(rebase.stderr || "Auto Sync rebase failed"));
18354
+ await git4(folder, ["rebase", "--abort"], timeoutMs, signal);
18355
+ if (input.forcePreparations) await reapplyPreparations();
18356
+ throw new Error(cleanError4(rebase.stderr || "Auto Sync rebase failed"));
17255
18357
  }
17256
- await runGit(["push", "--force-with-lease"], "Auto Sync push failed");
18358
+ const push = await git4(
18359
+ folder,
18360
+ ["push", "--force-with-lease"],
18361
+ timeoutMs,
18362
+ signal
18363
+ );
18364
+ if (push.exitCode !== 0) {
18365
+ if (input.forcePreparations) await reapplyPreparations();
18366
+ requireSuccess4(push, "Auto Sync push failed");
18367
+ }
18368
+ preparationResults = input.forcePreparations ? await reapplyPreparations() : await inspectPreparations();
17257
18369
  return {
17258
18370
  ...successfulProcess8,
17259
18371
  outcome: "SYNCED",
18372
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
18373
+ preparations: preparationResults,
17260
18374
  worktree: await inspectWorktreeItem(
17261
18375
  folder,
17262
18376
  folder,
@@ -17290,6 +18404,7 @@ var handlers = {
17290
18404
  [WORKTREE_MOVE_CHECKOUT_JOB_KIND]: checkoutMovedWorktree,
17291
18405
  [WORKTREE_DELETE_JOB_KIND]: deleteWorktree,
17292
18406
  [WORKTREE_OPERATION_JOB_KIND]: operateWorktree,
18407
+ [WORKTREE_PREPARATION_JOB_KIND]: prepareWorktree,
17293
18408
  [WORKTREE_GIT_INSPECT_JOB_KIND]: inspectWorktreeGit,
17294
18409
  [WORKTREE_GIT_OPERATION_JOB_KIND]: operateWorktreeGit,
17295
18410
  [WORKTREE_WATCH_JOB_KIND]: watchWorktree,
@@ -17328,8 +18443,8 @@ var RepositoryCoordinator = class {
17328
18443
  async run(key, task) {
17329
18444
  const previous = this.tails.get(key) ?? Promise.resolve();
17330
18445
  let release2;
17331
- const current = new Promise((resolve8) => {
17332
- release2 = resolve8;
18446
+ const current = new Promise((resolve9) => {
18447
+ release2 = resolve9;
17333
18448
  });
17334
18449
  const tail = previous.then(() => current);
17335
18450
  this.tails.set(key, tail);
@@ -17433,7 +18548,7 @@ var JobExecutor = class {
17433
18548
  );
17434
18549
  if (this.stopping) return;
17435
18550
  const delay = Math.min(3e4, 1e3 * 2 ** Math.min(retry++, 5));
17436
- await new Promise((resolve8) => setTimeout(resolve8, delay));
18551
+ await new Promise((resolve9) => setTimeout(resolve9, delay));
17437
18552
  }
17438
18553
  }
17439
18554
  }
@@ -17580,21 +18695,21 @@ var CodebaseMonitor = class {
17580
18695
 
17581
18696
  // src/runs/run-manager.ts
17582
18697
  import { execFile as execFile4 } from "node:child_process";
17583
- import { mkdir as mkdir6, rm as rm13 } from "node:fs/promises";
17584
- import { dirname as dirname10, join as join17 } from "node:path";
18698
+ import { mkdir as mkdir7, rm as rm14 } from "node:fs/promises";
18699
+ import { dirname as dirname11, join as join18 } from "node:path";
17585
18700
  import { promisify as promisify4 } from "node:util";
17586
18701
 
17587
18702
  // src/runs/journal.ts
17588
18703
  import { randomUUID as randomUUID4 } from "node:crypto";
17589
18704
  import {
17590
18705
  appendFile,
17591
- mkdir as mkdir5,
17592
- readFile as readFile9,
18706
+ mkdir as mkdir6,
18707
+ readFile as readFile10,
17593
18708
  rename as rename4,
17594
- rm as rm10,
17595
- writeFile as writeFile7
18709
+ rm as rm11,
18710
+ writeFile as writeFile8
17596
18711
  } from "node:fs/promises";
17597
- import { dirname as dirname8, join as join14 } from "node:path";
18712
+ import { dirname as dirname9, join as join15 } from "node:path";
17598
18713
  var RunJournal = class {
17599
18714
  constructor(runId, attemptId) {
17600
18715
  this.runId = runId;
@@ -17613,13 +18728,13 @@ var RunJournal = class {
17613
18728
  this.attemptId = attemptId;
17614
18729
  }
17615
18730
  get directory() {
17616
- return join14(dirname8(configPath()), "runs", this.runId);
18731
+ return join15(dirname9(configPath()), "runs", this.runId);
17617
18732
  }
17618
18733
  get eventsPath() {
17619
- return join14(this.directory, "events.jsonl");
18734
+ return join15(this.directory, "events.jsonl");
17620
18735
  }
17621
18736
  get statePath() {
17622
- return join14(this.directory, "state.json");
18737
+ return join15(this.directory, "state.json");
17623
18738
  }
17624
18739
  async load() {
17625
18740
  if (this.loaded) return;
@@ -17631,9 +18746,9 @@ var RunJournal = class {
17631
18746
  await this.loading;
17632
18747
  }
17633
18748
  async loadState() {
17634
- await mkdir5(this.directory, { recursive: true, mode: 448 });
18749
+ await mkdir6(this.directory, { recursive: true, mode: 448 });
17635
18750
  try {
17636
- const state = JSON.parse(await readFile9(this.statePath, "utf8"));
18751
+ const state = JSON.parse(await readFile10(this.statePath, "utf8"));
17637
18752
  this.acknowledged = state.acknowledged ?? -1;
17638
18753
  this.nextSequence = state.nextSequence ?? 0;
17639
18754
  } catch {
@@ -17708,7 +18823,7 @@ var RunJournal = class {
17708
18823
  }
17709
18824
  async readEvents() {
17710
18825
  try {
17711
- return (await readFile9(this.eventsPath, "utf8")).split("\n").filter(Boolean).map((line) => JSON.parse(line));
18826
+ return (await readFile10(this.eventsPath, "utf8")).split("\n").filter(Boolean).map((line) => JSON.parse(line));
17712
18827
  } catch (error) {
17713
18828
  if (error.code === "ENOENT") return [];
17714
18829
  throw error;
@@ -17720,10 +18835,10 @@ var RunJournal = class {
17720
18835
  const operation = this.saving.then(async () => {
17721
18836
  const temporary = `${this.statePath}.${process.pid}.${randomUUID4()}.tmp`;
17722
18837
  try {
17723
- await writeFile7(temporary, contents, { mode: 384 });
18838
+ await writeFile8(temporary, contents, { mode: 384 });
17724
18839
  await rename4(temporary, this.statePath);
17725
18840
  } catch (error) {
17726
- await rm10(temporary, { force: true }).catch(() => void 0);
18841
+ await rm11(temporary, { force: true }).catch(() => void 0);
17727
18842
  throw error;
17728
18843
  }
17729
18844
  });
@@ -26897,7 +28012,7 @@ function Yy(e) {
26897
28012
  var l = {};
26898
28013
  lt(l, { xid: () => u9, void: () => I9, uuidv7: () => n9, uuidv6: () => r9, uuidv4: () => t9, uuid: () => e9, url: () => o9, uppercase: () => Fl, unknown: () => Ke, union: () => $e, undefined: () => C9, ulid: () => l9, uint64: () => A9, uint32: () => w9, tuple: () => L9, trim: () => Wl, treeifyError: () => Yd, transform: () => jv, toUpperCase: () => Zl, toLowerCase: () => Kl, toJSONSchema: () => Js, templateLiteral: () => q9, symbol: () => O9, superRefine: () => ER, success: () => B9, stringbool: () => W9, stringFormat: () => x9, string: () => k, strictObject: () => N9, startsWith: () => Hl, size: () => $l, setErrorMap: () => J9, set: () => $9, safeParseAsync: () => gv, safeParse: () => mv, registry: () => hl, regexes: () => wo, regex: () => jl, refine: () => SR, record: () => je, readonly: () => hR, property: () => iv, promise: () => G9, prettifyError: () => Xd, preprocess: () => Km, prefault: () => lR, positive: () => tv, pipe: () => Fm, partialRecord: () => M9, parseAsync: () => fv, parse: () => dv, overwrite: () => Vn, optional: () => Ve, object: () => G, number: () => Ce, nullish: () => F9, nullable: () => zm, null: () => Bm, normalize: () => Vl, nonpositive: () => nv, nonoptional: () => uR, nonnegative: () => ov, never: () => Hm, negative: () => rv, nativeEnum: () => j9, nanoid: () => s9, nan: () => H9, multipleOf: () => wi, minSize: () => Ti, minLength: () => Ao, mime: () => Gl, maxSize: () => Ws, maxLength: () => Ks, map: () => U9, lte: () => Ur, lt: () => qn, lowercase: () => zl, looseObject: () => Bt, locales: () => Gs, literal: () => Z, length: () => Zs, lazy: () => bR, ksuid: () => p9, keyof: () => D9, jwt: () => b9, json: () => K9, iso: () => Ys, ipv6: () => f9, ipv4: () => d9, intersection: () => ru, int64: () => k9, int32: () => E9, int: () => hv, instanceof: () => V9, includes: () => Bl, guid: () => QZ, gte: () => ar, gt: () => Gn, globalRegistry: () => sr, getErrorMap: () => Y9, function: () => Dm, formatError: () => js, float64: () => S9, float32: () => v9, flattenError: () => $s, file: () => z9, enum: () => Jt, endsWith: () => ql, emoji: () => i9, email: () => XZ, e164: () => y9, discriminatedUnion: () => Vm, date: () => P9, custom: () => Hv, cuid2: () => c9, cuid: () => a9, core: () => Qr, config: () => ut, coerce: () => qv, clone: () => Ft, cidrv6: () => g9, cidrv4: () => m9, check: () => vR, catch: () => fR, boolean: () => ht, bigint: () => T9, base64url: () => _9, base64: () => h9, array: () => he, any: () => R9, _default: () => aR, _ZodString: () => _v, ZodXID: () => Tv, ZodVoid: () => JC, ZodUnknown: () => KC, ZodUnion: () => Mv, ZodUndefined: () => GC, ZodUUID: () => Wn, ZodURL: () => bv, ZodULID: () => wv, ZodType: () => de, ZodTuple: () => eR, ZodTransform: () => $v, ZodTemplateLiteral: () => _R, ZodSymbol: () => qC, ZodSuccess: () => pR, ZodStringFormat: () => Ge, ZodString: () => Xl, ZodSet: () => rR, ZodRecord: () => Uv, ZodRealError: () => Xs, ZodReadonly: () => gR, ZodPromise: () => xR, ZodPrefault: () => cR, ZodPipe: () => Bv, ZodOptional: () => zv, ZodObject: () => Gm, ZodNumberFormat: () => Qs, ZodNumber: () => Ql, ZodNullable: () => iR, ZodNull: () => VC, ZodNonOptional: () => Fv, ZodNever: () => ZC, ZodNanoID: () => vv, ZodNaN: () => mR, ZodMap: () => tR, ZodLiteral: () => nR, ZodLazy: () => yR, ZodKSUID: () => kv, ZodJWT: () => Nv, ZodIssueCode: () => Z9, ZodIntersection: () => QC, ZodISOTime: () => Um, ZodISODuration: () => $m, ZodISODateTime: () => Lm, ZodISODate: () => Mm, ZodIPv6: () => Ov, ZodIPv4: () => Av, ZodGUID: () => jm, ZodFile: () => oR, ZodError: () => JZ, ZodEnum: () => Yl, ZodEmoji: () => xv, ZodEmail: () => yv, ZodE164: () => Dv, ZodDiscriminatedUnion: () => XC, ZodDefault: () => sR, ZodDate: () => qm, ZodCustomStringFormat: () => HC, ZodCustom: () => Wm, ZodCatch: () => dR, ZodCUID2: () => Ev, ZodCUID: () => Sv, ZodCIDRv6: () => Rv, ZodCIDRv4: () => Cv, ZodBoolean: () => eu, ZodBigIntFormat: () => Lv, ZodBigInt: () => tu, ZodBase64URL: () => Pv, ZodBase64: () => Iv, ZodArray: () => YC, ZodAny: () => WC, TimePrecision: () => lm, NEVER: () => Kd, $output: () => sm, $input: () => am, $brand: () => Zd });
26899
28014
  var Qr = {};
26900
- lt(Qr, { version: () => tx, util: () => M, treeifyError: () => Yd, toJSONSchema: () => Js, toDotPath: () => yC, safeParseAsync: () => Eo, safeParse: () => So, registry: () => hl, regexes: () => wo, prettifyError: () => Xd, parseAsync: () => xi, parse: () => bi, locales: () => Gs, isValidJWT: () => MC, isValidBase64URL: () => LC, isValidBase64: () => ax, globalRegistry: () => sr, globalConfig: () => tl, function: () => Dm, formatError: () => js, flattenError: () => $s, config: () => ut, clone: () => Ft, _xid: () => Ol, _void: () => Tm, _uuidv7: () => vl, _uuidv6: () => xl, _uuidv4: () => bl, _uuid: () => yl, _url: () => Sl, _uppercase: () => Fl, _unknown: () => Ei, _union: () => OZ, _undefined: () => vm, _ulid: () => Al, _uint64: () => bm, _uint32: () => gm, _tuple: () => sv, _trim: () => Wl, _transform: () => UZ, _toUpperCase: () => Zl, _toLowerCase: () => Kl, _templateLiteral: () => VZ, _symbol: () => xm, _success: () => BZ, _stringbool: () => Im, _stringFormat: () => Pm, _string: () => cm, _startsWith: () => Hl, _size: () => $l, _set: () => DZ, _safeParseAsync: () => rf, _safeParse: () => tf, _regex: () => jl, _refine: () => Rm, _record: () => IZ, _readonly: () => GZ, _property: () => iv, _promise: () => KZ, _positive: () => tv, _pipe: () => qZ, _parseAsync: () => ef, _parse: () => Qd, _overwrite: () => Vn, _optional: () => $Z, _number: () => um, _nullable: () => jZ, _null: () => Sm, _normalize: () => Vl, _nonpositive: () => nv, _nonoptional: () => FZ, _nonnegative: () => ov, _never: () => wm, _negative: () => rv, _nativeEnum: () => LZ, _nanoid: () => wl, _nan: () => Am, _multipleOf: () => wi, _minSize: () => Ti, _minLength: () => Ao, _min: () => ar, _mime: () => Gl, _maxSize: () => Ws, _maxLength: () => Ks, _max: () => Ur, _map: () => PZ, _lte: () => Ur, _lt: () => qn, _lowercase: () => zl, _literal: () => MZ, _length: () => Zs, _lazy: () => WZ, _ksuid: () => Cl, _jwt: () => Ul, _isoTime: () => Zx, _isoDuration: () => Jx, _isoDateTime: () => Wx, _isoDate: () => Kx, _ipv6: () => Il, _ipv4: () => Rl, _intersection: () => RZ, _int64: () => ym, _int32: () => mm, _int: () => pm, _includes: () => Bl, _guid: () => Vs, _gte: () => ar, _gt: () => Gn, _float64: () => fm, _float32: () => dm, _file: () => Om, _enum: () => NZ, _endsWith: () => ql, _emoji: () => El, _email: () => _l, _e164: () => Ml, _discriminatedUnion: () => CZ, _default: () => zZ, _date: () => km, _custom: () => Cm, _cuid2: () => kl, _cuid: () => Tl, _coercedString: () => Vx, _coercedNumber: () => Yx, _coercedDate: () => ev, _coercedBoolean: () => Xx, _coercedBigint: () => Qx, _cidrv6: () => Dl, _cidrv4: () => Pl, _catch: () => HZ, _boolean: () => hm, _bigint: () => _m, _base64url: () => Ll, _base64: () => Nl, _array: () => Jl, _any: () => Em, TimePrecision: () => lm, NEVER: () => Kd, JSONSchemaGenerator: () => Nm, JSONSchema: () => zC, Doc: () => af, $output: () => sm, $input: () => am, $constructor: () => S, $brand: () => Zd, $ZodXID: () => bf, $ZodVoid: () => Uf, $ZodUnknown: () => Si, $ZodUnion: () => fl, $ZodUndefined: () => Df, $ZodUUID: () => pf, $ZodURL: () => ff, $ZodULID: () => yf, $ZodType: () => ie, $ZodTuple: () => ko, $ZodTransform: () => Hs, $ZodTemplateLiteral: () => rm11, $ZodSymbol: () => Pf, $ZodSuccess: () => Xf, $ZodStringFormat: () => Ue, $ZodString: () => To, $ZodSet: () => Hf, $ZodRegistry: () => gl, $ZodRecord: () => Ff, $ZodRealError: () => Us, $ZodReadonly: () => tm, $ZodPromise: () => nm, $ZodPrefault: () => Jf, $ZodPipe: () => qs, $ZodOptional: () => Wf, $ZodObject: () => dl, $ZodNumberFormat: () => Rf, $ZodNumber: () => ul, $ZodNullable: () => Kf, $ZodNull: () => Nf, $ZodNonOptional: () => Yf, $ZodNever: () => Mf, $ZodNanoID: () => gf, $ZodNaN: () => em, $ZodMap: () => Bf, $ZodLiteral: () => Gf, $ZodLazy: () => om, $ZodKSUID: () => xf, $ZodJWT: () => Of, $ZodIntersection: () => zf, $ZodISOTime: () => ix, $ZodISODuration: () => sx, $ZodISODateTime: () => nx, $ZodISODate: () => ox, $ZodIPv6: () => Sf, $ZodIPv4: () => vf, $ZodGUID: () => uf, $ZodFunction: () => av, $ZodFile: () => Vf, $ZodError: () => ll, $ZodEnum: () => qf, $ZodEmoji: () => mf, $ZodEmail: () => df, $ZodE164: () => Af, $ZodDiscriminatedUnion: () => jf, $ZodDefault: () => Zf, $ZodDate: () => $f, $ZodCustomStringFormat: () => Cf, $ZodCustom: () => im, $ZodCheckUpperCase: () => Kb, $ZodCheckStringFormat: () => zs, $ZodCheckStartsWith: () => Jb, $ZodCheckSizeEquals: () => Bb, $ZodCheckRegex: () => Vb, $ZodCheckProperty: () => Xb, $ZodCheckOverwrite: () => ex, $ZodCheckNumberFormat: () => $b, $ZodCheckMultipleOf: () => Ub, $ZodCheckMinSize: () => Fb, $ZodCheckMinLength: () => qb, $ZodCheckMimeType: () => Qb, $ZodCheckMaxSize: () => zb, $ZodCheckMaxLength: () => Hb, $ZodCheckLowerCase: () => Wb, $ZodCheckLessThan: () => of, $ZodCheckLengthEquals: () => Gb, $ZodCheckIncludes: () => Zb, $ZodCheckGreaterThan: () => sf, $ZodCheckEndsWith: () => Yb, $ZodCheckBigIntFormat: () => jb, $ZodCheck: () => Xe, $ZodCatch: () => Qf, $ZodCUID2: () => _f, $ZodCUID: () => hf, $ZodCIDRv6: () => wf, $ZodCIDRv4: () => Ef, $ZodBoolean: () => Fs, $ZodBigIntFormat: () => If, $ZodBigInt: () => pl, $ZodBase64URL: () => kf, $ZodBase64: () => Tf, $ZodAsyncError: () => Bn, $ZodArray: () => Bs, $ZodAny: () => Lf });
28015
+ lt(Qr, { version: () => tx, util: () => M, treeifyError: () => Yd, toJSONSchema: () => Js, toDotPath: () => yC, safeParseAsync: () => Eo, safeParse: () => So, registry: () => hl, regexes: () => wo, prettifyError: () => Xd, parseAsync: () => xi, parse: () => bi, locales: () => Gs, isValidJWT: () => MC, isValidBase64URL: () => LC, isValidBase64: () => ax, globalRegistry: () => sr, globalConfig: () => tl, function: () => Dm, formatError: () => js, flattenError: () => $s, config: () => ut, clone: () => Ft, _xid: () => Ol, _void: () => Tm, _uuidv7: () => vl, _uuidv6: () => xl, _uuidv4: () => bl, _uuid: () => yl, _url: () => Sl, _uppercase: () => Fl, _unknown: () => Ei, _union: () => OZ, _undefined: () => vm, _ulid: () => Al, _uint64: () => bm, _uint32: () => gm, _tuple: () => sv, _trim: () => Wl, _transform: () => UZ, _toUpperCase: () => Zl, _toLowerCase: () => Kl, _templateLiteral: () => VZ, _symbol: () => xm, _success: () => BZ, _stringbool: () => Im, _stringFormat: () => Pm, _string: () => cm, _startsWith: () => Hl, _size: () => $l, _set: () => DZ, _safeParseAsync: () => rf, _safeParse: () => tf, _regex: () => jl, _refine: () => Rm, _record: () => IZ, _readonly: () => GZ, _property: () => iv, _promise: () => KZ, _positive: () => tv, _pipe: () => qZ, _parseAsync: () => ef, _parse: () => Qd, _overwrite: () => Vn, _optional: () => $Z, _number: () => um, _nullable: () => jZ, _null: () => Sm, _normalize: () => Vl, _nonpositive: () => nv, _nonoptional: () => FZ, _nonnegative: () => ov, _never: () => wm, _negative: () => rv, _nativeEnum: () => LZ, _nanoid: () => wl, _nan: () => Am, _multipleOf: () => wi, _minSize: () => Ti, _minLength: () => Ao, _min: () => ar, _mime: () => Gl, _maxSize: () => Ws, _maxLength: () => Ks, _max: () => Ur, _map: () => PZ, _lte: () => Ur, _lt: () => qn, _lowercase: () => zl, _literal: () => MZ, _length: () => Zs, _lazy: () => WZ, _ksuid: () => Cl, _jwt: () => Ul, _isoTime: () => Zx, _isoDuration: () => Jx, _isoDateTime: () => Wx, _isoDate: () => Kx, _ipv6: () => Il, _ipv4: () => Rl, _intersection: () => RZ, _int64: () => ym, _int32: () => mm, _int: () => pm, _includes: () => Bl, _guid: () => Vs, _gte: () => ar, _gt: () => Gn, _float64: () => fm, _float32: () => dm, _file: () => Om, _enum: () => NZ, _endsWith: () => ql, _emoji: () => El, _email: () => _l, _e164: () => Ml, _discriminatedUnion: () => CZ, _default: () => zZ, _date: () => km, _custom: () => Cm, _cuid2: () => kl, _cuid: () => Tl, _coercedString: () => Vx, _coercedNumber: () => Yx, _coercedDate: () => ev, _coercedBoolean: () => Xx, _coercedBigint: () => Qx, _cidrv6: () => Dl, _cidrv4: () => Pl, _catch: () => HZ, _boolean: () => hm, _bigint: () => _m, _base64url: () => Ll, _base64: () => Nl, _array: () => Jl, _any: () => Em, TimePrecision: () => lm, NEVER: () => Kd, JSONSchemaGenerator: () => Nm, JSONSchema: () => zC, Doc: () => af, $output: () => sm, $input: () => am, $constructor: () => S, $brand: () => Zd, $ZodXID: () => bf, $ZodVoid: () => Uf, $ZodUnknown: () => Si, $ZodUnion: () => fl, $ZodUndefined: () => Df, $ZodUUID: () => pf, $ZodURL: () => ff, $ZodULID: () => yf, $ZodType: () => ie, $ZodTuple: () => ko, $ZodTransform: () => Hs, $ZodTemplateLiteral: () => rm12, $ZodSymbol: () => Pf, $ZodSuccess: () => Xf, $ZodStringFormat: () => Ue, $ZodString: () => To, $ZodSet: () => Hf, $ZodRegistry: () => gl, $ZodRecord: () => Ff, $ZodRealError: () => Us, $ZodReadonly: () => tm, $ZodPromise: () => nm, $ZodPrefault: () => Jf, $ZodPipe: () => qs, $ZodOptional: () => Wf, $ZodObject: () => dl, $ZodNumberFormat: () => Rf, $ZodNumber: () => ul, $ZodNullable: () => Kf, $ZodNull: () => Nf, $ZodNonOptional: () => Yf, $ZodNever: () => Mf, $ZodNanoID: () => gf, $ZodNaN: () => em, $ZodMap: () => Bf, $ZodLiteral: () => Gf, $ZodLazy: () => om, $ZodKSUID: () => xf, $ZodJWT: () => Of, $ZodIntersection: () => zf, $ZodISOTime: () => ix, $ZodISODuration: () => sx, $ZodISODateTime: () => nx, $ZodISODate: () => ox, $ZodIPv6: () => Sf, $ZodIPv4: () => vf, $ZodGUID: () => uf, $ZodFunction: () => av, $ZodFile: () => Vf, $ZodError: () => ll, $ZodEnum: () => qf, $ZodEmoji: () => mf, $ZodEmail: () => df, $ZodE164: () => Af, $ZodDiscriminatedUnion: () => jf, $ZodDefault: () => Zf, $ZodDate: () => $f, $ZodCustomStringFormat: () => Cf, $ZodCustom: () => im, $ZodCheckUpperCase: () => Kb, $ZodCheckStringFormat: () => zs, $ZodCheckStartsWith: () => Jb, $ZodCheckSizeEquals: () => Bb, $ZodCheckRegex: () => Vb, $ZodCheckProperty: () => Xb, $ZodCheckOverwrite: () => ex, $ZodCheckNumberFormat: () => $b, $ZodCheckMultipleOf: () => Ub, $ZodCheckMinSize: () => Fb, $ZodCheckMinLength: () => qb, $ZodCheckMimeType: () => Qb, $ZodCheckMaxSize: () => zb, $ZodCheckMaxLength: () => Hb, $ZodCheckLowerCase: () => Wb, $ZodCheckLessThan: () => of, $ZodCheckLengthEquals: () => Gb, $ZodCheckIncludes: () => Zb, $ZodCheckGreaterThan: () => sf, $ZodCheckEndsWith: () => Yb, $ZodCheckBigIntFormat: () => jb, $ZodCheck: () => Xe, $ZodCatch: () => Qf, $ZodCUID2: () => _f, $ZodCUID: () => hf, $ZodCIDRv6: () => wf, $ZodCIDRv4: () => Ef, $ZodBoolean: () => Fs, $ZodBigIntFormat: () => If, $ZodBigInt: () => pl, $ZodBase64URL: () => kf, $ZodBase64: () => Tf, $ZodAsyncError: () => Bn, $ZodArray: () => Bs, $ZodAny: () => Lf });
26901
28016
  var Kd = Object.freeze({ status: "aborted" });
26902
28017
  function S(e, t, r) {
26903
28018
  function n(a, c) {
@@ -28445,7 +29560,7 @@ var tm = S("$ZodReadonly", (e, t) => {
28445
29560
  function DC(e) {
28446
29561
  return e.value = Object.freeze(e.value), e;
28447
29562
  }
28448
- var rm11 = S("$ZodTemplateLiteral", (e, t) => {
29563
+ var rm12 = S("$ZodTemplateLiteral", (e, t) => {
28449
29564
  ie.init(e, t);
28450
29565
  let r = [];
28451
29566
  for (let n of t.parts) if (n instanceof ie) {
@@ -32252,7 +33367,7 @@ function hR(e) {
32252
33367
  return new gR({ type: "readonly", innerType: e });
32253
33368
  }
32254
33369
  var _R = S("ZodTemplateLiteral", (e, t) => {
32255
- rm11.init(e, t), de.init(e, t);
33370
+ rm12.init(e, t), de.init(e, t);
32256
33371
  });
32257
33372
  function q9(e, t) {
32258
33373
  return new _R({ type: "template_literal", parts: e, ...M.normalizeParams(t) });
@@ -43579,7 +44694,7 @@ var MessageQueue = class {
43579
44694
  if (value) return Promise.resolve({ value, done: false });
43580
44695
  if (this.closed)
43581
44696
  return Promise.resolve({ value: void 0, done: true });
43582
- return new Promise((resolve8) => this.waiters.push(resolve8));
44697
+ return new Promise((resolve9) => this.waiters.push(resolve9));
43583
44698
  }
43584
44699
  };
43585
44700
  }
@@ -43749,8 +44864,8 @@ var ClaudeAdapter = class {
43749
44864
  const requestId = options.toolUseID || randomUUID5();
43750
44865
  const questions = questionsFromInput(toolInput);
43751
44866
  await callbacks.onQuestion(requestId, questions);
43752
- const answers = await new Promise((resolve8) => {
43753
- pendingQuestions.set(requestId, { input: toolInput, resolve: resolve8 });
44867
+ const answers = await new Promise((resolve9) => {
44868
+ pendingQuestions.set(requestId, { input: toolInput, resolve: resolve9 });
43754
44869
  });
43755
44870
  return {
43756
44871
  behavior: "allow",
@@ -43893,9 +45008,9 @@ import {
43893
45008
  execFile as execFile3,
43894
45009
  spawn as spawn8
43895
45010
  } from "node:child_process";
43896
- import { mkdtemp as mkdtemp7, rm as rm12, writeFile as writeFile8 } from "node:fs/promises";
45011
+ import { mkdtemp as mkdtemp7, rm as rm13, writeFile as writeFile9 } from "node:fs/promises";
43897
45012
  import { tmpdir as tmpdir7 } from "node:os";
43898
- import { join as join16 } from "node:path";
45013
+ import { join as join17 } from "node:path";
43899
45014
  import { createInterface } from "node:readline";
43900
45015
  import { promisify as promisify3 } from "node:util";
43901
45016
  var SUPPORTED_CODEX_APP_SERVER_MINORS = ["0.144", "0.145"];
@@ -44006,8 +45121,8 @@ var CodexAppServer = class {
44006
45121
  });
44007
45122
  const lines = createInterface({ input: child.stdout });
44008
45123
  lines.on("line", (line) => this.receive(line));
44009
- await new Promise((resolve8, reject) => {
44010
- child.once("spawn", resolve8);
45124
+ await new Promise((resolve9, reject) => {
45125
+ child.once("spawn", resolve9);
44011
45126
  child.once("error", reject);
44012
45127
  });
44013
45128
  const initialized = asRecord(
@@ -44049,7 +45164,7 @@ var CodexAppServer = class {
44049
45164
  }
44050
45165
  }
44051
45166
  async createBundledModelCatalog(executable) {
44052
- const directory = await mkdtemp7(join16(tmpdir7(), "aide-codex-models-"));
45167
+ const directory = await mkdtemp7(join17(tmpdir7(), "aide-codex-models-"));
44053
45168
  try {
44054
45169
  const { stdout } = await execFileAsync2(
44055
45170
  executable,
@@ -44059,12 +45174,12 @@ var CodexAppServer = class {
44059
45174
  maxBuffer: 16 * 1024 * 1024
44060
45175
  }
44061
45176
  );
44062
- const catalogPath = join16(directory, "models.json");
44063
- await writeFile8(catalogPath, stdout, "utf8");
45177
+ const catalogPath = join17(directory, "models.json");
45178
+ await writeFile9(catalogPath, stdout, "utf8");
44064
45179
  this.modelCatalogDirectory = directory;
44065
45180
  return catalogPath;
44066
45181
  } catch (error) {
44067
- await rm12(directory, { recursive: true, force: true }).catch(
45182
+ await rm13(directory, { recursive: true, force: true }).catch(
44068
45183
  () => void 0
44069
45184
  );
44070
45185
  throw error;
@@ -44075,7 +45190,7 @@ var CodexAppServer = class {
44075
45190
  if (this.modelCatalogDirectory === directory) {
44076
45191
  this.modelCatalogDirectory = void 0;
44077
45192
  }
44078
- await rm12(directory, { recursive: true, force: true }).catch(
45193
+ await rm13(directory, { recursive: true, force: true }).catch(
44079
45194
  () => void 0
44080
45195
  );
44081
45196
  }
@@ -44115,8 +45230,8 @@ var CodexAppServer = class {
44115
45230
  }
44116
45231
  requestDirect(method, params) {
44117
45232
  const id2 = this.nextId++;
44118
- return new Promise((resolve8, reject) => {
44119
- this.pending.set(id2, { resolve: resolve8, reject });
45233
+ return new Promise((resolve9, reject) => {
45234
+ this.pending.set(id2, { resolve: resolve9, reject });
44120
45235
  this.write({ id: id2, method, params });
44121
45236
  });
44122
45237
  }
@@ -44279,8 +45394,8 @@ var CodexAdapter = class {
44279
45394
  let lastUsageSignature = "";
44280
45395
  const pendingQuestions = /* @__PURE__ */ new Map();
44281
45396
  let resolveCompletion;
44282
- const completion = new Promise((resolve8) => {
44283
- resolveCompletion = resolve8;
45397
+ const completion = new Promise((resolve9) => {
45398
+ resolveCompletion = resolve9;
44284
45399
  });
44285
45400
  const unsubscribe = this.server.listen(nativeId, (message) => {
44286
45401
  void (async () => {
@@ -44490,13 +45605,13 @@ var CodexAdapter = class {
44490
45605
  };
44491
45606
 
44492
45607
  // src/runs/opencode-adapter.ts
44493
- import { dirname as dirname9 } from "node:path";
45608
+ import { dirname as dirname10 } from "node:path";
44494
45609
  import { pathToFileURL } from "node:url";
44495
45610
 
44496
45611
  // ../../node_modules/@opencode-ai/sdk/dist/v2/gen/core/serverSentEvents.gen.js
44497
45612
  var createSseClient = ({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) => {
44498
45613
  let lastEventId;
44499
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
45614
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve9) => setTimeout(resolve9, ms)));
44500
45615
  const createStream = async function* () {
44501
45616
  let retryDelay = sseDefaultRetryDelay ?? 3e3;
44502
45617
  let attempt = 0;
@@ -49948,7 +51063,7 @@ async function createOpencodeServer(options) {
49948
51063
  });
49949
51064
  let clear = () => {
49950
51065
  };
49951
- const url = await new Promise((resolve8, reject) => {
51066
+ const url = await new Promise((resolve9, reject) => {
49952
51067
  const id2 = setTimeout(() => {
49953
51068
  clear();
49954
51069
  stop(proc);
@@ -49973,7 +51088,7 @@ async function createOpencodeServer(options) {
49973
51088
  }
49974
51089
  clearTimeout(id2);
49975
51090
  resolved = true;
49976
- resolve8(match[1]);
51091
+ resolve9(match[1]);
49977
51092
  return;
49978
51093
  }
49979
51094
  }
@@ -50138,11 +51253,11 @@ function responseItems(value) {
50138
51253
  }
50139
51254
  function waitForPoll(signal) {
50140
51255
  if (signal.aborted) return Promise.resolve();
50141
- return new Promise((resolve8) => {
51256
+ return new Promise((resolve9) => {
50142
51257
  const finish = () => {
50143
51258
  clearTimeout(timer);
50144
51259
  signal.removeEventListener("abort", finish);
50145
- resolve8();
51260
+ resolve9();
50146
51261
  };
50147
51262
  const timer = setTimeout(finish, QUESTION_RECONCILIATION_INTERVAL_MS);
50148
51263
  timer.unref();
@@ -50171,7 +51286,7 @@ var OpenCodeAdapter = class {
50171
51286
  "opencode was not found. Install it (brew install sst/tap/opencode, or npm install -g opencode-ai) or set CONTROL_AGENT_OPENCODE_EXECUTABLE to its full path."
50172
51287
  );
50173
51288
  }
50174
- prependPathDirectory(dirname9(executable));
51289
+ prependPathDirectory(dirname10(executable));
50175
51290
  this.runtime = await createOpencode({ port: 0 });
50176
51291
  }
50177
51292
  return this.runtime.client;
@@ -50795,7 +51910,7 @@ var RunManager = class {
50795
51910
  5
50796
51911
  );
50797
51912
  await this.completeCommand(command3.id, "SUCCEEDED");
50798
- await rm13(join17(dirname10(configPath()), "runs", run.id, "attachments"), {
51913
+ await rm14(join18(dirname11(configPath()), "runs", run.id, "attachments"), {
50799
51914
  recursive: true,
50800
51915
  force: true
50801
51916
  }).catch(() => void 0);
@@ -50977,7 +52092,7 @@ var RunManager = class {
50977
52092
  this.active.delete(run.id);
50978
52093
  this.interruptionRequests.delete(run.id);
50979
52094
  this.executingCommands.delete(command3.id);
50980
- await rm13(join17(dirname10(configPath()), "runs", run.id, "attachments"), {
52095
+ await rm14(join18(dirname11(configPath()), "runs", run.id, "attachments"), {
50981
52096
  recursive: true,
50982
52097
  force: true
50983
52098
  }).catch(() => void 0);
@@ -51205,11 +52320,11 @@ var RunManager = class {
51205
52320
  }
51206
52321
  async stageAttachments(runId, attachments) {
51207
52322
  if (!attachments.length) return [];
51208
- const directory = join17(dirname10(configPath()), "runs", runId, "attachments");
51209
- await mkdir6(directory, { recursive: true, mode: 448 });
52323
+ const directory = join18(dirname11(configPath()), "runs", runId, "attachments");
52324
+ await mkdir7(directory, { recursive: true, mode: 448 });
51210
52325
  return Promise.all(
51211
52326
  attachments.map(async (attachment) => {
51212
- const path = join17(
52327
+ const path = join18(
51213
52328
  directory,
51214
52329
  `${attachment.id}-${safeFilename(attachment.filename)}`
51215
52330
  );
@@ -51301,7 +52416,7 @@ var RunManager = class {
51301
52416
  return await operation();
51302
52417
  } catch (error) {
51303
52418
  if (this.stopped || attempt >= attempts) throw error;
51304
- await new Promise((resolve8) => setTimeout(resolve8, delay));
52419
+ await new Promise((resolve9) => setTimeout(resolve9, delay));
51305
52420
  delay = Math.min(delay * 2, 3e4);
51306
52421
  }
51307
52422
  }
@@ -51581,9 +52696,9 @@ async function runAgentSession(config, signal, onUnhealthy) {
51581
52696
  }
51582
52697
  }
51583
52698
  );
51584
- await new Promise((resolve8) => {
51585
- if (signal.aborted) resolve8();
51586
- else signal.addEventListener("abort", () => resolve8(), { once: true });
52699
+ await new Promise((resolve9) => {
52700
+ if (signal.aborted) resolve9();
52701
+ else signal.addEventListener("abort", () => resolve9(), { once: true });
51587
52702
  });
51588
52703
  if (heartbeatTimer) clearTimeout(heartbeatTimer);
51589
52704
  if (jobReconciliationTimer) clearTimeout(jobReconciliationTimer);
@@ -51650,7 +52765,7 @@ var defaultDependencies = {
51650
52765
  inventory: collectInventory,
51651
52766
  load: loadConfig,
51652
52767
  save: saveConfig,
51653
- wait: (milliseconds, signal) => new Promise((resolve8, reject) => {
52768
+ wait: (milliseconds, signal) => new Promise((resolve9, reject) => {
51654
52769
  if (signal.aborted) {
51655
52770
  reject(new Error("Development agent startup was cancelled"));
51656
52771
  return;
@@ -51661,7 +52776,7 @@ var defaultDependencies = {
51661
52776
  };
51662
52777
  const timer = setTimeout(() => {
51663
52778
  signal.removeEventListener("abort", onAbort);
51664
- resolve8();
52779
+ resolve9();
51665
52780
  }, milliseconds);
51666
52781
  signal.addEventListener("abort", onAbort, { once: true });
51667
52782
  })
@@ -51905,7 +53020,7 @@ async function unenroll() {
51905
53020
  config = await loadConfig(path);
51906
53021
  } catch {
51907
53022
  }
51908
- await rm14(path, { force: true });
53023
+ await rm15(path, { force: true });
51909
53024
  console.log(
51910
53025
  config ? `Removed the enrollment for ${config.name} (${config.agentId}) from ${path}` : `Removed ${path}`
51911
53026
  );