@osfactory/har 0.34.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -873,14 +873,14 @@ var require_url_state_machine = __commonJS({
873
873
  return url.replace(/\u0009|\u000A|\u000D/g, "");
874
874
  }
875
875
  function shortenPath(url) {
876
- const path60 = url.path;
877
- if (path60.length === 0) {
876
+ const path61 = url.path;
877
+ if (path61.length === 0) {
878
878
  return;
879
879
  }
880
- if (url.scheme === "file" && path60.length === 1 && isNormalizedWindowsDriveLetter(path60[0])) {
880
+ if (url.scheme === "file" && path61.length === 1 && isNormalizedWindowsDriveLetter(path61[0])) {
881
881
  return;
882
882
  }
883
- path60.pop();
883
+ path61.pop();
884
884
  }
885
885
  function includesCredentials(url) {
886
886
  return url.username !== "" || url.password !== "";
@@ -2200,7 +2200,7 @@ var require_lib2 = __commonJS({
2200
2200
  let accum = [];
2201
2201
  let accumBytes = 0;
2202
2202
  let abort = false;
2203
- return new Body.Promise(function(resolve44, reject) {
2203
+ return new Body.Promise(function(resolve45, reject) {
2204
2204
  let resTimeout;
2205
2205
  if (_this4.timeout) {
2206
2206
  resTimeout = setTimeout(function() {
@@ -2234,7 +2234,7 @@ var require_lib2 = __commonJS({
2234
2234
  }
2235
2235
  clearTimeout(resTimeout);
2236
2236
  try {
2237
- resolve44(Buffer.concat(accum, accumBytes));
2237
+ resolve45(Buffer.concat(accum, accumBytes));
2238
2238
  } catch (err) {
2239
2239
  reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
2240
2240
  }
@@ -2909,7 +2909,7 @@ var require_lib2 = __commonJS({
2909
2909
  throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
2910
2910
  }
2911
2911
  Body.Promise = fetch3.Promise;
2912
- return new fetch3.Promise(function(resolve44, reject) {
2912
+ return new fetch3.Promise(function(resolve45, reject) {
2913
2913
  const request = new Request3(url, opts);
2914
2914
  const options = getNodeRequestOptions(request);
2915
2915
  const send = (options.protocol === "https:" ? https : http2).request;
@@ -3042,7 +3042,7 @@ var require_lib2 = __commonJS({
3042
3042
  requestOpts.body = void 0;
3043
3043
  requestOpts.headers.delete("content-length");
3044
3044
  }
3045
- resolve44(fetch3(new Request3(locationURL, requestOpts)));
3045
+ resolve45(fetch3(new Request3(locationURL, requestOpts)));
3046
3046
  finalize();
3047
3047
  return;
3048
3048
  }
@@ -3063,7 +3063,7 @@ var require_lib2 = __commonJS({
3063
3063
  const codings = headers.get("Content-Encoding");
3064
3064
  if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
3065
3065
  response = new Response3(body, response_options);
3066
- resolve44(response);
3066
+ resolve45(response);
3067
3067
  return;
3068
3068
  }
3069
3069
  const zlibOptions = {
@@ -3073,7 +3073,7 @@ var require_lib2 = __commonJS({
3073
3073
  if (codings == "gzip" || codings == "x-gzip") {
3074
3074
  body = body.pipe(zlib.createGunzip(zlibOptions));
3075
3075
  response = new Response3(body, response_options);
3076
- resolve44(response);
3076
+ resolve45(response);
3077
3077
  return;
3078
3078
  }
3079
3079
  if (codings == "deflate" || codings == "x-deflate") {
@@ -3085,12 +3085,12 @@ var require_lib2 = __commonJS({
3085
3085
  body = body.pipe(zlib.createInflateRaw());
3086
3086
  }
3087
3087
  response = new Response3(body, response_options);
3088
- resolve44(response);
3088
+ resolve45(response);
3089
3089
  });
3090
3090
  raw.on("end", function() {
3091
3091
  if (!response) {
3092
3092
  response = new Response3(body, response_options);
3093
- resolve44(response);
3093
+ resolve45(response);
3094
3094
  }
3095
3095
  });
3096
3096
  return;
@@ -3098,11 +3098,11 @@ var require_lib2 = __commonJS({
3098
3098
  if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
3099
3099
  body = body.pipe(zlib.createBrotliDecompress());
3100
3100
  response = new Response3(body, response_options);
3101
- resolve44(response);
3101
+ resolve45(response);
3102
3102
  return;
3103
3103
  }
3104
3104
  response = new Response3(body, response_options);
3105
- resolve44(response);
3105
+ resolve45(response);
3106
3106
  });
3107
3107
  writeToStream(req, request);
3108
3108
  });
@@ -6459,14 +6459,14 @@ __export(fileFromPath_exports, {
6459
6459
  fileFromPathSync: () => fileFromPathSync,
6460
6460
  isFile: () => isFile
6461
6461
  });
6462
- function createFileFromPath(path60, { mtimeMs, size }, filenameOrOptions, options = {}) {
6462
+ function createFileFromPath(path61, { mtimeMs, size }, filenameOrOptions, options = {}) {
6463
6463
  let filename;
6464
6464
  if (isPlainObject_default2(filenameOrOptions)) {
6465
6465
  [options, filename] = [filenameOrOptions, void 0];
6466
6466
  } else {
6467
6467
  filename = filenameOrOptions;
6468
6468
  }
6469
- const file = new FileFromPath({ path: path60, size, lastModified: mtimeMs });
6469
+ const file = new FileFromPath({ path: path61, size, lastModified: mtimeMs });
6470
6470
  if (!filename) {
6471
6471
  filename = file.name;
6472
6472
  }
@@ -6475,13 +6475,13 @@ function createFileFromPath(path60, { mtimeMs, size }, filenameOrOptions, option
6475
6475
  lastModified: file.lastModified
6476
6476
  });
6477
6477
  }
6478
- function fileFromPathSync(path60, filenameOrOptions, options = {}) {
6479
- const stats = (0, import_fs5.statSync)(path60);
6480
- return createFileFromPath(path60, stats, filenameOrOptions, options);
6478
+ function fileFromPathSync(path61, filenameOrOptions, options = {}) {
6479
+ const stats = (0, import_fs5.statSync)(path61);
6480
+ return createFileFromPath(path61, stats, filenameOrOptions, options);
6481
6481
  }
6482
- async function fileFromPath2(path60, filenameOrOptions, options) {
6483
- const stats = await import_fs5.promises.stat(path60);
6484
- return createFileFromPath(path60, stats, filenameOrOptions, options);
6482
+ async function fileFromPath2(path61, filenameOrOptions, options) {
6483
+ const stats = await import_fs5.promises.stat(path61);
6484
+ return createFileFromPath(path61, stats, filenameOrOptions, options);
6485
6485
  }
6486
6486
  var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
6487
6487
  var init_fileFromPath = __esm({
@@ -6544,13 +6544,13 @@ var init_fileFromPath = __esm({
6544
6544
  // src/core/portal-credentials.ts
6545
6545
  function portalCredentialsPath() {
6546
6546
  if (process.env.HAR_CREDENTIALS_PATH) {
6547
- return path26.resolve(process.env.HAR_CREDENTIALS_PATH);
6547
+ return path27.resolve(process.env.HAR_CREDENTIALS_PATH);
6548
6548
  }
6549
- return path26.join(os5.homedir(), ".har", "credentials.json");
6549
+ return path27.join(os5.homedir(), ".har", "credentials.json");
6550
6550
  }
6551
6551
  function readPortalCredentials() {
6552
6552
  try {
6553
- const raw = fs27.readFileSync(portalCredentialsPath(), "utf8");
6553
+ const raw = fs28.readFileSync(portalCredentialsPath(), "utf8");
6554
6554
  const parsed = JSON.parse(raw);
6555
6555
  if (!parsed.portalUrl || !parsed.token) return null;
6556
6556
  return {
@@ -6566,17 +6566,17 @@ function readPortalCredentials() {
6566
6566
  }
6567
6567
  function writePortalCredentials(creds) {
6568
6568
  const file = portalCredentialsPath();
6569
- fs27.mkdirSync(path26.dirname(file), { recursive: true });
6570
- fs27.writeFileSync(file, JSON.stringify(creds, null, 2), { mode: 384 });
6571
- fs27.chmodSync(file, 384);
6569
+ fs28.mkdirSync(path27.dirname(file), { recursive: true });
6570
+ fs28.writeFileSync(file, JSON.stringify(creds, null, 2), { mode: 384 });
6571
+ fs28.chmodSync(file, 384);
6572
6572
  }
6573
- var fs27, os5, path26;
6573
+ var fs28, os5, path27;
6574
6574
  var init_portal_credentials = __esm({
6575
6575
  "src/core/portal-credentials.ts"() {
6576
6576
  "use strict";
6577
- fs27 = __toESM(require("fs"));
6577
+ fs28 = __toESM(require("fs"));
6578
6578
  os5 = __toESM(require("os"));
6579
- path26 = __toESM(require("path"));
6579
+ path27 = __toESM(require("path"));
6580
6580
  }
6581
6581
  });
6582
6582
 
@@ -6640,32 +6640,32 @@ __export(otel_hooks_exports, {
6640
6640
  });
6641
6641
  function getOtelHooksHome() {
6642
6642
  if (process.env.HAR_OTEL_HOOKS_HOME) {
6643
- return path45.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6643
+ return path46.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6644
6644
  }
6645
- return path45.join(os14.homedir(), ".har", "otel-hooks");
6645
+ return path46.join(os14.homedir(), ".har", "otel-hooks");
6646
6646
  }
6647
6647
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
6648
- return path45.join(hooksHome, "otel_config.json");
6648
+ return path46.join(hooksHome, "otel_config.json");
6649
6649
  }
6650
6650
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
6651
- return path45.join(hooksHome, "run-otel-hook.sh");
6651
+ return path46.join(hooksHome, "run-otel-hook.sh");
6652
6652
  }
6653
6653
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
6654
- return path45.join(hooksHome, "state");
6654
+ return path46.join(hooksHome, "state");
6655
6655
  }
6656
6656
  function localOtelHookBin(hooksHome) {
6657
- return path45.join(hooksHome, "node_modules", ".bin", "otel-hook");
6657
+ return path46.join(hooksHome, "node_modules", ".bin", "otel-hook");
6658
6658
  }
6659
6659
  function installedPackageVersion(hooksHome) {
6660
6660
  try {
6661
- const pkgPath = path45.join(
6661
+ const pkgPath = path46.join(
6662
6662
  hooksHome,
6663
6663
  "node_modules",
6664
6664
  "@osfactory",
6665
6665
  "otel-hook",
6666
6666
  "package.json"
6667
6667
  );
6668
- const pkg = JSON.parse(fs42.readFileSync(pkgPath, "utf8"));
6668
+ const pkg = JSON.parse(fs43.readFileSync(pkgPath, "utf8"));
6669
6669
  return typeof pkg.version === "string" ? pkg.version : null;
6670
6670
  } catch {
6671
6671
  return null;
@@ -6716,15 +6716,15 @@ function buildOtelHooksConfig(options) {
6716
6716
  };
6717
6717
  }
6718
6718
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
6719
- fs42.mkdirSync(hooksHome, { recursive: true });
6719
+ fs43.mkdirSync(hooksHome, { recursive: true });
6720
6720
  const configPath = getOtelHooksConfigPath(hooksHome);
6721
- fs42.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
6721
+ fs43.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
6722
6722
  `);
6723
6723
  return configPath;
6724
6724
  }
6725
6725
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
6726
- fs42.mkdirSync(hooksHome, { recursive: true });
6727
- fs42.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
6726
+ fs43.mkdirSync(hooksHome, { recursive: true });
6727
+ fs43.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
6728
6728
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
6729
6729
  const configPath = getOtelHooksConfigPath(hooksHome);
6730
6730
  const stateDir = getOtelHooksStateDir(hooksHome);
@@ -6736,9 +6736,9 @@ exec "${otelHookCommand}" run \\
6736
6736
  --state-dir "${stateDir}" \\
6737
6737
  "$@"
6738
6738
  `;
6739
- fs42.writeFileSync(wrapperPath, script, { mode: 493 });
6739
+ fs43.writeFileSync(wrapperPath, script, { mode: 493 });
6740
6740
  try {
6741
- fs42.chmodSync(wrapperPath, 493);
6741
+ fs43.chmodSync(wrapperPath, 493);
6742
6742
  } catch {
6743
6743
  }
6744
6744
  return wrapperPath;
@@ -6751,11 +6751,11 @@ function commandExists2(command2) {
6751
6751
  }
6752
6752
  function resolveOtelHookCommand(hooksHome) {
6753
6753
  const local = localOtelHookBin(hooksHome);
6754
- if (fs42.existsSync(local)) return local;
6754
+ if (fs43.existsSync(local)) return local;
6755
6755
  return null;
6756
6756
  }
6757
6757
  function tryInstallPackage(hooksHome) {
6758
- fs42.mkdirSync(hooksHome, { recursive: true });
6758
+ fs43.mkdirSync(hooksHome, { recursive: true });
6759
6759
  if (!commandExists2("npm")) {
6760
6760
  return {
6761
6761
  ok: false,
@@ -6767,7 +6767,7 @@ function tryInstallPackage(hooksHome) {
6767
6767
  ["install", "--prefix", hooksHome, "--no-fund", "--no-audit", OTEL_HOOKS_PACKAGE],
6768
6768
  { encoding: "utf8", timeout: 18e4 }
6769
6769
  );
6770
- if (result.status === 0 && fs42.existsSync(localOtelHookBin(hooksHome))) {
6770
+ if (result.status === 0 && fs43.existsSync(localOtelHookBin(hooksHome))) {
6771
6771
  return { ok: true, detail: `npm install --prefix ${hooksHome} ${OTEL_HOOKS_PACKAGE}` };
6772
6772
  }
6773
6773
  return {
@@ -6793,14 +6793,14 @@ function uninstallLegacyPythonHooks(hooksHome) {
6793
6793
  }
6794
6794
  function removeLegacyPythonArtifacts(hooksHome) {
6795
6795
  const legacyPaths = [
6796
- path45.join(hooksHome, ".venv"),
6797
- path45.join(hooksHome, "otel_config.yaml"),
6798
- path45.join(hooksHome, "venv")
6796
+ path46.join(hooksHome, ".venv"),
6797
+ path46.join(hooksHome, "otel_config.yaml"),
6798
+ path46.join(hooksHome, "venv")
6799
6799
  ];
6800
6800
  for (const target of legacyPaths) {
6801
6801
  try {
6802
- if (fs42.existsSync(target)) {
6803
- fs42.rmSync(target, { recursive: true, force: true });
6802
+ if (fs43.existsSync(target)) {
6803
+ fs43.rmSync(target, { recursive: true, force: true });
6804
6804
  }
6805
6805
  } catch {
6806
6806
  }
@@ -6841,10 +6841,10 @@ function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
6841
6841
  };
6842
6842
  }
6843
6843
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6844
- if (!fs42.existsSync(filePath)) return false;
6844
+ if (!fs43.existsSync(filePath)) return false;
6845
6845
  let raw;
6846
6846
  try {
6847
- raw = fs42.readFileSync(filePath, "utf8");
6847
+ raw = fs43.readFileSync(filePath, "utf8");
6848
6848
  } catch {
6849
6849
  return false;
6850
6850
  }
@@ -6891,15 +6891,15 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6891
6891
  return changed;
6892
6892
  };
6893
6893
  if (!walk(parsed)) return false;
6894
- fs42.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6894
+ fs43.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6895
6895
  `);
6896
6896
  return true;
6897
6897
  }
6898
6898
  function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
6899
- if (!fs42.existsSync(filePath)) return false;
6899
+ if (!fs43.existsSync(filePath)) return false;
6900
6900
  let raw;
6901
6901
  try {
6902
- raw = fs42.readFileSync(filePath, "utf8");
6902
+ raw = fs43.readFileSync(filePath, "utf8");
6903
6903
  } catch {
6904
6904
  return false;
6905
6905
  }
@@ -6934,21 +6934,21 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
6934
6934
  }
6935
6935
  }
6936
6936
  if (!changed) return false;
6937
- fs42.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6937
+ fs43.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6938
6938
  `);
6939
6939
  return true;
6940
6940
  }
6941
6941
  function rewriteKnownHookRegistrations(wrapperPath) {
6942
6942
  const home = os14.homedir();
6943
6943
  const candidates = [
6944
- path45.join(home, ".cursor", "hooks.json"),
6945
- path45.join(home, ".claude", "settings.json"),
6946
- path45.join(home, ".codex", "hooks.json")
6944
+ path46.join(home, ".cursor", "hooks.json"),
6945
+ path46.join(home, ".claude", "settings.json"),
6946
+ path46.join(home, ".codex", "hooks.json")
6947
6947
  ];
6948
6948
  for (const filePath of candidates) {
6949
6949
  try {
6950
6950
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
6951
- if (filePath.endsWith(`${path45.sep}.cursor${path45.sep}hooks.json`)) {
6951
+ if (filePath.endsWith(`${path46.sep}.cursor${path46.sep}hooks.json`)) {
6952
6952
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
6953
6953
  }
6954
6954
  } catch {
@@ -6964,7 +6964,7 @@ function ensureOtelHooks(options) {
6964
6964
  const hooksHome = getOtelHooksHome();
6965
6965
  const errors = [];
6966
6966
  const providersSetup = [];
6967
- fs42.mkdirSync(hooksHome, { recursive: true });
6967
+ fs43.mkdirSync(hooksHome, { recursive: true });
6968
6968
  let otelHookCommand = resolveOtelHookCommand(hooksHome);
6969
6969
  const needsInstall = !otelHookCommand || installedPackageVersion(hooksHome) !== pinnedVersion();
6970
6970
  if (needsInstall) {
@@ -7058,14 +7058,14 @@ function ensureOtelHooks(options) {
7058
7058
  function disableOtelHooksExport() {
7059
7059
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
7060
7060
  }
7061
- var import_child_process10, fs42, os14, path45, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
7061
+ var import_child_process10, fs43, os14, path46, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
7062
7062
  var init_otel_hooks = __esm({
7063
7063
  "src/core/otel-hooks.ts"() {
7064
7064
  "use strict";
7065
7065
  import_child_process10 = require("child_process");
7066
- fs42 = __toESM(require("fs"));
7066
+ fs43 = __toESM(require("fs"));
7067
7067
  os14 = __toESM(require("os"));
7068
- path45 = __toESM(require("path"));
7068
+ path46 = __toESM(require("path"));
7069
7069
  init_control_config();
7070
7070
  init_telemetry_config();
7071
7071
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.1.1";
@@ -8181,15 +8181,15 @@ var require_route = __commonJS({
8181
8181
  };
8182
8182
  }
8183
8183
  function wrapConversion(toModel, graph) {
8184
- const path60 = [graph[toModel].parent, toModel];
8184
+ const path61 = [graph[toModel].parent, toModel];
8185
8185
  let fn = conversions[graph[toModel].parent][toModel];
8186
8186
  let cur = graph[toModel].parent;
8187
8187
  while (graph[cur].parent) {
8188
- path60.unshift(graph[cur].parent);
8188
+ path61.unshift(graph[cur].parent);
8189
8189
  fn = link(conversions[graph[cur].parent][cur], fn);
8190
8190
  cur = graph[cur].parent;
8191
8191
  }
8192
- fn.conversion = path60;
8192
+ fn.conversion = path61;
8193
8193
  return fn;
8194
8194
  }
8195
8195
  module2.exports = function(fromModel) {
@@ -14119,7 +14119,7 @@ var require_iso2022 = __commonJS({
14119
14119
  // node_modules/chardet/index.js
14120
14120
  var require_chardet = __commonJS({
14121
14121
  "node_modules/chardet/index.js"(exports2, module2) {
14122
- var fs49 = require("fs");
14122
+ var fs50 = require("fs");
14123
14123
  var utf8 = require_utf8();
14124
14124
  var unicode = require_unicode();
14125
14125
  var mbcs = require_mbcs();
@@ -14193,28 +14193,28 @@ var require_chardet = __commonJS({
14193
14193
  var fd;
14194
14194
  var handler = function(err, buffer) {
14195
14195
  if (fd) {
14196
- fs49.closeSync(fd);
14196
+ fs50.closeSync(fd);
14197
14197
  }
14198
14198
  if (err) return cb(err, null);
14199
14199
  cb(null, self.detect(buffer, opts));
14200
14200
  };
14201
14201
  if (opts && opts.sampleSize) {
14202
- fd = fs49.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
14203
- fs49.read(fd, sample, 0, opts.sampleSize, null, function(err) {
14202
+ fd = fs50.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
14203
+ fs50.read(fd, sample, 0, opts.sampleSize, null, function(err) {
14204
14204
  handler(err, sample);
14205
14205
  });
14206
14206
  return;
14207
14207
  }
14208
- fs49.readFile(filepath, handler);
14208
+ fs50.readFile(filepath, handler);
14209
14209
  };
14210
14210
  module2.exports.detectFileSync = function(filepath, opts) {
14211
14211
  if (opts && opts.sampleSize) {
14212
- var fd = fs49.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
14213
- fs49.readSync(fd, sample2, 0, opts.sampleSize);
14214
- fs49.closeSync(fd);
14212
+ var fd = fs50.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
14213
+ fs50.readSync(fd, sample2, 0, opts.sampleSize);
14214
+ fs50.closeSync(fd);
14215
14215
  return self.detect(sample2, opts);
14216
14216
  }
14217
- return self.detect(fs49.readFileSync(filepath), opts);
14217
+ return self.detect(fs50.readFileSync(filepath), opts);
14218
14218
  };
14219
14219
  module2.exports.detectAll = function(buffer, opts) {
14220
14220
  if (typeof opts !== "object") {
@@ -17679,16 +17679,16 @@ var require_os_tmpdir = __commonJS({
17679
17679
  var isWindows = process.platform === "win32";
17680
17680
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
17681
17681
  module2.exports = function() {
17682
- var path60;
17682
+ var path61;
17683
17683
  if (isWindows) {
17684
- path60 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
17684
+ path61 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
17685
17685
  } else {
17686
- path60 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
17686
+ path61 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
17687
17687
  }
17688
- if (trailingSlashRe.test(path60)) {
17689
- path60 = path60.slice(0, -1);
17688
+ if (trailingSlashRe.test(path61)) {
17689
+ path61 = path61.slice(0, -1);
17690
17690
  }
17691
- return path60;
17691
+ return path61;
17692
17692
  };
17693
17693
  }
17694
17694
  });
@@ -17696,8 +17696,8 @@ var require_os_tmpdir = __commonJS({
17696
17696
  // node_modules/tmp/lib/tmp.js
17697
17697
  var require_tmp = __commonJS({
17698
17698
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
17699
- var fs49 = require("fs");
17700
- var path60 = require("path");
17699
+ var fs50 = require("fs");
17700
+ var path61 = require("path");
17701
17701
  var crypto6 = require("crypto");
17702
17702
  var osTmpDir = require_os_tmpdir();
17703
17703
  var _c2 = process.binding("constants");
@@ -17739,7 +17739,7 @@ var require_tmp = __commonJS({
17739
17739
  }
17740
17740
  function _generateTmpName(opts) {
17741
17741
  if (opts.name) {
17742
- return path60.join(opts.dir || tmpDir, opts.name);
17742
+ return path61.join(opts.dir || tmpDir, opts.name);
17743
17743
  }
17744
17744
  if (opts.template) {
17745
17745
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -17750,7 +17750,7 @@ var require_tmp = __commonJS({
17750
17750
  _randomChars(12),
17751
17751
  opts.postfix || ""
17752
17752
  ].join("");
17753
- return path60.join(opts.dir || tmpDir, name);
17753
+ return path61.join(opts.dir || tmpDir, name);
17754
17754
  }
17755
17755
  function tmpName(options, callback) {
17756
17756
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -17760,7 +17760,7 @@ var require_tmp = __commonJS({
17760
17760
  return cb(new Error("Invalid template provided"));
17761
17761
  (function _getUniqueName() {
17762
17762
  const name = _generateTmpName(opts);
17763
- fs49.stat(name, function(err) {
17763
+ fs50.stat(name, function(err) {
17764
17764
  if (!err) {
17765
17765
  if (tries-- > 0) return _getUniqueName();
17766
17766
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -17778,7 +17778,7 @@ var require_tmp = __commonJS({
17778
17778
  do {
17779
17779
  const name = _generateTmpName(opts);
17780
17780
  try {
17781
- fs49.statSync(name);
17781
+ fs50.statSync(name);
17782
17782
  } catch (e2) {
17783
17783
  return name;
17784
17784
  }
@@ -17790,13 +17790,13 @@ var require_tmp = __commonJS({
17790
17790
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
17791
17791
  tmpName(opts, function _tmpNameCreated(err, name) {
17792
17792
  if (err) return cb(err);
17793
- fs49.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
17793
+ fs50.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
17794
17794
  if (err2) return cb(err2);
17795
17795
  if (opts.discardDescriptor) {
17796
- return fs49.close(fd, function _discardCallback(err3) {
17796
+ return fs50.close(fd, function _discardCallback(err3) {
17797
17797
  if (err3) {
17798
17798
  try {
17799
- fs49.unlinkSync(name);
17799
+ fs50.unlinkSync(name);
17800
17800
  } catch (e2) {
17801
17801
  if (!isENOENT(e2)) {
17802
17802
  err3 = e2;
@@ -17819,9 +17819,9 @@ var require_tmp = __commonJS({
17819
17819
  opts.postfix = opts.postfix || ".tmp";
17820
17820
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
17821
17821
  const name = tmpNameSync(opts);
17822
- var fd = fs49.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
17822
+ var fd = fs50.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
17823
17823
  if (opts.discardDescriptor) {
17824
- fs49.closeSync(fd);
17824
+ fs50.closeSync(fd);
17825
17825
  fd = void 0;
17826
17826
  }
17827
17827
  return {
@@ -17833,9 +17833,9 @@ var require_tmp = __commonJS({
17833
17833
  function _rmdirRecursiveSync(root) {
17834
17834
  const dirs = [root];
17835
17835
  do {
17836
- var dir2 = dirs.pop(), deferred = false, files = fs49.readdirSync(dir2);
17836
+ var dir2 = dirs.pop(), deferred = false, files = fs50.readdirSync(dir2);
17837
17837
  for (var i2 = 0, length = files.length; i2 < length; i2++) {
17838
- var file2 = path60.join(dir2, files[i2]), stat = fs49.lstatSync(file2);
17838
+ var file2 = path61.join(dir2, files[i2]), stat = fs50.lstatSync(file2);
17839
17839
  if (stat.isDirectory()) {
17840
17840
  if (!deferred) {
17841
17841
  deferred = true;
@@ -17843,11 +17843,11 @@ var require_tmp = __commonJS({
17843
17843
  }
17844
17844
  dirs.push(file2);
17845
17845
  } else {
17846
- fs49.unlinkSync(file2);
17846
+ fs50.unlinkSync(file2);
17847
17847
  }
17848
17848
  }
17849
17849
  if (!deferred) {
17850
- fs49.rmdirSync(dir2);
17850
+ fs50.rmdirSync(dir2);
17851
17851
  }
17852
17852
  } while (dirs.length !== 0);
17853
17853
  }
@@ -17855,7 +17855,7 @@ var require_tmp = __commonJS({
17855
17855
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
17856
17856
  tmpName(opts, function _tmpNameCreated(err, name) {
17857
17857
  if (err) return cb(err);
17858
- fs49.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
17858
+ fs50.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
17859
17859
  if (err2) return cb(err2);
17860
17860
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
17861
17861
  });
@@ -17864,7 +17864,7 @@ var require_tmp = __commonJS({
17864
17864
  function dirSync(options) {
17865
17865
  var args = _parseArguments(options), opts = args[0];
17866
17866
  const name = tmpNameSync(opts);
17867
- fs49.mkdirSync(name, opts.mode || DIR_MODE);
17867
+ fs50.mkdirSync(name, opts.mode || DIR_MODE);
17868
17868
  return {
17869
17869
  name,
17870
17870
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -17874,7 +17874,7 @@ var require_tmp = __commonJS({
17874
17874
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
17875
17875
  try {
17876
17876
  if (0 <= fdPath[0]) {
17877
- fs49.closeSync(fdPath[0]);
17877
+ fs50.closeSync(fdPath[0]);
17878
17878
  }
17879
17879
  } catch (e2) {
17880
17880
  if (!isEBADF(e2) && !isENOENT(e2)) {
@@ -17882,7 +17882,7 @@ var require_tmp = __commonJS({
17882
17882
  }
17883
17883
  }
17884
17884
  try {
17885
- fs49.unlinkSync(fdPath[1]);
17885
+ fs50.unlinkSync(fdPath[1]);
17886
17886
  } catch (e2) {
17887
17887
  if (!isENOENT(e2)) {
17888
17888
  throw e2;
@@ -17895,7 +17895,7 @@ var require_tmp = __commonJS({
17895
17895
  return removeCallback;
17896
17896
  }
17897
17897
  function _prepareTmpDirRemoveCallback(name, opts) {
17898
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs49.rmdirSync.bind(fs49);
17898
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs50.rmdirSync.bind(fs50);
17899
17899
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
17900
17900
  if (!opts.keep) {
17901
17901
  _removeObjects.unshift(removeCallback);
@@ -19046,7 +19046,7 @@ var require_Observable = __commonJS({
19046
19046
  Observable2.prototype.forEach = function(next, promiseCtor) {
19047
19047
  var _this = this;
19048
19048
  promiseCtor = getPromiseCtor(promiseCtor);
19049
- return new promiseCtor(function(resolve44, reject) {
19049
+ return new promiseCtor(function(resolve45, reject) {
19050
19050
  var subscriber = new Subscriber_1.SafeSubscriber({
19051
19051
  next: function(value) {
19052
19052
  try {
@@ -19057,7 +19057,7 @@ var require_Observable = __commonJS({
19057
19057
  }
19058
19058
  },
19059
19059
  error: reject,
19060
- complete: resolve44
19060
+ complete: resolve45
19061
19061
  });
19062
19062
  _this.subscribe(subscriber);
19063
19063
  });
@@ -19079,14 +19079,14 @@ var require_Observable = __commonJS({
19079
19079
  Observable2.prototype.toPromise = function(promiseCtor) {
19080
19080
  var _this = this;
19081
19081
  promiseCtor = getPromiseCtor(promiseCtor);
19082
- return new promiseCtor(function(resolve44, reject) {
19082
+ return new promiseCtor(function(resolve45, reject) {
19083
19083
  var value;
19084
19084
  _this.subscribe(function(x2) {
19085
19085
  return value = x2;
19086
19086
  }, function(err) {
19087
19087
  return reject(err);
19088
19088
  }, function() {
19089
- return resolve44(value);
19089
+ return resolve45(value);
19090
19090
  });
19091
19091
  });
19092
19092
  };
@@ -21182,11 +21182,11 @@ var require_innerFrom = __commonJS({
21182
21182
  "use strict";
21183
21183
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P3, generator) {
21184
21184
  function adopt(value) {
21185
- return value instanceof P3 ? value : new P3(function(resolve44) {
21186
- resolve44(value);
21185
+ return value instanceof P3 ? value : new P3(function(resolve45) {
21186
+ resolve45(value);
21187
21187
  });
21188
21188
  }
21189
- return new (P3 || (P3 = Promise))(function(resolve44, reject) {
21189
+ return new (P3 || (P3 = Promise))(function(resolve45, reject) {
21190
21190
  function fulfilled(value) {
21191
21191
  try {
21192
21192
  step(generator.next(value));
@@ -21202,7 +21202,7 @@ var require_innerFrom = __commonJS({
21202
21202
  }
21203
21203
  }
21204
21204
  function step(result) {
21205
- result.done ? resolve44(result.value) : adopt(result.value).then(fulfilled, rejected);
21205
+ result.done ? resolve45(result.value) : adopt(result.value).then(fulfilled, rejected);
21206
21206
  }
21207
21207
  step((generator = generator.apply(thisArg, _arguments || [])).next());
21208
21208
  });
@@ -21284,14 +21284,14 @@ var require_innerFrom = __commonJS({
21284
21284
  }, i2);
21285
21285
  function verb(n2) {
21286
21286
  i2[n2] = o2[n2] && function(v3) {
21287
- return new Promise(function(resolve44, reject) {
21288
- v3 = o2[n2](v3), settle(resolve44, reject, v3.done, v3.value);
21287
+ return new Promise(function(resolve45, reject) {
21288
+ v3 = o2[n2](v3), settle(resolve45, reject, v3.done, v3.value);
21289
21289
  });
21290
21290
  };
21291
21291
  }
21292
- function settle(resolve44, reject, d2, v3) {
21292
+ function settle(resolve45, reject, d2, v3) {
21293
21293
  Promise.resolve(v3).then(function(v4) {
21294
- resolve44({ value: v4, done: d2 });
21294
+ resolve45({ value: v4, done: d2 });
21295
21295
  }, reject);
21296
21296
  }
21297
21297
  };
@@ -21910,7 +21910,7 @@ var require_lastValueFrom = __commonJS({
21910
21910
  var EmptyError_1 = require_EmptyError();
21911
21911
  function lastValueFrom2(source, config2) {
21912
21912
  var hasConfig = typeof config2 === "object";
21913
- return new Promise(function(resolve44, reject) {
21913
+ return new Promise(function(resolve45, reject) {
21914
21914
  var _hasValue = false;
21915
21915
  var _value;
21916
21916
  source.subscribe({
@@ -21921,9 +21921,9 @@ var require_lastValueFrom = __commonJS({
21921
21921
  error: reject,
21922
21922
  complete: function() {
21923
21923
  if (_hasValue) {
21924
- resolve44(_value);
21924
+ resolve45(_value);
21925
21925
  } else if (hasConfig) {
21926
- resolve44(config2.defaultValue);
21926
+ resolve45(config2.defaultValue);
21927
21927
  } else {
21928
21928
  reject(new EmptyError_1.EmptyError());
21929
21929
  }
@@ -21945,16 +21945,16 @@ var require_firstValueFrom = __commonJS({
21945
21945
  var Subscriber_1 = require_Subscriber();
21946
21946
  function firstValueFrom(source, config2) {
21947
21947
  var hasConfig = typeof config2 === "object";
21948
- return new Promise(function(resolve44, reject) {
21948
+ return new Promise(function(resolve45, reject) {
21949
21949
  var subscriber = new Subscriber_1.SafeSubscriber({
21950
21950
  next: function(value) {
21951
- resolve44(value);
21951
+ resolve45(value);
21952
21952
  subscriber.unsubscribe();
21953
21953
  },
21954
21954
  error: reject,
21955
21955
  complete: function() {
21956
21956
  if (hasConfig) {
21957
- resolve44(config2.defaultValue);
21957
+ resolve45(config2.defaultValue);
21958
21958
  } else {
21959
21959
  reject(new EmptyError_1.EmptyError());
21960
21960
  }
@@ -27747,14 +27747,14 @@ var require_run_async = __commonJS({
27747
27747
  return function() {
27748
27748
  var args = arguments;
27749
27749
  var originalThis = this;
27750
- var promise = new Promise(function(resolve44, reject) {
27750
+ var promise = new Promise(function(resolve45, reject) {
27751
27751
  var resolved = false;
27752
27752
  const wrappedResolve = function(value) {
27753
27753
  if (resolved) {
27754
27754
  console.warn("Run-async promise already resolved.");
27755
27755
  }
27756
27756
  resolved = true;
27757
- resolve44(value);
27757
+ resolve45(value);
27758
27758
  };
27759
27759
  var rejected = false;
27760
27760
  const wrappedReject = function(value) {
@@ -30783,7 +30783,7 @@ var require_compile = __commonJS({
30783
30783
  const schOrFunc = root.refs[ref];
30784
30784
  if (schOrFunc)
30785
30785
  return schOrFunc;
30786
- let _sch = resolve44.call(this, root, ref);
30786
+ let _sch = resolve45.call(this, root, ref);
30787
30787
  if (_sch === void 0) {
30788
30788
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
30789
30789
  const { schemaId } = this.opts;
@@ -30810,7 +30810,7 @@ var require_compile = __commonJS({
30810
30810
  function sameSchemaEnv(s1, s2) {
30811
30811
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
30812
30812
  }
30813
- function resolve44(root, ref) {
30813
+ function resolve45(root, ref) {
30814
30814
  let sch;
30815
30815
  while (typeof (sch = this.refs[ref]) == "string")
30816
30816
  ref = sch;
@@ -31028,8 +31028,8 @@ var require_utils2 = __commonJS({
31028
31028
  }
31029
31029
  return ind;
31030
31030
  }
31031
- function removeDotSegments(path60) {
31032
- let input = path60;
31031
+ function removeDotSegments(path61) {
31032
+ let input = path61;
31033
31033
  const output = [];
31034
31034
  let nextSlash = -1;
31035
31035
  let len = 0;
@@ -31281,8 +31281,8 @@ var require_schemes = __commonJS({
31281
31281
  wsComponent.secure = void 0;
31282
31282
  }
31283
31283
  if (wsComponent.resourceName) {
31284
- const [path60, query] = wsComponent.resourceName.split("?");
31285
- wsComponent.path = path60 && path60 !== "/" ? path60 : void 0;
31284
+ const [path61, query] = wsComponent.resourceName.split("?");
31285
+ wsComponent.path = path61 && path61 !== "/" ? path61 : void 0;
31286
31286
  wsComponent.query = query;
31287
31287
  wsComponent.resourceName = void 0;
31288
31288
  }
@@ -31441,7 +31441,7 @@ var require_fast_uri = __commonJS({
31441
31441
  }
31442
31442
  return uri;
31443
31443
  }
31444
- function resolve44(baseURI, relativeURI, options) {
31444
+ function resolve45(baseURI, relativeURI, options) {
31445
31445
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
31446
31446
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
31447
31447
  schemelessOptions.skipEscape = true;
@@ -31699,7 +31699,7 @@ var require_fast_uri = __commonJS({
31699
31699
  var fastUri = {
31700
31700
  SCHEMES,
31701
31701
  normalize: normalize3,
31702
- resolve: resolve44,
31702
+ resolve: resolve45,
31703
31703
  resolveComponent,
31704
31704
  equal,
31705
31705
  serialize,
@@ -34675,12 +34675,12 @@ var require_dist = __commonJS({
34675
34675
  throw new Error(`Unknown format "${name}"`);
34676
34676
  return f2;
34677
34677
  };
34678
- function addFormats(ajv, list, fs49, exportName) {
34678
+ function addFormats(ajv, list, fs50, exportName) {
34679
34679
  var _a3;
34680
34680
  var _b2;
34681
34681
  (_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
34682
34682
  for (const f2 of list)
34683
- ajv.addFormat(f2, fs49[f2]);
34683
+ ajv.addFormat(f2, fs50[f2]);
34684
34684
  }
34685
34685
  module2.exports = exports2 = formatsPlugin;
34686
34686
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -35964,11 +35964,11 @@ var parser = new YargsParser({
35964
35964
  resolve: import_path2.resolve,
35965
35965
  // TODO: figure out a way to combine ESM and CJS coverage, such that
35966
35966
  // we can exercise all the lines below:
35967
- require: (path60) => {
35967
+ require: (path61) => {
35968
35968
  if (typeof require !== "undefined") {
35969
- return require(path60);
35970
- } else if (path60.match(/\.json$/)) {
35971
- return JSON.parse((0, import_fs2.readFileSync)(path60, "utf8"));
35969
+ return require(path61);
35970
+ } else if (path61.match(/\.json$/)) {
35971
+ return JSON.parse((0, import_fs2.readFileSync)(path61, "utf8"));
35972
35972
  } else {
35973
35973
  throw Error("only .json config files are supported in ESM");
35974
35974
  }
@@ -38494,12 +38494,12 @@ var YargsInstance = class {
38494
38494
  async getCompletion(args, done) {
38495
38495
  argsert("<array> [function]", [args, done], arguments.length);
38496
38496
  if (!done) {
38497
- return new Promise((resolve44, reject) => {
38497
+ return new Promise((resolve45, reject) => {
38498
38498
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
38499
38499
  if (err)
38500
38500
  reject(err);
38501
38501
  else
38502
- resolve44(completions);
38502
+ resolve45(completions);
38503
38503
  });
38504
38504
  });
38505
38505
  } else {
@@ -40652,8 +40652,8 @@ function getErrorMap() {
40652
40652
 
40653
40653
  // node_modules/zod/v3/helpers/parseUtil.js
40654
40654
  var makeIssue = (params) => {
40655
- const { data, path: path60, errorMaps, issueData } = params;
40656
- const fullPath = [...path60, ...issueData.path || []];
40655
+ const { data, path: path61, errorMaps, issueData } = params;
40656
+ const fullPath = [...path61, ...issueData.path || []];
40657
40657
  const fullIssue = {
40658
40658
  ...issueData,
40659
40659
  path: fullPath
@@ -40769,11 +40769,11 @@ var errorUtil;
40769
40769
 
40770
40770
  // node_modules/zod/v3/types.js
40771
40771
  var ParseInputLazyPath = class {
40772
- constructor(parent, value, path60, key) {
40772
+ constructor(parent, value, path61, key) {
40773
40773
  this._cachedPath = [];
40774
40774
  this.parent = parent;
40775
40775
  this.data = value;
40776
- this._path = path60;
40776
+ this._path = path61;
40777
40777
  this._key = key;
40778
40778
  }
40779
40779
  get path() {
@@ -68312,16 +68312,16 @@ async function handleAgentSkills(options) {
68312
68312
  }
68313
68313
  async function askYesNo(question) {
68314
68314
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
68315
- return new Promise((resolve44) => {
68315
+ return new Promise((resolve45) => {
68316
68316
  process.stderr.write(`${question} `);
68317
68317
  rl.once("line", (answer) => {
68318
68318
  rl.close();
68319
68319
  const trimmed = answer.trim();
68320
68320
  if (trimmed === "") {
68321
- resolve44(true);
68321
+ resolve45(true);
68322
68322
  return;
68323
68323
  }
68324
- resolve44(/^y(es)?$/i.test(trimmed));
68324
+ resolve45(/^y(es)?$/i.test(trimmed));
68325
68325
  });
68326
68326
  });
68327
68327
  }
@@ -68400,11 +68400,11 @@ function handleRemove(argv) {
68400
68400
  }
68401
68401
 
68402
68402
  // src/cli/commands/env.ts
68403
- var path49 = __toESM(require("path"));
68403
+ var path50 = __toESM(require("path"));
68404
68404
 
68405
68405
  // src/core/harness.ts
68406
- var fs21 = __toESM(require("fs"));
68407
- var path20 = __toESM(require("path"));
68406
+ var fs22 = __toESM(require("fs"));
68407
+ var path21 = __toESM(require("path"));
68408
68408
 
68409
68409
  // src/harness/generator.ts
68410
68410
  var fs11 = __toESM(require("fs"));
@@ -69179,13 +69179,13 @@ var MultipartBody = class {
69179
69179
  // node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
69180
69180
  var import_web = require("node:stream/web");
69181
69181
  var fileFromPathWarned = false;
69182
- async function fileFromPath3(path60, ...args) {
69182
+ async function fileFromPath3(path61, ...args) {
69183
69183
  const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
69184
69184
  if (!fileFromPathWarned) {
69185
- console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path60)}) instead`);
69185
+ console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path61)}) instead`);
69186
69186
  fileFromPathWarned = true;
69187
69187
  }
69188
- return await _fileFromPath(path60, ...args);
69188
+ return await _fileFromPath(path61, ...args);
69189
69189
  }
69190
69190
  var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
69191
69191
  var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
@@ -69681,8 +69681,8 @@ async function defaultParseResponse(props) {
69681
69681
  }
69682
69682
  var APIPromise = class _APIPromise extends Promise {
69683
69683
  constructor(responsePromise, parseResponse = defaultParseResponse) {
69684
- super((resolve44) => {
69685
- resolve44(null);
69684
+ super((resolve45) => {
69685
+ resolve45(null);
69686
69686
  });
69687
69687
  this.responsePromise = responsePromise;
69688
69688
  this.parseResponse = parseResponse;
@@ -69782,29 +69782,29 @@ var APIClient = class {
69782
69782
  defaultIdempotencyKey() {
69783
69783
  return `stainless-node-retry-${uuid4()}`;
69784
69784
  }
69785
- get(path60, opts) {
69786
- return this.methodRequest("get", path60, opts);
69785
+ get(path61, opts) {
69786
+ return this.methodRequest("get", path61, opts);
69787
69787
  }
69788
- post(path60, opts) {
69789
- return this.methodRequest("post", path60, opts);
69788
+ post(path61, opts) {
69789
+ return this.methodRequest("post", path61, opts);
69790
69790
  }
69791
- patch(path60, opts) {
69792
- return this.methodRequest("patch", path60, opts);
69791
+ patch(path61, opts) {
69792
+ return this.methodRequest("patch", path61, opts);
69793
69793
  }
69794
- put(path60, opts) {
69795
- return this.methodRequest("put", path60, opts);
69794
+ put(path61, opts) {
69795
+ return this.methodRequest("put", path61, opts);
69796
69796
  }
69797
- delete(path60, opts) {
69798
- return this.methodRequest("delete", path60, opts);
69797
+ delete(path61, opts) {
69798
+ return this.methodRequest("delete", path61, opts);
69799
69799
  }
69800
- methodRequest(method, path60, opts) {
69800
+ methodRequest(method, path61, opts) {
69801
69801
  return this.request(Promise.resolve(opts).then(async (opts2) => {
69802
69802
  const body = opts2 && isBlobLike(opts2?.body) ? new DataView(await opts2.body.arrayBuffer()) : opts2?.body instanceof DataView ? opts2.body : opts2?.body instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2?.body) ? new DataView(opts2.body.buffer) : opts2?.body;
69803
- return { method, path: path60, ...opts2, body };
69803
+ return { method, path: path61, ...opts2, body };
69804
69804
  }));
69805
69805
  }
69806
- getAPIList(path60, Page, opts) {
69807
- return this.requestAPIList(Page, { method: "get", path: path60, ...opts });
69806
+ getAPIList(path61, Page, opts) {
69807
+ return this.requestAPIList(Page, { method: "get", path: path61, ...opts });
69808
69808
  }
69809
69809
  calculateContentLength(body) {
69810
69810
  if (typeof body === "string") {
@@ -69822,10 +69822,10 @@ var APIClient = class {
69822
69822
  return null;
69823
69823
  }
69824
69824
  buildRequest(options) {
69825
- const { method, path: path60, query, headers = {} } = options;
69825
+ const { method, path: path61, query, headers = {} } = options;
69826
69826
  const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
69827
69827
  const contentLength = this.calculateContentLength(body);
69828
- const url = this.buildURL(path60, query);
69828
+ const url = this.buildURL(path61, query);
69829
69829
  if ("timeout" in options)
69830
69830
  validatePositiveInteger("timeout", options.timeout);
69831
69831
  const timeout = options.timeout ?? this.timeout;
@@ -69934,8 +69934,8 @@ var APIClient = class {
69934
69934
  const request = this.makeRequest(options, null);
69935
69935
  return new PagePromise(this, request, Page);
69936
69936
  }
69937
- buildURL(path60, query) {
69938
- const url = isAbsoluteURL(path60) ? new URL(path60) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path60.startsWith("/") ? path60.slice(1) : path60));
69937
+ buildURL(path61, query) {
69938
+ const url = isAbsoluteURL(path61) ? new URL(path61) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path61.startsWith("/") ? path61.slice(1) : path61));
69939
69939
  const defaultQuery = this.defaultQuery();
69940
69940
  if (!isEmptyObj(defaultQuery)) {
69941
69941
  query = { ...defaultQuery, ...query };
@@ -70220,7 +70220,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
70220
70220
  var isAbsoluteURL = (url) => {
70221
70221
  return startsWithSchemeRegexp.test(url);
70222
70222
  };
70223
- var sleep = (ms) => new Promise((resolve44) => setTimeout(resolve44, ms));
70223
+ var sleep = (ms) => new Promise((resolve45) => setTimeout(resolve45, ms));
70224
70224
  var validatePositiveInteger = (name, n2) => {
70225
70225
  if (typeof n2 !== "number" || !Number.isInteger(n2)) {
70226
70226
  throw new AnthropicError(`${name} must be an integer`);
@@ -70711,12 +70711,12 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
70711
70711
  }
70712
70712
  return this._emit("error", new AnthropicError(String(error3)));
70713
70713
  });
70714
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve44, reject) => {
70715
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve44, "f");
70714
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve45, reject) => {
70715
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve45, "f");
70716
70716
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
70717
70717
  }), "f");
70718
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve44, reject) => {
70719
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve44, "f");
70718
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve45, reject) => {
70719
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve45, "f");
70720
70720
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
70721
70721
  }), "f");
70722
70722
  __classPrivateFieldGet8(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {
@@ -70845,11 +70845,11 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
70845
70845
  * const message = await stream.emitted('message') // rejects if the stream errors
70846
70846
  */
70847
70847
  emitted(event) {
70848
- return new Promise((resolve44, reject) => {
70848
+ return new Promise((resolve45, reject) => {
70849
70849
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
70850
70850
  if (event !== "error")
70851
70851
  this.once("error", reject);
70852
- this.once(event, resolve44);
70852
+ this.once(event, resolve45);
70853
70853
  });
70854
70854
  }
70855
70855
  async done() {
@@ -71076,7 +71076,7 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
71076
71076
  if (done) {
71077
71077
  return { value: void 0, done: true };
71078
71078
  }
71079
- return new Promise((resolve44, reject) => readQueue.push({ resolve: resolve44, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
71079
+ return new Promise((resolve45, reject) => readQueue.push({ resolve: resolve45, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
71080
71080
  }
71081
71081
  const chunk = pushQueue.shift();
71082
71082
  return { value: chunk, done: false };
@@ -71224,12 +71224,12 @@ var MessageStream = class _MessageStream {
71224
71224
  }
71225
71225
  return this._emit("error", new AnthropicError(String(error3)));
71226
71226
  });
71227
- __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve44, reject) => {
71228
- __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve44, "f");
71227
+ __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve45, reject) => {
71228
+ __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve45, "f");
71229
71229
  __classPrivateFieldSet8(this, _MessageStream_rejectConnectedPromise, reject, "f");
71230
71230
  }), "f");
71231
- __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve44, reject) => {
71232
- __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve44, "f");
71231
+ __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve45, reject) => {
71232
+ __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve45, "f");
71233
71233
  __classPrivateFieldSet8(this, _MessageStream_rejectEndPromise, reject, "f");
71234
71234
  }), "f");
71235
71235
  __classPrivateFieldGet9(this, _MessageStream_connectedPromise, "f").catch(() => {
@@ -71358,11 +71358,11 @@ var MessageStream = class _MessageStream {
71358
71358
  * const message = await stream.emitted('message') // rejects if the stream errors
71359
71359
  */
71360
71360
  emitted(event) {
71361
- return new Promise((resolve44, reject) => {
71361
+ return new Promise((resolve45, reject) => {
71362
71362
  __classPrivateFieldSet8(this, _MessageStream_catchingPromiseCreated, true, "f");
71363
71363
  if (event !== "error")
71364
71364
  this.once("error", reject);
71365
- this.once(event, resolve44);
71365
+ this.once(event, resolve45);
71366
71366
  });
71367
71367
  }
71368
71368
  async done() {
@@ -71589,7 +71589,7 @@ var MessageStream = class _MessageStream {
71589
71589
  if (done) {
71590
71590
  return { value: void 0, done: true };
71591
71591
  }
71592
- return new Promise((resolve44, reject) => readQueue.push({ resolve: resolve44, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
71592
+ return new Promise((resolve45, reject) => readQueue.push({ resolve: resolve45, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
71593
71593
  }
71594
71594
  const chunk = pushQueue.shift();
71595
71595
  return { value: chunk, done: false };
@@ -71849,11 +71849,11 @@ async function promptApplyAgentMdProposal(repoPath) {
71849
71849
  }
71850
71850
  async function askYesNo2(question) {
71851
71851
  const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
71852
- return new Promise((resolve44) => {
71852
+ return new Promise((resolve45) => {
71853
71853
  process.stderr.write(`${question} `);
71854
71854
  rl.once("line", (answer) => {
71855
71855
  rl.close();
71856
- resolve44(/^y(es)?$/i.test(answer.trim()));
71856
+ resolve45(/^y(es)?$/i.test(answer.trim()));
71857
71857
  });
71858
71858
  });
71859
71859
  }
@@ -72083,7 +72083,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
72083
72083
  }
72084
72084
  async function askUser(question, options) {
72085
72085
  const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
72086
- return new Promise((resolve44) => {
72086
+ return new Promise((resolve45) => {
72087
72087
  process.stderr.write("\n");
72088
72088
  process.stderr.write(`\u2753 ${question}
72089
72089
  `);
@@ -72094,7 +72094,7 @@ async function askUser(question, options) {
72094
72094
  process.stderr.write("> ");
72095
72095
  rl.once("line", (answer) => {
72096
72096
  rl.close();
72097
- resolve44(answer.trim());
72097
+ resolve45(answer.trim());
72098
72098
  });
72099
72099
  });
72100
72100
  }
@@ -72238,7 +72238,7 @@ function runScript(scriptPath, args = [], options = {}) {
72238
72238
  function runScriptCapture(scriptPath, args = [], options = {}) {
72239
72239
  const stream = options.stream ?? false;
72240
72240
  const { stream: _stream, ...spawnOptions } = options;
72241
- return new Promise((resolve44) => {
72241
+ return new Promise((resolve45) => {
72242
72242
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
72243
72243
  ...spawnOptions,
72244
72244
  stdio: ["inherit", "pipe", "pipe"]
@@ -72253,13 +72253,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
72253
72253
  stderr += d2;
72254
72254
  if (stream) process.stderr.write(d2);
72255
72255
  });
72256
- proc.on("close", (code) => resolve44({ stdout, stderr, code: code ?? 0 }));
72256
+ proc.on("close", (code) => resolve45({ stdout, stderr, code: code ?? 0 }));
72257
72257
  });
72258
72258
  }
72259
72259
  function runShellCommand(command2, options = {}) {
72260
72260
  const stream = options.stream ?? false;
72261
72261
  const { stream: _stream, ...spawnOptions } = options;
72262
- return new Promise((resolve44) => {
72262
+ return new Promise((resolve45) => {
72263
72263
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
72264
72264
  ...spawnOptions,
72265
72265
  stdio: ["inherit", "pipe", "pipe"]
@@ -72274,7 +72274,7 @@ function runShellCommand(command2, options = {}) {
72274
72274
  stderr += d2;
72275
72275
  if (stream) process.stderr.write(d2);
72276
72276
  });
72277
- proc.on("close", (code) => resolve44({ stdout, stderr, code: code ?? 0 }));
72277
+ proc.on("close", (code) => resolve45({ stdout, stderr, code: code ?? 0 }));
72278
72278
  });
72279
72279
  }
72280
72280
 
@@ -72576,9 +72576,406 @@ function compareHarnessToTemplate(repoPath) {
72576
72576
  }
72577
72577
 
72578
72578
  // src/harness/maintain-bundle.ts
72579
- var fs18 = __toESM(require("fs"));
72579
+ var fs21 = __toESM(require("fs"));
72580
72580
  var os4 = __toESM(require("os"));
72581
+ var path20 = __toESM(require("path"));
72582
+
72583
+ // src/harness/plugin-drift.ts
72584
+ var fs20 = __toESM(require("fs"));
72585
+ var path19 = __toESM(require("path"));
72586
+
72587
+ // src/harness/plugins.ts
72588
+ var fs19 = __toESM(require("fs"));
72581
72589
  var path18 = __toESM(require("path"));
72590
+
72591
+ // src/harness/parser.ts
72592
+ var fs18 = __toESM(require("fs"));
72593
+ function harnessExists(repoPath) {
72594
+ return fs18.existsSync(`${repoPath}/.har/setup-infra.sh`);
72595
+ }
72596
+
72597
+ // src/harness/plugins.ts
72598
+ var PLUGIN_IDS = ["playwright", "rocketsim"];
72599
+ var PluginManifestFileSchema = external_exports.object({
72600
+ src: external_exports.string().min(1),
72601
+ dest: external_exports.string().min(1),
72602
+ executable: external_exports.boolean().optional(),
72603
+ skipFlag: external_exports.string().optional()
72604
+ });
72605
+ var PluginManifestSchema = external_exports.object({
72606
+ id: external_exports.enum(PLUGIN_IDS),
72607
+ stageId: external_exports.string().min(1),
72608
+ verificationStages: external_exports.array(external_exports.string().min(1)).min(1),
72609
+ stage: external_exports.record(external_exports.unknown()),
72610
+ files: external_exports.array(PluginManifestFileSchema).min(1),
72611
+ optionalFiles: external_exports.array(PluginManifestFileSchema).optional(),
72612
+ merge: external_exports.record(external_exports.string()).optional(),
72613
+ nextSteps: external_exports.array(external_exports.string().min(1)).min(1),
72614
+ docsPath: external_exports.string().min(1)
72615
+ });
72616
+ function resolvePluginDir(pluginId) {
72617
+ const dir = path18.join(resolveTemplatesDir(), "plugins", pluginId);
72618
+ if (!fs19.existsSync(dir)) {
72619
+ throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
72620
+ }
72621
+ return dir;
72622
+ }
72623
+ function readPluginManifest(pluginId) {
72624
+ const manifestPath = path18.join(resolvePluginDir(pluginId), "template.manifest.json");
72625
+ const parsed = PluginManifestSchema.safeParse(
72626
+ JSON.parse(fs19.readFileSync(manifestPath, "utf8"))
72627
+ );
72628
+ if (!parsed.success) {
72629
+ throw new Error(`Invalid plugin manifest for ${pluginId}: ${parsed.error.message}`);
72630
+ }
72631
+ if (parsed.data.id !== pluginId) {
72632
+ throw new Error(`Plugin manifest id mismatch: expected ${pluginId}, got ${parsed.data.id}`);
72633
+ }
72634
+ return parsed.data;
72635
+ }
72636
+ function ensureParentDir(filePath) {
72637
+ const parent = path18.dirname(filePath);
72638
+ if (!fs19.existsSync(parent)) {
72639
+ fs19.mkdirSync(parent, { recursive: true });
72640
+ }
72641
+ }
72642
+ function copyPluginFile(pluginDir, file, repoPath, force) {
72643
+ const srcPath = path18.join(pluginDir, file.src);
72644
+ const destPath = path18.join(repoPath, file.dest);
72645
+ if (!fs19.existsSync(srcPath)) {
72646
+ throw new Error(`Plugin file missing: ${file.src}`);
72647
+ }
72648
+ if (fs19.existsSync(destPath) && !force) {
72649
+ throw new Error(
72650
+ `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
72651
+ );
72652
+ }
72653
+ ensureParentDir(destPath);
72654
+ fs19.copyFileSync(srcPath, destPath);
72655
+ if (file.executable) {
72656
+ fs19.chmodSync(destPath, 493);
72657
+ }
72658
+ return { written: true, path: file.dest };
72659
+ }
72660
+ function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
72661
+ const packagePath = path18.join(repoPath, "package.json");
72662
+ if (!fs19.existsSync(packagePath)) {
72663
+ throw new Error("No package.json in repo root. Add one before applying this plugin.");
72664
+ }
72665
+ const fragmentPath = path18.join(pluginDir, fragmentRelPath);
72666
+ if (!fs19.existsSync(fragmentPath)) {
72667
+ throw new Error(`Package fragment missing: ${fragmentRelPath}`);
72668
+ }
72669
+ const pkg = JSON.parse(fs19.readFileSync(packagePath, "utf8"));
72670
+ const fragment = JSON.parse(fs19.readFileSync(fragmentPath, "utf8"));
72671
+ for (const section of ["scripts", "devDependencies"]) {
72672
+ const existing = pkg[section] ?? {};
72673
+ const incoming = fragment[section] ?? {};
72674
+ for (const [key, value] of Object.entries(incoming)) {
72675
+ if (existing[key] !== void 0 && existing[key] !== value) {
72676
+ warnings.push(`package.json ${section}.${key} already set \u2014 kept existing value`);
72677
+ continue;
72678
+ }
72679
+ existing[key] = value;
72680
+ }
72681
+ pkg[section] = existing;
72682
+ }
72683
+ fs19.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
72684
+ }
72685
+ function patchStageRegistry(repoPath, manifest, force) {
72686
+ const registry2 = readStageRegistry(repoPath);
72687
+ const stage = HarnessStageSchema.parse(manifest.stage);
72688
+ const existing = registry2.stages.find((s2) => s2.id === stage.id);
72689
+ if (existing && !force) {
72690
+ throw new Error(
72691
+ `Stage "${stage.id}" already registered in .har/stages.json. Use --force to replace.`
72692
+ );
72693
+ }
72694
+ const stages = existing ? registry2.stages.map((s2) => s2.id === stage.id ? stage : s2) : [...registry2.stages, stage];
72695
+ const verificationStages = [...registry2.verificationStages ?? []];
72696
+ for (const id of manifest.verificationStages) {
72697
+ if (!verificationStages.includes(id)) {
72698
+ verificationStages.push(id);
72699
+ }
72700
+ }
72701
+ const verifyIdx = stages.findIndex((s2) => s2.id === "verify");
72702
+ if (verifyIdx >= 0) {
72703
+ stages[verifyIdx] = {
72704
+ ...stages[verifyIdx],
72705
+ description: `Verification pipeline (quick smoke by default; --full runs the registry's verificationStages: ${verificationStages.join(", ")})`,
72706
+ acceptsArgs: ["--full"]
72707
+ };
72708
+ }
72709
+ const updated = {
72710
+ ...registry2,
72711
+ stages,
72712
+ verificationStages
72713
+ };
72714
+ writeStageRegistry(repoPath, updated);
72715
+ }
72716
+ function assertHarnessPresent(repoPath) {
72717
+ if (!harnessExists(repoPath)) {
72718
+ throw new Error('No .har/ harness found. Run "har env init" first.');
72719
+ }
72720
+ }
72721
+ function assertStageNotPresent(repoPath, stageId, force) {
72722
+ if (force) return;
72723
+ const scriptPath = path18.join(repoPath, ".har", "stages", `${stageId}.sh`);
72724
+ if (fs19.existsSync(scriptPath)) {
72725
+ throw new Error(
72726
+ `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
72727
+ );
72728
+ }
72729
+ const registry2 = readStageRegistry(repoPath);
72730
+ if (registry2.stages.some((s2) => s2.id === stageId)) {
72731
+ throw new Error(
72732
+ `Stage "${stageId}" already registered in .har/stages.json. Use --force to replace.`
72733
+ );
72734
+ }
72735
+ }
72736
+ function applyPlugin(repoPath, pluginId, options = {}) {
72737
+ const resolved = path18.resolve(repoPath);
72738
+ const force = options.force ?? false;
72739
+ const warnings = [];
72740
+ const filesWritten = [];
72741
+ assertHarnessPresent(resolved);
72742
+ const manifest = readPluginManifest(pluginId);
72743
+ assertStageNotPresent(resolved, manifest.stageId, force);
72744
+ const pluginDir = resolvePluginDir(pluginId);
72745
+ for (const file of manifest.files) {
72746
+ const result = copyPluginFile(pluginDir, file, resolved, force);
72747
+ if (result.written) {
72748
+ filesWritten.push(result.path);
72749
+ }
72750
+ }
72751
+ if (manifest.optionalFiles) {
72752
+ for (const file of manifest.optionalFiles) {
72753
+ if (file.skipFlag === "skipCi" && options.skipCi) {
72754
+ continue;
72755
+ }
72756
+ if (fs19.existsSync(path18.join(resolved, file.dest)) && !force) {
72757
+ warnings.push(`Skipped optional file (exists): ${file.dest}`);
72758
+ continue;
72759
+ }
72760
+ const result = copyPluginFile(pluginDir, file, resolved, force);
72761
+ if (result.written) {
72762
+ filesWritten.push(result.path);
72763
+ }
72764
+ }
72765
+ }
72766
+ if (manifest.merge) {
72767
+ for (const fragmentRel of Object.values(manifest.merge)) {
72768
+ mergePackageJson(resolved, pluginDir, fragmentRel, warnings);
72769
+ filesWritten.push("package.json");
72770
+ }
72771
+ }
72772
+ patchStageRegistry(resolved, manifest, force);
72773
+ success(`Applied plugin: ${pluginId}`);
72774
+ info(`Registered stage: ${manifest.stageId}`);
72775
+ for (const file of filesWritten) {
72776
+ info(` + ${file}`);
72777
+ }
72778
+ for (const warning of warnings) {
72779
+ warn(` \u26A0 ${warning}`);
72780
+ }
72781
+ return {
72782
+ pluginId,
72783
+ stageId: manifest.stageId,
72784
+ filesWritten,
72785
+ warnings,
72786
+ nextSteps: manifest.nextSteps,
72787
+ docsPath: manifest.docsPath
72788
+ };
72789
+ }
72790
+ function listPluginIds() {
72791
+ const root = path18.join(resolveTemplatesDir(), "plugins");
72792
+ if (!fs19.existsSync(root)) return [...PLUGIN_IDS];
72793
+ return fs19.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
72794
+ }
72795
+
72796
+ // src/harness/plugin-drift.ts
72797
+ var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
72798
+ function detectInstalledPlugins(repoPath) {
72799
+ const resolved = path19.resolve(repoPath);
72800
+ const registryPath = path19.join(resolved, ".har", "stages.json");
72801
+ if (!fs20.existsSync(registryPath)) return [];
72802
+ const registry2 = readStageRegistry(resolved);
72803
+ const stageIds = new Set(registry2.stages.map((stage) => stage.id));
72804
+ const installed = [];
72805
+ for (const pluginId of PLUGIN_IDS) {
72806
+ const manifest = readPluginManifest(pluginId);
72807
+ if (stageIds.has(manifest.stageId)) {
72808
+ installed.push(pluginId);
72809
+ }
72810
+ }
72811
+ return installed;
72812
+ }
72813
+ function pluginTemplatePath(pluginId, srcRel) {
72814
+ return path19.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
72815
+ }
72816
+ function readBundledPluginFile(pluginId, srcRel) {
72817
+ return fs20.readFileSync(pluginTemplatePath(pluginId, srcRel), "utf8");
72818
+ }
72819
+ function listPluginDestPaths(pluginId, repoPath) {
72820
+ const manifest = readPluginManifest(pluginId);
72821
+ const paths = manifest.files.map((file) => file.dest);
72822
+ if (manifest.optionalFiles) {
72823
+ for (const file of manifest.optionalFiles) {
72824
+ if (fs20.existsSync(path19.join(repoPath, file.dest))) {
72825
+ paths.push(file.dest);
72826
+ }
72827
+ }
72828
+ }
72829
+ if (manifest.merge) {
72830
+ for (const dest of Object.keys(manifest.merge)) {
72831
+ if (!paths.includes(dest)) paths.push(dest);
72832
+ }
72833
+ }
72834
+ return paths.sort();
72835
+ }
72836
+ function manifestEntryForDest(pluginId, dest) {
72837
+ const manifest = readPluginManifest(pluginId);
72838
+ return [...manifest.files, ...manifest.optionalFiles ?? []].find((file) => file.dest === dest);
72839
+ }
72840
+ function extractPackageFragment(pkgContent, fragmentContent) {
72841
+ const pkg = JSON.parse(pkgContent);
72842
+ const fragment = JSON.parse(fragmentContent);
72843
+ const extracted = {};
72844
+ for (const section of PACKAGE_SECTIONS) {
72845
+ const incoming = fragment[section] ?? {};
72846
+ const existing = pkg[section] ?? {};
72847
+ const picked = {};
72848
+ for (const key of Object.keys(incoming)) {
72849
+ if (existing[key] !== void 0) picked[key] = existing[key];
72850
+ }
72851
+ if (Object.keys(picked).length > 0) extracted[section] = picked;
72852
+ }
72853
+ return `${JSON.stringify(extracted, null, 2)}
72854
+ `;
72855
+ }
72856
+ function pluginKeysMatch(installedContent, fragmentContent) {
72857
+ const pkg = JSON.parse(installedContent);
72858
+ const fragment = JSON.parse(fragmentContent);
72859
+ for (const section of PACKAGE_SECTIONS) {
72860
+ const incoming = fragment[section] ?? {};
72861
+ const existing = pkg[section] ?? {};
72862
+ for (const [key, value] of Object.entries(incoming)) {
72863
+ if (existing[key] !== value) return false;
72864
+ }
72865
+ }
72866
+ return true;
72867
+ }
72868
+ function readTemplatePluginFile(pluginId, dest) {
72869
+ const entry = manifestEntryForDest(pluginId, dest);
72870
+ if (entry) {
72871
+ return readBundledPluginFile(pluginId, entry.src);
72872
+ }
72873
+ const manifest = readPluginManifest(pluginId);
72874
+ const fragmentRel = manifest.merge?.[dest];
72875
+ if (fragmentRel) {
72876
+ const fragment = JSON.parse(readBundledPluginFile(pluginId, fragmentRel));
72877
+ return `${JSON.stringify(fragment, null, 2)}
72878
+ `;
72879
+ }
72880
+ return null;
72881
+ }
72882
+ function readInstalledPluginFile(repoPath, pluginId, dest) {
72883
+ const installedPath = path19.join(path19.resolve(repoPath), dest);
72884
+ if (!fs20.existsSync(installedPath)) return null;
72885
+ const content = fs20.readFileSync(installedPath, "utf8");
72886
+ const manifest = readPluginManifest(pluginId);
72887
+ const fragmentRel = manifest.merge?.[dest];
72888
+ if (fragmentRel) {
72889
+ return extractPackageFragment(content, readBundledPluginFile(pluginId, fragmentRel));
72890
+ }
72891
+ return content;
72892
+ }
72893
+ function pluginActionHint(pluginId, dest, kind2) {
72894
+ if (kind2 === "missing") {
72895
+ return `Copy/adapt from maintain/plugins/${pluginId}/templates/${dest} or run: har env add-plugin ${pluginId} --force`;
72896
+ }
72897
+ if (dest === "package.json") {
72898
+ return `Merge plugin script/devDependency keys from maintain/plugins/${pluginId}/diffs/${dest}.diff or run: har env add-plugin ${pluginId} --force`;
72899
+ }
72900
+ return `Merge maintain/plugins/${pluginId}/diffs/${dest}.diff or run: har env add-plugin ${pluginId} --force`;
72901
+ }
72902
+ function comparePluginToTemplate(repoPath, pluginId) {
72903
+ const manifest = readPluginManifest(pluginId);
72904
+ const resolved = path19.resolve(repoPath);
72905
+ const destPaths = listPluginDestPaths(pluginId, resolved);
72906
+ const missing = [];
72907
+ const checksumMismatch = [];
72908
+ const unchanged = [];
72909
+ for (const dest of destPaths) {
72910
+ const templateContent = readTemplatePluginFile(pluginId, dest);
72911
+ if (templateContent === null) continue;
72912
+ const installedContent = readInstalledPluginFile(resolved, pluginId, dest);
72913
+ if (installedContent === null) {
72914
+ missing.push(dest);
72915
+ continue;
72916
+ }
72917
+ if (dest === "package.json") {
72918
+ const fragmentRel = manifest.merge?.[dest];
72919
+ const installedPath = path19.join(resolved, dest);
72920
+ const installedRaw = fs20.readFileSync(installedPath, "utf8");
72921
+ if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
72922
+ unchanged.push(dest);
72923
+ } else if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
72924
+ unchanged.push(dest);
72925
+ } else {
72926
+ checksumMismatch.push(dest);
72927
+ }
72928
+ continue;
72929
+ }
72930
+ if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
72931
+ unchanged.push(dest);
72932
+ } else {
72933
+ checksumMismatch.push(dest);
72934
+ }
72935
+ }
72936
+ return {
72937
+ pluginId,
72938
+ stageId: manifest.stageId,
72939
+ missing,
72940
+ checksumMismatch,
72941
+ unchanged
72942
+ };
72943
+ }
72944
+ function compareInstalledPluginsToTemplate(repoPath) {
72945
+ return detectInstalledPlugins(repoPath).map(
72946
+ (pluginId) => comparePluginToTemplate(repoPath, pluginId)
72947
+ );
72948
+ }
72949
+ function buildPluginDriftActions(repoPath, pluginDrift) {
72950
+ const actions = [];
72951
+ for (const drift of pluginDrift) {
72952
+ for (const file of drift.missing) {
72953
+ actions.push({
72954
+ pluginId: drift.pluginId,
72955
+ file,
72956
+ kind: "missing",
72957
+ template: `maintain/plugins/${drift.pluginId}/templates/${file}`,
72958
+ hint: pluginActionHint(drift.pluginId, file, "missing")
72959
+ });
72960
+ }
72961
+ for (const file of drift.checksumMismatch) {
72962
+ actions.push({
72963
+ pluginId: drift.pluginId,
72964
+ file,
72965
+ kind: "drift",
72966
+ template: `maintain/plugins/${drift.pluginId}/templates/${file}`,
72967
+ installed: `maintain/plugins/${drift.pluginId}/installed/${file}`,
72968
+ diff: `maintain/plugins/${drift.pluginId}/diffs/${file}.diff`,
72969
+ hint: pluginActionHint(drift.pluginId, file, "drift")
72970
+ });
72971
+ }
72972
+ }
72973
+ return actions.sort(
72974
+ (a2, b3) => a2.pluginId.localeCompare(b3.pluginId) || a2.file.localeCompare(b3.file)
72975
+ );
72976
+ }
72977
+
72978
+ // src/harness/maintain-bundle.ts
72582
72979
  var MAINTAIN_DIR = "maintain";
72583
72980
  var PROFILE_DIRS3 = {
72584
72981
  default: "har-boilerplate",
@@ -72589,14 +72986,14 @@ function substituteProjectName2(content, projectName) {
72589
72986
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
72590
72987
  }
72591
72988
  function projectNameFromRepo(repoPath) {
72592
- return path18.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
72989
+ return path20.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
72593
72990
  }
72594
72991
  function boilerplateDirForProfile(profile) {
72595
- return path18.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
72992
+ return path20.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
72596
72993
  }
72597
72994
  function readBundledTemplateContent(repoPath, profile, file) {
72598
- const templatePath = path18.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
72599
- let content = fs18.readFileSync(templatePath, "utf8");
72995
+ const templatePath = path20.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
72996
+ let content = fs21.readFileSync(templatePath, "utf8");
72600
72997
  if (file === "harness.env") {
72601
72998
  content = substituteProjectName2(content, projectNameFromRepo(repoPath));
72602
72999
  }
@@ -72627,12 +73024,12 @@ function actionHint(file, kind2) {
72627
73024
  return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
72628
73025
  }
72629
73026
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
72630
- const tmpDir = fs18.mkdtempSync(path18.join(os4.tmpdir(), "har-maintain-diff-"));
73027
+ const tmpDir = fs21.mkdtempSync(path20.join(os4.tmpdir(), "har-maintain-diff-"));
72631
73028
  try {
72632
- const installedPath = path18.join(tmpDir, "installed");
72633
- const templatePath = path18.join(tmpDir, "template");
72634
- fs18.writeFileSync(installedPath, installedContent);
72635
- fs18.writeFileSync(templatePath, templateContent);
73029
+ const installedPath = path20.join(tmpDir, "installed");
73030
+ const templatePath = path20.join(tmpDir, "template");
73031
+ fs21.writeFileSync(installedPath, installedContent);
73032
+ fs21.writeFileSync(templatePath, templateContent);
72636
73033
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
72637
73034
  const body = result.stdout.trim();
72638
73035
  if (!body) return "";
@@ -72641,7 +73038,7 @@ function createUnifiedDiff(installedContent, templateContent, installedLabel, te
72641
73038
  ${body.split("\n").slice(2).join("\n")}
72642
73039
  `;
72643
73040
  } finally {
72644
- fs18.rmSync(tmpDir, { recursive: true, force: true });
73041
+ fs21.rmSync(tmpDir, { recursive: true, force: true });
72645
73042
  }
72646
73043
  }
72647
73044
  function buildActions(repoPath, profile, drift) {
@@ -72656,7 +73053,7 @@ function buildActions(repoPath, profile, drift) {
72656
73053
  });
72657
73054
  }
72658
73055
  for (const file of drift.checksumMismatch) {
72659
- const installedPath = path18.join(harnessDir, file);
73056
+ const installedPath = path20.join(harnessDir, file);
72660
73057
  const installedRel = `maintain/installed/${file}`;
72661
73058
  const templateRel = `maintain/templates/${file}`;
72662
73059
  const diffRel = `maintain/diffs/${file}.diff`;
@@ -72664,7 +73061,7 @@ function buildActions(repoPath, profile, drift) {
72664
73061
  file,
72665
73062
  kind: "drift",
72666
73063
  template: templateRel,
72667
- installed: fs18.existsSync(installedPath) ? installedRel : void 0,
73064
+ installed: fs21.existsSync(installedPath) ? installedRel : void 0,
72668
73065
  diff: diffRel,
72669
73066
  hint: actionHint(file, "drift")
72670
73067
  });
@@ -72698,7 +73095,7 @@ function buildReadme(report) {
72698
73095
  }
72699
73096
  lines2.push("", "## Drift actions", "");
72700
73097
  if (report.actions.length === 0) {
72701
- lines2.push("No missing or drifted template files.");
73098
+ lines2.push("No missing or drifted harness template files.");
72702
73099
  } else {
72703
73100
  lines2.push("| File | Status | Reference |");
72704
73101
  lines2.push("|------|--------|-----------|");
@@ -72707,6 +73104,22 @@ function buildReadme(report) {
72707
73104
  lines2.push(`| ${action.file} | ${action.kind} | ${ref} |`);
72708
73105
  }
72709
73106
  }
73107
+ lines2.push("", "## Plugin drift (installed verification plugins)", "");
73108
+ if (report.pluginActions.length === 0) {
73109
+ lines2.push("No installed plugins detected, or all plugin files match bundled templates.");
73110
+ } else {
73111
+ lines2.push("| Plugin | File | Status | Reference |");
73112
+ lines2.push("|--------|------|--------|-----------|");
73113
+ for (const action of report.pluginActions) {
73114
+ const ref = action.kind === "missing" ? `plugins/${action.pluginId}/templates/${action.file}` : `plugins/${action.pluginId}/diffs/${action.file}.diff`;
73115
+ lines2.push(`| ${action.pluginId} | ${action.file} | ${action.kind} | ${ref} |`);
73116
+ }
73117
+ lines2.push(
73118
+ "",
73119
+ "To refresh all plugin files: `har env add-plugin <id> --force` (overwrites plugin-owned paths).",
73120
+ ""
73121
+ );
73122
+ }
72710
73123
  if (report.missingPortVars.length > 0) {
72711
73124
  lines2.push("", "## Missing port vars in harness.env", "");
72712
73125
  for (const v3 of report.missingPortVars) {
@@ -72737,38 +73150,39 @@ function buildReadme(report) {
72737
73150
  "",
72738
73151
  "## Next steps",
72739
73152
  "",
72740
- "1. Resolve each drift action (merge diffs; keep repo-specific customizations).",
72741
- "2. Review stale files \u2014 delete or merge superseded scripts.",
72742
- "3. Re-run `har env maintain` until validation passes and drift is clear.",
72743
- '4. `har env maintain --finalize --summary "<what changed>"`',
73153
+ "1. Resolve each harness drift action (merge diffs; keep repo-specific customizations).",
73154
+ "2. Merge plugin drift under `maintain/plugins/` or run `har env add-plugin <id> --force`.",
73155
+ "3. Review stale files \u2014 delete or merge superseded scripts.",
73156
+ "4. Re-run `har env maintain` until validation passes and drift is clear.",
73157
+ '5. `har env maintain --finalize --summary "<what changed>"`',
72744
73158
  ""
72745
73159
  );
72746
73160
  return lines2.join("\n");
72747
73161
  }
72748
73162
  function writeBundleArtifacts(repoPath, profile, drift, report) {
72749
73163
  const harnessDir = getHarnessDir(repoPath);
72750
- const bundleDir = path18.join(harnessDir, MAINTAIN_DIR);
72751
- if (fs18.existsSync(bundleDir)) {
72752
- fs18.rmSync(bundleDir, { recursive: true, force: true });
73164
+ const bundleDir = path20.join(harnessDir, MAINTAIN_DIR);
73165
+ if (fs21.existsSync(bundleDir)) {
73166
+ fs21.rmSync(bundleDir, { recursive: true, force: true });
72753
73167
  }
72754
73168
  const dirs = [
72755
73169
  bundleDir,
72756
- path18.join(bundleDir, "templates"),
72757
- path18.join(bundleDir, "installed"),
72758
- path18.join(bundleDir, "diffs"),
72759
- path18.join(bundleDir, "stale")
73170
+ path20.join(bundleDir, "templates"),
73171
+ path20.join(bundleDir, "installed"),
73172
+ path20.join(bundleDir, "diffs"),
73173
+ path20.join(bundleDir, "stale")
72760
73174
  ];
72761
73175
  for (const dir of dirs) {
72762
- fs18.mkdirSync(dir, { recursive: true });
73176
+ fs21.mkdirSync(dir, { recursive: true });
72763
73177
  }
72764
73178
  const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
72765
73179
  for (const file of affectedFiles) {
72766
73180
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
72767
- writeFileSafe(path18.join(bundleDir, "templates", file), templateContent);
72768
- const harnessPath = path18.join(harnessDir, file);
72769
- if (fs18.existsSync(harnessPath)) {
72770
- const installedContent = fs18.readFileSync(harnessPath, "utf8");
72771
- writeFileSafe(path18.join(bundleDir, "installed", file), installedContent);
73181
+ writeFileSafe(path20.join(bundleDir, "templates", file), templateContent);
73182
+ const harnessPath = path20.join(harnessDir, file);
73183
+ if (fs21.existsSync(harnessPath)) {
73184
+ const installedContent = fs21.readFileSync(harnessPath, "utf8");
73185
+ writeFileSafe(path20.join(bundleDir, "installed", file), installedContent);
72772
73186
  const diff = createUnifiedDiff(
72773
73187
  installedContent,
72774
73188
  templateContent,
@@ -72776,14 +73190,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72776
73190
  `templates/${file}`
72777
73191
  );
72778
73192
  if (diff) {
72779
- writeFileSafe(path18.join(bundleDir, "diffs", `${file}.diff`), diff);
73193
+ writeFileSafe(path20.join(bundleDir, "diffs", `${file}.diff`), diff);
72780
73194
  }
72781
73195
  }
72782
73196
  }
72783
- writeFileSafe(path18.join(bundleDir, "README.md"), buildReadme(report));
72784
- writeFileSafe(path18.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
73197
+ writeFileSafe(path20.join(bundleDir, "README.md"), buildReadme(report));
73198
+ writeFileSafe(path20.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
72785
73199
  writeFileSafe(
72786
- path18.join(bundleDir, "validation.json"),
73200
+ path20.join(bundleDir, "validation.json"),
72787
73201
  JSON.stringify(report.validation, null, 2) + "\n"
72788
73202
  );
72789
73203
  if (report.stale.length > 0) {
@@ -72795,20 +73209,64 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72795
73209
  ...report.stale.map((s2) => `- **${s2.file}** \u2014 ${s2.hint}`),
72796
73210
  ""
72797
73211
  ];
72798
- writeFileSafe(path18.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
73212
+ writeFileSafe(path20.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
72799
73213
  }
72800
73214
  return bundleDir;
72801
73215
  }
73216
+ function ensureParentDir2(filePath) {
73217
+ const parent = path20.dirname(filePath);
73218
+ if (!fs21.existsSync(parent)) {
73219
+ fs21.mkdirSync(parent, { recursive: true });
73220
+ }
73221
+ }
73222
+ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
73223
+ if (report.pluginActions.length === 0) return;
73224
+ for (const action of report.pluginActions) {
73225
+ const pluginRoot = path20.join(bundleDir, "plugins", action.pluginId);
73226
+ const templatesDir = path20.join(pluginRoot, "templates");
73227
+ const installedDir = path20.join(pluginRoot, "installed");
73228
+ const diffsDir = path20.join(pluginRoot, "diffs");
73229
+ for (const dir of [templatesDir, installedDir, diffsDir]) {
73230
+ fs21.mkdirSync(dir, { recursive: true });
73231
+ }
73232
+ const templateContent = readTemplatePluginFile(action.pluginId, action.file);
73233
+ if (templateContent === null) continue;
73234
+ const templatePath = path20.join(templatesDir, action.file);
73235
+ ensureParentDir2(templatePath);
73236
+ writeFileSafe(templatePath, templateContent);
73237
+ const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
73238
+ if (installedContent !== null) {
73239
+ const installedPath = path20.join(installedDir, action.file);
73240
+ ensureParentDir2(installedPath);
73241
+ writeFileSafe(installedPath, installedContent);
73242
+ const diff = createUnifiedDiff(
73243
+ installedContent,
73244
+ templateContent,
73245
+ `installed/${action.file}`,
73246
+ `templates/${action.file}`
73247
+ );
73248
+ if (diff) {
73249
+ const diffPath = path20.join(diffsDir, `${action.file}.diff`);
73250
+ ensureParentDir2(diffPath);
73251
+ writeFileSafe(diffPath, diff);
73252
+ }
73253
+ }
73254
+ }
73255
+ }
72802
73256
  function buildMaintainBundle(repoPath, validation2, drift) {
72803
73257
  const manifest = readManifest(repoPath);
72804
73258
  const profile = manifest?.profile ?? "default";
72805
73259
  const errors = validation2.issues.filter((i2) => i2.severity === "error");
72806
73260
  const warnings = validation2.issues.filter((i2) => i2.severity === "warning");
73261
+ const pluginDrift = compareInstalledPluginsToTemplate(repoPath);
73262
+ const pluginActions = buildPluginDriftActions(repoPath, pluginDrift);
72807
73263
  const report = {
72808
73264
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
72809
73265
  generatorVersion: drift.generatorVersion,
72810
73266
  profile,
72811
73267
  actions: buildActions(repoPath, profile, drift),
73268
+ pluginDrift,
73269
+ pluginActions,
72812
73270
  stale: buildStale(drift),
72813
73271
  missingPortVars: drift.missingPortVars,
72814
73272
  agentSlotMismatch: drift.agentSlotMismatch,
@@ -72819,12 +73277,13 @@ function buildMaintainBundle(repoPath, validation2, drift) {
72819
73277
  }
72820
73278
  };
72821
73279
  const bundleDir = writeBundleArtifacts(repoPath, profile, drift, report);
73280
+ writePluginBundleArtifacts(repoPath, bundleDir, report);
72822
73281
  return { bundleDir, report };
72823
73282
  }
72824
73283
  function removeMaintainBundle(repoPath) {
72825
- const bundleDir = path18.join(getHarnessDir(repoPath), MAINTAIN_DIR);
72826
- if (fs18.existsSync(bundleDir)) {
72827
- fs18.rmSync(bundleDir, { recursive: true, force: true });
73284
+ const bundleDir = path20.join(getHarnessDir(repoPath), MAINTAIN_DIR);
73285
+ if (fs21.existsSync(bundleDir)) {
73286
+ fs21.rmSync(bundleDir, { recursive: true, force: true });
72828
73287
  }
72829
73288
  }
72830
73289
  function formatMaintainBundlePromptSection(report) {
@@ -72832,7 +73291,8 @@ function formatMaintainBundlePromptSection(report) {
72832
73291
  "## Step 0 \u2014 Read the maintenance bundle",
72833
73292
  "",
72834
73293
  "Open `.har/maintain/README.md` and `.har/maintain/drift-report.json`.",
72835
- "All reference templates are under `.har/maintain/templates/`.",
73294
+ "Harness reference templates: `.har/maintain/templates/`.",
73295
+ "Plugin reference templates: `.har/maintain/plugins/<plugin-id>/`.",
72836
73296
  "Do **not** read files from the globally installed har package.",
72837
73297
  ""
72838
73298
  ];
@@ -72851,6 +73311,19 @@ function formatMaintainBundlePromptSection(report) {
72851
73311
  }
72852
73312
  lines2.push("");
72853
73313
  }
73314
+ if (report.pluginActions.length > 0) {
73315
+ lines2.push(
73316
+ "### Plugin drift",
73317
+ "",
73318
+ "| Plugin | File | Status | Reference |",
73319
+ "|--------|------|--------|-----------|"
73320
+ );
73321
+ for (const action of report.pluginActions) {
73322
+ const ref = action.kind === "missing" ? `maintain/plugins/${action.pluginId}/templates/${action.file}` : `maintain/plugins/${action.pluginId}/diffs/${action.file}.diff`;
73323
+ lines2.push(`| ${action.pluginId} | ${action.file} | ${action.kind} | ${ref} |`);
73324
+ }
73325
+ lines2.push("");
73326
+ }
72854
73327
  if (report.stale.length > 0) {
72855
73328
  lines2.push("### Stale files", "");
72856
73329
  for (const stale of report.stale) {
@@ -72876,221 +73349,12 @@ function formatMaintainBundlePromptSection(report) {
72876
73349
  ""
72877
73350
  );
72878
73351
  }
72879
- if (report.actions.length === 0 && report.stale.length === 0 && report.missingPortVars.length === 0 && !report.agentSlotMismatch && report.validation.errors.length === 0) {
73352
+ if (report.actions.length === 0 && report.pluginActions.length === 0 && report.stale.length === 0 && report.missingPortVars.length === 0 && !report.agentSlotMismatch && report.validation.errors.length === 0) {
72880
73353
  lines2.push("No template drift detected. Review repo stack changes manually if needed.", "");
72881
73354
  }
72882
73355
  return lines2.join("\n");
72883
73356
  }
72884
73357
 
72885
- // src/harness/plugins.ts
72886
- var fs20 = __toESM(require("fs"));
72887
- var path19 = __toESM(require("path"));
72888
-
72889
- // src/harness/parser.ts
72890
- var fs19 = __toESM(require("fs"));
72891
- function harnessExists(repoPath) {
72892
- return fs19.existsSync(`${repoPath}/.har/setup-infra.sh`);
72893
- }
72894
-
72895
- // src/harness/plugins.ts
72896
- var PLUGIN_IDS = ["playwright", "rocketsim"];
72897
- var PluginManifestFileSchema = external_exports.object({
72898
- src: external_exports.string().min(1),
72899
- dest: external_exports.string().min(1),
72900
- executable: external_exports.boolean().optional(),
72901
- skipFlag: external_exports.string().optional()
72902
- });
72903
- var PluginManifestSchema = external_exports.object({
72904
- id: external_exports.enum(PLUGIN_IDS),
72905
- stageId: external_exports.string().min(1),
72906
- verificationStages: external_exports.array(external_exports.string().min(1)).min(1),
72907
- stage: external_exports.record(external_exports.unknown()),
72908
- files: external_exports.array(PluginManifestFileSchema).min(1),
72909
- optionalFiles: external_exports.array(PluginManifestFileSchema).optional(),
72910
- merge: external_exports.record(external_exports.string()).optional(),
72911
- nextSteps: external_exports.array(external_exports.string().min(1)).min(1),
72912
- docsPath: external_exports.string().min(1)
72913
- });
72914
- function resolvePluginDir(pluginId) {
72915
- const dir = path19.join(resolveTemplatesDir(), "plugins", pluginId);
72916
- if (!fs20.existsSync(dir)) {
72917
- throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
72918
- }
72919
- return dir;
72920
- }
72921
- function readPluginManifest(pluginId) {
72922
- const manifestPath = path19.join(resolvePluginDir(pluginId), "template.manifest.json");
72923
- const parsed = PluginManifestSchema.safeParse(
72924
- JSON.parse(fs20.readFileSync(manifestPath, "utf8"))
72925
- );
72926
- if (!parsed.success) {
72927
- throw new Error(`Invalid plugin manifest for ${pluginId}: ${parsed.error.message}`);
72928
- }
72929
- if (parsed.data.id !== pluginId) {
72930
- throw new Error(`Plugin manifest id mismatch: expected ${pluginId}, got ${parsed.data.id}`);
72931
- }
72932
- return parsed.data;
72933
- }
72934
- function ensureParentDir(filePath) {
72935
- const parent = path19.dirname(filePath);
72936
- if (!fs20.existsSync(parent)) {
72937
- fs20.mkdirSync(parent, { recursive: true });
72938
- }
72939
- }
72940
- function copyPluginFile(pluginDir, file, repoPath, force) {
72941
- const srcPath = path19.join(pluginDir, file.src);
72942
- const destPath = path19.join(repoPath, file.dest);
72943
- if (!fs20.existsSync(srcPath)) {
72944
- throw new Error(`Plugin file missing: ${file.src}`);
72945
- }
72946
- if (fs20.existsSync(destPath) && !force) {
72947
- throw new Error(
72948
- `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
72949
- );
72950
- }
72951
- ensureParentDir(destPath);
72952
- fs20.copyFileSync(srcPath, destPath);
72953
- if (file.executable) {
72954
- fs20.chmodSync(destPath, 493);
72955
- }
72956
- return { written: true, path: file.dest };
72957
- }
72958
- function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
72959
- const packagePath = path19.join(repoPath, "package.json");
72960
- if (!fs20.existsSync(packagePath)) {
72961
- throw new Error("No package.json in repo root. Add one before applying this plugin.");
72962
- }
72963
- const fragmentPath = path19.join(pluginDir, fragmentRelPath);
72964
- if (!fs20.existsSync(fragmentPath)) {
72965
- throw new Error(`Package fragment missing: ${fragmentRelPath}`);
72966
- }
72967
- const pkg = JSON.parse(fs20.readFileSync(packagePath, "utf8"));
72968
- const fragment = JSON.parse(fs20.readFileSync(fragmentPath, "utf8"));
72969
- for (const section of ["scripts", "devDependencies"]) {
72970
- const existing = pkg[section] ?? {};
72971
- const incoming = fragment[section] ?? {};
72972
- for (const [key, value] of Object.entries(incoming)) {
72973
- if (existing[key] !== void 0 && existing[key] !== value) {
72974
- warnings.push(`package.json ${section}.${key} already set \u2014 kept existing value`);
72975
- continue;
72976
- }
72977
- existing[key] = value;
72978
- }
72979
- pkg[section] = existing;
72980
- }
72981
- fs20.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
72982
- }
72983
- function patchStageRegistry(repoPath, manifest, force) {
72984
- const registry2 = readStageRegistry(repoPath);
72985
- const stage = HarnessStageSchema.parse(manifest.stage);
72986
- const existing = registry2.stages.find((s2) => s2.id === stage.id);
72987
- if (existing && !force) {
72988
- throw new Error(
72989
- `Stage "${stage.id}" already registered in .har/stages.json. Use --force to replace.`
72990
- );
72991
- }
72992
- const stages = existing ? registry2.stages.map((s2) => s2.id === stage.id ? stage : s2) : [...registry2.stages, stage];
72993
- const verificationStages = [...registry2.verificationStages ?? []];
72994
- for (const id of manifest.verificationStages) {
72995
- if (!verificationStages.includes(id)) {
72996
- verificationStages.push(id);
72997
- }
72998
- }
72999
- const verifyIdx = stages.findIndex((s2) => s2.id === "verify");
73000
- if (verifyIdx >= 0) {
73001
- stages[verifyIdx] = {
73002
- ...stages[verifyIdx],
73003
- description: `Verification pipeline (quick smoke by default; --full runs the registry's verificationStages: ${verificationStages.join(", ")})`,
73004
- acceptsArgs: ["--full"]
73005
- };
73006
- }
73007
- const updated = {
73008
- ...registry2,
73009
- stages,
73010
- verificationStages
73011
- };
73012
- writeStageRegistry(repoPath, updated);
73013
- }
73014
- function assertHarnessPresent(repoPath) {
73015
- if (!harnessExists(repoPath)) {
73016
- throw new Error('No .har/ harness found. Run "har env init" first.');
73017
- }
73018
- }
73019
- function assertStageNotPresent(repoPath, stageId, force) {
73020
- if (force) return;
73021
- const scriptPath = path19.join(repoPath, ".har", "stages", `${stageId}.sh`);
73022
- if (fs20.existsSync(scriptPath)) {
73023
- throw new Error(
73024
- `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
73025
- );
73026
- }
73027
- const registry2 = readStageRegistry(repoPath);
73028
- if (registry2.stages.some((s2) => s2.id === stageId)) {
73029
- throw new Error(
73030
- `Stage "${stageId}" already registered in .har/stages.json. Use --force to replace.`
73031
- );
73032
- }
73033
- }
73034
- function applyPlugin(repoPath, pluginId, options = {}) {
73035
- const resolved = path19.resolve(repoPath);
73036
- const force = options.force ?? false;
73037
- const warnings = [];
73038
- const filesWritten = [];
73039
- assertHarnessPresent(resolved);
73040
- const manifest = readPluginManifest(pluginId);
73041
- assertStageNotPresent(resolved, manifest.stageId, force);
73042
- const pluginDir = resolvePluginDir(pluginId);
73043
- for (const file of manifest.files) {
73044
- const result = copyPluginFile(pluginDir, file, resolved, force);
73045
- if (result.written) {
73046
- filesWritten.push(result.path);
73047
- }
73048
- }
73049
- if (manifest.optionalFiles) {
73050
- for (const file of manifest.optionalFiles) {
73051
- if (file.skipFlag === "skipCi" && options.skipCi) {
73052
- continue;
73053
- }
73054
- if (fs20.existsSync(path19.join(resolved, file.dest)) && !force) {
73055
- warnings.push(`Skipped optional file (exists): ${file.dest}`);
73056
- continue;
73057
- }
73058
- const result = copyPluginFile(pluginDir, file, resolved, force);
73059
- if (result.written) {
73060
- filesWritten.push(result.path);
73061
- }
73062
- }
73063
- }
73064
- if (manifest.merge) {
73065
- for (const fragmentRel of Object.values(manifest.merge)) {
73066
- mergePackageJson(resolved, pluginDir, fragmentRel, warnings);
73067
- filesWritten.push("package.json");
73068
- }
73069
- }
73070
- patchStageRegistry(resolved, manifest, force);
73071
- success(`Applied plugin: ${pluginId}`);
73072
- info(`Registered stage: ${manifest.stageId}`);
73073
- for (const file of filesWritten) {
73074
- info(` + ${file}`);
73075
- }
73076
- for (const warning of warnings) {
73077
- warn(` \u26A0 ${warning}`);
73078
- }
73079
- return {
73080
- pluginId,
73081
- stageId: manifest.stageId,
73082
- filesWritten,
73083
- warnings,
73084
- nextSteps: manifest.nextSteps,
73085
- docsPath: manifest.docsPath
73086
- };
73087
- }
73088
- function listPluginIds() {
73089
- const root = path19.join(resolveTemplatesDir(), "plugins");
73090
- if (!fs20.existsSync(root)) return [...PLUGIN_IDS];
73091
- return fs20.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
73092
- }
73093
-
73094
73358
  // src/utils/validation.ts
73095
73359
  function requireApiKey() {
73096
73360
  const key = process.env.ANTHROPIC_API_KEY;
@@ -73113,11 +73377,11 @@ function validateAgentId(id, repoPath) {
73113
73377
  // src/core/harness.ts
73114
73378
  function listHarnessScripts(repoPath) {
73115
73379
  const harnessDir = getHarnessDir(repoPath);
73116
- if (!fs21.existsSync(harnessDir)) return [];
73117
- return fs21.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
73380
+ if (!fs22.existsSync(harnessDir)) return [];
73381
+ return fs22.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
73118
73382
  }
73119
73383
  function describeProject(repoPath) {
73120
- const resolved = path20.resolve(repoPath);
73384
+ const resolved = path21.resolve(repoPath);
73121
73385
  const manifest = readManifest(resolved);
73122
73386
  const present = harnessExists(resolved);
73123
73387
  return {
@@ -73137,8 +73401,8 @@ function describeProject(repoPath) {
73137
73401
  };
73138
73402
  }
73139
73403
  async function initHarness(options) {
73140
- const repoPath = path20.resolve(options.repoPath);
73141
- if (!fs21.existsSync(repoPath)) {
73404
+ const repoPath = path21.resolve(options.repoPath);
73405
+ if (!fs22.existsSync(repoPath)) {
73142
73406
  throw new Error(`Path not found: ${repoPath}`);
73143
73407
  }
73144
73408
  const scaffold = scaffoldHarnessBoilerplate(repoPath, {
@@ -73170,9 +73434,9 @@ async function initHarness(options) {
73170
73434
  };
73171
73435
  }
73172
73436
  async function maintainHarness(options) {
73173
- const repoPath = path20.resolve(options.repoPath);
73437
+ const repoPath = path21.resolve(options.repoPath);
73174
73438
  const harnessDir = getHarnessDir(repoPath);
73175
- if (!fs21.existsSync(harnessDir)) {
73439
+ if (!fs22.existsSync(harnessDir)) {
73176
73440
  throw new Error('No .har/ found. Run "har env init" first.');
73177
73441
  }
73178
73442
  if (options.auto) {
@@ -73224,11 +73488,11 @@ function addPlugin(repoPath, pluginId, options = {}) {
73224
73488
  }
73225
73489
 
73226
73490
  // src/harness/custom-stage.ts
73227
- var fs22 = __toESM(require("fs"));
73228
- var path21 = __toESM(require("path"));
73491
+ var fs23 = __toESM(require("fs"));
73492
+ var path22 = __toESM(require("path"));
73229
73493
  var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
73230
73494
  function addCustomStage(repoPath, options) {
73231
- const resolved = path21.resolve(repoPath);
73495
+ const resolved = path22.resolve(repoPath);
73232
73496
  if (!harnessExists(resolved)) {
73233
73497
  throw new Error('No .har/ harness found. Run "har env init" first.');
73234
73498
  }
@@ -73265,20 +73529,20 @@ function addCustomStage(repoPath, options) {
73265
73529
  if (options.command) {
73266
73530
  stage.command = options.command;
73267
73531
  } else {
73268
- const scriptRel = path21.join("stages", `${id}.sh`);
73269
- const scriptAbs = path21.join(resolved, ".har", scriptRel);
73270
- if (fs22.existsSync(scriptAbs) && !options.force) {
73532
+ const scriptRel = path22.join("stages", `${id}.sh`);
73533
+ const scriptAbs = path22.join(resolved, ".har", scriptRel);
73534
+ if (fs23.existsSync(scriptAbs) && !options.force) {
73271
73535
  throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
73272
73536
  }
73273
- const skeletonPath = path21.join(
73537
+ const skeletonPath = path22.join(
73274
73538
  resolveTemplatesDir(),
73275
73539
  "plugins",
73276
73540
  "custom-stage-skeleton.sh"
73277
73541
  );
73278
- const skeleton = fs22.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind2).replace(/__STAGE_DESCRIPTION__/g, stage.description);
73279
- fs22.mkdirSync(path21.dirname(scriptAbs), { recursive: true });
73280
- fs22.writeFileSync(scriptAbs, skeleton);
73281
- fs22.chmodSync(scriptAbs, 493);
73542
+ const skeleton = fs23.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind2).replace(/__STAGE_DESCRIPTION__/g, stage.description);
73543
+ fs23.mkdirSync(path22.dirname(scriptAbs), { recursive: true });
73544
+ fs23.writeFileSync(scriptAbs, skeleton);
73545
+ fs23.chmodSync(scriptAbs, 493);
73282
73546
  filesWritten.push(`.har/${scriptRel}`);
73283
73547
  stage.script = scriptRel;
73284
73548
  stage.artifacts = [
@@ -73326,8 +73590,8 @@ function addCustomStage(repoPath, options) {
73326
73590
  }
73327
73591
 
73328
73592
  // src/harness/adaptation-prompt.ts
73329
- var fs23 = __toESM(require("fs"));
73330
- var path22 = __toESM(require("path"));
73593
+ var fs24 = __toESM(require("fs"));
73594
+ var path23 = __toESM(require("path"));
73331
73595
  var readline4 = __toESM(require("readline"));
73332
73596
 
73333
73597
  // src/utils/clipboard.ts
@@ -73414,7 +73678,7 @@ function loadTemplate(name) {
73414
73678
  if (!filePath) {
73415
73679
  throw new Error(`Adaptation prompt template not found: ${name}. Run npm run build.`);
73416
73680
  }
73417
- return fs23.readFileSync(filePath, "utf8");
73681
+ return fs24.readFileSync(filePath, "utf8");
73418
73682
  }
73419
73683
  function applyProfilePlaceholders(content, profile) {
73420
73684
  return content.replace(/\{\{PROFILE\}\}/g, profile).replace(/\{\{PROFILE_HINT\}\}/g, PROFILE_HINTS[profile]);
@@ -73436,7 +73700,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
73436
73700
  }
73437
73701
  function writeAdaptationPrompt(repoPath, content) {
73438
73702
  const harnessDir = getHarnessDir(repoPath);
73439
- const filePath = path22.join(harnessDir, ADAPTATION_PROMPT_FILE);
73703
+ const filePath = path23.join(harnessDir, ADAPTATION_PROMPT_FILE);
73440
73704
  writeFileSafe(filePath, content);
73441
73705
  return filePath;
73442
73706
  }
@@ -73455,12 +73719,12 @@ function printAdaptationPrompt(content) {
73455
73719
  }
73456
73720
  function askYesNo3(question) {
73457
73721
  const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
73458
- return new Promise((resolve44) => {
73722
+ return new Promise((resolve45) => {
73459
73723
  process.stderr.write(`${question} `);
73460
73724
  rl.once("line", (answer) => {
73461
73725
  rl.close();
73462
73726
  const trimmed = answer.trim();
73463
- resolve44(trimmed === "" || /^y(es)?$/i.test(trimmed));
73727
+ resolve45(trimmed === "" || /^y(es)?$/i.test(trimmed));
73464
73728
  });
73465
73729
  });
73466
73730
  }
@@ -73491,25 +73755,25 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
73491
73755
  }
73492
73756
 
73493
73757
  // src/harness/cursor-rule.ts
73494
- var fs24 = __toESM(require("fs"));
73495
- var path23 = __toESM(require("path"));
73758
+ var fs25 = __toESM(require("fs"));
73759
+ var path24 = __toESM(require("path"));
73496
73760
  var readline5 = __toESM(require("readline"));
73497
73761
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
73498
73762
  function getCursorRulePath(repoPath) {
73499
- return path23.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
73763
+ return path24.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
73500
73764
  }
73501
73765
  function isCursorWorkspace(repoPath) {
73502
- return fs24.existsSync(path23.join(repoPath, ".cursor"));
73766
+ return fs25.existsSync(path24.join(repoPath, ".cursor"));
73503
73767
  }
73504
73768
  function cursorRuleExists(repoPath) {
73505
- return fs24.existsSync(getCursorRulePath(repoPath));
73769
+ return fs25.existsSync(getCursorRulePath(repoPath));
73506
73770
  }
73507
73771
  function scaffoldCursorRule(repoPath) {
73508
73772
  const templatePath = resolveTemplateFile("cursor-rule.mdc.template");
73509
73773
  if (!templatePath) {
73510
73774
  throw new Error("Cursor rule template not found (cursor-rule.mdc.template). Run npm run build.");
73511
73775
  }
73512
- const content = fs24.readFileSync(templatePath, "utf8");
73776
+ const content = fs25.readFileSync(templatePath, "utf8");
73513
73777
  writeFileSafe(getCursorRulePath(repoPath), content);
73514
73778
  }
73515
73779
  async function handleCursorRule(options) {
@@ -73547,16 +73811,16 @@ async function promptScaffoldCursorRule(exists) {
73547
73811
  }
73548
73812
  async function askYesNo4(question) {
73549
73813
  const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
73550
- return new Promise((resolve44) => {
73814
+ return new Promise((resolve45) => {
73551
73815
  process.stderr.write(`${question} `);
73552
73816
  rl.once("line", (answer) => {
73553
73817
  rl.close();
73554
73818
  const trimmed = answer.trim();
73555
73819
  if (trimmed === "") {
73556
- resolve44(true);
73820
+ resolve45(true);
73557
73821
  return;
73558
73822
  }
73559
- resolve44(/^y(es)?$/i.test(trimmed));
73823
+ resolve45(/^y(es)?$/i.test(trimmed));
73560
73824
  });
73561
73825
  });
73562
73826
  }
@@ -73638,26 +73902,26 @@ function buildStageResult(input) {
73638
73902
  var crypto5 = __toESM(require("crypto"));
73639
73903
 
73640
73904
  // src/core/local-executor.ts
73641
- var fs26 = __toESM(require("fs"));
73642
- var path25 = __toESM(require("path"));
73905
+ var fs27 = __toESM(require("fs"));
73906
+ var path26 = __toESM(require("path"));
73643
73907
 
73644
73908
  // src/core/slot-registry.ts
73645
- var fs25 = __toESM(require("fs"));
73646
- var path24 = __toESM(require("path"));
73909
+ var fs26 = __toESM(require("fs"));
73910
+ var path25 = __toESM(require("path"));
73647
73911
  function getSlotRegistryDir(repoPath) {
73648
- return path24.join(getHarnessDir(repoPath), "slots");
73912
+ return path25.join(getHarnessDir(repoPath), "slots");
73649
73913
  }
73650
73914
  function getSlotRegistryPath(repoPath, agentId) {
73651
- return path24.join(getSlotRegistryDir(repoPath), `agent-${agentId}.json`);
73915
+ return path25.join(getSlotRegistryDir(repoPath), `agent-${agentId}.json`);
73652
73916
  }
73653
73917
  function isSlotResumable(session) {
73654
73918
  return session?.status === "failed" || session?.status === "starting";
73655
73919
  }
73656
73920
  function readSlotRegistry(repoPath, agentId) {
73657
73921
  const file = getSlotRegistryPath(repoPath, agentId);
73658
- if (!fs25.existsSync(file)) return void 0;
73922
+ if (!fs26.existsSync(file)) return void 0;
73659
73923
  try {
73660
- const raw = JSON.parse(fs25.readFileSync(file, "utf8"));
73924
+ const raw = JSON.parse(fs26.readFileSync(file, "utf8"));
73661
73925
  const result = SlotRegistryEntrySchema.safeParse(raw);
73662
73926
  return result.success ? result.data : void 0;
73663
73927
  } catch {
@@ -73666,9 +73930,9 @@ function readSlotRegistry(repoPath, agentId) {
73666
73930
  }
73667
73931
  function listSlotRegistryEntries(repoPath) {
73668
73932
  const dir = getSlotRegistryDir(repoPath);
73669
- if (!fs25.existsSync(dir)) return [];
73933
+ if (!fs26.existsSync(dir)) return [];
73670
73934
  const entries = [];
73671
- for (const name of fs25.readdirSync(dir)) {
73935
+ for (const name of fs26.readdirSync(dir)) {
73672
73936
  const match = name.match(/^agent-(\d+)\.json$/);
73673
73937
  if (!match) continue;
73674
73938
  const entry = readSlotRegistry(repoPath, Number(match[1]));
@@ -73694,7 +73958,7 @@ function buildLaunchFlagArgs(flags) {
73694
73958
  return args;
73695
73959
  }
73696
73960
  function resolveRepoPath(repoPath) {
73697
- return path25.resolve(repoPath);
73961
+ return path26.resolve(repoPath);
73698
73962
  }
73699
73963
  function buildPreviewUrlsFromPorts(ports, env3) {
73700
73964
  const urls = {};
@@ -73746,14 +74010,14 @@ function substituteAgentId(value, agentId) {
73746
74010
  function resolveStageScriptPath(repoPath, stage) {
73747
74011
  const harnessDir = getHarnessDir(repoPath);
73748
74012
  if (stage.script) {
73749
- return path25.join(harnessDir, stage.script);
74013
+ return path26.join(harnessDir, stage.script);
73750
74014
  }
73751
74015
  if (stage.command) {
73752
74016
  const scriptName = stage.command.split(/\s+/)[0].replace(/^\.\/\.har\//, "").replace(/^\.\//, "");
73753
- return path25.join(harnessDir, scriptName);
74017
+ return path26.join(harnessDir, scriptName);
73754
74018
  }
73755
- const stageScript = path25.join(harnessDir, "stages", `${stage.id}.sh`);
73756
- if (fs26.existsSync(stageScript)) {
74019
+ const stageScript = path26.join(harnessDir, "stages", `${stage.id}.sh`);
74020
+ if (fs27.existsSync(stageScript)) {
73757
74021
  return stageScript;
73758
74022
  }
73759
74023
  throw new Error(
@@ -73768,7 +74032,7 @@ function buildExecutionPlan(repoPath, stage, options) {
73768
74032
  ...harnessEnv,
73769
74033
  ...stage.env ?? {}
73770
74034
  };
73771
- const cwd = stage.cwd ? path25.resolve(resolvedRepo, stage.cwd) : resolvedRepo;
74035
+ const cwd = stage.cwd ? path26.resolve(resolvedRepo, stage.cwd) : resolvedRepo;
73772
74036
  const extraArgs = options.args ?? [];
73773
74037
  const launchFlagArgs = stage.kind === "launch" && options.launchFlags ? buildLaunchFlagArgs(options.launchFlags) : [];
73774
74038
  if (stage.command) {
@@ -73838,19 +74102,19 @@ var LocalScriptExecutor = class {
73838
74102
  const repoPath = resolveRepoPath(ctx.repoPath);
73839
74103
  const harnessDir = getHarnessDir(repoPath);
73840
74104
  const artifactsDirName = getArtifactsDir(repoPath);
73841
- const artifactsDir = path25.join(harnessDir, artifactsDirName);
73842
- if (!fs26.existsSync(artifactsDir)) return [];
74105
+ const artifactsDir = path26.join(harnessDir, artifactsDirName);
74106
+ if (!fs27.existsSync(artifactsDir)) return [];
73843
74107
  const entries = [];
73844
74108
  const walk = (dir, prefix) => {
73845
- for (const entry of fs26.readdirSync(dir, { withFileTypes: true })) {
73846
- const full = path25.join(dir, entry.name);
73847
- const relative3 = path25.join(prefix, entry.name);
74109
+ for (const entry of fs27.readdirSync(dir, { withFileTypes: true })) {
74110
+ const full = path26.join(dir, entry.name);
74111
+ const relative3 = path26.join(prefix, entry.name);
73848
74112
  if (entry.isDirectory()) {
73849
74113
  walk(full, relative3);
73850
74114
  continue;
73851
74115
  }
73852
74116
  if (filter2?.stageId && !relative3.includes(filter2.stageId)) continue;
73853
- const stat = fs26.statSync(full);
74117
+ const stat = fs27.statSync(full);
73854
74118
  entries.push({
73855
74119
  path: full,
73856
74120
  relativePath: relative3,
@@ -73866,19 +74130,19 @@ var LocalScriptExecutor = class {
73866
74130
  var localScriptExecutor = new LocalScriptExecutor();
73867
74131
 
73868
74132
  // src/core/control-sync.ts
73869
- var path43 = __toESM(require("path"));
74133
+ var path44 = __toESM(require("path"));
73870
74134
  init_control_config();
73871
74135
 
73872
74136
  // src/core/control-registry.ts
73873
- var fs29 = __toESM(require("fs"));
74137
+ var fs30 = __toESM(require("fs"));
73874
74138
  var os6 = __toESM(require("os"));
73875
- var path28 = __toESM(require("path"));
74139
+ var path29 = __toESM(require("path"));
73876
74140
 
73877
74141
  // src/core/control-repo-path.ts
73878
- var fs28 = __toESM(require("fs"));
73879
- var path27 = __toESM(require("path"));
74142
+ var fs29 = __toESM(require("fs"));
74143
+ var path28 = __toESM(require("path"));
73880
74144
  function tryGit(cwd, args) {
73881
- if (!fs28.existsSync(cwd)) return void 0;
74145
+ if (!fs29.existsSync(cwd)) return void 0;
73882
74146
  const result = run(`git ${args}`, { cwd });
73883
74147
  return result.code === 0 ? result.stdout.trim() : void 0;
73884
74148
  }
@@ -73886,58 +74150,58 @@ function resolveMainWorkingTree(cwd) {
73886
74150
  const toplevel = tryGit(cwd, "rev-parse --show-toplevel");
73887
74151
  if (!toplevel) return void 0;
73888
74152
  const commonDirRaw = tryGit(cwd, "rev-parse --git-common-dir");
73889
- const commonDir = commonDirRaw ? path27.resolve(cwd, commonDirRaw) : void 0;
73890
- if (!commonDir) return path27.resolve(toplevel);
73891
- if (path27.basename(commonDir) === ".git") {
73892
- return path27.dirname(commonDir);
74153
+ const commonDir = commonDirRaw ? path28.resolve(cwd, commonDirRaw) : void 0;
74154
+ if (!commonDir) return path28.resolve(toplevel);
74155
+ if (path28.basename(commonDir) === ".git") {
74156
+ return path28.dirname(commonDir);
73893
74157
  }
73894
74158
  const porcelain = tryGit(cwd, "worktree list --porcelain");
73895
74159
  if (porcelain) {
73896
74160
  for (const line of porcelain.split("\n")) {
73897
74161
  if (line.startsWith("worktree ")) {
73898
- return path27.resolve(line.slice("worktree ".length));
74162
+ return path28.resolve(line.slice("worktree ".length));
73899
74163
  }
73900
74164
  }
73901
74165
  }
73902
- return path27.resolve(toplevel);
74166
+ return path28.resolve(toplevel);
73903
74167
  }
73904
74168
  function canonicalizeControlRepoPath(repoPath) {
73905
- const resolved = path27.resolve(repoPath);
74169
+ const resolved = path28.resolve(repoPath);
73906
74170
  const toplevel = tryGit(resolved, "rev-parse --show-toplevel");
73907
74171
  if (!toplevel) return resolved;
73908
74172
  const mainRoot = resolveMainWorkingTree(resolved);
73909
74173
  if (!mainRoot) return resolved;
73910
- const top2 = path27.resolve(toplevel);
73911
- const main = path27.resolve(mainRoot);
74174
+ const top2 = path28.resolve(toplevel);
74175
+ const main = path28.resolve(mainRoot);
73912
74176
  if (top2 === main) return resolved;
73913
- const rel = path27.relative(top2, resolved);
74177
+ const rel = path28.relative(top2, resolved);
73914
74178
  if (!rel || rel === ".") return main;
73915
- if (rel.startsWith(`..${path27.sep}`) || rel === ".." || path27.isAbsolute(rel)) {
74179
+ if (rel.startsWith(`..${path28.sep}`) || rel === ".." || path28.isAbsolute(rel)) {
73916
74180
  return resolved;
73917
74181
  }
73918
- return path27.resolve(main, rel);
74182
+ return path28.resolve(main, rel);
73919
74183
  }
73920
74184
 
73921
74185
  // src/core/control-registry.ts
73922
74186
  function getRegistryPath() {
73923
74187
  if (process.env.HAR_CONTROL_REGISTRY_PATH) {
73924
- return path28.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
74188
+ return path29.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
73925
74189
  }
73926
- return path28.join(os6.homedir(), ".har", "repos.json");
74190
+ return path29.join(os6.homedir(), ".har", "repos.json");
73927
74191
  }
73928
74192
  function readRegistry() {
73929
74193
  const registryPath = getRegistryPath();
73930
74194
  try {
73931
- if (!fs29.existsSync(registryPath)) return { repos: [] };
73932
- return JSON.parse(fs29.readFileSync(registryPath, "utf8"));
74195
+ if (!fs30.existsSync(registryPath)) return { repos: [] };
74196
+ return JSON.parse(fs30.readFileSync(registryPath, "utf8"));
73933
74197
  } catch {
73934
74198
  return { repos: [] };
73935
74199
  }
73936
74200
  }
73937
74201
  function writeRegistry(registry2) {
73938
74202
  const registryPath = getRegistryPath();
73939
- fs29.mkdirSync(path28.dirname(registryPath), { recursive: true });
73940
- fs29.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
74203
+ fs30.mkdirSync(path29.dirname(registryPath), { recursive: true });
74204
+ fs30.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
73941
74205
  }
73942
74206
  function registryChanged(before, after) {
73943
74207
  if (before.length !== after.length) return true;
@@ -73959,7 +74223,7 @@ function removeRegisteredRepo(repoPath) {
73959
74223
  try {
73960
74224
  return canonicalizeControlRepoPath(entry) !== resolved;
73961
74225
  } catch {
73962
- return path28.resolve(entry) !== resolved;
74226
+ return path29.resolve(entry) !== resolved;
73963
74227
  }
73964
74228
  });
73965
74229
  if (next.length === registry2.repos.length) return false;
@@ -73971,9 +74235,9 @@ function listRegisteredRepos() {
73971
74235
  const kept = [];
73972
74236
  const seen = /* @__PURE__ */ new Set();
73973
74237
  for (const repoPath of registry2.repos) {
73974
- if (!fs29.existsSync(repoPath)) continue;
74238
+ if (!fs30.existsSync(repoPath)) continue;
73975
74239
  const canonical = canonicalizeControlRepoPath(repoPath);
73976
- if (!fs29.existsSync(canonical) || !readManifest(canonical)) continue;
74240
+ if (!fs30.existsSync(canonical) || !readManifest(canonical)) continue;
73977
74241
  if (seen.has(canonical)) continue;
73978
74242
  seen.add(canonical);
73979
74243
  kept.push(canonical);
@@ -73995,17 +74259,17 @@ function clearRegisteredRepos() {
73995
74259
  init_portal_credentials();
73996
74260
 
73997
74261
  // src/core/slot-status.ts
73998
- var fs34 = __toESM(require("fs"));
74262
+ var fs35 = __toESM(require("fs"));
73999
74263
  var os9 = __toESM(require("os"));
74000
- var path34 = __toESM(require("path"));
74264
+ var path35 = __toESM(require("path"));
74001
74265
  var import_child_process8 = require("child_process");
74002
74266
 
74003
74267
  // src/core/runs.ts
74004
74268
  var crypto2 = __toESM(require("crypto"));
74005
74269
  var import_child_process3 = require("child_process");
74006
- var fs30 = __toESM(require("fs"));
74270
+ var fs31 = __toESM(require("fs"));
74007
74271
  var os7 = __toESM(require("os"));
74008
- var path29 = __toESM(require("path"));
74272
+ var path30 = __toESM(require("path"));
74009
74273
  var RUNS_DIR = "runs";
74010
74274
  function gitCommonDir(cwd) {
74011
74275
  try {
@@ -74014,7 +74278,7 @@ function gitCommonDir(cwd) {
74014
74278
  encoding: "utf8",
74015
74279
  stdio: ["pipe", "pipe", "ignore"]
74016
74280
  }).trim();
74017
- return out ? path29.resolve(cwd, out) : void 0;
74281
+ return out ? path30.resolve(cwd, out) : void 0;
74018
74282
  } catch {
74019
74283
  return void 0;
74020
74284
  }
@@ -74036,7 +74300,7 @@ function gitPrefix(cwd) {
74036
74300
  }
74037
74301
  }
74038
74302
  function getRunsDir(harnessRoot) {
74039
- return path29.join(getHarnessDir(harnessRoot), RUNS_DIR);
74303
+ return path30.join(getHarnessDir(harnessRoot), RUNS_DIR);
74040
74304
  }
74041
74305
  function formatLocalDate(d2) {
74042
74306
  const y2 = d2.getFullYear();
@@ -74056,24 +74320,24 @@ function buildRunRelativePath(stageId, agentId, startedAt, runId, runsDir) {
74056
74320
  const timePart = formatLocalTime(started);
74057
74321
  const agentPart = agentId !== void 0 ? `_agent-${agentId}` : "";
74058
74322
  let filename = `${timePart}_${stageId}${agentPart}.json`;
74059
- const fullPath = path29.join(runsDir, dateFolder, filename);
74060
- if (fs30.existsSync(fullPath)) {
74323
+ const fullPath = path30.join(runsDir, dateFolder, filename);
74324
+ if (fs31.existsSync(fullPath)) {
74061
74325
  filename = `${timePart}_${stageId}${agentPart}-${runId.slice(0, 8)}.json`;
74062
74326
  }
74063
- return path29.join(dateFolder, filename);
74327
+ return path30.join(dateFolder, filename);
74064
74328
  }
74065
74329
  function resolveRunFilePath(harnessRoot, run2) {
74066
74330
  if (run2.relativePath) {
74067
- return path29.join(getRunsDir(harnessRoot), run2.relativePath);
74331
+ return path30.join(getRunsDir(harnessRoot), run2.relativePath);
74068
74332
  }
74069
- return path29.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
74333
+ return path30.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
74070
74334
  }
74071
74335
  function collectRunFiles(runsDir) {
74072
- if (!fs30.existsSync(runsDir)) return [];
74336
+ if (!fs31.existsSync(runsDir)) return [];
74073
74337
  const files = [];
74074
74338
  const walk = (dir) => {
74075
- for (const entry of fs30.readdirSync(dir, { withFileTypes: true })) {
74076
- const full = path29.join(dir, entry.name);
74339
+ for (const entry of fs31.readdirSync(dir, { withFileTypes: true })) {
74340
+ const full = path30.join(dir, entry.name);
74077
74341
  if (entry.isDirectory()) {
74078
74342
  walk(full);
74079
74343
  } else if (entry.name.endsWith(".json")) {
@@ -74087,30 +74351,30 @@ function collectRunFiles(runsDir) {
74087
74351
  function resolveAgentWorkDir(harnessRoot, agentId) {
74088
74352
  if (agentId === void 0) return void 0;
74089
74353
  const entry = readSlotRegistry(harnessRoot, agentId);
74090
- if (entry?.workDir && fs30.existsSync(entry.workDir)) return entry.workDir;
74354
+ if (entry?.workDir && fs31.existsSync(entry.workDir)) return entry.workDir;
74091
74355
  const env3 = readHarnessEnv(harnessRoot);
74092
- const projectName = env3.HARNESS_PROJECT_NAME ?? path29.basename(harnessRoot);
74093
- const worktreeDir = path29.join(os7.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
74356
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path30.basename(harnessRoot);
74357
+ const worktreeDir = path30.join(os7.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
74094
74358
  const relPrefix = gitPrefix(harnessRoot);
74095
74359
  const sessionEnvFiles = [];
74096
- const worktreesRoot = path29.join(os7.homedir(), "worktrees");
74097
- if (fs30.existsSync(worktreesRoot)) {
74360
+ const worktreesRoot = path30.join(os7.homedir(), "worktrees");
74361
+ if (fs31.existsSync(worktreesRoot)) {
74098
74362
  const suffix = `-har-agent-${agentId}-`;
74099
- for (const entry2 of fs30.readdirSync(worktreesRoot, { withFileTypes: true })) {
74363
+ for (const entry2 of fs31.readdirSync(worktreesRoot, { withFileTypes: true })) {
74100
74364
  if (!entry2.isDirectory() || !entry2.name.includes(suffix)) continue;
74101
- const sessionDir = path29.join(worktreesRoot, entry2.name);
74365
+ const sessionDir = path30.join(worktreesRoot, entry2.name);
74102
74366
  if (!sameGitCheckout(harnessRoot, sessionDir)) continue;
74103
- sessionEnvFiles.push(path29.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
74367
+ sessionEnvFiles.push(path30.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
74104
74368
  }
74105
74369
  }
74106
74370
  const candidates = [
74107
- path29.join(worktreeDir, `.env.agent.${agentId}`),
74108
- path29.join(harnessRoot, `.env.agent.${agentId}`),
74371
+ path30.join(worktreeDir, `.env.agent.${agentId}`),
74372
+ path30.join(harnessRoot, `.env.agent.${agentId}`),
74109
74373
  ...sessionEnvFiles.sort()
74110
74374
  ];
74111
74375
  for (const envFile of candidates) {
74112
- if (!fs30.existsSync(envFile)) continue;
74113
- const content = fs30.readFileSync(envFile, "utf8");
74376
+ if (!fs31.existsSync(envFile)) continue;
74377
+ const content = fs31.readFileSync(envFile, "utf8");
74114
74378
  const match = content.match(/^REPO_ROOT=(.+)$/m);
74115
74379
  if (match) return match[1].trim();
74116
74380
  }
@@ -74122,11 +74386,11 @@ function createRun(ctx, meta) {
74122
74386
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
74123
74387
  const runId = crypto2.randomUUID();
74124
74388
  const relativePath = buildRunRelativePath(meta.stageId, meta.agentId, startedAt, runId, runsDir);
74125
- const runFilePath = path29.join(runsDir, relativePath);
74126
- fs30.mkdirSync(path29.dirname(runFilePath), { recursive: true });
74389
+ const runFilePath = path30.join(runsDir, relativePath);
74390
+ fs31.mkdirSync(path30.dirname(runFilePath), { recursive: true });
74127
74391
  const run2 = RunRecordSchema.parse({
74128
74392
  runId,
74129
- repoPath: path29.resolve(ctx.repoPath),
74393
+ repoPath: path30.resolve(ctx.repoPath),
74130
74394
  harnessRoot,
74131
74395
  stageId: meta.stageId,
74132
74396
  kind: meta.kind,
@@ -74139,7 +74403,7 @@ function createRun(ctx, meta) {
74139
74403
  workUnitId: ctx.workUnitId,
74140
74404
  attemptId: ctx.attemptId
74141
74405
  });
74142
- fs30.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
74406
+ fs31.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
74143
74407
  return run2;
74144
74408
  }
74145
74409
  function finishRun(repoPath, runId, update) {
@@ -74158,13 +74422,13 @@ function finishRun(repoPath, runId, update) {
74158
74422
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
74159
74423
  });
74160
74424
  const runPath = resolveRunFilePath(harnessRoot, finished);
74161
- fs30.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
74425
+ fs31.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
74162
74426
  return finished;
74163
74427
  }
74164
74428
  function findRunRecord(harnessRoot, runId) {
74165
74429
  const runsDir = getRunsDir(harnessRoot);
74166
74430
  for (const filePath of collectRunFiles(runsDir)) {
74167
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs30.readFileSync(filePath, "utf8")));
74431
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs31.readFileSync(filePath, "utf8")));
74168
74432
  if (parsed.success && parsed.data.runId === runId) {
74169
74433
  return parsed.data;
74170
74434
  }
@@ -74176,10 +74440,10 @@ function getRun(repoPath, runId) {
74176
74440
  }
74177
74441
  function listRuns(repoPath, filter2 = {}) {
74178
74442
  const runsDir = getRunsDir(resolveHarnessRoot(repoPath));
74179
- if (!fs30.existsSync(runsDir)) return [];
74443
+ if (!fs31.existsSync(runsDir)) return [];
74180
74444
  const runs = [];
74181
74445
  for (const filePath of collectRunFiles(runsDir)) {
74182
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs30.readFileSync(filePath, "utf8")));
74446
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs31.readFileSync(filePath, "utf8")));
74183
74447
  if (!parsed.success) continue;
74184
74448
  if (filter2.stageId && parsed.data.stageId !== filter2.stageId) continue;
74185
74449
  runs.push(parsed.data);
@@ -74192,18 +74456,18 @@ function listRuns(repoPath, filter2 = {}) {
74192
74456
  }
74193
74457
 
74194
74458
  // src/core/slot-preflight.ts
74195
- var path33 = __toESM(require("path"));
74459
+ var path34 = __toESM(require("path"));
74196
74460
 
74197
74461
  // src/core/control-port.ts
74198
74462
  var import_child_process5 = require("child_process");
74199
- var fs32 = __toESM(require("fs"));
74200
- var path31 = __toESM(require("path"));
74463
+ var fs33 = __toESM(require("fs"));
74464
+ var path32 = __toESM(require("path"));
74201
74465
  init_control_config();
74202
74466
 
74203
74467
  // src/core/slot-ports.ts
74204
74468
  var import_child_process4 = require("child_process");
74205
- var fs31 = __toESM(require("fs"));
74206
- var path30 = __toESM(require("path"));
74469
+ var fs32 = __toESM(require("fs"));
74470
+ var path31 = __toESM(require("path"));
74207
74471
  function portStep(env3) {
74208
74472
  return Number(env3.HARNESS_PORT_STEP ?? 10);
74209
74473
  }
@@ -74259,7 +74523,7 @@ function allocateAppPorts(repoPath, agentId) {
74259
74523
  }
74260
74524
  function harnessUsesPm2(repoPath) {
74261
74525
  const harnessRoot = resolveHarnessRoot(repoPath);
74262
- return fs31.existsSync(path30.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
74526
+ return fs32.existsSync(path31.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
74263
74527
  }
74264
74528
 
74265
74529
  // src/core/control-port.ts
@@ -74314,13 +74578,13 @@ function controlDefaultPortWarnings(containers, defaultFrontendPort, allocatedFr
74314
74578
  return [formatControlDefaultPortWarning(control.name, defaultFrontendPort, allocatedFrontend)];
74315
74579
  }
74316
74580
  function inspectControlUpReadiness(repoPath) {
74317
- const resolved = path31.resolve(repoPath);
74581
+ const resolved = path32.resolve(repoPath);
74318
74582
  const port = parseControlHostPort();
74319
74583
  const containers = listDockerContainers();
74320
74584
  const control = controlContainerOnPort(containers, port);
74321
74585
  const warnings = [];
74322
- const controlHarnessDir = path31.join(resolved, "control", ".har");
74323
- const harnessSlot1Active = fs32.existsSync(controlHarnessDir) && readSlotRegistry(path31.join(resolved, "control"), 1)?.status === "active";
74586
+ const controlHarnessDir = path32.join(resolved, "control", ".har");
74587
+ const harnessSlot1Active = fs33.existsSync(controlHarnessDir) && readSlotRegistry(path32.join(resolved, "control"), 1)?.status === "active";
74324
74588
  if (control) {
74325
74589
  return {
74326
74590
  warnings,
@@ -74351,9 +74615,9 @@ function inspectControlUpReadiness(repoPath) {
74351
74615
  }
74352
74616
 
74353
74617
  // src/core/slot-launch-guard-occupied.ts
74354
- var fs33 = __toESM(require("fs"));
74618
+ var fs34 = __toESM(require("fs"));
74355
74619
  var os8 = __toESM(require("os"));
74356
- var path32 = __toESM(require("path"));
74620
+ var path33 = __toESM(require("path"));
74357
74621
  var import_child_process6 = require("child_process");
74358
74622
  function runGit(cwd, args) {
74359
74623
  try {
@@ -74372,7 +74636,7 @@ function worktreeDirty(worktreePath) {
74372
74636
  }
74373
74637
  function gitCommonDir2(cwd) {
74374
74638
  const out = runGit(cwd, "rev-parse --git-common-dir");
74375
- return out ? path32.resolve(cwd, out) : void 0;
74639
+ return out ? path33.resolve(cwd, out) : void 0;
74376
74640
  }
74377
74641
  function sameGitCheckout2(a2, b3) {
74378
74642
  const left2 = gitCommonDir2(a2);
@@ -74381,20 +74645,20 @@ function sameGitCheckout2(a2, b3) {
74381
74645
  }
74382
74646
  function discoverWorktree(harnessRoot, agentId, projectName) {
74383
74647
  const session = readSlotRegistry(harnessRoot, agentId);
74384
- if (session?.worktreePath && fs33.existsSync(session.worktreePath)) {
74648
+ if (session?.worktreePath && fs34.existsSync(session.worktreePath)) {
74385
74649
  return session.worktreePath;
74386
74650
  }
74387
- const legacy = path32.join(os8.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
74388
- if (fs33.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
74389
- const worktreesRoot = path32.join(os8.homedir(), "worktrees");
74390
- if (!fs33.existsSync(worktreesRoot)) return void 0;
74651
+ const legacy = path33.join(os8.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
74652
+ if (fs34.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
74653
+ const worktreesRoot = path33.join(os8.homedir(), "worktrees");
74654
+ if (!fs34.existsSync(worktreesRoot)) return void 0;
74391
74655
  const suffix = `-har-agent-${agentId}-`;
74392
74656
  const relPrefix = runGit(harnessRoot, "rev-parse --show-prefix") ?? "";
74393
- for (const name of fs33.readdirSync(worktreesRoot)) {
74657
+ for (const name of fs34.readdirSync(worktreesRoot)) {
74394
74658
  if (!name.includes(suffix)) continue;
74395
- const candidate = path32.join(worktreesRoot, name);
74659
+ const candidate = path33.join(worktreesRoot, name);
74396
74660
  if (!sameGitCheckout2(harnessRoot, candidate)) continue;
74397
- if (!fs33.existsSync(path32.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
74661
+ if (!fs34.existsSync(path33.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
74398
74662
  return candidate;
74399
74663
  }
74400
74664
  return void 0;
@@ -74402,13 +74666,13 @@ function discoverWorktree(harnessRoot, agentId, projectName) {
74402
74666
  function collectOccupiedSlot(repoPath, agentId) {
74403
74667
  const harnessRoot = resolveHarnessRoot(repoPath);
74404
74668
  const env3 = readHarnessEnv(harnessRoot);
74405
- const projectName = env3.HARNESS_PROJECT_NAME ?? path32.basename(harnessRoot);
74669
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path33.basename(harnessRoot);
74406
74670
  const session = readSlotRegistry(harnessRoot, agentId);
74407
74671
  const worktreePath = discoverWorktree(harnessRoot, agentId, projectName);
74408
74672
  const workDir = session?.workDir;
74409
- const envInWorkDir = workDir ? fs33.existsSync(path32.join(workDir, `.env.agent.${agentId}`)) : false;
74410
- const envInRoot = fs33.existsSync(path32.join(harnessRoot, `.env.agent.${agentId}`));
74411
- const envInWorktree = worktreePath ? fs33.existsSync(path32.join(worktreePath, `.env.agent.${agentId}`)) : false;
74673
+ const envInWorkDir = workDir ? fs34.existsSync(path33.join(workDir, `.env.agent.${agentId}`)) : false;
74674
+ const envInRoot = fs34.existsSync(path33.join(harnessRoot, `.env.agent.${agentId}`));
74675
+ const envInWorktree = worktreePath ? fs34.existsSync(path33.join(worktreePath, `.env.agent.${agentId}`)) : false;
74412
74676
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
74413
74677
  if (!active) return void 0;
74414
74678
  const dirty = worktreePath ? worktreeDirty(worktreePath) : void 0;
@@ -74574,7 +74838,7 @@ function checkInfraPort(env3, varName, defaultPort, scanStart, scanEnd) {
74574
74838
  function inspectSlotReadiness(repoPath, agentId, options = {}) {
74575
74839
  const harnessRoot = resolveHarnessRoot(repoPath);
74576
74840
  const env3 = readHarnessEnv(harnessRoot);
74577
- const projectName = env3.HARNESS_PROJECT_NAME ?? path33.basename(harnessRoot);
74841
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path34.basename(harnessRoot);
74578
74842
  const usesPm2 = harnessUsesPm2(repoPath);
74579
74843
  const blockers = [];
74580
74844
  const remediations = [];
@@ -74776,7 +75040,7 @@ function readWorktreeBranch(worktreePath) {
74776
75040
  }
74777
75041
  function gitCommonDir3(cwd) {
74778
75042
  const out = runGit2(cwd, "rev-parse --git-common-dir");
74779
- return out ? path34.resolve(cwd, out) : void 0;
75043
+ return out ? path35.resolve(cwd, out) : void 0;
74780
75044
  }
74781
75045
  function sameGitCheckout3(a2, b3) {
74782
75046
  const left2 = gitCommonDir3(a2);
@@ -74788,12 +75052,12 @@ function gitPrefix2(cwd) {
74788
75052
  return out ?? "";
74789
75053
  }
74790
75054
  function discoverSessionWorktreePath(harnessRoot, agentId) {
74791
- const worktreesRoot = path34.join(os9.homedir(), "worktrees");
74792
- if (!fs34.existsSync(worktreesRoot)) return void 0;
75055
+ const worktreesRoot = path35.join(os9.homedir(), "worktrees");
75056
+ if (!fs35.existsSync(worktreesRoot)) return void 0;
74793
75057
  const suffix = `-har-agent-${agentId}-`;
74794
75058
  const relPrefix = gitPrefix2(harnessRoot);
74795
- const matches = fs34.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path34.join(worktreesRoot, entry.name)).filter(
74796
- (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs34.existsSync(path34.join(candidate, relPrefix, `.env.agent.${agentId}`))
75059
+ const matches = fs35.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path35.join(worktreesRoot, entry.name)).filter(
75060
+ (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs35.existsSync(path35.join(candidate, relPrefix, `.env.agent.${agentId}`))
74797
75061
  );
74798
75062
  return matches.sort()[0];
74799
75063
  }
@@ -74868,18 +75132,18 @@ function detectPm2Issue(projectName, agentId, session, procs) {
74868
75132
  }
74869
75133
  function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
74870
75134
  const env3 = readHarnessEnv(harnessRoot);
74871
- const projectName = env3.HARNESS_PROJECT_NAME ?? path34.basename(harnessRoot);
75135
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path35.basename(harnessRoot);
74872
75136
  const session = readSlotRegistry(harnessRoot, agentId);
74873
- const legacyWorktreePath = path34.join(
75137
+ const legacyWorktreePath = path35.join(
74874
75138
  os9.homedir(),
74875
75139
  "worktrees",
74876
75140
  `${projectName}-agent-${agentId}`
74877
75141
  );
74878
- const worktreePath = session?.worktreePath && fs34.existsSync(session.worktreePath) ? session.worktreePath : fs34.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
75142
+ const worktreePath = session?.worktreePath && fs35.existsSync(session.worktreePath) ? session.worktreePath : fs35.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
74879
75143
  const workDir = resolveAgentWorkDir(harnessRoot, agentId);
74880
- const envInWorkDir = workDir ? fs34.existsSync(path34.join(workDir, `.env.agent.${agentId}`)) : false;
74881
- const envInRoot = fs34.existsSync(path34.join(harnessRoot, `.env.agent.${agentId}`));
74882
- const envInWorktree = worktreePath ? fs34.existsSync(path34.join(worktreePath, `.env.agent.${agentId}`)) : false;
75144
+ const envInWorkDir = workDir ? fs35.existsSync(path35.join(workDir, `.env.agent.${agentId}`)) : false;
75145
+ const envInRoot = fs35.existsSync(path35.join(harnessRoot, `.env.agent.${agentId}`));
75146
+ const envInWorktree = worktreePath ? fs35.existsSync(path35.join(worktreePath, `.env.agent.${agentId}`)) : false;
74883
75147
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
74884
75148
  const latest = latestRunForAgent(runs, agentId);
74885
75149
  const verifyRun = runs.find((r2) => r2.agentId === agentId && r2.stageId === "verify");
@@ -74933,7 +75197,7 @@ function collectEnvironmentStatus(repoPath) {
74933
75197
  const slotIds = getAgentSlotIds(harnessRoot);
74934
75198
  const pm2Procs = listPm2Processes2();
74935
75199
  return {
74936
- repoPath: path34.resolve(repoPath),
75200
+ repoPath: path35.resolve(repoPath),
74937
75201
  harnessRoot,
74938
75202
  gitRemote: readGitRemote(harnessRoot),
74939
75203
  profile: manifest?.profile,
@@ -74944,13 +75208,13 @@ function collectEnvironmentStatus(repoPath) {
74944
75208
 
74945
75209
  // src/core/validations.ts
74946
75210
  var crypto3 = __toESM(require("crypto"));
74947
- var fs36 = __toESM(require("fs"));
74948
- var path36 = __toESM(require("path"));
75211
+ var fs37 = __toESM(require("fs"));
75212
+ var path37 = __toESM(require("path"));
74949
75213
 
74950
75214
  // src/core/change-batch.ts
74951
- var fs35 = __toESM(require("fs"));
75215
+ var fs36 = __toESM(require("fs"));
74952
75216
  var os10 = __toESM(require("os"));
74953
- var path35 = __toESM(require("path"));
75217
+ var path36 = __toESM(require("path"));
74954
75218
  function git(checkoutDir, args, env3) {
74955
75219
  const result = run(`git ${args}`, { cwd: checkoutDir, env: env3 });
74956
75220
  if (result.code !== 0) {
@@ -74966,7 +75230,7 @@ function isCheckoutRoot(checkoutDir) {
74966
75230
  const toplevel = tryGit2(checkoutDir, "rev-parse --show-toplevel");
74967
75231
  if (!toplevel) return false;
74968
75232
  try {
74969
- return fs35.realpathSync(toplevel) === fs35.realpathSync(checkoutDir);
75233
+ return fs36.realpathSync(toplevel) === fs36.realpathSync(checkoutDir);
74970
75234
  } catch {
74971
75235
  return false;
74972
75236
  }
@@ -74988,7 +75252,7 @@ function isMergeOrRebaseInProgress(checkoutDir) {
74988
75252
  if (tryGit2(checkoutDir, "rev-parse -q --verify MERGE_HEAD") !== void 0) return true;
74989
75253
  for (const dir of ["rebase-merge", "rebase-apply"]) {
74990
75254
  const gitPath = tryGit2(checkoutDir, `rev-parse --git-path ${dir}`);
74991
- if (gitPath && fs35.existsSync(path35.resolve(checkoutDir, gitPath))) return true;
75255
+ if (gitPath && fs36.existsSync(path36.resolve(checkoutDir, gitPath))) return true;
74992
75256
  }
74993
75257
  return false;
74994
75258
  }
@@ -75011,8 +75275,8 @@ function parseNameStatus(output) {
75011
75275
  return files;
75012
75276
  }
75013
75277
  function computeWorktreeSnapshot(checkoutDir) {
75014
- const tmpDir = fs35.mkdtempSync(path35.join(os10.tmpdir(), "har-idx-"));
75015
- const tmpIndex = path35.join(tmpDir, "index");
75278
+ const tmpDir = fs36.mkdtempSync(path36.join(os10.tmpdir(), "har-idx-"));
75279
+ const tmpIndex = path36.join(tmpDir, "index");
75016
75280
  const env3 = { GIT_INDEX_FILE: tmpIndex };
75017
75281
  try {
75018
75282
  const headTree = getHeadTree(checkoutDir);
@@ -75035,7 +75299,7 @@ function computeWorktreeSnapshot(checkoutDir) {
75035
75299
  changedFiles: parseNameStatus(diffOutput)
75036
75300
  };
75037
75301
  } finally {
75038
- fs35.rmSync(tmpDir, { recursive: true, force: true });
75302
+ fs36.rmSync(tmpDir, { recursive: true, force: true });
75039
75303
  }
75040
75304
  }
75041
75305
 
@@ -75048,28 +75312,28 @@ function resolveValidationCheckoutDir(input) {
75048
75312
  return candidates.find(isCheckoutRoot) ?? candidates[0] ?? input.harnessRoot;
75049
75313
  }
75050
75314
  function getValidationsDir(checkoutDir) {
75051
- return path36.join(checkoutDir, ".har", VALIDATIONS_DIR);
75315
+ return path37.join(checkoutDir, ".har", VALIDATIONS_DIR);
75052
75316
  }
75053
75317
  function validationPath(checkoutDir, treeHash) {
75054
- return path36.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
75318
+ return path37.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
75055
75319
  }
75056
75320
  function writeRecord(checkoutDir, record2) {
75057
75321
  const dir = getValidationsDir(checkoutDir);
75058
- fs36.mkdirSync(dir, { recursive: true });
75059
- fs36.writeFileSync(
75322
+ fs37.mkdirSync(dir, { recursive: true });
75323
+ fs37.writeFileSync(
75060
75324
  validationPath(checkoutDir, record2.treeHash),
75061
75325
  `${JSON.stringify(record2, null, 2)}
75062
75326
  `
75063
75327
  );
75064
75328
  }
75065
75329
  function ensureValidationsIgnored(checkoutDir) {
75066
- const harDir = path36.join(checkoutDir, ".har");
75067
- if (!fs36.existsSync(harDir)) return;
75068
- const gitignorePath = path36.join(harDir, ".gitignore");
75069
- const content = fs36.existsSync(gitignorePath) ? fs36.readFileSync(gitignorePath, "utf8") : "";
75330
+ const harDir = path37.join(checkoutDir, ".har");
75331
+ if (!fs37.existsSync(harDir)) return;
75332
+ const gitignorePath = path37.join(harDir, ".gitignore");
75333
+ const content = fs37.existsSync(gitignorePath) ? fs37.readFileSync(gitignorePath, "utf8") : "";
75070
75334
  if (content.split("\n").some((line) => line.trim() === `${VALIDATIONS_DIR}/`)) return;
75071
75335
  const suffix = content.length === 0 || content.endsWith("\n") ? "" : "\n";
75072
- fs36.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
75336
+ fs37.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
75073
75337
  `);
75074
75338
  }
75075
75339
  function recordValidation(input) {
@@ -75086,8 +75350,8 @@ function recordValidation(input) {
75086
75350
  treeHash: snapshot.treeHash,
75087
75351
  headSha: snapshot.headSha,
75088
75352
  branch: snapshot.branch,
75089
- workDir: path36.resolve(input.checkoutDir),
75090
- harnessRoot: path36.resolve(input.harnessRoot),
75353
+ workDir: path37.resolve(input.checkoutDir),
75354
+ harnessRoot: path37.resolve(input.harnessRoot),
75091
75355
  agentId: input.agentId,
75092
75356
  status: input.status,
75093
75357
  full: input.full,
@@ -75099,16 +75363,16 @@ function recordValidation(input) {
75099
75363
  committedAt: existing?.committedAt
75100
75364
  });
75101
75365
  writeRecord(input.checkoutDir, record2);
75102
- if (path36.resolve(input.harnessRoot) !== path36.resolve(input.checkoutDir)) {
75366
+ if (path37.resolve(input.harnessRoot) !== path37.resolve(input.checkoutDir)) {
75103
75367
  writeRecord(input.harnessRoot, record2);
75104
75368
  }
75105
75369
  return record2;
75106
75370
  }
75107
75371
  function findValidation(checkoutDir, treeHash) {
75108
75372
  const file = validationPath(checkoutDir, treeHash);
75109
- if (!fs36.existsSync(file)) return void 0;
75373
+ if (!fs37.existsSync(file)) return void 0;
75110
75374
  try {
75111
- return ValidationRecordSchema.parse(JSON.parse(fs36.readFileSync(file, "utf8")));
75375
+ return ValidationRecordSchema.parse(JSON.parse(fs37.readFileSync(file, "utf8")));
75112
75376
  } catch {
75113
75377
  return void 0;
75114
75378
  }
@@ -75123,19 +75387,19 @@ function attachCommit(checkoutDir, treeHash, commitSha) {
75123
75387
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
75124
75388
  };
75125
75389
  writeRecord(checkoutDir, updated);
75126
- if (record2.harnessRoot && path36.resolve(record2.harnessRoot) !== path36.resolve(checkoutDir) && fs36.existsSync(path36.join(record2.harnessRoot, ".har"))) {
75390
+ if (record2.harnessRoot && path37.resolve(record2.harnessRoot) !== path37.resolve(checkoutDir) && fs37.existsSync(path37.join(record2.harnessRoot, ".har"))) {
75127
75391
  writeRecord(record2.harnessRoot, updated);
75128
75392
  }
75129
75393
  return updated;
75130
75394
  }
75131
75395
  function listValidations(harnessRoot) {
75132
75396
  const dir = getValidationsDir(harnessRoot);
75133
- if (!fs36.existsSync(dir)) return [];
75397
+ if (!fs37.existsSync(dir)) return [];
75134
75398
  const records = [];
75135
- for (const entry of fs36.readdirSync(dir)) {
75399
+ for (const entry of fs37.readdirSync(dir)) {
75136
75400
  if (!entry.endsWith(".json")) continue;
75137
75401
  try {
75138
- records.push(ValidationRecordSchema.parse(JSON.parse(fs36.readFileSync(path36.join(dir, entry), "utf8"))));
75402
+ records.push(ValidationRecordSchema.parse(JSON.parse(fs37.readFileSync(path37.join(dir, entry), "utf8"))));
75139
75403
  } catch {
75140
75404
  }
75141
75405
  }
@@ -75144,46 +75408,46 @@ function listValidations(harnessRoot) {
75144
75408
 
75145
75409
  // src/core/work-units.ts
75146
75410
  var crypto4 = __toESM(require("crypto"));
75147
- var fs37 = __toESM(require("fs"));
75148
- var path37 = __toESM(require("path"));
75411
+ var fs38 = __toESM(require("fs"));
75412
+ var path38 = __toESM(require("path"));
75149
75413
  var WORK_UNITS_DIR = "work-units";
75150
75414
  var WORK_ATTEMPTS_DIR = "work-attempts";
75151
75415
  var VALIDATION_BINDINGS_DIR = "validation-bindings";
75152
75416
  var EVIDENCE_DIRS = [WORK_UNITS_DIR, WORK_ATTEMPTS_DIR, VALIDATION_BINDINGS_DIR];
75153
75417
  function harEvidenceDir(harnessRoot, name) {
75154
- return path37.join(harnessRoot, ".har", name);
75418
+ return path38.join(harnessRoot, ".har", name);
75155
75419
  }
75156
75420
  function hashedRecordPath(harnessRoot, dir, id) {
75157
75421
  const digest = crypto4.createHash("sha256").update(id).digest("hex");
75158
- return path37.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
75422
+ return path38.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
75159
75423
  }
75160
75424
  function writeRecord2(file, value) {
75161
- fs37.mkdirSync(path37.dirname(file), { recursive: true });
75425
+ fs38.mkdirSync(path38.dirname(file), { recursive: true });
75162
75426
  const temp = `${file}.${process.pid}.tmp`;
75163
- fs37.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
75427
+ fs38.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
75164
75428
  `);
75165
- fs37.renameSync(temp, file);
75429
+ fs38.renameSync(temp, file);
75166
75430
  }
75167
75431
  function ensureWorkEvidenceIgnored(harnessRoot) {
75168
- const harDir = path37.join(harnessRoot, ".har");
75169
- if (!fs37.existsSync(harDir)) return;
75170
- const gitignorePath = path37.join(harDir, ".gitignore");
75171
- const content = fs37.existsSync(gitignorePath) ? fs37.readFileSync(gitignorePath, "utf8") : "";
75432
+ const harDir = path38.join(harnessRoot, ".har");
75433
+ if (!fs38.existsSync(harDir)) return;
75434
+ const gitignorePath = path38.join(harDir, ".gitignore");
75435
+ const content = fs38.existsSync(gitignorePath) ? fs38.readFileSync(gitignorePath, "utf8") : "";
75172
75436
  const lines2 = new Set(content.split("\n").map((line) => line.trim()));
75173
75437
  const missing = EVIDENCE_DIRS.map((dir) => `${dir}/`).filter((dir) => !lines2.has(dir));
75174
75438
  if (missing.length === 0) return;
75175
75439
  const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
75176
- fs37.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
75440
+ fs38.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
75177
75441
  `);
75178
75442
  }
75179
75443
  function listRecords(harnessRoot, dir, parse4) {
75180
75444
  const recordDir = harEvidenceDir(harnessRoot, dir);
75181
- if (!fs37.existsSync(recordDir)) return [];
75445
+ if (!fs38.existsSync(recordDir)) return [];
75182
75446
  const records = [];
75183
- for (const name of fs37.readdirSync(recordDir)) {
75447
+ for (const name of fs38.readdirSync(recordDir)) {
75184
75448
  if (!name.endsWith(".json")) continue;
75185
75449
  try {
75186
- records.push(parse4(JSON.parse(fs37.readFileSync(path37.join(recordDir, name), "utf8"))));
75450
+ records.push(parse4(JSON.parse(fs38.readFileSync(path38.join(recordDir, name), "utf8"))));
75187
75451
  } catch {
75188
75452
  }
75189
75453
  }
@@ -75192,9 +75456,9 @@ function listRecords(harnessRoot, dir, parse4) {
75192
75456
  function findWorkUnit(harnessRoot, workUnitId) {
75193
75457
  const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
75194
75458
  const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
75195
- if (!fs37.existsSync(file)) return void 0;
75459
+ if (!fs38.existsSync(file)) return void 0;
75196
75460
  try {
75197
- return WorkUnitRecordSchema.parse(JSON.parse(fs37.readFileSync(file, "utf8")));
75461
+ return WorkUnitRecordSchema.parse(JSON.parse(fs38.readFileSync(file, "utf8")));
75198
75462
  } catch {
75199
75463
  return void 0;
75200
75464
  }
@@ -75271,10 +75535,10 @@ function bindValidationToAttempt(harnessRoot, input) {
75271
75535
  VALIDATION_BINDINGS_DIR,
75272
75536
  stableKey
75273
75537
  );
75274
- if (fs37.existsSync(existingFile)) {
75538
+ if (fs38.existsSync(existingFile)) {
75275
75539
  try {
75276
75540
  return ValidationBindingRecordSchema.parse(
75277
- JSON.parse(fs37.readFileSync(existingFile, "utf8"))
75541
+ JSON.parse(fs38.readFileSync(existingFile, "utf8"))
75278
75542
  );
75279
75543
  } catch {
75280
75544
  }
@@ -75335,14 +75599,14 @@ function createRemoteExecutor(apiUrl, apiKey) {
75335
75599
  init_telemetry_config();
75336
75600
 
75337
75601
  // src/core/usage-harvest/claude.ts
75338
- var fs39 = __toESM(require("fs"));
75602
+ var fs40 = __toESM(require("fs"));
75339
75603
  var os11 = __toESM(require("os"));
75340
- var path39 = __toESM(require("path"));
75604
+ var path40 = __toESM(require("path"));
75341
75605
  init_telemetry_config();
75342
75606
 
75343
75607
  // src/core/telemetry-env.ts
75344
- var fs38 = __toESM(require("fs"));
75345
- var path38 = __toESM(require("path"));
75608
+ var fs39 = __toESM(require("fs"));
75609
+ var path39 = __toESM(require("path"));
75346
75610
  init_control_config();
75347
75611
  function escapeAttrValue(value) {
75348
75612
  return value.replace(/[,=]/g, "_");
@@ -75388,8 +75652,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
75388
75652
  ${TELEMETRY_MARKER_END}
75389
75653
  `;
75390
75654
  let existing = "";
75391
- if (fs38.existsSync(envFilePath)) {
75392
- existing = fs38.readFileSync(envFilePath, "utf8");
75655
+ if (fs39.existsSync(envFilePath)) {
75656
+ existing = fs39.readFileSync(envFilePath, "utf8");
75393
75657
  const start = existing.indexOf(TELEMETRY_MARKER_START);
75394
75658
  if (start >= 0) {
75395
75659
  const end = existing.indexOf(TELEMETRY_MARKER_END, start);
@@ -75400,28 +75664,28 @@ ${TELEMETRY_MARKER_END}
75400
75664
  }
75401
75665
  }
75402
75666
  }
75403
- fs38.mkdirSync(path38.dirname(envFilePath), { recursive: true });
75667
+ fs39.mkdirSync(path39.dirname(envFilePath), { recursive: true });
75404
75668
  const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
75405
- fs38.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
75669
+ fs39.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
75406
75670
  }
75407
75671
 
75408
75672
  // src/core/usage-harvest/claude.ts
75409
75673
  function pathsMatch(candidate, targets) {
75410
- const norm = path39.resolve(candidate);
75674
+ const norm = path40.resolve(candidate);
75411
75675
  return targets.some((t2) => {
75412
- const target = path39.resolve(t2);
75413
- return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
75676
+ const target = path40.resolve(t2);
75677
+ return norm === target || norm.startsWith(target + path40.sep) || target.startsWith(norm + path40.sep);
75414
75678
  });
75415
75679
  }
75416
75680
  function claudeProjectsRoot() {
75417
- return process.env.HAR_CLAUDE_PROJECTS_DIR ? path39.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path39.join(os11.homedir(), ".claude", "projects");
75681
+ return process.env.HAR_CLAUDE_PROJECTS_DIR ? path40.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path40.join(os11.homedir(), ".claude", "projects");
75418
75682
  }
75419
75683
  function encodeClaudeProjectDir(cwd) {
75420
75684
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
75421
75685
  }
75422
75686
  function readJsonlRecords(filePath) {
75423
- if (!fs39.existsSync(filePath)) return [];
75424
- const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
75687
+ if (!fs40.existsSync(filePath)) return [];
75688
+ const lines2 = fs40.readFileSync(filePath, "utf8").split(/\r?\n/);
75425
75689
  const out = [];
75426
75690
  for (const line of lines2) {
75427
75691
  const trimmed = line.trim();
@@ -75485,16 +75749,16 @@ function findMatchingClaudeTranscripts(slot) {
75485
75749
  const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
75486
75750
  if (targets.length === 0) return [];
75487
75751
  const root = claudeProjectsRoot();
75488
- if (!fs39.existsSync(root)) return [];
75752
+ if (!fs40.existsSync(root)) return [];
75489
75753
  const matches = [];
75490
- for (const entry of fs39.readdirSync(root, { withFileTypes: true })) {
75754
+ for (const entry of fs40.readdirSync(root, { withFileTypes: true })) {
75491
75755
  if (!entry.isDirectory()) continue;
75492
- const projectDir = path39.join(root, entry.name);
75756
+ const projectDir = path40.join(root, entry.name);
75493
75757
  const encodedHit = targets.some((t2) => entry.name.includes(encodeClaudeProjectDir(t2).slice(0, 40)));
75494
- for (const file of fs39.readdirSync(projectDir)) {
75758
+ for (const file of fs40.readdirSync(projectDir)) {
75495
75759
  if (!file.endsWith(".jsonl")) continue;
75496
- const filePath = path39.join(projectDir, file);
75497
- const stat = fs39.statSync(filePath);
75760
+ const filePath = path40.join(projectDir, file);
75761
+ const stat = fs40.statSync(filePath);
75498
75762
  const records = readJsonlRecords(filePath);
75499
75763
  let cwdHit = encodedHit;
75500
75764
  for (const record2 of records) {
@@ -75606,30 +75870,30 @@ function harvestClaudeEvents(slot) {
75606
75870
  }
75607
75871
 
75608
75872
  // src/core/usage-harvest/codex.ts
75609
- var fs40 = __toESM(require("fs"));
75873
+ var fs41 = __toESM(require("fs"));
75610
75874
  var os12 = __toESM(require("os"));
75611
- var path40 = __toESM(require("path"));
75875
+ var path41 = __toESM(require("path"));
75612
75876
  function pathsMatch2(candidate, targets) {
75613
- const norm = path40.resolve(candidate);
75877
+ const norm = path41.resolve(candidate);
75614
75878
  return targets.some((t2) => {
75615
- const target = path40.resolve(t2);
75616
- return norm === target || norm.startsWith(target + path40.sep) || target.startsWith(norm + path40.sep);
75879
+ const target = path41.resolve(t2);
75880
+ return norm === target || norm.startsWith(target + path41.sep) || target.startsWith(norm + path41.sep);
75617
75881
  });
75618
75882
  }
75619
75883
  function codexSessionsRoot() {
75620
- return process.env.HAR_CODEX_SESSIONS_DIR ? path40.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path40.join(os12.homedir(), ".codex", "sessions");
75884
+ return process.env.HAR_CODEX_SESSIONS_DIR ? path41.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path41.join(os12.homedir(), ".codex", "sessions");
75621
75885
  }
75622
75886
  function walkJsonlFiles(dir, out = []) {
75623
- if (!fs40.existsSync(dir)) return out;
75624
- for (const entry of fs40.readdirSync(dir, { withFileTypes: true })) {
75625
- const full = path40.join(dir, entry.name);
75887
+ if (!fs41.existsSync(dir)) return out;
75888
+ for (const entry of fs41.readdirSync(dir, { withFileTypes: true })) {
75889
+ const full = path41.join(dir, entry.name);
75626
75890
  if (entry.isDirectory()) walkJsonlFiles(full, out);
75627
75891
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
75628
75892
  }
75629
75893
  return out;
75630
75894
  }
75631
75895
  function readJsonl(filePath) {
75632
- const lines2 = fs40.readFileSync(filePath, "utf8").split(/\r?\n/);
75896
+ const lines2 = fs41.readFileSync(filePath, "utf8").split(/\r?\n/);
75633
75897
  const out = [];
75634
75898
  for (const line of lines2) {
75635
75899
  const trimmed = line.trim();
@@ -75693,7 +75957,7 @@ function harvestCodexUsage(slot) {
75693
75957
  const extracted = extractCodexTokens(records);
75694
75958
  if (!extracted.cwd || !pathsMatch2(extracted.cwd, targets)) continue;
75695
75959
  if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
75696
- const mtime = fs40.statSync(file).mtimeMs;
75960
+ const mtime = fs41.statSync(file).mtimeMs;
75697
75961
  if (mtime >= bestMtime) {
75698
75962
  bestMtime = mtime;
75699
75963
  best = extracted;
@@ -75735,23 +75999,23 @@ function harvestEventsForSlot(slot) {
75735
75999
  }
75736
76000
 
75737
76001
  // src/core/control-persisted-usage.ts
75738
- var path42 = __toESM(require("path"));
76002
+ var path43 = __toESM(require("path"));
75739
76003
 
75740
76004
  // src/core/portal-watermark.ts
75741
- var fs41 = __toESM(require("fs"));
76005
+ var fs42 = __toESM(require("fs"));
75742
76006
  var os13 = __toESM(require("os"));
75743
- var path41 = __toESM(require("path"));
76007
+ var path42 = __toESM(require("path"));
75744
76008
  function getStatePath() {
75745
76009
  if (process.env.HAR_PORTAL_SYNC_STATE_PATH) {
75746
- return path41.resolve(process.env.HAR_PORTAL_SYNC_STATE_PATH);
76010
+ return path42.resolve(process.env.HAR_PORTAL_SYNC_STATE_PATH);
75747
76011
  }
75748
- return path41.join(os13.homedir(), ".har", "portal-sync-state.json");
76012
+ return path42.join(os13.homedir(), ".har", "portal-sync-state.json");
75749
76013
  }
75750
76014
  function readState() {
75751
76015
  const statePath = getStatePath();
75752
76016
  try {
75753
- if (!fs41.existsSync(statePath)) return { states: [] };
75754
- const parsed = JSON.parse(fs41.readFileSync(statePath, "utf8"));
76017
+ if (!fs42.existsSync(statePath)) return { states: [] };
76018
+ const parsed = JSON.parse(fs42.readFileSync(statePath, "utf8"));
75755
76019
  return Array.isArray(parsed.states) ? parsed : { states: [] };
75756
76020
  } catch {
75757
76021
  return { states: [] };
@@ -75759,8 +76023,8 @@ function readState() {
75759
76023
  }
75760
76024
  function writeState(state) {
75761
76025
  const statePath = getStatePath();
75762
- fs41.mkdirSync(path41.dirname(statePath), { recursive: true });
75763
- fs41.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
76026
+ fs42.mkdirSync(path42.dirname(statePath), { recursive: true });
76027
+ fs42.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
75764
76028
  }
75765
76029
  function readPortalWatermark(repoPath, portalUrl) {
75766
76030
  const canonical = canonicalizeControlRepoPath(repoPath);
@@ -75811,8 +76075,8 @@ async function getJson(url) {
75811
76075
  async function resolveControlRepoId(apiUrl, repoPath) {
75812
76076
  const repos = await getJson(`${apiUrl}/api/repos`);
75813
76077
  if (!Array.isArray(repos)) return null;
75814
- const target = path42.resolve(repoPath);
75815
- return repos.find((repo) => path42.resolve(repo.path) === target)?.id ?? null;
76078
+ const target = path43.resolve(repoPath);
76079
+ return repos.find((repo) => path43.resolve(repo.path) === target)?.id ?? null;
75816
76080
  }
75817
76081
  function optionalString(value) {
75818
76082
  return value == null ? void 0 : value;
@@ -76115,7 +76379,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
76115
76379
  const deadline = Date.now() + timeoutMs;
76116
76380
  while (Date.now() < deadline) {
76117
76381
  if (await isControlApiReachable(apiUrl)) return true;
76118
- await new Promise((resolve44) => setTimeout(resolve44, intervalMs));
76382
+ await new Promise((resolve45) => setTimeout(resolve45, intervalMs));
76119
76383
  }
76120
76384
  return false;
76121
76385
  }
@@ -76207,7 +76471,7 @@ async function syncRepoWithLocalControl(options) {
76207
76471
  const listResponse = await fetch(`${apiUrl}/api/repos`);
76208
76472
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
76209
76473
  const repos = await listResponse.json();
76210
- const existing = repos.find((r2) => path43.resolve(r2.path) === repoPath);
76474
+ const existing = repos.find((r2) => path44.resolve(r2.path) === repoPath);
76211
76475
  if (!existing) {
76212
76476
  return;
76213
76477
  }
@@ -76410,7 +76674,7 @@ init_control_config();
76410
76674
 
76411
76675
  // src/core/control-lifecycle.ts
76412
76676
  var import_child_process9 = require("child_process");
76413
- var path44 = __toESM(require("path"));
76677
+ var path45 = __toESM(require("path"));
76414
76678
 
76415
76679
  // src/core/control-image.ts
76416
76680
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -76434,10 +76698,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
76434
76698
  var CONTROL_CONTAINER_PORT = 3847;
76435
76699
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
76436
76700
  function resolveControlDir() {
76437
- return path44.resolve(__dirname, "..", "control");
76701
+ return path45.resolve(__dirname, "..", "control");
76438
76702
  }
76439
76703
  function resolveControlBuildContext() {
76440
- return path44.resolve(resolveControlDir(), "..");
76704
+ return path45.resolve(resolveControlDir(), "..");
76441
76705
  }
76442
76706
  function buildDockerRunArgs(options) {
76443
76707
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -76493,7 +76757,7 @@ async function startMissionControl(options) {
76493
76757
  "-t",
76494
76758
  imageRef,
76495
76759
  "-f",
76496
- path44.join(resolveControlDir(), "Dockerfile"),
76760
+ path45.join(resolveControlDir(), "Dockerfile"),
76497
76761
  resolveControlBuildContext()
76498
76762
  ]);
76499
76763
  if (buildCode !== 0) {
@@ -76638,7 +76902,7 @@ async function ensureTelemetryInfrastructure(options) {
76638
76902
 
76639
76903
  // src/core/run-service.ts
76640
76904
  init_telemetry_config();
76641
- var path46 = __toESM(require("path"));
76905
+ var path47 = __toESM(require("path"));
76642
76906
  function extractShellOutput(result) {
76643
76907
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
76644
76908
  const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
@@ -76848,12 +77112,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
76848
77112
  suffix: session.suffix,
76849
77113
  createdAt: session.createdAt
76850
77114
  });
76851
- const envFile = path46.join(session.workDir, `.env.agent.${options.agentId}`);
77115
+ const envFile = path47.join(session.workDir, `.env.agent.${options.agentId}`);
76852
77116
  try {
76853
77117
  appendTelemetryEnvToFile(envFile, {
76854
77118
  sessionKey,
76855
77119
  agentId: options.agentId,
76856
- repoPath: path46.resolve(options.repoPath),
77120
+ repoPath: path47.resolve(options.repoPath),
76857
77121
  workDir: session.workDir,
76858
77122
  branch: session.branch,
76859
77123
  suffix: session.suffix,
@@ -77089,9 +77353,9 @@ var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunSer
77089
77353
  var readline6 = __toESM(require("readline"));
77090
77354
 
77091
77355
  // src/core/hooks.ts
77092
- var fs43 = __toESM(require("fs"));
77356
+ var fs44 = __toESM(require("fs"));
77093
77357
  var os15 = __toESM(require("os"));
77094
- var path47 = __toESM(require("path"));
77358
+ var path48 = __toESM(require("path"));
77095
77359
  var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
77096
77360
  var MARKER_END = "# <<< har commit gate <<<";
77097
77361
  var PRE_COMMIT_BLOCK = [
@@ -77116,7 +77380,7 @@ function resolveCheckoutRoot(cwd) {
77116
77380
  function resolveHooksDir(checkoutDir) {
77117
77381
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
77118
77382
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
77119
- return path47.resolve(checkoutDir, hooksPath);
77383
+ return path48.resolve(checkoutDir, hooksPath);
77120
77384
  }
77121
77385
  function getConfiguredHooksPath(checkoutDir) {
77122
77386
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -77124,9 +77388,9 @@ function getConfiguredHooksPath(checkoutDir) {
77124
77388
  function defaultHarInvocation() {
77125
77389
  const entry = process.argv[1];
77126
77390
  if (entry && entry.endsWith(".js")) {
77127
- return `"${process.execPath}" "${path47.resolve(entry)}"`;
77391
+ return `"${process.execPath}" "${path48.resolve(entry)}"`;
77128
77392
  }
77129
- if (entry) return `"${path47.resolve(entry)}"`;
77393
+ if (entry) return `"${path48.resolve(entry)}"`;
77130
77394
  return "har";
77131
77395
  }
77132
77396
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -77147,40 +77411,40 @@ exit 0
77147
77411
  `;
77148
77412
  }
77149
77413
  function upsertMarkedBlock(filePath, block) {
77150
- if (!fs43.existsSync(filePath)) {
77151
- fs43.writeFileSync(filePath, `#!/bin/sh
77414
+ if (!fs44.existsSync(filePath)) {
77415
+ fs44.writeFileSync(filePath, `#!/bin/sh
77152
77416
  ${block}
77153
77417
  `, { mode: 493 });
77154
77418
  return "created";
77155
77419
  }
77156
- const content = fs43.readFileSync(filePath, "utf8");
77420
+ const content = fs44.readFileSync(filePath, "utf8");
77157
77421
  if (content.includes(MARKER_START)) {
77158
77422
  const pattern = new RegExp(
77159
77423
  `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
77160
77424
  );
77161
- fs43.writeFileSync(filePath, content.replace(pattern, block));
77162
- fs43.chmodSync(filePath, 493);
77425
+ fs44.writeFileSync(filePath, content.replace(pattern, block));
77426
+ fs44.chmodSync(filePath, 493);
77163
77427
  return "updated";
77164
77428
  }
77165
77429
  const suffix = content.endsWith("\n") ? "" : "\n";
77166
- fs43.writeFileSync(filePath, `${content}${suffix}
77430
+ fs44.writeFileSync(filePath, `${content}${suffix}
77167
77431
  ${block}
77168
77432
  `);
77169
- fs43.chmodSync(filePath, 493);
77433
+ fs44.chmodSync(filePath, 493);
77170
77434
  return "appended";
77171
77435
  }
77172
77436
  function removeMarkedBlock(filePath) {
77173
- if (!fs43.existsSync(filePath)) return false;
77174
- const content = fs43.readFileSync(filePath, "utf8");
77437
+ if (!fs44.existsSync(filePath)) return false;
77438
+ const content = fs44.readFileSync(filePath, "utf8");
77175
77439
  if (!content.includes(MARKER_START)) return false;
77176
77440
  const pattern = new RegExp(
77177
77441
  `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
77178
77442
  );
77179
77443
  const stripped = content.replace(pattern, "\n");
77180
77444
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
77181
- fs43.rmSync(filePath);
77445
+ fs44.rmSync(filePath);
77182
77446
  } else {
77183
- fs43.writeFileSync(filePath, stripped);
77447
+ fs44.writeFileSync(filePath, stripped);
77184
77448
  }
77185
77449
  return true;
77186
77450
  }
@@ -77202,20 +77466,20 @@ Or re-run with --force to write into that directory anyway.`
77202
77466
  );
77203
77467
  }
77204
77468
  const hooksDir = resolveHooksDir(checkout);
77205
- fs43.mkdirSync(hooksDir, { recursive: true });
77469
+ fs44.mkdirSync(hooksDir, { recursive: true });
77206
77470
  const invocation = options.harInvocation ?? defaultHarInvocation();
77207
- fs43.writeFileSync(
77208
- path47.join(hooksDir, "har-pre-commit"),
77471
+ fs44.writeFileSync(
77472
+ path48.join(hooksDir, "har-pre-commit"),
77209
77473
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
77210
77474
  { mode: 493 }
77211
77475
  );
77212
- fs43.writeFileSync(
77213
- path47.join(hooksDir, "har-post-commit"),
77476
+ fs44.writeFileSync(
77477
+ path48.join(hooksDir, "har-post-commit"),
77214
77478
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
77215
77479
  { mode: 493 }
77216
77480
  );
77217
- const preCommit = upsertMarkedBlock(path47.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
77218
- const postCommit = upsertMarkedBlock(path47.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
77481
+ const preCommit = upsertMarkedBlock(path48.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
77482
+ const postCommit = upsertMarkedBlock(path48.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
77219
77483
  ensureValidationsIgnored(checkout);
77220
77484
  return { hooksDir, preCommit, postCommit };
77221
77485
  }
@@ -77224,12 +77488,12 @@ function uninstallHooks(repoPath) {
77224
77488
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
77225
77489
  const hooksDir = resolveHooksDir(checkout);
77226
77490
  let removed = false;
77227
- removed = removeMarkedBlock(path47.join(hooksDir, "pre-commit")) || removed;
77228
- removed = removeMarkedBlock(path47.join(hooksDir, "post-commit")) || removed;
77491
+ removed = removeMarkedBlock(path48.join(hooksDir, "pre-commit")) || removed;
77492
+ removed = removeMarkedBlock(path48.join(hooksDir, "post-commit")) || removed;
77229
77493
  for (const file of ["har-pre-commit", "har-post-commit"]) {
77230
- const full = path47.join(hooksDir, file);
77231
- if (fs43.existsSync(full)) {
77232
- fs43.rmSync(full);
77494
+ const full = path48.join(hooksDir, file);
77495
+ if (fs44.existsSync(full)) {
77496
+ fs44.rmSync(full);
77233
77497
  removed = true;
77234
77498
  }
77235
77499
  }
@@ -77248,10 +77512,10 @@ function isAgentWorktree(checkoutDir) {
77248
77512
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
77249
77513
  return true;
77250
77514
  }
77251
- const worktreesRoot = path47.join(os15.homedir(), "worktrees");
77252
- const resolved = path47.resolve(checkoutDir);
77253
- const name = path47.basename(resolved);
77254
- return resolved.startsWith(`${worktreesRoot}${path47.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
77515
+ const worktreesRoot = path48.join(os15.homedir(), "worktrees");
77516
+ const resolved = path48.resolve(checkoutDir);
77517
+ const name = path48.basename(resolved);
77518
+ return resolved.startsWith(`${worktreesRoot}${path48.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
77255
77519
  }
77256
77520
  function resolveEffectiveMode(checkoutDir, gate) {
77257
77521
  if (!gate.enabled) return "off";
@@ -77264,15 +77528,15 @@ function getHooksStatus(repoPath) {
77264
77528
  const hooksDir = resolveHooksDir(checkout);
77265
77529
  const gate = getCommitGateConfig(checkout);
77266
77530
  const hasBlock = (name) => {
77267
- const file = path47.join(hooksDir, name);
77268
- return fs43.existsSync(file) && fs43.readFileSync(file, "utf8").includes(MARKER_START);
77531
+ const file = path48.join(hooksDir, name);
77532
+ return fs44.existsSync(file) && fs44.readFileSync(file, "utf8").includes(MARKER_START);
77269
77533
  };
77270
77534
  return {
77271
77535
  checkout,
77272
77536
  hooksDir,
77273
77537
  configuredHooksPath: getConfiguredHooksPath(checkout),
77274
- preCommitInstalled: hasBlock("pre-commit") && fs43.existsSync(path47.join(hooksDir, "har-pre-commit")),
77275
- postCommitInstalled: hasBlock("post-commit") && fs43.existsSync(path47.join(hooksDir, "har-post-commit")),
77538
+ preCommitInstalled: hasBlock("pre-commit") && fs44.existsSync(path48.join(hooksDir, "har-pre-commit")),
77539
+ postCommitInstalled: hasBlock("post-commit") && fs44.existsSync(path48.join(hooksDir, "har-post-commit")),
77276
77540
  gate,
77277
77541
  effectiveMode: resolveEffectiveMode(checkout, gate)
77278
77542
  };
@@ -77283,7 +77547,7 @@ function checkCommitGate(cwd) {
77283
77547
  }
77284
77548
  const checkout = resolveCheckoutRoot(cwd);
77285
77549
  if (!checkout) return { exitCode: 0, messages: [] };
77286
- if (!fs43.existsSync(path47.join(checkout, ".har", "stages.json"))) {
77550
+ if (!fs44.existsSync(path48.join(checkout, ".har", "stages.json"))) {
77287
77551
  return { exitCode: 0, messages: [] };
77288
77552
  }
77289
77553
  const gate = getCommitGateConfig(checkout);
@@ -77356,12 +77620,12 @@ async function recordCommitAssociation(cwd) {
77356
77620
  // src/core/commit-gate-onboarding.ts
77357
77621
  function askYesNo5(question) {
77358
77622
  const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
77359
- return new Promise((resolve44) => {
77623
+ return new Promise((resolve45) => {
77360
77624
  process.stderr.write(`${question} `);
77361
77625
  rl.once("line", (answer) => {
77362
77626
  rl.close();
77363
77627
  const trimmed = answer.trim();
77364
- resolve44(trimmed === "" || /^y(es)?$/i.test(trimmed));
77628
+ resolve45(trimmed === "" || /^y(es)?$/i.test(trimmed));
77365
77629
  });
77366
77630
  });
77367
77631
  }
@@ -77403,20 +77667,20 @@ async function handleCommitGateOnboarding(options) {
77403
77667
  }
77404
77668
 
77405
77669
  // src/core/onboarding-preferences.ts
77406
- var fs44 = __toESM(require("fs"));
77670
+ var fs45 = __toESM(require("fs"));
77407
77671
  var os16 = __toESM(require("os"));
77408
- var path48 = __toESM(require("path"));
77672
+ var path49 = __toESM(require("path"));
77409
77673
  function getOnboardingPreferencesPath() {
77410
77674
  if (process.env.HAR_PREFERENCES_PATH) {
77411
- return path48.resolve(process.env.HAR_PREFERENCES_PATH);
77675
+ return path49.resolve(process.env.HAR_PREFERENCES_PATH);
77412
77676
  }
77413
- return path48.join(os16.homedir(), ".har", "preferences.json");
77677
+ return path49.join(os16.homedir(), ".har", "preferences.json");
77414
77678
  }
77415
77679
  function readOnboardingPreferences() {
77416
77680
  const preferencePath = getOnboardingPreferencesPath();
77417
77681
  try {
77418
- if (!fs44.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
77419
- return OnboardingPreferencesSchema.parse(JSON.parse(fs44.readFileSync(preferencePath, "utf8")));
77682
+ if (!fs45.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
77683
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs45.readFileSync(preferencePath, "utf8")));
77420
77684
  } catch {
77421
77685
  return OnboardingPreferencesSchema.parse({});
77422
77686
  }
@@ -77441,8 +77705,8 @@ function writeOnboardingPreferences(overrides) {
77441
77705
  };
77442
77706
  const parsed = OnboardingPreferencesSchema.parse(preference);
77443
77707
  const preferencePath = getOnboardingPreferencesPath();
77444
- fs44.mkdirSync(path48.dirname(preferencePath), { recursive: true });
77445
- fs44.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
77708
+ fs45.mkdirSync(path49.dirname(preferencePath), { recursive: true });
77709
+ fs45.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
77446
77710
  `);
77447
77711
  return parsed;
77448
77712
  }
@@ -77745,7 +78009,7 @@ var envCommand = {
77745
78009
  }
77746
78010
  };
77747
78011
  async function handleInit(argv) {
77748
- const repoPath = path49.resolve(argv.repo);
78012
+ const repoPath = path50.resolve(argv.repo);
77749
78013
  const onboarding = resolveOnboardingOptions(argv);
77750
78014
  header("har env init");
77751
78015
  info(`Repository: ${repoPath}`);
@@ -77809,7 +78073,7 @@ async function handleInit(argv) {
77809
78073
  }
77810
78074
  }
77811
78075
  async function handleMaintain(argv) {
77812
- const repoPath = path49.resolve(argv.repo);
78076
+ const repoPath = path50.resolve(argv.repo);
77813
78077
  const onboarding = resolveOnboardingOptions(argv);
77814
78078
  header("har env maintain");
77815
78079
  info(`Repository: ${repoPath}`);
@@ -77931,7 +78195,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
77931
78195
  if (autoYes) {
77932
78196
  const proposal = readAgentMdProposal(repoPath);
77933
78197
  if (proposal) {
77934
- writeFileSafe(path49.join(repoPath, "AGENT.md"), proposal.content);
78198
+ writeFileSafe(path50.join(repoPath, "AGENT.md"), proposal.content);
77935
78199
  clearAgentMdProposal(repoPath);
77936
78200
  info("Applied AGENT.md proposal (--yes)");
77937
78201
  }
@@ -77940,7 +78204,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
77940
78204
  await promptApplyAgentMdProposal(repoPath);
77941
78205
  }
77942
78206
  async function handleAddPlugin(argv) {
77943
- const repoPath = path49.resolve(argv.repo);
78207
+ const repoPath = path50.resolve(argv.repo);
77944
78208
  const available = listPluginIds();
77945
78209
  if (argv.list) {
77946
78210
  for (const id of available) {
@@ -77978,7 +78242,7 @@ async function handleAddPlugin(argv) {
77978
78242
  }
77979
78243
  }
77980
78244
  async function handleAddStage(argv) {
77981
- const repoPath = path49.resolve(argv.repo);
78245
+ const repoPath = path50.resolve(argv.repo);
77982
78246
  const available = listPluginIds();
77983
78247
  if (argv.list) {
77984
78248
  warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
@@ -78044,7 +78308,7 @@ async function handleAddStage(argv) {
78044
78308
  });
78045
78309
  }
78046
78310
  async function handlePreflight(argv) {
78047
- const repo = path49.resolve(argv.repo);
78311
+ const repo = path50.resolve(argv.repo);
78048
78312
  const agentId = validateAgentId(argv.id, repo);
78049
78313
  const result = await preflightEnvironment({
78050
78314
  repoPath: repo,
@@ -78062,7 +78326,7 @@ async function handlePreflight(argv) {
78062
78326
  process.exit(result.code);
78063
78327
  }
78064
78328
  async function handleLaunch(argv) {
78065
- const repo = path49.resolve(argv.repo);
78329
+ const repo = path50.resolve(argv.repo);
78066
78330
  const agentId = validateAgentId(argv.id, repo);
78067
78331
  let confirmReplace = argv.replace;
78068
78332
  let force = argv.force;
@@ -78074,8 +78338,8 @@ async function handleLaunch(argv) {
78074
78338
  console.error(guard.reason ?? "");
78075
78339
  const readline10 = await import("readline");
78076
78340
  const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
78077
- const answer = await new Promise((resolve44) => {
78078
- rl.question("Replace this slot? [y/N] ", resolve44);
78341
+ const answer = await new Promise((resolve45) => {
78342
+ rl.question("Replace this slot? [y/N] ", resolve45);
78079
78343
  });
78080
78344
  rl.close();
78081
78345
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -78091,8 +78355,8 @@ async function handleLaunch(argv) {
78091
78355
  warn("Worktree has uncommitted changes.");
78092
78356
  const readline10 = await import("readline");
78093
78357
  const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
78094
- const answer = await new Promise((resolve44) => {
78095
- rl.question("Discard uncommitted changes? [y/N] ", resolve44);
78358
+ const answer = await new Promise((resolve45) => {
78359
+ rl.question("Discard uncommitted changes? [y/N] ", resolve45);
78096
78360
  });
78097
78361
  rl.close();
78098
78362
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -78156,7 +78420,7 @@ async function handleRecover(argv) {
78156
78420
  });
78157
78421
  }
78158
78422
  async function handleVerify(argv) {
78159
- const repo = path49.resolve(argv.repo);
78423
+ const repo = path50.resolve(argv.repo);
78160
78424
  const agentId = validateAgentId(argv.id, repo);
78161
78425
  const result = await runVerification({
78162
78426
  repoPath: repo,
@@ -78168,7 +78432,7 @@ async function handleVerify(argv) {
78168
78432
  process.exit(result.code);
78169
78433
  }
78170
78434
  async function handleTeardown(argv) {
78171
- const repo = path49.resolve(argv.repo);
78435
+ const repo = path50.resolve(argv.repo);
78172
78436
  const agentId = validateAgentId(argv.id, repo);
78173
78437
  const result = await teardownEnvironment({
78174
78438
  repoPath: repo,
@@ -78179,7 +78443,7 @@ async function handleTeardown(argv) {
78179
78443
  process.exit(result.code);
78180
78444
  }
78181
78445
  async function handleComplete(argv) {
78182
- const repo = path49.resolve(argv.repo);
78446
+ const repo = path50.resolve(argv.repo);
78183
78447
  const agentId = validateAgentId(argv.id, repo);
78184
78448
  const result = await completeEnvironment({
78185
78449
  repoPath: repo,
@@ -78200,7 +78464,7 @@ async function handleComplete(argv) {
78200
78464
  process.exit(result.code);
78201
78465
  }
78202
78466
  async function handleStatus(argv) {
78203
- const repoPath = path49.resolve(argv.repo);
78467
+ const repoPath = path50.resolve(argv.repo);
78204
78468
  if (argv.json) {
78205
78469
  const status = collectEnvironmentStatus(repoPath);
78206
78470
  const output = EnvironmentStatusSchema.parse(status);
@@ -78213,7 +78477,7 @@ async function handleStatus(argv) {
78213
78477
  });
78214
78478
  }
78215
78479
  async function handleRunsList(argv) {
78216
- const repoPath = path49.resolve(argv.repo);
78480
+ const repoPath = path50.resolve(argv.repo);
78217
78481
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
78218
78482
  if (argv.json) {
78219
78483
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -78230,7 +78494,7 @@ async function handleRunsList(argv) {
78230
78494
  }
78231
78495
  }
78232
78496
  async function handleRunsGet(argv) {
78233
- const run2 = getRun(path49.resolve(argv.repo), argv.runId);
78497
+ const run2 = getRun(path50.resolve(argv.repo), argv.runId);
78234
78498
  if (!run2) {
78235
78499
  error(`Run not found: ${argv.runId}`);
78236
78500
  process.exit(1);
@@ -78284,9 +78548,16 @@ function printDrift(drift) {
78284
78548
  function printMaintainBundleSummary(report) {
78285
78549
  const missing = report.actions.filter((a2) => a2.kind === "missing").length;
78286
78550
  const drifted = report.actions.filter((a2) => a2.kind === "drift").length;
78551
+ const pluginMissing = report.pluginActions.filter((a2) => a2.kind === "missing").length;
78552
+ const pluginDrifted = report.pluginActions.filter((a2) => a2.kind === "drift").length;
78287
78553
  const stale = report.stale.length;
78288
78554
  info(`Maintenance bundle: .har/maintain/`);
78289
- info(` ${missing} missing, ${drifted} drifted, ${stale} stale`);
78555
+ info(` Harness: ${missing} missing, ${drifted} drifted, ${stale} stale`);
78556
+ if (report.pluginDrift.length > 0) {
78557
+ info(
78558
+ ` Plugins (${report.pluginDrift.map((p2) => p2.pluginId).join(", ")}): ${pluginMissing} missing, ${pluginDrifted} drifted`
78559
+ );
78560
+ }
78290
78561
  if (!report.validation.pass) {
78291
78562
  warn(` Validation: ${report.validation.errors.length} error(s) \u2014 blocks --finalize`);
78292
78563
  }
@@ -78309,7 +78580,7 @@ function printNextSteps(auto2) {
78309
78580
  }
78310
78581
 
78311
78582
  // src/cli/commands/control.ts
78312
- var path53 = __toESM(require("path"));
78583
+ var path54 = __toESM(require("path"));
78313
78584
 
78314
78585
  // node_modules/@inquirer/core/dist/esm/lib/key.mjs
78315
78586
  var isUpKey = (key) => (
@@ -79329,13 +79600,13 @@ var PromisePolyfill = class extends Promise {
79329
79600
  // Available starting from Node 22
79330
79601
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
79331
79602
  static withResolver() {
79332
- let resolve44;
79603
+ let resolve45;
79333
79604
  let reject;
79334
79605
  const promise = new Promise((res, rej) => {
79335
- resolve44 = res;
79606
+ resolve45 = res;
79336
79607
  reject = rej;
79337
79608
  });
79338
- return { promise, resolve: resolve44, reject };
79609
+ return { promise, resolve: resolve45, reject };
79339
79610
  }
79340
79611
  };
79341
79612
 
@@ -79352,7 +79623,7 @@ function createPrompt(view) {
79352
79623
  output
79353
79624
  });
79354
79625
  const screen = new ScreenManager(rl);
79355
- const { promise, resolve: resolve44, reject } = PromisePolyfill.withResolver();
79626
+ const { promise, resolve: resolve45, reject } = PromisePolyfill.withResolver();
79356
79627
  const cancel = () => reject(new CancelPromptError());
79357
79628
  if (signal) {
79358
79629
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -79376,7 +79647,7 @@ function createPrompt(view) {
79376
79647
  cycle(() => {
79377
79648
  try {
79378
79649
  const nextView = view(config2, (value) => {
79379
- setImmediate(() => resolve44(value));
79650
+ setImmediate(() => resolve45(value));
79380
79651
  });
79381
79652
  const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
79382
79653
  screen.render(content, bottomContent);
@@ -80363,9 +80634,9 @@ var import_run_async = __toESM(require_run_async(), 1);
80363
80634
  var import_mute_stream2 = __toESM(require_lib3(), 1);
80364
80635
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
80365
80636
  var _2 = {
80366
- set: (obj, path60 = "", value) => {
80637
+ set: (obj, path61 = "", value) => {
80367
80638
  let pointer = obj;
80368
- path60.split(".").forEach((key, index, arr) => {
80639
+ path61.split(".").forEach((key, index, arr) => {
80369
80640
  if (key === "__proto__" || key === "constructor")
80370
80641
  return;
80371
80642
  if (index === arr.length - 1) {
@@ -80376,8 +80647,8 @@ var _2 = {
80376
80647
  pointer = pointer[key];
80377
80648
  });
80378
80649
  },
80379
- get: (obj, path60 = "", defaultValue) => {
80380
- const travel = (regexp) => String.prototype.split.call(path60, regexp).filter(Boolean).reduce(
80650
+ get: (obj, path61 = "", defaultValue) => {
80651
+ const travel = (regexp) => String.prototype.split.call(path61, regexp).filter(Boolean).reduce(
80381
80652
  // @ts-expect-error implicit any on res[key]
80382
80653
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
80383
80654
  obj
@@ -80491,7 +80762,7 @@ var PromptsRunner = class {
80491
80762
  throw new Error(`Prompt for type ${question.type} not found`);
80492
80763
  }
80493
80764
  let cleanupSignal;
80494
- const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve44, reject) => {
80765
+ const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve45, reject) => {
80495
80766
  const rl = import_node_readline.default.createInterface(setupReadlineOptions(this.opt));
80496
80767
  rl.resume();
80497
80768
  const onClose = () => {
@@ -80527,7 +80798,7 @@ var PromptsRunner = class {
80527
80798
  cleanupSignal = void 0;
80528
80799
  };
80529
80800
  }
80530
- activePrompt.run().then(resolve44, reject).finally(cleanup);
80801
+ activePrompt.run().then(resolve45, reject).finally(cleanup);
80531
80802
  }) : prompt2;
80532
80803
  const { signal: moduleSignal } = this.opt;
80533
80804
  if (moduleSignal?.aborted) {
@@ -80629,20 +80900,20 @@ var esm_default13 = inquirer;
80629
80900
  init_control_config();
80630
80901
 
80631
80902
  // src/core/control-sync-selection.ts
80632
- var fs45 = __toESM(require("fs"));
80903
+ var fs46 = __toESM(require("fs"));
80633
80904
  var os17 = __toESM(require("os"));
80634
- var path50 = __toESM(require("path"));
80905
+ var path51 = __toESM(require("path"));
80635
80906
  function getSelectionPath() {
80636
80907
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
80637
- return path50.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
80908
+ return path51.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
80638
80909
  }
80639
- return path50.join(os17.homedir(), ".har", "sync-selection.json");
80910
+ return path51.join(os17.homedir(), ".har", "sync-selection.json");
80640
80911
  }
80641
80912
  function readSyncSelection() {
80642
80913
  const selectionPath = getSelectionPath();
80643
80914
  try {
80644
- if (!fs45.existsSync(selectionPath)) return null;
80645
- const parsed = JSON.parse(fs45.readFileSync(selectionPath, "utf8"));
80915
+ if (!fs46.existsSync(selectionPath)) return null;
80916
+ const parsed = JSON.parse(fs46.readFileSync(selectionPath, "utf8"));
80646
80917
  if (!Array.isArray(parsed.repos)) return null;
80647
80918
  return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
80648
80919
  } catch {
@@ -80652,8 +80923,8 @@ function readSyncSelection() {
80652
80923
  function writeSyncSelection(repos) {
80653
80924
  const selectionPath = getSelectionPath();
80654
80925
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
80655
- fs45.mkdirSync(path50.dirname(selectionPath), { recursive: true });
80656
- fs45.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
80926
+ fs46.mkdirSync(path51.dirname(selectionPath), { recursive: true });
80927
+ fs46.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
80657
80928
  }
80658
80929
  function resolveSyncSelection(input) {
80659
80930
  const { discovered, stored, forceSelect, isTTY } = input;
@@ -80700,7 +80971,7 @@ function openBrowser(url) {
80700
80971
  }
80701
80972
  async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
80702
80973
  const state = (0, import_crypto.randomUUID)();
80703
- return new Promise((resolve44, reject) => {
80974
+ return new Promise((resolve45, reject) => {
80704
80975
  let timer;
80705
80976
  const server = http.createServer((req, res) => {
80706
80977
  const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
@@ -80723,7 +80994,7 @@ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
80723
80994
  res.writeHead(200, { "Content-Type": "text/html" });
80724
80995
  res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
80725
80996
  cleanup();
80726
- resolve44({ portalUrl, token, workspace, email: email2, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
80997
+ resolve45({ portalUrl, token, workspace, email: email2, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
80727
80998
  });
80728
80999
  const cleanup = () => {
80729
81000
  clearTimeout(timer);
@@ -80750,16 +81021,16 @@ If your browser did not open, paste that URL.
80750
81021
  }
80751
81022
 
80752
81023
  // src/core/control-unregister.ts
80753
- var fs46 = __toESM(require("fs"));
80754
- var path51 = __toESM(require("path"));
81024
+ var fs47 = __toESM(require("fs"));
81025
+ var path52 = __toESM(require("path"));
80755
81026
  init_control_config();
80756
81027
  function listUnregisterWorktreeCandidates(repoPath) {
80757
81028
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
80758
81029
  const byPath = /* @__PURE__ */ new Map();
80759
81030
  const add = (partial2) => {
80760
- const resolved = path51.resolve(partial2.worktreePath);
81031
+ const resolved = path52.resolve(partial2.worktreePath);
80761
81032
  if (!resolved || resolved === harnessRoot) return;
80762
- const exists = partial2.exists ?? fs46.existsSync(resolved);
81033
+ const exists = partial2.exists ?? fs47.existsSync(resolved);
80763
81034
  const prev = byPath.get(resolved);
80764
81035
  if (prev) {
80765
81036
  byPath.set(resolved, {
@@ -80810,8 +81081,8 @@ async function askYesNo6(question) {
80810
81081
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
80811
81082
  const readline10 = await import("readline");
80812
81083
  const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
80813
- const answer = await new Promise((resolve44) => {
80814
- rl.question(question, resolve44);
81084
+ const answer = await new Promise((resolve45) => {
81085
+ rl.question(question, resolve45);
80815
81086
  });
80816
81087
  rl.close();
80817
81088
  return /^[Yy]$/.test(answer.trim());
@@ -80873,28 +81144,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
80873
81144
  trigger: "cli"
80874
81145
  });
80875
81146
  if (result.code !== 0) {
80876
- if (fs46.existsSync(candidate.worktreePath)) {
80877
- fs46.rmSync(candidate.worktreePath, { recursive: true, force: true });
81147
+ if (fs47.existsSync(candidate.worktreePath)) {
81148
+ fs47.rmSync(candidate.worktreePath, { recursive: true, force: true });
80878
81149
  }
80879
81150
  }
80880
81151
  outcomes.push({
80881
81152
  path: candidate.worktreePath,
80882
81153
  agentId: candidate.agentId,
80883
- deleted: !fs46.existsSync(candidate.worktreePath),
80884
- error: result.code !== 0 && fs46.existsSync(candidate.worktreePath) ? result.stderr : void 0
81154
+ deleted: !fs47.existsSync(candidate.worktreePath),
81155
+ error: result.code !== 0 && fs47.existsSync(candidate.worktreePath) ? result.stderr : void 0
80885
81156
  });
80886
81157
  } catch (err) {
80887
81158
  const message = err instanceof Error ? err.message : String(err);
80888
81159
  try {
80889
- if (fs46.existsSync(candidate.worktreePath)) {
80890
- fs46.rmSync(candidate.worktreePath, { recursive: true, force: true });
81160
+ if (fs47.existsSync(candidate.worktreePath)) {
81161
+ fs47.rmSync(candidate.worktreePath, { recursive: true, force: true });
80891
81162
  }
80892
81163
  } catch {
80893
81164
  }
80894
81165
  outcomes.push({
80895
81166
  path: candidate.worktreePath,
80896
81167
  agentId: candidate.agentId,
80897
- deleted: !fs46.existsSync(candidate.worktreePath),
81168
+ deleted: !fs47.existsSync(candidate.worktreePath),
80898
81169
  error: message
80899
81170
  });
80900
81171
  }
@@ -80956,16 +81227,16 @@ async function unregisterRepoWithControl(options) {
80956
81227
  init_control_config();
80957
81228
 
80958
81229
  // src/core/harness-scrub.ts
80959
- var fs47 = __toESM(require("fs"));
80960
- var path52 = __toESM(require("path"));
81230
+ var fs48 = __toESM(require("fs"));
81231
+ var path53 = __toESM(require("path"));
80961
81232
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
80962
81233
  function scrubLocalHarnessDirs(repoPath) {
80963
81234
  const results = [];
80964
- const resolved = path52.resolve(repoPath);
80965
- if (!fs47.existsSync(resolved)) {
81235
+ const resolved = path53.resolve(repoPath);
81236
+ if (!fs48.existsSync(resolved)) {
80966
81237
  for (const directory of HARNESS_SCRUB_DIRS) {
80967
81238
  results.push({
80968
- path: path52.join(resolved, ".har", directory),
81239
+ path: path53.join(resolved, ".har", directory),
80969
81240
  directory,
80970
81241
  deleted: false,
80971
81242
  error: "repository path does not exist"
@@ -80974,24 +81245,24 @@ function scrubLocalHarnessDirs(repoPath) {
80974
81245
  return results;
80975
81246
  }
80976
81247
  for (const directory of HARNESS_SCRUB_DIRS) {
80977
- const target = path52.join(resolved, ".har", directory);
80978
- if (!fs47.existsSync(target)) {
81248
+ const target = path53.join(resolved, ".har", directory);
81249
+ if (!fs48.existsSync(target)) {
80979
81250
  results.push({ path: target, directory, deleted: true });
80980
81251
  continue;
80981
81252
  }
80982
81253
  try {
80983
- fs47.rmSync(target, { recursive: true, force: true });
81254
+ fs48.rmSync(target, { recursive: true, force: true });
80984
81255
  results.push({
80985
81256
  path: target,
80986
81257
  directory,
80987
- deleted: !fs47.existsSync(target),
80988
- error: fs47.existsSync(target) ? "failed to remove directory" : void 0
81258
+ deleted: !fs48.existsSync(target),
81259
+ error: fs48.existsSync(target) ? "failed to remove directory" : void 0
80989
81260
  });
80990
81261
  } catch (err) {
80991
81262
  results.push({
80992
81263
  path: target,
80993
81264
  directory,
80994
- deleted: !fs47.existsSync(target),
81265
+ deleted: !fs48.existsSync(target),
80995
81266
  error: err instanceof Error ? err.message : String(err)
80996
81267
  });
80997
81268
  }
@@ -81002,7 +81273,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
81002
81273
  const results = [];
81003
81274
  const seen = /* @__PURE__ */ new Set();
81004
81275
  for (const repoPath of repoPaths) {
81005
- const key = path52.resolve(repoPath);
81276
+ const key = path53.resolve(repoPath);
81006
81277
  if (seen.has(key)) continue;
81007
81278
  seen.add(key);
81008
81279
  results.push(...scrubLocalHarnessDirs(key));
@@ -81015,8 +81286,8 @@ async function askYesNo7(question) {
81015
81286
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
81016
81287
  const readline10 = await import("readline");
81017
81288
  const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
81018
- const answer = await new Promise((resolve44) => {
81019
- rl.question(question, resolve44);
81289
+ const answer = await new Promise((resolve45) => {
81290
+ rl.question(question, resolve45);
81020
81291
  });
81021
81292
  rl.close();
81022
81293
  return /^[Yy]$/.test(answer.trim());
@@ -81261,7 +81532,7 @@ async function handleDown() {
81261
81532
  process.exit(code);
81262
81533
  }
81263
81534
  async function handleRegister(argv) {
81264
- const repoPath = path53.resolve(argv.repo);
81535
+ const repoPath = path54.resolve(argv.repo);
81265
81536
  header("har control register");
81266
81537
  info(`Repository: ${repoPath}`);
81267
81538
  try {
@@ -81353,7 +81624,7 @@ async function handleReset(argv) {
81353
81624
  }
81354
81625
  }
81355
81626
  async function handleUnregister(argv) {
81356
- const repoPath = path53.resolve(argv.repo);
81627
+ const repoPath = path54.resolve(argv.repo);
81357
81628
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
81358
81629
  try {
81359
81630
  let deleteWorktrees = argv.deleteWorktrees;
@@ -81514,7 +81785,7 @@ async function handleWatch(argv) {
81514
81785
  };
81515
81786
  const tick = async () => {
81516
81787
  if (argv.repo) {
81517
- await syncOne(path53.resolve(argv.repo));
81788
+ await syncOne(path54.resolve(argv.repo));
81518
81789
  return;
81519
81790
  }
81520
81791
  try {
@@ -81564,11 +81835,11 @@ async function handleLogin(argv) {
81564
81835
  }
81565
81836
 
81566
81837
  // src/cli/commands/hooks.ts
81567
- var path55 = __toESM(require("path"));
81838
+ var path56 = __toESM(require("path"));
81568
81839
 
81569
81840
  // src/core/claude-hooks.ts
81570
- var fs48 = __toESM(require("fs"));
81571
- var path54 = __toESM(require("path"));
81841
+ var fs49 = __toESM(require("fs"));
81842
+ var path55 = __toESM(require("path"));
81572
81843
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
81573
81844
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
81574
81845
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -81579,8 +81850,8 @@ function isHarGuardEntry(entry) {
81579
81850
  );
81580
81851
  }
81581
81852
  function readSettings(settingsPath) {
81582
- if (!fs48.existsSync(settingsPath)) return {};
81583
- const raw = fs48.readFileSync(settingsPath, "utf8").trim();
81853
+ if (!fs49.existsSync(settingsPath)) return {};
81854
+ const raw = fs49.readFileSync(settingsPath, "utf8").trim();
81584
81855
  if (raw === "") return {};
81585
81856
  const parsed = JSON.parse(raw);
81586
81857
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -81589,19 +81860,19 @@ function readSettings(settingsPath) {
81589
81860
  return parsed;
81590
81861
  }
81591
81862
  function writeSettings(settingsPath, settings) {
81592
- fs48.mkdirSync(path54.dirname(settingsPath), { recursive: true });
81593
- fs48.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
81863
+ fs49.mkdirSync(path55.dirname(settingsPath), { recursive: true });
81864
+ fs49.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
81594
81865
  }
81595
81866
  function installClaudeGuard(repoPath) {
81596
81867
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
81597
81868
  if (!templatePath) {
81598
81869
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
81599
81870
  }
81600
- const guardScript = path54.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
81601
- fs48.mkdirSync(path54.dirname(guardScript), { recursive: true });
81602
- fs48.copyFileSync(templatePath, guardScript);
81603
- fs48.chmodSync(guardScript, 493);
81604
- const settingsPath = path54.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81871
+ const guardScript = path55.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
81872
+ fs49.mkdirSync(path55.dirname(guardScript), { recursive: true });
81873
+ fs49.copyFileSync(templatePath, guardScript);
81874
+ fs49.chmodSync(guardScript, 493);
81875
+ const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81605
81876
  const settings = readSettings(settingsPath);
81606
81877
  const hooks = settings.hooks ?? {};
81607
81878
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -81615,15 +81886,15 @@ function installClaudeGuard(repoPath) {
81615
81886
  }
81616
81887
  function uninstallClaudeGuard(repoPath) {
81617
81888
  let removed = false;
81618
- const guardScript = path54.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
81619
- if (fs48.existsSync(guardScript)) {
81620
- fs48.rmSync(guardScript);
81889
+ const guardScript = path55.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
81890
+ if (fs49.existsSync(guardScript)) {
81891
+ fs49.rmSync(guardScript);
81621
81892
  removed = true;
81622
- const parent = path54.dirname(guardScript);
81623
- if (fs48.existsSync(parent) && fs48.readdirSync(parent).length === 0) fs48.rmdirSync(parent);
81893
+ const parent = path55.dirname(guardScript);
81894
+ if (fs49.existsSync(parent) && fs49.readdirSync(parent).length === 0) fs49.rmdirSync(parent);
81624
81895
  }
81625
- const settingsPath = path54.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81626
- if (fs48.existsSync(settingsPath)) {
81896
+ const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81897
+ if (fs49.existsSync(settingsPath)) {
81627
81898
  const settings = readSettings(settingsPath);
81628
81899
  const preToolUse = settings.hooks?.PreToolUse;
81629
81900
  if (preToolUse) {
@@ -81648,8 +81919,8 @@ function uninstallClaudeGuard(repoPath) {
81648
81919
  return { removed };
81649
81920
  }
81650
81921
  function claudeGuardInstalled(repoPath) {
81651
- const settingsPath = path54.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81652
- if (!fs48.existsSync(settingsPath)) return false;
81922
+ const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
81923
+ if (!fs49.existsSync(settingsPath)) return false;
81653
81924
  try {
81654
81925
  const settings = readSettings(settingsPath);
81655
81926
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -81665,7 +81936,7 @@ function repoOption(y2) {
81665
81936
  function handleInstall2(argv) {
81666
81937
  try {
81667
81938
  if (argv.claude) {
81668
- const result2 = installClaudeGuard(path55.resolve(argv.repo));
81939
+ const result2 = installClaudeGuard(path56.resolve(argv.repo));
81669
81940
  success("Claude Code worktree guard installed.");
81670
81941
  info(`Guard script: ${result2.guardScript}`);
81671
81942
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -81673,7 +81944,7 @@ function handleInstall2(argv) {
81673
81944
  info("Commit both files so the guard travels with the repo.");
81674
81945
  return;
81675
81946
  }
81676
- const result = installHooks({ repoPath: path55.resolve(argv.repo), force: argv.force });
81947
+ const result = installHooks({ repoPath: path56.resolve(argv.repo), force: argv.force });
81677
81948
  success(`Commit gate installed in ${result.hooksDir}`);
81678
81949
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
81679
81950
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -81686,7 +81957,7 @@ function handleInstall2(argv) {
81686
81957
  function handleUninstall(argv) {
81687
81958
  try {
81688
81959
  if (argv.claude) {
81689
- const result2 = uninstallClaudeGuard(path55.resolve(argv.repo));
81960
+ const result2 = uninstallClaudeGuard(path56.resolve(argv.repo));
81690
81961
  if (result2.removed) {
81691
81962
  success("Claude Code worktree guard removed.");
81692
81963
  } else {
@@ -81694,7 +81965,7 @@ function handleUninstall(argv) {
81694
81965
  }
81695
81966
  return;
81696
81967
  }
81697
- const result = uninstallHooks(path55.resolve(argv.repo));
81968
+ const result = uninstallHooks(path56.resolve(argv.repo));
81698
81969
  if (result.removed) {
81699
81970
  success(`Commit gate removed from ${result.hooksDir}`);
81700
81971
  } else {
@@ -81707,7 +81978,7 @@ function handleUninstall(argv) {
81707
81978
  }
81708
81979
  function handleStatus2(argv) {
81709
81980
  try {
81710
- const status = getHooksStatus(path55.resolve(argv.repo));
81981
+ const status = getHooksStatus(path56.resolve(argv.repo));
81711
81982
  if (argv.json) {
81712
81983
  process.stdout.write(`${JSON.stringify(status, null, 2)}
81713
81984
  `);
@@ -81725,7 +81996,7 @@ function handleStatus2(argv) {
81725
81996
  );
81726
81997
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
81727
81998
  info(
81728
- `Claude guard: ${claudeGuardInstalled(path55.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
81999
+ `Claude guard: ${claudeGuardInstalled(path56.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
81729
82000
  );
81730
82001
  } catch (err) {
81731
82002
  error(err instanceof Error ? err.message : String(err));
@@ -81986,10 +82257,10 @@ function assignProp(target, prop, value) {
81986
82257
  configurable: true
81987
82258
  });
81988
82259
  }
81989
- function getElementAtPath(obj, path60) {
81990
- if (!path60)
82260
+ function getElementAtPath(obj, path61) {
82261
+ if (!path61)
81991
82262
  return obj;
81992
- return path60.reduce((acc, key) => acc?.[key], obj);
82263
+ return path61.reduce((acc, key) => acc?.[key], obj);
81993
82264
  }
81994
82265
  function promiseAllObject(promisesObj) {
81995
82266
  const keys = Object.keys(promisesObj);
@@ -82309,11 +82580,11 @@ function aborted(x2, startIndex = 0) {
82309
82580
  }
82310
82581
  return false;
82311
82582
  }
82312
- function prefixIssues(path60, issues) {
82583
+ function prefixIssues(path61, issues) {
82313
82584
  return issues.map((iss) => {
82314
82585
  var _a3;
82315
82586
  (_a3 = iss).path ?? (_a3.path = []);
82316
- iss.path.unshift(path60);
82587
+ iss.path.unshift(path61);
82317
82588
  return iss;
82318
82589
  });
82319
82590
  }
@@ -87636,7 +87907,7 @@ var Protocol = class {
87636
87907
  return;
87637
87908
  }
87638
87909
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
87639
- await new Promise((resolve44) => setTimeout(resolve44, pollInterval));
87910
+ await new Promise((resolve45) => setTimeout(resolve45, pollInterval));
87640
87911
  options?.signal?.throwIfAborted();
87641
87912
  }
87642
87913
  } catch (error3) {
@@ -87653,7 +87924,7 @@ var Protocol = class {
87653
87924
  */
87654
87925
  request(request, resultSchema, options) {
87655
87926
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
87656
- return new Promise((resolve44, reject) => {
87927
+ return new Promise((resolve45, reject) => {
87657
87928
  const earlyReject = (error3) => {
87658
87929
  reject(error3);
87659
87930
  };
@@ -87731,7 +88002,7 @@ var Protocol = class {
87731
88002
  if (!parseResult.success) {
87732
88003
  reject(parseResult.error);
87733
88004
  } else {
87734
- resolve44(parseResult.data);
88005
+ resolve45(parseResult.data);
87735
88006
  }
87736
88007
  } catch (error3) {
87737
88008
  reject(error3);
@@ -87992,12 +88263,12 @@ var Protocol = class {
87992
88263
  }
87993
88264
  } catch {
87994
88265
  }
87995
- return new Promise((resolve44, reject) => {
88266
+ return new Promise((resolve45, reject) => {
87996
88267
  if (signal.aborted) {
87997
88268
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
87998
88269
  return;
87999
88270
  }
88000
- const timeoutId = setTimeout(resolve44, interval);
88271
+ const timeoutId = setTimeout(resolve45, interval);
88001
88272
  signal.addEventListener("abort", () => {
88002
88273
  clearTimeout(timeoutId);
88003
88274
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -88787,7 +89058,7 @@ var Server = class extends Protocol {
88787
89058
  };
88788
89059
 
88789
89060
  // src/mcp/server.ts
88790
- var path56 = __toESM(require("path"));
89061
+ var path57 = __toESM(require("path"));
88791
89062
 
88792
89063
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
88793
89064
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -88870,12 +89141,12 @@ var StdioServerTransport = class {
88870
89141
  this.onclose?.();
88871
89142
  }
88872
89143
  send(message) {
88873
- return new Promise((resolve44) => {
89144
+ return new Promise((resolve45) => {
88874
89145
  const json = serializeMessage(message);
88875
89146
  if (this._stdout.write(json)) {
88876
- resolve44();
89147
+ resolve45();
88877
89148
  } else {
88878
- this._stdout.once("drain", resolve44);
89149
+ this._stdout.once("drain", resolve45);
88879
89150
  }
88880
89151
  });
88881
89152
  }
@@ -89450,7 +89721,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
89450
89721
  const input = ControlUpInputSchema.parse({ ...args, repo });
89451
89722
  const result = await startControlAndSync({
89452
89723
  detach: input.detach,
89453
- cwd: path56.resolve(input.repo)
89724
+ cwd: path57.resolve(input.repo)
89454
89725
  });
89455
89726
  if (result.code !== 0) {
89456
89727
  return {
@@ -89514,10 +89785,10 @@ var mcpCommand = {
89514
89785
  };
89515
89786
 
89516
89787
  // src/cli/commands/onboard.ts
89517
- var path58 = __toESM(require("path"));
89788
+ var path59 = __toESM(require("path"));
89518
89789
 
89519
89790
  // src/core/onboarding.ts
89520
- var path57 = __toESM(require("path"));
89791
+ var path58 = __toESM(require("path"));
89521
89792
  init_control_config();
89522
89793
  init_otel_hooks();
89523
89794
  init_telemetry_config();
@@ -89645,7 +89916,7 @@ async function defaultEnsureControl(options) {
89645
89916
  return { started: true, apiUrl: result.apiUrl };
89646
89917
  }
89647
89918
  async function runOnboarding(options, deps = {}) {
89648
- const repoPath = path57.resolve(options.repoPath);
89919
+ const repoPath = path58.resolve(options.repoPath);
89649
89920
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
89650
89921
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
89651
89922
  const init = deps.initHarness ?? initHarness;
@@ -89796,7 +90067,7 @@ async function promptChoices(args) {
89796
90067
  };
89797
90068
  }
89798
90069
  const pluginChoices = listPluginChoices();
89799
- const alreadyPresent = harnessExists(path58.resolve(args.repo));
90070
+ const alreadyPresent = harnessExists(path59.resolve(args.repo));
89800
90071
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
89801
90072
  const answers = await esm_default13.prompt([
89802
90073
  {
@@ -89878,7 +90149,7 @@ function printSummary(result) {
89878
90149
  console.error("");
89879
90150
  }
89880
90151
  async function handleOnboard(argv) {
89881
- const repoPath = path58.resolve(argv.repo);
90152
+ const repoPath = path59.resolve(argv.repo);
89882
90153
  header("har onboard");
89883
90154
  info(`Repository: ${repoPath}`);
89884
90155
  try {
@@ -90109,7 +90380,7 @@ var preferencesCommand = {
90109
90380
  };
90110
90381
 
90111
90382
  // src/cli/commands/telemetry.ts
90112
- var path59 = __toESM(require("path"));
90383
+ var path60 = __toESM(require("path"));
90113
90384
  init_control_config();
90114
90385
  init_otel_hooks();
90115
90386
  init_telemetry_config();
@@ -90196,7 +90467,7 @@ async function handleOff() {
90196
90467
  info("Mission Control will not auto-start. Existing usage rows are kept.");
90197
90468
  }
90198
90469
  async function handleWriteEnv(argv) {
90199
- const repoPath = path59.resolve(argv.repo);
90470
+ const repoPath = path60.resolve(argv.repo);
90200
90471
  const harnessRoot = resolveHarnessRoot(repoPath);
90201
90472
  const session = readSlotRegistry(harnessRoot, argv.agentId);
90202
90473
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -90208,7 +90479,7 @@ async function handleWriteEnv(argv) {
90208
90479
  suffix,
90209
90480
  createdAt: session?.createdAt
90210
90481
  });
90211
- const envFile = argv.envFile ?? path59.join(workDir, `.env.agent.${argv.agentId}`);
90482
+ const envFile = argv.envFile ?? path60.join(workDir, `.env.agent.${argv.agentId}`);
90212
90483
  const attrs = {
90213
90484
  sessionKey,
90214
90485
  agentId: argv.agentId,
@@ -90224,7 +90495,7 @@ async function handleWriteEnv(argv) {
90224
90495
  success(`Wrote session attribution to ${envFile}`);
90225
90496
  }
90226
90497
  function handlePrintEnv(argv) {
90227
- const repoPath = path59.resolve(argv.repo);
90498
+ const repoPath = path60.resolve(argv.repo);
90228
90499
  const workDir = argv.workDir ?? repoPath;
90229
90500
  const sessionKey = buildSessionKey({
90230
90501
  branch: argv.branch,