@osfactory/har 0.21.0 → 0.24.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +1021 -597
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -765,14 +765,14 @@ var require_url_state_machine = __commonJS({
765
765
  return url.replace(/\u0009|\u000A|\u000D/g, "");
766
766
  }
767
767
  function shortenPath(url) {
768
- const path53 = url.path;
769
- if (path53.length === 0) {
768
+ const path54 = url.path;
769
+ if (path54.length === 0) {
770
770
  return;
771
771
  }
772
- if (url.scheme === "file" && path53.length === 1 && isNormalizedWindowsDriveLetter(path53[0])) {
772
+ if (url.scheme === "file" && path54.length === 1 && isNormalizedWindowsDriveLetter(path54[0])) {
773
773
  return;
774
774
  }
775
- path53.pop();
775
+ path54.pop();
776
776
  }
777
777
  function includesCredentials(url) {
778
778
  return url.username !== "" || url.password !== "";
@@ -1811,7 +1811,7 @@ var require_lib2 = __commonJS({
1811
1811
  return ex && typeof ex === "object" && "default" in ex ? ex["default"] : ex;
1812
1812
  }
1813
1813
  var Stream2 = _interopDefault(require("stream"));
1814
- var http = _interopDefault(require("http"));
1814
+ var http2 = _interopDefault(require("http"));
1815
1815
  var Url = _interopDefault(require("url"));
1816
1816
  var whatwgUrl = _interopDefault(require_public_api());
1817
1817
  var https = _interopDefault(require("https"));
@@ -2092,7 +2092,7 @@ var require_lib2 = __commonJS({
2092
2092
  let accum = [];
2093
2093
  let accumBytes = 0;
2094
2094
  let abort = false;
2095
- return new Body.Promise(function(resolve37, reject) {
2095
+ return new Body.Promise(function(resolve38, reject) {
2096
2096
  let resTimeout;
2097
2097
  if (_this4.timeout) {
2098
2098
  resTimeout = setTimeout(function() {
@@ -2126,7 +2126,7 @@ var require_lib2 = __commonJS({
2126
2126
  }
2127
2127
  clearTimeout(resTimeout);
2128
2128
  try {
2129
- resolve37(Buffer.concat(accum, accumBytes));
2129
+ resolve38(Buffer.concat(accum, accumBytes));
2130
2130
  } catch (err) {
2131
2131
  reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
2132
2132
  }
@@ -2551,7 +2551,7 @@ var require_lib2 = __commonJS({
2551
2551
  return headers;
2552
2552
  }
2553
2553
  var INTERNALS$1 = Symbol("Response internals");
2554
- var STATUS_CODES = http.STATUS_CODES;
2554
+ var STATUS_CODES = http2.STATUS_CODES;
2555
2555
  var Response3 = class _Response {
2556
2556
  constructor() {
2557
2557
  let body = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : null;
@@ -2801,10 +2801,10 @@ var require_lib2 = __commonJS({
2801
2801
  throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
2802
2802
  }
2803
2803
  Body.Promise = fetch3.Promise;
2804
- return new fetch3.Promise(function(resolve37, reject) {
2804
+ return new fetch3.Promise(function(resolve38, reject) {
2805
2805
  const request = new Request3(url, opts);
2806
2806
  const options = getNodeRequestOptions(request);
2807
- const send = (options.protocol === "https:" ? https : http).request;
2807
+ const send = (options.protocol === "https:" ? https : http2).request;
2808
2808
  const signal = request.signal;
2809
2809
  let response = null;
2810
2810
  const abort = function abort2() {
@@ -2934,7 +2934,7 @@ var require_lib2 = __commonJS({
2934
2934
  requestOpts.body = void 0;
2935
2935
  requestOpts.headers.delete("content-length");
2936
2936
  }
2937
- resolve37(fetch3(new Request3(locationURL, requestOpts)));
2937
+ resolve38(fetch3(new Request3(locationURL, requestOpts)));
2938
2938
  finalize();
2939
2939
  return;
2940
2940
  }
@@ -2955,7 +2955,7 @@ var require_lib2 = __commonJS({
2955
2955
  const codings = headers.get("Content-Encoding");
2956
2956
  if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
2957
2957
  response = new Response3(body, response_options);
2958
- resolve37(response);
2958
+ resolve38(response);
2959
2959
  return;
2960
2960
  }
2961
2961
  const zlibOptions = {
@@ -2965,7 +2965,7 @@ var require_lib2 = __commonJS({
2965
2965
  if (codings == "gzip" || codings == "x-gzip") {
2966
2966
  body = body.pipe(zlib.createGunzip(zlibOptions));
2967
2967
  response = new Response3(body, response_options);
2968
- resolve37(response);
2968
+ resolve38(response);
2969
2969
  return;
2970
2970
  }
2971
2971
  if (codings == "deflate" || codings == "x-deflate") {
@@ -2977,12 +2977,12 @@ var require_lib2 = __commonJS({
2977
2977
  body = body.pipe(zlib.createInflateRaw());
2978
2978
  }
2979
2979
  response = new Response3(body, response_options);
2980
- resolve37(response);
2980
+ resolve38(response);
2981
2981
  });
2982
2982
  raw.on("end", function() {
2983
2983
  if (!response) {
2984
2984
  response = new Response3(body, response_options);
2985
- resolve37(response);
2985
+ resolve38(response);
2986
2986
  }
2987
2987
  });
2988
2988
  return;
@@ -2990,11 +2990,11 @@ var require_lib2 = __commonJS({
2990
2990
  if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
2991
2991
  body = body.pipe(zlib.createBrotliDecompress());
2992
2992
  response = new Response3(body, response_options);
2993
- resolve37(response);
2993
+ resolve38(response);
2994
2994
  return;
2995
2995
  }
2996
2996
  response = new Response3(body, response_options);
2997
- resolve37(response);
2997
+ resolve38(response);
2998
2998
  });
2999
2999
  writeToStream(req, request);
3000
3000
  });
@@ -6351,14 +6351,14 @@ __export(fileFromPath_exports, {
6351
6351
  fileFromPathSync: () => fileFromPathSync,
6352
6352
  isFile: () => isFile
6353
6353
  });
6354
- function createFileFromPath(path53, { mtimeMs, size }, filenameOrOptions, options = {}) {
6354
+ function createFileFromPath(path54, { mtimeMs, size }, filenameOrOptions, options = {}) {
6355
6355
  let filename;
6356
6356
  if (isPlainObject_default2(filenameOrOptions)) {
6357
6357
  [options, filename] = [filenameOrOptions, void 0];
6358
6358
  } else {
6359
6359
  filename = filenameOrOptions;
6360
6360
  }
6361
- const file = new FileFromPath({ path: path53, size, lastModified: mtimeMs });
6361
+ const file = new FileFromPath({ path: path54, size, lastModified: mtimeMs });
6362
6362
  if (!filename) {
6363
6363
  filename = file.name;
6364
6364
  }
@@ -6367,13 +6367,13 @@ function createFileFromPath(path53, { mtimeMs, size }, filenameOrOptions, option
6367
6367
  lastModified: file.lastModified
6368
6368
  });
6369
6369
  }
6370
- function fileFromPathSync(path53, filenameOrOptions, options = {}) {
6371
- const stats = (0, import_fs5.statSync)(path53);
6372
- return createFileFromPath(path53, stats, filenameOrOptions, options);
6370
+ function fileFromPathSync(path54, filenameOrOptions, options = {}) {
6371
+ const stats = (0, import_fs5.statSync)(path54);
6372
+ return createFileFromPath(path54, stats, filenameOrOptions, options);
6373
6373
  }
6374
- async function fileFromPath2(path53, filenameOrOptions, options) {
6375
- const stats = await import_fs5.promises.stat(path53);
6376
- return createFileFromPath(path53, stats, filenameOrOptions, options);
6374
+ async function fileFromPath2(path54, filenameOrOptions, options) {
6375
+ const stats = await import_fs5.promises.stat(path54);
6376
+ return createFileFromPath(path54, stats, filenameOrOptions, options);
6377
6377
  }
6378
6378
  var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
6379
6379
  var init_fileFromPath = __esm({
@@ -6433,6 +6433,45 @@ var init_fileFromPath = __esm({
6433
6433
  }
6434
6434
  });
6435
6435
 
6436
+ // src/core/portal-credentials.ts
6437
+ function portalCredentialsPath() {
6438
+ if (process.env.HAR_CREDENTIALS_PATH) {
6439
+ return path25.resolve(process.env.HAR_CREDENTIALS_PATH);
6440
+ }
6441
+ return path25.join(os4.homedir(), ".har", "credentials.json");
6442
+ }
6443
+ function readPortalCredentials() {
6444
+ try {
6445
+ const raw = fs26.readFileSync(portalCredentialsPath(), "utf8");
6446
+ const parsed = JSON.parse(raw);
6447
+ if (!parsed.portalUrl || !parsed.token) return null;
6448
+ return {
6449
+ portalUrl: parsed.portalUrl,
6450
+ token: parsed.token,
6451
+ workspace: parsed.workspace,
6452
+ email: parsed.email,
6453
+ createdAt: parsed.createdAt ?? ""
6454
+ };
6455
+ } catch {
6456
+ return null;
6457
+ }
6458
+ }
6459
+ function writePortalCredentials(creds) {
6460
+ const file = portalCredentialsPath();
6461
+ fs26.mkdirSync(path25.dirname(file), { recursive: true });
6462
+ fs26.writeFileSync(file, JSON.stringify(creds, null, 2), { mode: 384 });
6463
+ fs26.chmodSync(file, 384);
6464
+ }
6465
+ var fs26, os4, path25;
6466
+ var init_portal_credentials = __esm({
6467
+ "src/core/portal-credentials.ts"() {
6468
+ "use strict";
6469
+ fs26 = __toESM(require("fs"));
6470
+ os4 = __toESM(require("os"));
6471
+ path25 = __toESM(require("path"));
6472
+ }
6473
+ });
6474
+
6436
6475
  // src/core/control-config.ts
6437
6476
  function getControlApiUrl() {
6438
6477
  return process.env.HAR_CONTROL_API_URL ?? DEFAULT_CONTROL_API_URL;
@@ -6440,10 +6479,33 @@ function getControlApiUrl() {
6440
6479
  function isControlEnabled() {
6441
6480
  return process.env.HAR_CONTROL_DISABLED !== "true";
6442
6481
  }
6482
+ function normalizeUrl(url) {
6483
+ return url.replace(/\/+$/, "");
6484
+ }
6485
+ function getPortalTarget() {
6486
+ if (process.env.HAR_PORTAL_URL && process.env.HAR_PORTAL_TOKEN) {
6487
+ return {
6488
+ url: normalizeUrl(process.env.HAR_PORTAL_URL),
6489
+ token: process.env.HAR_PORTAL_TOKEN
6490
+ };
6491
+ }
6492
+ const stored = readPortalCredentials();
6493
+ if (stored) {
6494
+ return { url: normalizeUrl(stored.portalUrl), token: stored.token };
6495
+ }
6496
+ if (process.env.HAR_CLOUD_API_URL && process.env.HAR_CLOUD_API_KEY) {
6497
+ return {
6498
+ url: normalizeUrl(process.env.HAR_CLOUD_API_URL),
6499
+ token: process.env.HAR_CLOUD_API_KEY
6500
+ };
6501
+ }
6502
+ return null;
6503
+ }
6443
6504
  var DEFAULT_CONTROL_API_URL;
6444
6505
  var init_control_config = __esm({
6445
6506
  "src/core/control-config.ts"() {
6446
6507
  "use strict";
6508
+ init_portal_credentials();
6447
6509
  DEFAULT_CONTROL_API_URL = "http://localhost:3847";
6448
6510
  }
6449
6511
  });
@@ -6451,9 +6513,9 @@ var init_control_config = __esm({
6451
6513
  // src/core/telemetry-config.ts
6452
6514
  function getPreferencePath() {
6453
6515
  if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
6454
- return path36.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6516
+ return path37.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6455
6517
  }
6456
- return path36.join(os9.homedir(), ".har", "telemetry.json");
6518
+ return path37.join(os10.homedir(), ".har", "telemetry.json");
6457
6519
  }
6458
6520
  function parseEnvOverride(raw) {
6459
6521
  if (raw === void 0 || raw === "") return void 0;
@@ -6474,10 +6536,10 @@ function normalizeSignals(enabled, raw) {
6474
6536
  function readTelemetryPreference() {
6475
6537
  const preferencePath = getPreferencePath();
6476
6538
  try {
6477
- if (!fs36.existsSync(preferencePath)) {
6539
+ if (!fs37.existsSync(preferencePath)) {
6478
6540
  return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
6479
6541
  }
6480
- const parsed = JSON.parse(fs36.readFileSync(preferencePath, "utf8"));
6542
+ const parsed = JSON.parse(fs37.readFileSync(preferencePath, "utf8"));
6481
6543
  const enabled = parsed.enabled !== false;
6482
6544
  return {
6483
6545
  enabled,
@@ -6500,8 +6562,8 @@ function writeTelemetryPreference(enabled, signals2) {
6500
6562
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6501
6563
  };
6502
6564
  const preferencePath = getPreferencePath();
6503
- fs36.mkdirSync(path36.dirname(preferencePath), { recursive: true });
6504
- fs36.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6565
+ fs37.mkdirSync(path37.dirname(preferencePath), { recursive: true });
6566
+ fs37.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6505
6567
  return preference;
6506
6568
  }
6507
6569
  function isTelemetryEnabled() {
@@ -6516,13 +6578,13 @@ function getTelemetrySignals() {
6516
6578
  function getTelemetryPreferencePath() {
6517
6579
  return getPreferencePath();
6518
6580
  }
6519
- var fs36, os9, path36, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6581
+ var fs37, os10, path37, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6520
6582
  var init_telemetry_config = __esm({
6521
6583
  "src/core/telemetry-config.ts"() {
6522
6584
  "use strict";
6523
- fs36 = __toESM(require("fs"));
6524
- os9 = __toESM(require("os"));
6525
- path36 = __toESM(require("path"));
6585
+ fs37 = __toESM(require("fs"));
6586
+ os10 = __toESM(require("os"));
6587
+ path37 = __toESM(require("path"));
6526
6588
  DEFAULT_SIGNALS_ON = {
6527
6589
  metrics: true,
6528
6590
  logs: true,
@@ -6563,15 +6625,15 @@ __export(otel_hooks_exports, {
6563
6625
  });
6564
6626
  function getOtelHooksHome() {
6565
6627
  if (process.env.HAR_OTEL_HOOKS_HOME) {
6566
- return path42.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6628
+ return path43.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6567
6629
  }
6568
- return path42.join(os12.homedir(), ".har", "otel-hooks");
6630
+ return path43.join(os13.homedir(), ".har", "otel-hooks");
6569
6631
  }
6570
6632
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
6571
- return path42.join(hooksHome, "otel_config.json");
6633
+ return path43.join(hooksHome, "otel_config.json");
6572
6634
  }
6573
6635
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
6574
- return path42.join(hooksHome, "run-otel-hook.sh");
6636
+ return path43.join(hooksHome, "run-otel-hook.sh");
6575
6637
  }
6576
6638
  function buildOtelHooksConfig(options) {
6577
6639
  const enabled = options?.enabled ?? isTelemetryEnabled();
@@ -6590,18 +6652,18 @@ function buildOtelHooksConfig(options) {
6590
6652
  };
6591
6653
  }
6592
6654
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
6593
- fs40.mkdirSync(hooksHome, { recursive: true });
6655
+ fs41.mkdirSync(hooksHome, { recursive: true });
6594
6656
  const configPath = getOtelHooksConfigPath(hooksHome);
6595
6657
  const payload = {
6596
6658
  _comment: "Managed by har telemetry \u2014 do not edit by hand; use: har telemetry on|off",
6597
6659
  ...config2
6598
6660
  };
6599
- fs40.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6661
+ fs41.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6600
6662
  `);
6601
6663
  return configPath;
6602
6664
  }
6603
6665
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
6604
- fs40.mkdirSync(hooksHome, { recursive: true });
6666
+ fs41.mkdirSync(hooksHome, { recursive: true });
6605
6667
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
6606
6668
  const script = `#!/usr/bin/env bash
6607
6669
  # Managed by har telemetry \u2014 invokes opentelemetry-hooks with HAR config home.
@@ -6609,29 +6671,29 @@ set -euo pipefail
6609
6671
  export IDE_OTEL_HOOK_HOME="${hooksHome}"
6610
6672
  exec "${otelHookCommand}" "$@"
6611
6673
  `;
6612
- fs40.writeFileSync(wrapperPath, script, { mode: 493 });
6674
+ fs41.writeFileSync(wrapperPath, script, { mode: 493 });
6613
6675
  try {
6614
- fs40.chmodSync(wrapperPath, 493);
6676
+ fs41.chmodSync(wrapperPath, 493);
6615
6677
  } catch {
6616
6678
  }
6617
6679
  return wrapperPath;
6618
6680
  }
6619
- function commandExists(command2) {
6620
- const result = (0, import_child_process9.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
6681
+ function commandExists2(command2) {
6682
+ const result = (0, import_child_process10.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
6621
6683
  encoding: "utf8"
6622
6684
  });
6623
6685
  return result.status === 0 && Boolean(result.stdout?.trim());
6624
6686
  }
6625
6687
  function resolveOtelHookCommand() {
6626
- if (commandExists("otel-hook")) {
6627
- const which = (0, import_child_process9.spawnSync)("sh", ["-c", "command -v otel-hook"], { encoding: "utf8" });
6688
+ if (commandExists2("otel-hook")) {
6689
+ const which = (0, import_child_process10.spawnSync)("sh", ["-c", "command -v otel-hook"], { encoding: "utf8" });
6628
6690
  return which.stdout?.trim() || "otel-hook";
6629
6691
  }
6630
6692
  return null;
6631
6693
  }
6632
6694
  function tryInstallPackage() {
6633
- if (commandExists("uv")) {
6634
- const result = (0, import_child_process9.spawnSync)(
6695
+ if (commandExists2("uv")) {
6696
+ const result = (0, import_child_process10.spawnSync)(
6635
6697
  "uv",
6636
6698
  ["tool", "install", "--force", OTEL_HOOKS_PACKAGE],
6637
6699
  { encoding: "utf8", timeout: 18e4 }
@@ -6640,8 +6702,8 @@ function tryInstallPackage() {
6640
6702
  return { ok: true, detail: `uv tool install ${OTEL_HOOKS_PACKAGE}` };
6641
6703
  }
6642
6704
  }
6643
- if (commandExists("pipx")) {
6644
- const result = (0, import_child_process9.spawnSync)("pipx", ["install", "--force", OTEL_HOOKS_PACKAGE], {
6705
+ if (commandExists2("pipx")) {
6706
+ const result = (0, import_child_process10.spawnSync)("pipx", ["install", "--force", OTEL_HOOKS_PACKAGE], {
6645
6707
  encoding: "utf8",
6646
6708
  timeout: 18e4
6647
6709
  });
@@ -6653,9 +6715,9 @@ function tryInstallPackage() {
6653
6715
  detail: `pipx install failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
6654
6716
  };
6655
6717
  }
6656
- if (commandExists("pip3") || commandExists("pip")) {
6657
- const pip = commandExists("pip3") ? "pip3" : "pip";
6658
- const result = (0, import_child_process9.spawnSync)(
6718
+ if (commandExists2("pip3") || commandExists2("pip")) {
6719
+ const pip = commandExists2("pip3") ? "pip3" : "pip";
6720
+ const result = (0, import_child_process10.spawnSync)(
6659
6721
  pip,
6660
6722
  ["install", "--user", OTEL_HOOKS_PACKAGE],
6661
6723
  { encoding: "utf8", timeout: 18e4 }
@@ -6674,7 +6736,7 @@ function tryInstallPackage() {
6674
6736
  };
6675
6737
  }
6676
6738
  function runSetupAgent(agent, otelHookCommand, hooksHome) {
6677
- const result = (0, import_child_process9.spawnSync)(otelHookCommand, ["setup", "--agent", agent], {
6739
+ const result = (0, import_child_process10.spawnSync)(otelHookCommand, ["setup", "--agent", agent], {
6678
6740
  encoding: "utf8",
6679
6741
  env: {
6680
6742
  ...process.env,
@@ -6691,10 +6753,10 @@ function runSetupAgent(agent, otelHookCommand, hooksHome) {
6691
6753
  };
6692
6754
  }
6693
6755
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6694
- if (!fs40.existsSync(filePath)) return false;
6756
+ if (!fs41.existsSync(filePath)) return false;
6695
6757
  let raw;
6696
6758
  try {
6697
- raw = fs40.readFileSync(filePath, "utf8");
6759
+ raw = fs41.readFileSync(filePath, "utf8");
6698
6760
  } catch {
6699
6761
  return false;
6700
6762
  }
@@ -6733,16 +6795,16 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6733
6795
  return changed;
6734
6796
  };
6735
6797
  if (!walk(parsed)) return false;
6736
- fs40.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6798
+ fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6737
6799
  `);
6738
6800
  return true;
6739
6801
  }
6740
6802
  function rewriteKnownHookRegistrations(wrapperPath) {
6741
- const home = os12.homedir();
6803
+ const home = os13.homedir();
6742
6804
  const candidates = [
6743
- path42.join(home, ".cursor", "hooks.json"),
6744
- path42.join(home, ".claude", "settings.json"),
6745
- path42.join(home, ".codex", "hooks.json")
6805
+ path43.join(home, ".cursor", "hooks.json"),
6806
+ path43.join(home, ".claude", "settings.json"),
6807
+ path43.join(home, ".codex", "hooks.json")
6746
6808
  ];
6747
6809
  for (const filePath of candidates) {
6748
6810
  try {
@@ -6755,7 +6817,7 @@ function ensureOtelHooks(options) {
6755
6817
  const hooksHome = getOtelHooksHome();
6756
6818
  const errors = [];
6757
6819
  const agentsSetup = [];
6758
- fs40.mkdirSync(hooksHome, { recursive: true });
6820
+ fs41.mkdirSync(hooksHome, { recursive: true });
6759
6821
  let otelHookCommand = resolveOtelHookCommand();
6760
6822
  if (!otelHookCommand) {
6761
6823
  const installed = tryInstallPackage();
@@ -6824,14 +6886,14 @@ function ensureOtelHooks(options) {
6824
6886
  function disableOtelHooksExport() {
6825
6887
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
6826
6888
  }
6827
- var import_child_process9, fs40, os12, path42, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6889
+ var import_child_process10, fs41, os13, path43, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6828
6890
  var init_otel_hooks = __esm({
6829
6891
  "src/core/otel-hooks.ts"() {
6830
6892
  "use strict";
6831
- import_child_process9 = require("child_process");
6832
- fs40 = __toESM(require("fs"));
6833
- os12 = __toESM(require("os"));
6834
- path42 = __toESM(require("path"));
6893
+ import_child_process10 = require("child_process");
6894
+ fs41 = __toESM(require("fs"));
6895
+ os13 = __toESM(require("os"));
6896
+ path43 = __toESM(require("path"));
6835
6897
  init_control_config();
6836
6898
  init_telemetry_config();
6837
6899
  OTEL_HOOKS_PACKAGE = "opentelemetry-hooks==0.14.0";
@@ -9790,7 +9852,7 @@ var require_compile = __commonJS({
9790
9852
  const schOrFunc = root.refs[ref];
9791
9853
  if (schOrFunc)
9792
9854
  return schOrFunc;
9793
- let _sch = resolve37.call(this, root, ref);
9855
+ let _sch = resolve38.call(this, root, ref);
9794
9856
  if (_sch === void 0) {
9795
9857
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
9796
9858
  const { schemaId } = this.opts;
@@ -9817,7 +9879,7 @@ var require_compile = __commonJS({
9817
9879
  function sameSchemaEnv(s1, s2) {
9818
9880
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
9819
9881
  }
9820
- function resolve37(root, ref) {
9882
+ function resolve38(root, ref) {
9821
9883
  let sch;
9822
9884
  while (typeof (sch = this.refs[ref]) == "string")
9823
9885
  ref = sch;
@@ -10035,8 +10097,8 @@ var require_utils2 = __commonJS({
10035
10097
  }
10036
10098
  return ind;
10037
10099
  }
10038
- function removeDotSegments(path53) {
10039
- let input = path53;
10100
+ function removeDotSegments(path54) {
10101
+ let input = path54;
10040
10102
  const output = [];
10041
10103
  let nextSlash = -1;
10042
10104
  let len = 0;
@@ -10288,8 +10350,8 @@ var require_schemes = __commonJS({
10288
10350
  wsComponent.secure = void 0;
10289
10351
  }
10290
10352
  if (wsComponent.resourceName) {
10291
- const [path53, query] = wsComponent.resourceName.split("?");
10292
- wsComponent.path = path53 && path53 !== "/" ? path53 : void 0;
10353
+ const [path54, query] = wsComponent.resourceName.split("?");
10354
+ wsComponent.path = path54 && path54 !== "/" ? path54 : void 0;
10293
10355
  wsComponent.query = query;
10294
10356
  wsComponent.resourceName = void 0;
10295
10357
  }
@@ -10348,7 +10410,7 @@ var require_schemes = __commonJS({
10348
10410
  urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
10349
10411
  return urnComponent;
10350
10412
  }
10351
- var http = (
10413
+ var http2 = (
10352
10414
  /** @type {SchemeHandler} */
10353
10415
  {
10354
10416
  scheme: "http",
@@ -10361,7 +10423,7 @@ var require_schemes = __commonJS({
10361
10423
  /** @type {SchemeHandler} */
10362
10424
  {
10363
10425
  scheme: "https",
10364
- domainHost: http.domainHost,
10426
+ domainHost: http2.domainHost,
10365
10427
  parse: httpParse,
10366
10428
  serialize: httpSerialize
10367
10429
  }
@@ -10405,7 +10467,7 @@ var require_schemes = __commonJS({
10405
10467
  var SCHEMES = (
10406
10468
  /** @type {Record<SchemeName, SchemeHandler>} */
10407
10469
  {
10408
- http,
10470
+ http: http2,
10409
10471
  https,
10410
10472
  ws,
10411
10473
  wss,
@@ -10448,7 +10510,7 @@ var require_fast_uri = __commonJS({
10448
10510
  }
10449
10511
  return uri;
10450
10512
  }
10451
- function resolve37(baseURI, relativeURI, options) {
10513
+ function resolve38(baseURI, relativeURI, options) {
10452
10514
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
10453
10515
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
10454
10516
  schemelessOptions.skipEscape = true;
@@ -10706,7 +10768,7 @@ var require_fast_uri = __commonJS({
10706
10768
  var fastUri = {
10707
10769
  SCHEMES,
10708
10770
  normalize: normalize3,
10709
- resolve: resolve37,
10771
+ resolve: resolve38,
10710
10772
  resolveComponent,
10711
10773
  equal,
10712
10774
  serialize,
@@ -13682,12 +13744,12 @@ var require_dist = __commonJS({
13682
13744
  throw new Error(`Unknown format "${name}"`);
13683
13745
  return f2;
13684
13746
  };
13685
- function addFormats(ajv, list, fs45, exportName) {
13747
+ function addFormats(ajv, list, fs46, exportName) {
13686
13748
  var _a3;
13687
13749
  var _b2;
13688
13750
  (_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
13689
13751
  for (const f2 of list)
13690
- ajv.addFormat(f2, fs45[f2]);
13752
+ ajv.addFormat(f2, fs46[f2]);
13691
13753
  }
13692
13754
  module2.exports = exports2 = formatsPlugin;
13693
13755
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -14787,15 +14849,15 @@ var require_route = __commonJS({
14787
14849
  };
14788
14850
  }
14789
14851
  function wrapConversion(toModel, graph) {
14790
- const path53 = [graph[toModel].parent, toModel];
14852
+ const path54 = [graph[toModel].parent, toModel];
14791
14853
  let fn = conversions[graph[toModel].parent][toModel];
14792
14854
  let cur = graph[toModel].parent;
14793
14855
  while (graph[cur].parent) {
14794
- path53.unshift(graph[cur].parent);
14856
+ path54.unshift(graph[cur].parent);
14795
14857
  fn = link(conversions[graph[cur].parent][cur], fn);
14796
14858
  cur = graph[cur].parent;
14797
14859
  }
14798
- fn.conversion = path53;
14860
+ fn.conversion = path54;
14799
14861
  return fn;
14800
14862
  }
14801
14863
  module2.exports = function(fromModel) {
@@ -20725,7 +20787,7 @@ var require_iso2022 = __commonJS({
20725
20787
  // node_modules/chardet/index.js
20726
20788
  var require_chardet = __commonJS({
20727
20789
  "node_modules/chardet/index.js"(exports2, module2) {
20728
- var fs45 = require("fs");
20790
+ var fs46 = require("fs");
20729
20791
  var utf8 = require_utf8();
20730
20792
  var unicode = require_unicode();
20731
20793
  var mbcs = require_mbcs();
@@ -20799,28 +20861,28 @@ var require_chardet = __commonJS({
20799
20861
  var fd;
20800
20862
  var handler = function(err, buffer) {
20801
20863
  if (fd) {
20802
- fs45.closeSync(fd);
20864
+ fs46.closeSync(fd);
20803
20865
  }
20804
20866
  if (err) return cb(err, null);
20805
20867
  cb(null, self.detect(buffer, opts));
20806
20868
  };
20807
20869
  if (opts && opts.sampleSize) {
20808
- fd = fs45.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
20809
- fs45.read(fd, sample, 0, opts.sampleSize, null, function(err) {
20870
+ fd = fs46.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
20871
+ fs46.read(fd, sample, 0, opts.sampleSize, null, function(err) {
20810
20872
  handler(err, sample);
20811
20873
  });
20812
20874
  return;
20813
20875
  }
20814
- fs45.readFile(filepath, handler);
20876
+ fs46.readFile(filepath, handler);
20815
20877
  };
20816
20878
  module2.exports.detectFileSync = function(filepath, opts) {
20817
20879
  if (opts && opts.sampleSize) {
20818
- var fd = fs45.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
20819
- fs45.readSync(fd, sample2, 0, opts.sampleSize);
20820
- fs45.closeSync(fd);
20880
+ var fd = fs46.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
20881
+ fs46.readSync(fd, sample2, 0, opts.sampleSize);
20882
+ fs46.closeSync(fd);
20821
20883
  return self.detect(sample2, opts);
20822
20884
  }
20823
- return self.detect(fs45.readFileSync(filepath), opts);
20885
+ return self.detect(fs46.readFileSync(filepath), opts);
20824
20886
  };
20825
20887
  module2.exports.detectAll = function(buffer, opts) {
20826
20888
  if (typeof opts !== "object") {
@@ -24285,16 +24347,16 @@ var require_os_tmpdir = __commonJS({
24285
24347
  var isWindows = process.platform === "win32";
24286
24348
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
24287
24349
  module2.exports = function() {
24288
- var path53;
24350
+ var path54;
24289
24351
  if (isWindows) {
24290
- path53 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24352
+ path54 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24291
24353
  } else {
24292
- path53 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24354
+ path54 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24293
24355
  }
24294
- if (trailingSlashRe.test(path53)) {
24295
- path53 = path53.slice(0, -1);
24356
+ if (trailingSlashRe.test(path54)) {
24357
+ path54 = path54.slice(0, -1);
24296
24358
  }
24297
- return path53;
24359
+ return path54;
24298
24360
  };
24299
24361
  }
24300
24362
  });
@@ -24302,8 +24364,8 @@ var require_os_tmpdir = __commonJS({
24302
24364
  // node_modules/tmp/lib/tmp.js
24303
24365
  var require_tmp = __commonJS({
24304
24366
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
24305
- var fs45 = require("fs");
24306
- var path53 = require("path");
24367
+ var fs46 = require("fs");
24368
+ var path54 = require("path");
24307
24369
  var crypto6 = require("crypto");
24308
24370
  var osTmpDir = require_os_tmpdir();
24309
24371
  var _c2 = process.binding("constants");
@@ -24345,7 +24407,7 @@ var require_tmp = __commonJS({
24345
24407
  }
24346
24408
  function _generateTmpName(opts) {
24347
24409
  if (opts.name) {
24348
- return path53.join(opts.dir || tmpDir, opts.name);
24410
+ return path54.join(opts.dir || tmpDir, opts.name);
24349
24411
  }
24350
24412
  if (opts.template) {
24351
24413
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -24356,7 +24418,7 @@ var require_tmp = __commonJS({
24356
24418
  _randomChars(12),
24357
24419
  opts.postfix || ""
24358
24420
  ].join("");
24359
- return path53.join(opts.dir || tmpDir, name);
24421
+ return path54.join(opts.dir || tmpDir, name);
24360
24422
  }
24361
24423
  function tmpName(options, callback) {
24362
24424
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -24366,7 +24428,7 @@ var require_tmp = __commonJS({
24366
24428
  return cb(new Error("Invalid template provided"));
24367
24429
  (function _getUniqueName() {
24368
24430
  const name = _generateTmpName(opts);
24369
- fs45.stat(name, function(err) {
24431
+ fs46.stat(name, function(err) {
24370
24432
  if (!err) {
24371
24433
  if (tries-- > 0) return _getUniqueName();
24372
24434
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -24384,7 +24446,7 @@ var require_tmp = __commonJS({
24384
24446
  do {
24385
24447
  const name = _generateTmpName(opts);
24386
24448
  try {
24387
- fs45.statSync(name);
24449
+ fs46.statSync(name);
24388
24450
  } catch (e2) {
24389
24451
  return name;
24390
24452
  }
@@ -24396,13 +24458,13 @@ var require_tmp = __commonJS({
24396
24458
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
24397
24459
  tmpName(opts, function _tmpNameCreated(err, name) {
24398
24460
  if (err) return cb(err);
24399
- fs45.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24461
+ fs46.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24400
24462
  if (err2) return cb(err2);
24401
24463
  if (opts.discardDescriptor) {
24402
- return fs45.close(fd, function _discardCallback(err3) {
24464
+ return fs46.close(fd, function _discardCallback(err3) {
24403
24465
  if (err3) {
24404
24466
  try {
24405
- fs45.unlinkSync(name);
24467
+ fs46.unlinkSync(name);
24406
24468
  } catch (e2) {
24407
24469
  if (!isENOENT(e2)) {
24408
24470
  err3 = e2;
@@ -24425,9 +24487,9 @@ var require_tmp = __commonJS({
24425
24487
  opts.postfix = opts.postfix || ".tmp";
24426
24488
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
24427
24489
  const name = tmpNameSync(opts);
24428
- var fd = fs45.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24490
+ var fd = fs46.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24429
24491
  if (opts.discardDescriptor) {
24430
- fs45.closeSync(fd);
24492
+ fs46.closeSync(fd);
24431
24493
  fd = void 0;
24432
24494
  }
24433
24495
  return {
@@ -24439,9 +24501,9 @@ var require_tmp = __commonJS({
24439
24501
  function _rmdirRecursiveSync(root) {
24440
24502
  const dirs = [root];
24441
24503
  do {
24442
- var dir2 = dirs.pop(), deferred = false, files = fs45.readdirSync(dir2);
24504
+ var dir2 = dirs.pop(), deferred = false, files = fs46.readdirSync(dir2);
24443
24505
  for (var i2 = 0, length = files.length; i2 < length; i2++) {
24444
- var file2 = path53.join(dir2, files[i2]), stat = fs45.lstatSync(file2);
24506
+ var file2 = path54.join(dir2, files[i2]), stat = fs46.lstatSync(file2);
24445
24507
  if (stat.isDirectory()) {
24446
24508
  if (!deferred) {
24447
24509
  deferred = true;
@@ -24449,11 +24511,11 @@ var require_tmp = __commonJS({
24449
24511
  }
24450
24512
  dirs.push(file2);
24451
24513
  } else {
24452
- fs45.unlinkSync(file2);
24514
+ fs46.unlinkSync(file2);
24453
24515
  }
24454
24516
  }
24455
24517
  if (!deferred) {
24456
- fs45.rmdirSync(dir2);
24518
+ fs46.rmdirSync(dir2);
24457
24519
  }
24458
24520
  } while (dirs.length !== 0);
24459
24521
  }
@@ -24461,7 +24523,7 @@ var require_tmp = __commonJS({
24461
24523
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
24462
24524
  tmpName(opts, function _tmpNameCreated(err, name) {
24463
24525
  if (err) return cb(err);
24464
- fs45.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24526
+ fs46.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24465
24527
  if (err2) return cb(err2);
24466
24528
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
24467
24529
  });
@@ -24470,7 +24532,7 @@ var require_tmp = __commonJS({
24470
24532
  function dirSync(options) {
24471
24533
  var args = _parseArguments(options), opts = args[0];
24472
24534
  const name = tmpNameSync(opts);
24473
- fs45.mkdirSync(name, opts.mode || DIR_MODE);
24535
+ fs46.mkdirSync(name, opts.mode || DIR_MODE);
24474
24536
  return {
24475
24537
  name,
24476
24538
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -24480,7 +24542,7 @@ var require_tmp = __commonJS({
24480
24542
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
24481
24543
  try {
24482
24544
  if (0 <= fdPath[0]) {
24483
- fs45.closeSync(fdPath[0]);
24545
+ fs46.closeSync(fdPath[0]);
24484
24546
  }
24485
24547
  } catch (e2) {
24486
24548
  if (!isEBADF(e2) && !isENOENT(e2)) {
@@ -24488,7 +24550,7 @@ var require_tmp = __commonJS({
24488
24550
  }
24489
24551
  }
24490
24552
  try {
24491
- fs45.unlinkSync(fdPath[1]);
24553
+ fs46.unlinkSync(fdPath[1]);
24492
24554
  } catch (e2) {
24493
24555
  if (!isENOENT(e2)) {
24494
24556
  throw e2;
@@ -24501,7 +24563,7 @@ var require_tmp = __commonJS({
24501
24563
  return removeCallback;
24502
24564
  }
24503
24565
  function _prepareTmpDirRemoveCallback(name, opts) {
24504
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs45.rmdirSync.bind(fs45);
24566
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs46.rmdirSync.bind(fs46);
24505
24567
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
24506
24568
  if (!opts.keep) {
24507
24569
  _removeObjects.unshift(removeCallback);
@@ -25652,7 +25714,7 @@ var require_Observable = __commonJS({
25652
25714
  Observable2.prototype.forEach = function(next, promiseCtor) {
25653
25715
  var _this = this;
25654
25716
  promiseCtor = getPromiseCtor(promiseCtor);
25655
- return new promiseCtor(function(resolve37, reject) {
25717
+ return new promiseCtor(function(resolve38, reject) {
25656
25718
  var subscriber = new Subscriber_1.SafeSubscriber({
25657
25719
  next: function(value) {
25658
25720
  try {
@@ -25663,7 +25725,7 @@ var require_Observable = __commonJS({
25663
25725
  }
25664
25726
  },
25665
25727
  error: reject,
25666
- complete: resolve37
25728
+ complete: resolve38
25667
25729
  });
25668
25730
  _this.subscribe(subscriber);
25669
25731
  });
@@ -25685,14 +25747,14 @@ var require_Observable = __commonJS({
25685
25747
  Observable2.prototype.toPromise = function(promiseCtor) {
25686
25748
  var _this = this;
25687
25749
  promiseCtor = getPromiseCtor(promiseCtor);
25688
- return new promiseCtor(function(resolve37, reject) {
25750
+ return new promiseCtor(function(resolve38, reject) {
25689
25751
  var value;
25690
25752
  _this.subscribe(function(x2) {
25691
25753
  return value = x2;
25692
25754
  }, function(err) {
25693
25755
  return reject(err);
25694
25756
  }, function() {
25695
- return resolve37(value);
25757
+ return resolve38(value);
25696
25758
  });
25697
25759
  });
25698
25760
  };
@@ -27788,11 +27850,11 @@ var require_innerFrom = __commonJS({
27788
27850
  "use strict";
27789
27851
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
27790
27852
  function adopt(value) {
27791
- return value instanceof P2 ? value : new P2(function(resolve37) {
27792
- resolve37(value);
27853
+ return value instanceof P2 ? value : new P2(function(resolve38) {
27854
+ resolve38(value);
27793
27855
  });
27794
27856
  }
27795
- return new (P2 || (P2 = Promise))(function(resolve37, reject) {
27857
+ return new (P2 || (P2 = Promise))(function(resolve38, reject) {
27796
27858
  function fulfilled(value) {
27797
27859
  try {
27798
27860
  step(generator.next(value));
@@ -27808,7 +27870,7 @@ var require_innerFrom = __commonJS({
27808
27870
  }
27809
27871
  }
27810
27872
  function step(result) {
27811
- result.done ? resolve37(result.value) : adopt(result.value).then(fulfilled, rejected);
27873
+ result.done ? resolve38(result.value) : adopt(result.value).then(fulfilled, rejected);
27812
27874
  }
27813
27875
  step((generator = generator.apply(thisArg, _arguments || [])).next());
27814
27876
  });
@@ -27890,14 +27952,14 @@ var require_innerFrom = __commonJS({
27890
27952
  }, i2);
27891
27953
  function verb(n2) {
27892
27954
  i2[n2] = o2[n2] && function(v2) {
27893
- return new Promise(function(resolve37, reject) {
27894
- v2 = o2[n2](v2), settle(resolve37, reject, v2.done, v2.value);
27955
+ return new Promise(function(resolve38, reject) {
27956
+ v2 = o2[n2](v2), settle(resolve38, reject, v2.done, v2.value);
27895
27957
  });
27896
27958
  };
27897
27959
  }
27898
- function settle(resolve37, reject, d2, v2) {
27960
+ function settle(resolve38, reject, d2, v2) {
27899
27961
  Promise.resolve(v2).then(function(v3) {
27900
- resolve37({ value: v3, done: d2 });
27962
+ resolve38({ value: v3, done: d2 });
27901
27963
  }, reject);
27902
27964
  }
27903
27965
  };
@@ -28516,7 +28578,7 @@ var require_lastValueFrom = __commonJS({
28516
28578
  var EmptyError_1 = require_EmptyError();
28517
28579
  function lastValueFrom2(source, config2) {
28518
28580
  var hasConfig = typeof config2 === "object";
28519
- return new Promise(function(resolve37, reject) {
28581
+ return new Promise(function(resolve38, reject) {
28520
28582
  var _hasValue = false;
28521
28583
  var _value;
28522
28584
  source.subscribe({
@@ -28527,9 +28589,9 @@ var require_lastValueFrom = __commonJS({
28527
28589
  error: reject,
28528
28590
  complete: function() {
28529
28591
  if (_hasValue) {
28530
- resolve37(_value);
28592
+ resolve38(_value);
28531
28593
  } else if (hasConfig) {
28532
- resolve37(config2.defaultValue);
28594
+ resolve38(config2.defaultValue);
28533
28595
  } else {
28534
28596
  reject(new EmptyError_1.EmptyError());
28535
28597
  }
@@ -28551,16 +28613,16 @@ var require_firstValueFrom = __commonJS({
28551
28613
  var Subscriber_1 = require_Subscriber();
28552
28614
  function firstValueFrom(source, config2) {
28553
28615
  var hasConfig = typeof config2 === "object";
28554
- return new Promise(function(resolve37, reject) {
28616
+ return new Promise(function(resolve38, reject) {
28555
28617
  var subscriber = new Subscriber_1.SafeSubscriber({
28556
28618
  next: function(value) {
28557
- resolve37(value);
28619
+ resolve38(value);
28558
28620
  subscriber.unsubscribe();
28559
28621
  },
28560
28622
  error: reject,
28561
28623
  complete: function() {
28562
28624
  if (hasConfig) {
28563
- resolve37(config2.defaultValue);
28625
+ resolve38(config2.defaultValue);
28564
28626
  } else {
28565
28627
  reject(new EmptyError_1.EmptyError());
28566
28628
  }
@@ -34353,14 +34415,14 @@ var require_run_async = __commonJS({
34353
34415
  return function() {
34354
34416
  var args = arguments;
34355
34417
  var originalThis = this;
34356
- var promise = new Promise(function(resolve37, reject) {
34418
+ var promise = new Promise(function(resolve38, reject) {
34357
34419
  var resolved = false;
34358
34420
  const wrappedResolve = function(value) {
34359
34421
  if (resolved) {
34360
34422
  console.warn("Run-async promise already resolved.");
34361
34423
  }
34362
34424
  resolved = true;
34363
- resolve37(value);
34425
+ resolve38(value);
34364
34426
  };
34365
34427
  var rejected = false;
34366
34428
  const wrappedReject = function(value) {
@@ -35714,11 +35776,11 @@ var parser = new YargsParser({
35714
35776
  resolve: import_path2.resolve,
35715
35777
  // TODO: figure out a way to combine ESM and CJS coverage, such that
35716
35778
  // we can exercise all the lines below:
35717
- require: (path53) => {
35779
+ require: (path54) => {
35718
35780
  if (typeof require !== "undefined") {
35719
- return require(path53);
35720
- } else if (path53.match(/\.json$/)) {
35721
- return JSON.parse((0, import_fs2.readFileSync)(path53, "utf8"));
35781
+ return require(path54);
35782
+ } else if (path54.match(/\.json$/)) {
35783
+ return JSON.parse((0, import_fs2.readFileSync)(path54, "utf8"));
35722
35784
  } else {
35723
35785
  throw Error("only .json config files are supported in ESM");
35724
35786
  }
@@ -38244,12 +38306,12 @@ var YargsInstance = class {
38244
38306
  async getCompletion(args, done) {
38245
38307
  argsert("<array> [function]", [args, done], arguments.length);
38246
38308
  if (!done) {
38247
- return new Promise((resolve37, reject) => {
38309
+ return new Promise((resolve38, reject) => {
38248
38310
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
38249
38311
  if (err)
38250
38312
  reject(err);
38251
38313
  else
38252
- resolve37(completions);
38314
+ resolve38(completions);
38253
38315
  });
38254
38316
  });
38255
38317
  } else {
@@ -40399,8 +40461,8 @@ function getErrorMap() {
40399
40461
 
40400
40462
  // node_modules/zod/v3/helpers/parseUtil.js
40401
40463
  var makeIssue = (params) => {
40402
- const { data, path: path53, errorMaps, issueData } = params;
40403
- const fullPath = [...path53, ...issueData.path || []];
40464
+ const { data, path: path54, errorMaps, issueData } = params;
40465
+ const fullPath = [...path54, ...issueData.path || []];
40404
40466
  const fullIssue = {
40405
40467
  ...issueData,
40406
40468
  path: fullPath
@@ -40516,11 +40578,11 @@ var errorUtil;
40516
40578
 
40517
40579
  // node_modules/zod/v3/types.js
40518
40580
  var ParseInputLazyPath = class {
40519
- constructor(parent, value, path53, key) {
40581
+ constructor(parent, value, path54, key) {
40520
40582
  this._cachedPath = [];
40521
40583
  this.parent = parent;
40522
40584
  this.data = value;
40523
- this._path = path53;
40585
+ this._path = path54;
40524
40586
  this._key = key;
40525
40587
  }
40526
40588
  get path() {
@@ -44659,16 +44721,16 @@ async function handleAgentSkills(options) {
44659
44721
  }
44660
44722
  async function askYesNo(question) {
44661
44723
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
44662
- return new Promise((resolve37) => {
44724
+ return new Promise((resolve38) => {
44663
44725
  process.stderr.write(`${question} `);
44664
44726
  rl.once("line", (answer) => {
44665
44727
  rl.close();
44666
44728
  const trimmed = answer.trim();
44667
44729
  if (trimmed === "") {
44668
- resolve37(true);
44730
+ resolve38(true);
44669
44731
  return;
44670
44732
  }
44671
- resolve37(/^y(es)?$/i.test(trimmed));
44733
+ resolve38(/^y(es)?$/i.test(trimmed));
44672
44734
  });
44673
44735
  });
44674
44736
  }
@@ -44747,7 +44809,7 @@ function handleRemove(argv) {
44747
44809
  }
44748
44810
 
44749
44811
  // src/cli/commands/env.ts
44750
- var path46 = __toESM(require("path"));
44812
+ var path47 = __toESM(require("path"));
44751
44813
 
44752
44814
  // src/core/harness.ts
44753
44815
  var fs20 = __toESM(require("fs"));
@@ -45526,13 +45588,13 @@ var MultipartBody = class {
45526
45588
  // node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
45527
45589
  var import_web = require("node:stream/web");
45528
45590
  var fileFromPathWarned = false;
45529
- async function fileFromPath3(path53, ...args) {
45591
+ async function fileFromPath3(path54, ...args) {
45530
45592
  const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
45531
45593
  if (!fileFromPathWarned) {
45532
- console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path53)}) instead`);
45594
+ console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path54)}) instead`);
45533
45595
  fileFromPathWarned = true;
45534
45596
  }
45535
- return await _fileFromPath(path53, ...args);
45597
+ return await _fileFromPath(path54, ...args);
45536
45598
  }
45537
45599
  var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
45538
45600
  var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
@@ -46028,8 +46090,8 @@ async function defaultParseResponse(props) {
46028
46090
  }
46029
46091
  var APIPromise = class _APIPromise extends Promise {
46030
46092
  constructor(responsePromise, parseResponse = defaultParseResponse) {
46031
- super((resolve37) => {
46032
- resolve37(null);
46093
+ super((resolve38) => {
46094
+ resolve38(null);
46033
46095
  });
46034
46096
  this.responsePromise = responsePromise;
46035
46097
  this.parseResponse = parseResponse;
@@ -46129,29 +46191,29 @@ var APIClient = class {
46129
46191
  defaultIdempotencyKey() {
46130
46192
  return `stainless-node-retry-${uuid4()}`;
46131
46193
  }
46132
- get(path53, opts) {
46133
- return this.methodRequest("get", path53, opts);
46194
+ get(path54, opts) {
46195
+ return this.methodRequest("get", path54, opts);
46134
46196
  }
46135
- post(path53, opts) {
46136
- return this.methodRequest("post", path53, opts);
46197
+ post(path54, opts) {
46198
+ return this.methodRequest("post", path54, opts);
46137
46199
  }
46138
- patch(path53, opts) {
46139
- return this.methodRequest("patch", path53, opts);
46200
+ patch(path54, opts) {
46201
+ return this.methodRequest("patch", path54, opts);
46140
46202
  }
46141
- put(path53, opts) {
46142
- return this.methodRequest("put", path53, opts);
46203
+ put(path54, opts) {
46204
+ return this.methodRequest("put", path54, opts);
46143
46205
  }
46144
- delete(path53, opts) {
46145
- return this.methodRequest("delete", path53, opts);
46206
+ delete(path54, opts) {
46207
+ return this.methodRequest("delete", path54, opts);
46146
46208
  }
46147
- methodRequest(method, path53, opts) {
46209
+ methodRequest(method, path54, opts) {
46148
46210
  return this.request(Promise.resolve(opts).then(async (opts2) => {
46149
46211
  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;
46150
- return { method, path: path53, ...opts2, body };
46212
+ return { method, path: path54, ...opts2, body };
46151
46213
  }));
46152
46214
  }
46153
- getAPIList(path53, Page, opts) {
46154
- return this.requestAPIList(Page, { method: "get", path: path53, ...opts });
46215
+ getAPIList(path54, Page, opts) {
46216
+ return this.requestAPIList(Page, { method: "get", path: path54, ...opts });
46155
46217
  }
46156
46218
  calculateContentLength(body) {
46157
46219
  if (typeof body === "string") {
@@ -46169,10 +46231,10 @@ var APIClient = class {
46169
46231
  return null;
46170
46232
  }
46171
46233
  buildRequest(options) {
46172
- const { method, path: path53, query, headers = {} } = options;
46234
+ const { method, path: path54, query, headers = {} } = options;
46173
46235
  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;
46174
46236
  const contentLength = this.calculateContentLength(body);
46175
- const url = this.buildURL(path53, query);
46237
+ const url = this.buildURL(path54, query);
46176
46238
  if ("timeout" in options)
46177
46239
  validatePositiveInteger("timeout", options.timeout);
46178
46240
  const timeout = options.timeout ?? this.timeout;
@@ -46281,8 +46343,8 @@ var APIClient = class {
46281
46343
  const request = this.makeRequest(options, null);
46282
46344
  return new PagePromise(this, request, Page);
46283
46345
  }
46284
- buildURL(path53, query) {
46285
- const url = isAbsoluteURL(path53) ? new URL(path53) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path53.startsWith("/") ? path53.slice(1) : path53));
46346
+ buildURL(path54, query) {
46347
+ const url = isAbsoluteURL(path54) ? new URL(path54) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path54.startsWith("/") ? path54.slice(1) : path54));
46286
46348
  const defaultQuery = this.defaultQuery();
46287
46349
  if (!isEmptyObj(defaultQuery)) {
46288
46350
  query = { ...defaultQuery, ...query };
@@ -46567,7 +46629,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
46567
46629
  var isAbsoluteURL = (url) => {
46568
46630
  return startsWithSchemeRegexp.test(url);
46569
46631
  };
46570
- var sleep = (ms) => new Promise((resolve37) => setTimeout(resolve37, ms));
46632
+ var sleep = (ms) => new Promise((resolve38) => setTimeout(resolve38, ms));
46571
46633
  var validatePositiveInteger = (name, n2) => {
46572
46634
  if (typeof n2 !== "number" || !Number.isInteger(n2)) {
46573
46635
  throw new AnthropicError(`${name} must be an integer`);
@@ -47058,12 +47120,12 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
47058
47120
  }
47059
47121
  return this._emit("error", new AnthropicError(String(error3)));
47060
47122
  });
47061
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve37, reject) => {
47062
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve37, "f");
47123
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve38, reject) => {
47124
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve38, "f");
47063
47125
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
47064
47126
  }), "f");
47065
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve37, reject) => {
47066
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve37, "f");
47127
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve38, reject) => {
47128
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve38, "f");
47067
47129
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
47068
47130
  }), "f");
47069
47131
  __classPrivateFieldGet8(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {
@@ -47192,11 +47254,11 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
47192
47254
  * const message = await stream.emitted('message') // rejects if the stream errors
47193
47255
  */
47194
47256
  emitted(event) {
47195
- return new Promise((resolve37, reject) => {
47257
+ return new Promise((resolve38, reject) => {
47196
47258
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
47197
47259
  if (event !== "error")
47198
47260
  this.once("error", reject);
47199
- this.once(event, resolve37);
47261
+ this.once(event, resolve38);
47200
47262
  });
47201
47263
  }
47202
47264
  async done() {
@@ -47423,7 +47485,7 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
47423
47485
  if (done) {
47424
47486
  return { value: void 0, done: true };
47425
47487
  }
47426
- return new Promise((resolve37, reject) => readQueue.push({ resolve: resolve37, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47488
+ return new Promise((resolve38, reject) => readQueue.push({ resolve: resolve38, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47427
47489
  }
47428
47490
  const chunk = pushQueue.shift();
47429
47491
  return { value: chunk, done: false };
@@ -47571,12 +47633,12 @@ var MessageStream = class _MessageStream {
47571
47633
  }
47572
47634
  return this._emit("error", new AnthropicError(String(error3)));
47573
47635
  });
47574
- __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve37, reject) => {
47575
- __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve37, "f");
47636
+ __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve38, reject) => {
47637
+ __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve38, "f");
47576
47638
  __classPrivateFieldSet8(this, _MessageStream_rejectConnectedPromise, reject, "f");
47577
47639
  }), "f");
47578
- __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve37, reject) => {
47579
- __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve37, "f");
47640
+ __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve38, reject) => {
47641
+ __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve38, "f");
47580
47642
  __classPrivateFieldSet8(this, _MessageStream_rejectEndPromise, reject, "f");
47581
47643
  }), "f");
47582
47644
  __classPrivateFieldGet9(this, _MessageStream_connectedPromise, "f").catch(() => {
@@ -47705,11 +47767,11 @@ var MessageStream = class _MessageStream {
47705
47767
  * const message = await stream.emitted('message') // rejects if the stream errors
47706
47768
  */
47707
47769
  emitted(event) {
47708
- return new Promise((resolve37, reject) => {
47770
+ return new Promise((resolve38, reject) => {
47709
47771
  __classPrivateFieldSet8(this, _MessageStream_catchingPromiseCreated, true, "f");
47710
47772
  if (event !== "error")
47711
47773
  this.once("error", reject);
47712
- this.once(event, resolve37);
47774
+ this.once(event, resolve38);
47713
47775
  });
47714
47776
  }
47715
47777
  async done() {
@@ -47936,7 +47998,7 @@ var MessageStream = class _MessageStream {
47936
47998
  if (done) {
47937
47999
  return { value: void 0, done: true };
47938
48000
  }
47939
- return new Promise((resolve37, reject) => readQueue.push({ resolve: resolve37, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
48001
+ return new Promise((resolve38, reject) => readQueue.push({ resolve: resolve38, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47940
48002
  }
47941
48003
  const chunk = pushQueue.shift();
47942
48004
  return { value: chunk, done: false };
@@ -48196,11 +48258,11 @@ async function promptApplyAgentMdProposal(repoPath) {
48196
48258
  }
48197
48259
  async function askYesNo2(question) {
48198
48260
  const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
48199
- return new Promise((resolve37) => {
48261
+ return new Promise((resolve38) => {
48200
48262
  process.stderr.write(`${question} `);
48201
48263
  rl.once("line", (answer) => {
48202
48264
  rl.close();
48203
- resolve37(/^y(es)?$/i.test(answer.trim()));
48265
+ resolve38(/^y(es)?$/i.test(answer.trim()));
48204
48266
  });
48205
48267
  });
48206
48268
  }
@@ -48430,7 +48492,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
48430
48492
  }
48431
48493
  async function askUser(question, options) {
48432
48494
  const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
48433
- return new Promise((resolve37) => {
48495
+ return new Promise((resolve38) => {
48434
48496
  process.stderr.write("\n");
48435
48497
  process.stderr.write(`\u2753 ${question}
48436
48498
  `);
@@ -48441,7 +48503,7 @@ async function askUser(question, options) {
48441
48503
  process.stderr.write("> ");
48442
48504
  rl.once("line", (answer) => {
48443
48505
  rl.close();
48444
- resolve37(answer.trim());
48506
+ resolve38(answer.trim());
48445
48507
  });
48446
48508
  });
48447
48509
  }
@@ -48585,7 +48647,7 @@ function runScript(scriptPath, args = [], options = {}) {
48585
48647
  function runScriptCapture(scriptPath, args = [], options = {}) {
48586
48648
  const stream = options.stream ?? false;
48587
48649
  const { stream: _stream, ...spawnOptions } = options;
48588
- return new Promise((resolve37) => {
48650
+ return new Promise((resolve38) => {
48589
48651
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
48590
48652
  ...spawnOptions,
48591
48653
  stdio: ["inherit", "pipe", "pipe"]
@@ -48600,13 +48662,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
48600
48662
  stderr += d2;
48601
48663
  if (stream) process.stderr.write(d2);
48602
48664
  });
48603
- proc.on("close", (code) => resolve37({ stdout, stderr, code: code ?? 0 }));
48665
+ proc.on("close", (code) => resolve38({ stdout, stderr, code: code ?? 0 }));
48604
48666
  });
48605
48667
  }
48606
48668
  function runShellCommand(command2, options = {}) {
48607
48669
  const stream = options.stream ?? false;
48608
48670
  const { stream: _stream, ...spawnOptions } = options;
48609
- return new Promise((resolve37) => {
48671
+ return new Promise((resolve38) => {
48610
48672
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
48611
48673
  ...spawnOptions,
48612
48674
  stdio: ["inherit", "pipe", "pipe"]
@@ -48621,7 +48683,7 @@ function runShellCommand(command2, options = {}) {
48621
48683
  stderr += d2;
48622
48684
  if (stream) process.stderr.write(d2);
48623
48685
  });
48624
- proc.on("close", (code) => resolve37({ stdout, stderr, code: code ?? 0 }));
48686
+ proc.on("close", (code) => resolve38({ stdout, stderr, code: code ?? 0 }));
48625
48687
  });
48626
48688
  }
48627
48689
 
@@ -49677,6 +49739,81 @@ function addCustomStage(repoPath, options) {
49677
49739
  // src/harness/adaptation-prompt.ts
49678
49740
  var fs22 = __toESM(require("fs"));
49679
49741
  var path21 = __toESM(require("path"));
49742
+ var readline4 = __toESM(require("readline"));
49743
+
49744
+ // src/utils/clipboard.ts
49745
+ var import_child_process2 = require("child_process");
49746
+ function commandExists(command2) {
49747
+ const probe = process.platform === "win32" ? (0, import_child_process2.spawnSync)("where", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] }) : (0, import_child_process2.spawnSync)("which", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] });
49748
+ return probe.status === 0;
49749
+ }
49750
+ function tryPipeCommand(command2, args, text) {
49751
+ const result = (0, import_child_process2.spawnSync)(command2, args, {
49752
+ input: text,
49753
+ encoding: "utf8",
49754
+ stdio: ["pipe", "ignore", "ignore"]
49755
+ });
49756
+ return result.status === 0 && !result.error;
49757
+ }
49758
+ function writeOsc52Clipboard(text, stream = process.stderr) {
49759
+ if (!("isTTY" in stream) || !stream.isTTY) return false;
49760
+ if (Buffer.byteLength(text, "utf8") > 2e5) return false;
49761
+ const b64 = Buffer.from(text, "utf8").toString("base64");
49762
+ stream.write(`\x1B]52;c;${b64}\x07`);
49763
+ return true;
49764
+ }
49765
+ function copyViaPlatformTools(text) {
49766
+ if (process.platform === "darwin" && commandExists("pbcopy")) {
49767
+ if (tryPipeCommand("pbcopy", [], text)) return { ok: true, method: "pbcopy" };
49768
+ }
49769
+ if (process.platform === "win32") {
49770
+ if (commandExists("powershell")) {
49771
+ const result = (0, import_child_process2.spawnSync)(
49772
+ "powershell",
49773
+ [
49774
+ "-NoProfile",
49775
+ "-NonInteractive",
49776
+ "-Command",
49777
+ "$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new(); Set-Clipboard -Value ([Console]::In.ReadToEnd())"
49778
+ ],
49779
+ {
49780
+ input: text,
49781
+ encoding: "utf8",
49782
+ stdio: ["pipe", "ignore", "ignore"]
49783
+ }
49784
+ );
49785
+ if (result.status === 0 && !result.error) return { ok: true, method: "powershell" };
49786
+ }
49787
+ if (commandExists("clip") && tryPipeCommand("clip", [], text)) {
49788
+ return { ok: true, method: "clip" };
49789
+ }
49790
+ }
49791
+ if (process.platform === "linux" || process.platform === "freebsd" || process.platform === "openbsd") {
49792
+ if (commandExists("wl-copy") && tryPipeCommand("wl-copy", [], text)) {
49793
+ return { ok: true, method: "wl-copy" };
49794
+ }
49795
+ if (commandExists("xclip") && tryPipeCommand("xclip", ["-selection", "clipboard"], text)) {
49796
+ return { ok: true, method: "xclip" };
49797
+ }
49798
+ if (commandExists("xsel") && tryPipeCommand("xsel", ["--clipboard", "--input"], text)) {
49799
+ return { ok: true, method: "xsel" };
49800
+ }
49801
+ }
49802
+ return {
49803
+ ok: false,
49804
+ detail: "No system clipboard command available (pbcopy, wl-copy/xclip/xsel, or clip)"
49805
+ };
49806
+ }
49807
+ function copyTextToClipboard(text) {
49808
+ const platform = copyViaPlatformTools(text);
49809
+ if (platform.ok) return platform;
49810
+ if (writeOsc52Clipboard(text)) {
49811
+ return { ok: true, method: "osc52" };
49812
+ }
49813
+ return platform;
49814
+ }
49815
+
49816
+ // src/harness/adaptation-prompt.ts
49680
49817
  var ADAPTATION_PROMPT_FILE = "ADAPT-PROMPT.md";
49681
49818
  var PROFILE_HINTS = {
49682
49819
  default: "Web app profile (SaaS/full-stack) \u2014 Docker Compose for shared infra (HARNESS_INFRA_SERVICES), PM2 for the primary application only, git worktree per agent slot by default. Launch provisions toolchain via harness.env (HARNESS_ECOSYSTEM, HARNESS_INSTALL_CMD) and writes paths to .env.agent.<id>. Identify the primary app agents modify; run supporting services shared.",
@@ -49727,11 +49864,47 @@ function printAdaptationPrompt(content) {
49727
49864
  `);
49728
49865
  process.stderr.write("\n");
49729
49866
  }
49867
+ function askYesNo3(question) {
49868
+ const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
49869
+ return new Promise((resolve38) => {
49870
+ process.stderr.write(`${question} `);
49871
+ rl.once("line", (answer) => {
49872
+ rl.close();
49873
+ const trimmed = answer.trim();
49874
+ resolve38(trimmed === "" || /^y(es)?$/i.test(trimmed));
49875
+ });
49876
+ });
49877
+ }
49878
+ async function offerAdaptationPromptClipboard(content, options = {}) {
49879
+ const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY);
49880
+ if (!interactive && !options.autoYes) {
49881
+ info("Prompt also saved to .har/ADAPT-PROMPT.md (open or copy from there)");
49882
+ return false;
49883
+ }
49884
+ let shouldCopy = options.autoYes === true;
49885
+ if (!shouldCopy && interactive) {
49886
+ shouldCopy = await askYesNo3("Copy adaptation prompt to clipboard for your coding agent? [Y/n]");
49887
+ }
49888
+ if (!shouldCopy) {
49889
+ info("Skipped clipboard copy \u2014 prompt is in .har/ADAPT-PROMPT.md");
49890
+ return false;
49891
+ }
49892
+ const result = copyTextToClipboard(content);
49893
+ if (result.ok) {
49894
+ success(
49895
+ result.method === "osc52" ? "Copied adaptation prompt to clipboard (terminal OSC 52) \u2014 paste into your coding agent" : "Copied adaptation prompt to clipboard \u2014 paste into your coding agent"
49896
+ );
49897
+ return true;
49898
+ }
49899
+ warn(`Could not copy to clipboard: ${result.detail}`);
49900
+ info("Open .har/ADAPT-PROMPT.md and paste that into your coding agent instead");
49901
+ return false;
49902
+ }
49730
49903
 
49731
49904
  // src/harness/cursor-rule.ts
49732
49905
  var fs23 = __toESM(require("fs"));
49733
49906
  var path22 = __toESM(require("path"));
49734
- var readline4 = __toESM(require("readline"));
49907
+ var readline5 = __toESM(require("readline"));
49735
49908
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
49736
49909
  function getCursorRulePath(repoPath) {
49737
49910
  return path22.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
@@ -49781,20 +49954,20 @@ async function handleCursorRule(options) {
49781
49954
  }
49782
49955
  async function promptScaffoldCursorRule(exists) {
49783
49956
  const action = exists ? "Update" : "Create";
49784
- return askYesNo3(`${action} ${CURSOR_RULE_RELATIVE_PATH}? [Y/n]`);
49957
+ return askYesNo4(`${action} ${CURSOR_RULE_RELATIVE_PATH}? [Y/n]`);
49785
49958
  }
49786
- async function askYesNo3(question) {
49787
- const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
49788
- return new Promise((resolve37) => {
49959
+ async function askYesNo4(question) {
49960
+ const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
49961
+ return new Promise((resolve38) => {
49789
49962
  process.stderr.write(`${question} `);
49790
49963
  rl.once("line", (answer) => {
49791
49964
  rl.close();
49792
49965
  const trimmed = answer.trim();
49793
49966
  if (trimmed === "") {
49794
- resolve37(true);
49967
+ resolve38(true);
49795
49968
  return;
49796
49969
  }
49797
- resolve37(/^y(es)?$/i.test(trimmed));
49970
+ resolve38(/^y(es)?$/i.test(trimmed));
49798
49971
  });
49799
49972
  });
49800
49973
  }
@@ -50104,19 +50277,19 @@ var LocalScriptExecutor = class {
50104
50277
  var localScriptExecutor = new LocalScriptExecutor();
50105
50278
 
50106
50279
  // src/core/control-sync.ts
50107
- var path40 = __toESM(require("path"));
50280
+ var path41 = __toESM(require("path"));
50108
50281
  init_control_config();
50109
50282
 
50110
50283
  // src/core/control-registry.ts
50111
- var fs27 = __toESM(require("fs"));
50112
- var os4 = __toESM(require("os"));
50113
- var path26 = __toESM(require("path"));
50284
+ var fs28 = __toESM(require("fs"));
50285
+ var os5 = __toESM(require("os"));
50286
+ var path27 = __toESM(require("path"));
50114
50287
 
50115
50288
  // src/core/control-repo-path.ts
50116
- var fs26 = __toESM(require("fs"));
50117
- var path25 = __toESM(require("path"));
50289
+ var fs27 = __toESM(require("fs"));
50290
+ var path26 = __toESM(require("path"));
50118
50291
  function tryGit(cwd, args) {
50119
- if (!fs26.existsSync(cwd)) return void 0;
50292
+ if (!fs27.existsSync(cwd)) return void 0;
50120
50293
  const result = run(`git ${args}`, { cwd });
50121
50294
  return result.code === 0 ? result.stdout.trim() : void 0;
50122
50295
  }
@@ -50124,58 +50297,58 @@ function resolveMainWorkingTree(cwd) {
50124
50297
  const toplevel = tryGit(cwd, "rev-parse --show-toplevel");
50125
50298
  if (!toplevel) return void 0;
50126
50299
  const commonDirRaw = tryGit(cwd, "rev-parse --git-common-dir");
50127
- const commonDir = commonDirRaw ? path25.resolve(cwd, commonDirRaw) : void 0;
50128
- if (!commonDir) return path25.resolve(toplevel);
50129
- if (path25.basename(commonDir) === ".git") {
50130
- return path25.dirname(commonDir);
50300
+ const commonDir = commonDirRaw ? path26.resolve(cwd, commonDirRaw) : void 0;
50301
+ if (!commonDir) return path26.resolve(toplevel);
50302
+ if (path26.basename(commonDir) === ".git") {
50303
+ return path26.dirname(commonDir);
50131
50304
  }
50132
50305
  const porcelain = tryGit(cwd, "worktree list --porcelain");
50133
50306
  if (porcelain) {
50134
50307
  for (const line of porcelain.split("\n")) {
50135
50308
  if (line.startsWith("worktree ")) {
50136
- return path25.resolve(line.slice("worktree ".length));
50309
+ return path26.resolve(line.slice("worktree ".length));
50137
50310
  }
50138
50311
  }
50139
50312
  }
50140
- return path25.resolve(toplevel);
50313
+ return path26.resolve(toplevel);
50141
50314
  }
50142
50315
  function canonicalizeControlRepoPath(repoPath) {
50143
- const resolved = path25.resolve(repoPath);
50316
+ const resolved = path26.resolve(repoPath);
50144
50317
  const toplevel = tryGit(resolved, "rev-parse --show-toplevel");
50145
50318
  if (!toplevel) return resolved;
50146
50319
  const mainRoot = resolveMainWorkingTree(resolved);
50147
50320
  if (!mainRoot) return resolved;
50148
- const top2 = path25.resolve(toplevel);
50149
- const main = path25.resolve(mainRoot);
50321
+ const top2 = path26.resolve(toplevel);
50322
+ const main = path26.resolve(mainRoot);
50150
50323
  if (top2 === main) return resolved;
50151
- const rel = path25.relative(top2, resolved);
50324
+ const rel = path26.relative(top2, resolved);
50152
50325
  if (!rel || rel === ".") return main;
50153
- if (rel.startsWith(`..${path25.sep}`) || rel === ".." || path25.isAbsolute(rel)) {
50326
+ if (rel.startsWith(`..${path26.sep}`) || rel === ".." || path26.isAbsolute(rel)) {
50154
50327
  return resolved;
50155
50328
  }
50156
- return path25.resolve(main, rel);
50329
+ return path26.resolve(main, rel);
50157
50330
  }
50158
50331
 
50159
50332
  // src/core/control-registry.ts
50160
50333
  function getRegistryPath() {
50161
50334
  if (process.env.HAR_CONTROL_REGISTRY_PATH) {
50162
- return path26.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
50335
+ return path27.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
50163
50336
  }
50164
- return path26.join(os4.homedir(), ".har", "repos.json");
50337
+ return path27.join(os5.homedir(), ".har", "repos.json");
50165
50338
  }
50166
50339
  function readRegistry() {
50167
50340
  const registryPath = getRegistryPath();
50168
50341
  try {
50169
- if (!fs27.existsSync(registryPath)) return { repos: [] };
50170
- return JSON.parse(fs27.readFileSync(registryPath, "utf8"));
50342
+ if (!fs28.existsSync(registryPath)) return { repos: [] };
50343
+ return JSON.parse(fs28.readFileSync(registryPath, "utf8"));
50171
50344
  } catch {
50172
50345
  return { repos: [] };
50173
50346
  }
50174
50347
  }
50175
50348
  function writeRegistry(registry2) {
50176
50349
  const registryPath = getRegistryPath();
50177
- fs27.mkdirSync(path26.dirname(registryPath), { recursive: true });
50178
- fs27.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
50350
+ fs28.mkdirSync(path27.dirname(registryPath), { recursive: true });
50351
+ fs28.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
50179
50352
  }
50180
50353
  function registryChanged(before, after) {
50181
50354
  if (before.length !== after.length) return true;
@@ -50197,7 +50370,7 @@ function removeRegisteredRepo(repoPath) {
50197
50370
  try {
50198
50371
  return canonicalizeControlRepoPath(entry) !== resolved;
50199
50372
  } catch {
50200
- return path26.resolve(entry) !== resolved;
50373
+ return path27.resolve(entry) !== resolved;
50201
50374
  }
50202
50375
  });
50203
50376
  if (next.length === registry2.repos.length) return false;
@@ -50209,9 +50382,9 @@ function listRegisteredRepos() {
50209
50382
  const kept = [];
50210
50383
  const seen = /* @__PURE__ */ new Set();
50211
50384
  for (const repoPath of registry2.repos) {
50212
- if (!fs27.existsSync(repoPath)) continue;
50385
+ if (!fs28.existsSync(repoPath)) continue;
50213
50386
  const canonical = canonicalizeControlRepoPath(repoPath);
50214
- if (!fs27.existsSync(canonical) || !readManifest(canonical)) continue;
50387
+ if (!fs28.existsSync(canonical) || !readManifest(canonical)) continue;
50215
50388
  if (seen.has(canonical)) continue;
50216
50389
  seen.add(canonical);
50217
50390
  kept.push(canonical);
@@ -50222,27 +50395,30 @@ function listRegisteredRepos() {
50222
50395
  return kept;
50223
50396
  }
50224
50397
 
50398
+ // src/core/control-sync.ts
50399
+ init_portal_credentials();
50400
+
50225
50401
  // src/core/slot-status.ts
50226
- var fs32 = __toESM(require("fs"));
50227
- var os7 = __toESM(require("os"));
50228
- var path32 = __toESM(require("path"));
50229
- var import_child_process7 = require("child_process");
50402
+ var fs33 = __toESM(require("fs"));
50403
+ var os8 = __toESM(require("os"));
50404
+ var path33 = __toESM(require("path"));
50405
+ var import_child_process8 = require("child_process");
50230
50406
 
50231
50407
  // src/core/runs.ts
50232
50408
  var crypto2 = __toESM(require("crypto"));
50233
- var import_child_process2 = require("child_process");
50234
- var fs28 = __toESM(require("fs"));
50235
- var os5 = __toESM(require("os"));
50236
- var path27 = __toESM(require("path"));
50409
+ var import_child_process3 = require("child_process");
50410
+ var fs29 = __toESM(require("fs"));
50411
+ var os6 = __toESM(require("os"));
50412
+ var path28 = __toESM(require("path"));
50237
50413
  var RUNS_DIR = "runs";
50238
50414
  function gitCommonDir(cwd) {
50239
50415
  try {
50240
- const out = (0, import_child_process2.execSync)("git rev-parse --git-common-dir", {
50416
+ const out = (0, import_child_process3.execSync)("git rev-parse --git-common-dir", {
50241
50417
  cwd,
50242
50418
  encoding: "utf8",
50243
50419
  stdio: ["pipe", "pipe", "ignore"]
50244
50420
  }).trim();
50245
- return out ? path27.resolve(cwd, out) : void 0;
50421
+ return out ? path28.resolve(cwd, out) : void 0;
50246
50422
  } catch {
50247
50423
  return void 0;
50248
50424
  }
@@ -50254,7 +50430,7 @@ function sameGitCheckout(a2, b2) {
50254
50430
  }
50255
50431
  function gitPrefix(cwd) {
50256
50432
  try {
50257
- return (0, import_child_process2.execSync)("git rev-parse --show-prefix", {
50433
+ return (0, import_child_process3.execSync)("git rev-parse --show-prefix", {
50258
50434
  cwd,
50259
50435
  encoding: "utf8",
50260
50436
  stdio: ["pipe", "pipe", "ignore"]
@@ -50264,7 +50440,7 @@ function gitPrefix(cwd) {
50264
50440
  }
50265
50441
  }
50266
50442
  function getRunsDir(harnessRoot) {
50267
- return path27.join(getHarnessDir(harnessRoot), RUNS_DIR);
50443
+ return path28.join(getHarnessDir(harnessRoot), RUNS_DIR);
50268
50444
  }
50269
50445
  function formatLocalDate(d2) {
50270
50446
  const y2 = d2.getFullYear();
@@ -50284,24 +50460,24 @@ function buildRunRelativePath(stageId, agentId, startedAt, runId, runsDir) {
50284
50460
  const timePart = formatLocalTime(started);
50285
50461
  const agentPart = agentId !== void 0 ? `_agent-${agentId}` : "";
50286
50462
  let filename = `${timePart}_${stageId}${agentPart}.json`;
50287
- const fullPath = path27.join(runsDir, dateFolder, filename);
50288
- if (fs28.existsSync(fullPath)) {
50463
+ const fullPath = path28.join(runsDir, dateFolder, filename);
50464
+ if (fs29.existsSync(fullPath)) {
50289
50465
  filename = `${timePart}_${stageId}${agentPart}-${runId.slice(0, 8)}.json`;
50290
50466
  }
50291
- return path27.join(dateFolder, filename);
50467
+ return path28.join(dateFolder, filename);
50292
50468
  }
50293
50469
  function resolveRunFilePath(harnessRoot, run2) {
50294
50470
  if (run2.relativePath) {
50295
- return path27.join(getRunsDir(harnessRoot), run2.relativePath);
50471
+ return path28.join(getRunsDir(harnessRoot), run2.relativePath);
50296
50472
  }
50297
- return path27.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
50473
+ return path28.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
50298
50474
  }
50299
50475
  function collectRunFiles(runsDir) {
50300
- if (!fs28.existsSync(runsDir)) return [];
50476
+ if (!fs29.existsSync(runsDir)) return [];
50301
50477
  const files = [];
50302
50478
  const walk = (dir) => {
50303
- for (const entry of fs28.readdirSync(dir, { withFileTypes: true })) {
50304
- const full = path27.join(dir, entry.name);
50479
+ for (const entry of fs29.readdirSync(dir, { withFileTypes: true })) {
50480
+ const full = path28.join(dir, entry.name);
50305
50481
  if (entry.isDirectory()) {
50306
50482
  walk(full);
50307
50483
  } else if (entry.name.endsWith(".json")) {
@@ -50315,30 +50491,30 @@ function collectRunFiles(runsDir) {
50315
50491
  function resolveAgentWorkDir(harnessRoot, agentId) {
50316
50492
  if (agentId === void 0) return void 0;
50317
50493
  const entry = readSlotRegistry(harnessRoot, agentId);
50318
- if (entry?.workDir && fs28.existsSync(entry.workDir)) return entry.workDir;
50494
+ if (entry?.workDir && fs29.existsSync(entry.workDir)) return entry.workDir;
50319
50495
  const env3 = readHarnessEnv(harnessRoot);
50320
- const projectName = env3.HARNESS_PROJECT_NAME ?? path27.basename(harnessRoot);
50321
- const worktreeDir = path27.join(os5.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50496
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path28.basename(harnessRoot);
50497
+ const worktreeDir = path28.join(os6.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50322
50498
  const relPrefix = gitPrefix(harnessRoot);
50323
50499
  const sessionEnvFiles = [];
50324
- const worktreesRoot = path27.join(os5.homedir(), "worktrees");
50325
- if (fs28.existsSync(worktreesRoot)) {
50500
+ const worktreesRoot = path28.join(os6.homedir(), "worktrees");
50501
+ if (fs29.existsSync(worktreesRoot)) {
50326
50502
  const suffix = `-har-agent-${agentId}-`;
50327
- for (const entry2 of fs28.readdirSync(worktreesRoot, { withFileTypes: true })) {
50503
+ for (const entry2 of fs29.readdirSync(worktreesRoot, { withFileTypes: true })) {
50328
50504
  if (!entry2.isDirectory() || !entry2.name.includes(suffix)) continue;
50329
- const sessionDir = path27.join(worktreesRoot, entry2.name);
50505
+ const sessionDir = path28.join(worktreesRoot, entry2.name);
50330
50506
  if (!sameGitCheckout(harnessRoot, sessionDir)) continue;
50331
- sessionEnvFiles.push(path27.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
50507
+ sessionEnvFiles.push(path28.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
50332
50508
  }
50333
50509
  }
50334
50510
  const candidates = [
50335
- path27.join(worktreeDir, `.env.agent.${agentId}`),
50336
- path27.join(harnessRoot, `.env.agent.${agentId}`),
50511
+ path28.join(worktreeDir, `.env.agent.${agentId}`),
50512
+ path28.join(harnessRoot, `.env.agent.${agentId}`),
50337
50513
  ...sessionEnvFiles.sort()
50338
50514
  ];
50339
50515
  for (const envFile of candidates) {
50340
- if (!fs28.existsSync(envFile)) continue;
50341
- const content = fs28.readFileSync(envFile, "utf8");
50516
+ if (!fs29.existsSync(envFile)) continue;
50517
+ const content = fs29.readFileSync(envFile, "utf8");
50342
50518
  const match = content.match(/^REPO_ROOT=(.+)$/m);
50343
50519
  if (match) return match[1].trim();
50344
50520
  }
@@ -50350,11 +50526,11 @@ function createRun(ctx, meta) {
50350
50526
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
50351
50527
  const runId = crypto2.randomUUID();
50352
50528
  const relativePath = buildRunRelativePath(meta.stageId, meta.agentId, startedAt, runId, runsDir);
50353
- const runFilePath = path27.join(runsDir, relativePath);
50354
- fs28.mkdirSync(path27.dirname(runFilePath), { recursive: true });
50529
+ const runFilePath = path28.join(runsDir, relativePath);
50530
+ fs29.mkdirSync(path28.dirname(runFilePath), { recursive: true });
50355
50531
  const run2 = RunRecordSchema.parse({
50356
50532
  runId,
50357
- repoPath: path27.resolve(ctx.repoPath),
50533
+ repoPath: path28.resolve(ctx.repoPath),
50358
50534
  harnessRoot,
50359
50535
  stageId: meta.stageId,
50360
50536
  kind: meta.kind,
@@ -50367,7 +50543,7 @@ function createRun(ctx, meta) {
50367
50543
  workUnitId: ctx.workUnitId,
50368
50544
  attemptId: ctx.attemptId
50369
50545
  });
50370
- fs28.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
50546
+ fs29.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
50371
50547
  return run2;
50372
50548
  }
50373
50549
  function finishRun(repoPath, runId, update) {
@@ -50386,13 +50562,13 @@ function finishRun(repoPath, runId, update) {
50386
50562
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
50387
50563
  });
50388
50564
  const runPath = resolveRunFilePath(harnessRoot, finished);
50389
- fs28.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
50565
+ fs29.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
50390
50566
  return finished;
50391
50567
  }
50392
50568
  function findRunRecord(harnessRoot, runId) {
50393
50569
  const runsDir = getRunsDir(harnessRoot);
50394
50570
  for (const filePath of collectRunFiles(runsDir)) {
50395
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs28.readFileSync(filePath, "utf8")));
50571
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs29.readFileSync(filePath, "utf8")));
50396
50572
  if (parsed.success && parsed.data.runId === runId) {
50397
50573
  return parsed.data;
50398
50574
  }
@@ -50404,10 +50580,10 @@ function getRun(repoPath, runId) {
50404
50580
  }
50405
50581
  function listRuns(repoPath, filter2 = {}) {
50406
50582
  const runsDir = getRunsDir(resolveHarnessRoot(repoPath));
50407
- if (!fs28.existsSync(runsDir)) return [];
50583
+ if (!fs29.existsSync(runsDir)) return [];
50408
50584
  const runs = [];
50409
50585
  for (const filePath of collectRunFiles(runsDir)) {
50410
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs28.readFileSync(filePath, "utf8")));
50586
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs29.readFileSync(filePath, "utf8")));
50411
50587
  if (!parsed.success) continue;
50412
50588
  if (filter2.stageId && parsed.data.stageId !== filter2.stageId) continue;
50413
50589
  runs.push(parsed.data);
@@ -50420,18 +50596,18 @@ function listRuns(repoPath, filter2 = {}) {
50420
50596
  }
50421
50597
 
50422
50598
  // src/core/slot-preflight.ts
50423
- var path31 = __toESM(require("path"));
50599
+ var path32 = __toESM(require("path"));
50424
50600
 
50425
50601
  // src/core/control-port.ts
50426
- var import_child_process4 = require("child_process");
50427
- var fs30 = __toESM(require("fs"));
50428
- var path29 = __toESM(require("path"));
50602
+ var import_child_process5 = require("child_process");
50603
+ var fs31 = __toESM(require("fs"));
50604
+ var path30 = __toESM(require("path"));
50429
50605
  init_control_config();
50430
50606
 
50431
50607
  // src/core/slot-ports.ts
50432
- var import_child_process3 = require("child_process");
50433
- var fs29 = __toESM(require("fs"));
50434
- var path28 = __toESM(require("path"));
50608
+ var import_child_process4 = require("child_process");
50609
+ var fs30 = __toESM(require("fs"));
50610
+ var path29 = __toESM(require("path"));
50435
50611
  function portStep(env3) {
50436
50612
  return Number(env3.HARNESS_PORT_STEP ?? 10);
50437
50613
  }
@@ -50443,7 +50619,7 @@ function slotPortLaneEnd(defaultPort, step) {
50443
50619
  }
50444
50620
  function isPortInUse(port, host = "127.0.0.1") {
50445
50621
  try {
50446
- (0, import_child_process3.execSync)(`bash -c 'exec 3<>/dev/tcp/${host}/${port}'`, { stdio: "ignore" });
50622
+ (0, import_child_process4.execSync)(`bash -c 'exec 3<>/dev/tcp/${host}/${port}'`, { stdio: "ignore" });
50447
50623
  return true;
50448
50624
  } catch {
50449
50625
  return false;
@@ -50487,7 +50663,7 @@ function allocateAppPorts(repoPath, agentId) {
50487
50663
  }
50488
50664
  function harnessUsesPm2(repoPath) {
50489
50665
  const harnessRoot = resolveHarnessRoot(repoPath);
50490
- return fs29.existsSync(path28.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
50666
+ return fs30.existsSync(path29.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
50491
50667
  }
50492
50668
 
50493
50669
  // src/core/control-port.ts
@@ -50514,7 +50690,7 @@ function controlContainerOnPort(containers, port) {
50514
50690
  }
50515
50691
  function listDockerContainers() {
50516
50692
  try {
50517
- const raw = (0, import_child_process4.execSync)("docker ps --format {{.Names}}\\t{{.Ports}}", {
50693
+ const raw = (0, import_child_process5.execSync)("docker ps --format {{.Names}}\\t{{.Ports}}", {
50518
50694
  encoding: "utf8",
50519
50695
  stdio: ["pipe", "pipe", "ignore"],
50520
50696
  timeout: 3e3
@@ -50542,13 +50718,13 @@ function controlDefaultPortWarnings(containers, defaultFrontendPort, allocatedFr
50542
50718
  return [formatControlDefaultPortWarning(control.name, defaultFrontendPort, allocatedFrontend)];
50543
50719
  }
50544
50720
  function inspectControlUpReadiness(repoPath) {
50545
- const resolved = path29.resolve(repoPath);
50721
+ const resolved = path30.resolve(repoPath);
50546
50722
  const port = parseControlHostPort();
50547
50723
  const containers = listDockerContainers();
50548
50724
  const control = controlContainerOnPort(containers, port);
50549
50725
  const warnings = [];
50550
- const controlHarnessDir = path29.join(resolved, "control", ".har");
50551
- const harnessSlot1Active = fs30.existsSync(controlHarnessDir) && readSlotRegistry(path29.join(resolved, "control"), 1)?.status === "active";
50726
+ const controlHarnessDir = path30.join(resolved, "control", ".har");
50727
+ const harnessSlot1Active = fs31.existsSync(controlHarnessDir) && readSlotRegistry(path30.join(resolved, "control"), 1)?.status === "active";
50552
50728
  if (control) {
50553
50729
  return {
50554
50730
  warnings,
@@ -50579,13 +50755,13 @@ function inspectControlUpReadiness(repoPath) {
50579
50755
  }
50580
50756
 
50581
50757
  // src/core/slot-launch-guard-occupied.ts
50582
- var fs31 = __toESM(require("fs"));
50583
- var os6 = __toESM(require("os"));
50584
- var path30 = __toESM(require("path"));
50585
- var import_child_process5 = require("child_process");
50758
+ var fs32 = __toESM(require("fs"));
50759
+ var os7 = __toESM(require("os"));
50760
+ var path31 = __toESM(require("path"));
50761
+ var import_child_process6 = require("child_process");
50586
50762
  function runGit(cwd, args) {
50587
50763
  try {
50588
- return (0, import_child_process5.execSync)(`git ${args}`, {
50764
+ return (0, import_child_process6.execSync)(`git ${args}`, {
50589
50765
  cwd,
50590
50766
  encoding: "utf8",
50591
50767
  stdio: ["pipe", "pipe", "ignore"]
@@ -50600,7 +50776,7 @@ function worktreeDirty(worktreePath) {
50600
50776
  }
50601
50777
  function gitCommonDir2(cwd) {
50602
50778
  const out = runGit(cwd, "rev-parse --git-common-dir");
50603
- return out ? path30.resolve(cwd, out) : void 0;
50779
+ return out ? path31.resolve(cwd, out) : void 0;
50604
50780
  }
50605
50781
  function sameGitCheckout2(a2, b2) {
50606
50782
  const left2 = gitCommonDir2(a2);
@@ -50609,20 +50785,20 @@ function sameGitCheckout2(a2, b2) {
50609
50785
  }
50610
50786
  function discoverWorktree(harnessRoot, agentId, projectName) {
50611
50787
  const session = readSlotRegistry(harnessRoot, agentId);
50612
- if (session?.worktreePath && fs31.existsSync(session.worktreePath)) {
50788
+ if (session?.worktreePath && fs32.existsSync(session.worktreePath)) {
50613
50789
  return session.worktreePath;
50614
50790
  }
50615
- const legacy = path30.join(os6.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50616
- if (fs31.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
50617
- const worktreesRoot = path30.join(os6.homedir(), "worktrees");
50618
- if (!fs31.existsSync(worktreesRoot)) return void 0;
50791
+ const legacy = path31.join(os7.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50792
+ if (fs32.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
50793
+ const worktreesRoot = path31.join(os7.homedir(), "worktrees");
50794
+ if (!fs32.existsSync(worktreesRoot)) return void 0;
50619
50795
  const suffix = `-har-agent-${agentId}-`;
50620
50796
  const relPrefix = runGit(harnessRoot, "rev-parse --show-prefix") ?? "";
50621
- for (const name of fs31.readdirSync(worktreesRoot)) {
50797
+ for (const name of fs32.readdirSync(worktreesRoot)) {
50622
50798
  if (!name.includes(suffix)) continue;
50623
- const candidate = path30.join(worktreesRoot, name);
50799
+ const candidate = path31.join(worktreesRoot, name);
50624
50800
  if (!sameGitCheckout2(harnessRoot, candidate)) continue;
50625
- if (!fs31.existsSync(path30.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
50801
+ if (!fs32.existsSync(path31.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
50626
50802
  return candidate;
50627
50803
  }
50628
50804
  return void 0;
@@ -50630,13 +50806,13 @@ function discoverWorktree(harnessRoot, agentId, projectName) {
50630
50806
  function collectOccupiedSlot(repoPath, agentId) {
50631
50807
  const harnessRoot = resolveHarnessRoot(repoPath);
50632
50808
  const env3 = readHarnessEnv(harnessRoot);
50633
- const projectName = env3.HARNESS_PROJECT_NAME ?? path30.basename(harnessRoot);
50809
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path31.basename(harnessRoot);
50634
50810
  const session = readSlotRegistry(harnessRoot, agentId);
50635
50811
  const worktreePath = discoverWorktree(harnessRoot, agentId, projectName);
50636
50812
  const workDir = session?.workDir;
50637
- const envInWorkDir = workDir ? fs31.existsSync(path30.join(workDir, `.env.agent.${agentId}`)) : false;
50638
- const envInRoot = fs31.existsSync(path30.join(harnessRoot, `.env.agent.${agentId}`));
50639
- const envInWorktree = worktreePath ? fs31.existsSync(path30.join(worktreePath, `.env.agent.${agentId}`)) : false;
50813
+ const envInWorkDir = workDir ? fs32.existsSync(path31.join(workDir, `.env.agent.${agentId}`)) : false;
50814
+ const envInRoot = fs32.existsSync(path31.join(harnessRoot, `.env.agent.${agentId}`));
50815
+ const envInWorktree = worktreePath ? fs32.existsSync(path31.join(worktreePath, `.env.agent.${agentId}`)) : false;
50640
50816
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
50641
50817
  if (!active) return void 0;
50642
50818
  const dirty = worktreePath ? worktreeDirty(worktreePath) : void 0;
@@ -50751,10 +50927,10 @@ function checkLaunchGuard(repoPath, agentId, options = {}) {
50751
50927
  }
50752
50928
 
50753
50929
  // src/core/slot-preflight.ts
50754
- var import_child_process6 = require("child_process");
50930
+ var import_child_process7 = require("child_process");
50755
50931
  function listPm2Processes() {
50756
50932
  try {
50757
- const raw = (0, import_child_process6.execSync)("npx --yes pm2 jlist", {
50933
+ const raw = (0, import_child_process7.execSync)("npx --yes pm2 jlist", {
50758
50934
  encoding: "utf8",
50759
50935
  stdio: ["pipe", "pipe", "ignore"],
50760
50936
  timeout: 3e3
@@ -50802,7 +50978,7 @@ function checkInfraPort(env3, varName, defaultPort, scanStart, scanEnd) {
50802
50978
  function inspectSlotReadiness(repoPath, agentId, options = {}) {
50803
50979
  const harnessRoot = resolveHarnessRoot(repoPath);
50804
50980
  const env3 = readHarnessEnv(harnessRoot);
50805
- const projectName = env3.HARNESS_PROJECT_NAME ?? path31.basename(harnessRoot);
50981
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path32.basename(harnessRoot);
50806
50982
  const usesPm2 = harnessUsesPm2(repoPath);
50807
50983
  const blockers = [];
50808
50984
  const remediations = [];
@@ -50978,7 +51154,7 @@ function formatPreflightReport(agentId, readiness) {
50978
51154
  var BYPASS_WARNING_MS = 15 * 60 * 1e3;
50979
51155
  function readGitRemote(repoPath) {
50980
51156
  try {
50981
- const remote = (0, import_child_process7.execSync)("git remote get-url origin", {
51157
+ const remote = (0, import_child_process8.execSync)("git remote get-url origin", {
50982
51158
  cwd: repoPath,
50983
51159
  encoding: "utf8",
50984
51160
  stdio: ["pipe", "pipe", "ignore"]
@@ -50990,7 +51166,7 @@ function readGitRemote(repoPath) {
50990
51166
  }
50991
51167
  function runGit2(cwd, args) {
50992
51168
  try {
50993
- return (0, import_child_process7.execSync)(`git ${args}`, {
51169
+ return (0, import_child_process8.execSync)(`git ${args}`, {
50994
51170
  cwd,
50995
51171
  encoding: "utf8",
50996
51172
  stdio: ["pipe", "pipe", "ignore"]
@@ -51004,7 +51180,7 @@ function readWorktreeBranch(worktreePath) {
51004
51180
  }
51005
51181
  function gitCommonDir3(cwd) {
51006
51182
  const out = runGit2(cwd, "rev-parse --git-common-dir");
51007
- return out ? path32.resolve(cwd, out) : void 0;
51183
+ return out ? path33.resolve(cwd, out) : void 0;
51008
51184
  }
51009
51185
  function sameGitCheckout3(a2, b2) {
51010
51186
  const left2 = gitCommonDir3(a2);
@@ -51016,12 +51192,12 @@ function gitPrefix2(cwd) {
51016
51192
  return out ?? "";
51017
51193
  }
51018
51194
  function discoverSessionWorktreePath(harnessRoot, agentId) {
51019
- const worktreesRoot = path32.join(os7.homedir(), "worktrees");
51020
- if (!fs32.existsSync(worktreesRoot)) return void 0;
51195
+ const worktreesRoot = path33.join(os8.homedir(), "worktrees");
51196
+ if (!fs33.existsSync(worktreesRoot)) return void 0;
51021
51197
  const suffix = `-har-agent-${agentId}-`;
51022
51198
  const relPrefix = gitPrefix2(harnessRoot);
51023
- const matches = fs32.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path32.join(worktreesRoot, entry.name)).filter(
51024
- (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs32.existsSync(path32.join(candidate, relPrefix, `.env.agent.${agentId}`))
51199
+ const matches = fs33.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path33.join(worktreesRoot, entry.name)).filter(
51200
+ (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs33.existsSync(path33.join(candidate, relPrefix, `.env.agent.${agentId}`))
51025
51201
  );
51026
51202
  return matches.sort()[0];
51027
51203
  }
@@ -51066,7 +51242,7 @@ function lastBuildPass(run2) {
51066
51242
  }
51067
51243
  function listPm2Processes2() {
51068
51244
  try {
51069
- const raw = (0, import_child_process7.execSync)("npx --yes pm2 jlist", {
51245
+ const raw = (0, import_child_process8.execSync)("npx --yes pm2 jlist", {
51070
51246
  encoding: "utf8",
51071
51247
  stdio: ["pipe", "pipe", "ignore"],
51072
51248
  timeout: 3e3
@@ -51096,18 +51272,18 @@ function detectPm2Issue(projectName, agentId, session, procs) {
51096
51272
  }
51097
51273
  function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
51098
51274
  const env3 = readHarnessEnv(harnessRoot);
51099
- const projectName = env3.HARNESS_PROJECT_NAME ?? path32.basename(harnessRoot);
51275
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path33.basename(harnessRoot);
51100
51276
  const session = readSlotRegistry(harnessRoot, agentId);
51101
- const legacyWorktreePath = path32.join(
51102
- os7.homedir(),
51277
+ const legacyWorktreePath = path33.join(
51278
+ os8.homedir(),
51103
51279
  "worktrees",
51104
51280
  `${projectName}-agent-${agentId}`
51105
51281
  );
51106
- const worktreePath = session?.worktreePath && fs32.existsSync(session.worktreePath) ? session.worktreePath : fs32.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
51282
+ const worktreePath = session?.worktreePath && fs33.existsSync(session.worktreePath) ? session.worktreePath : fs33.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
51107
51283
  const workDir = resolveAgentWorkDir(harnessRoot, agentId);
51108
- const envInWorkDir = workDir ? fs32.existsSync(path32.join(workDir, `.env.agent.${agentId}`)) : false;
51109
- const envInRoot = fs32.existsSync(path32.join(harnessRoot, `.env.agent.${agentId}`));
51110
- const envInWorktree = worktreePath ? fs32.existsSync(path32.join(worktreePath, `.env.agent.${agentId}`)) : false;
51284
+ const envInWorkDir = workDir ? fs33.existsSync(path33.join(workDir, `.env.agent.${agentId}`)) : false;
51285
+ const envInRoot = fs33.existsSync(path33.join(harnessRoot, `.env.agent.${agentId}`));
51286
+ const envInWorktree = worktreePath ? fs33.existsSync(path33.join(worktreePath, `.env.agent.${agentId}`)) : false;
51111
51287
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
51112
51288
  const latest = latestRunForAgent(runs, agentId);
51113
51289
  const verifyRun = runs.find((r2) => r2.agentId === agentId && r2.stageId === "verify");
@@ -51161,7 +51337,7 @@ function collectEnvironmentStatus(repoPath) {
51161
51337
  const slotIds = getAgentSlotIds(harnessRoot);
51162
51338
  const pm2Procs = listPm2Processes2();
51163
51339
  return {
51164
- repoPath: path32.resolve(repoPath),
51340
+ repoPath: path33.resolve(repoPath),
51165
51341
  harnessRoot,
51166
51342
  gitRemote: readGitRemote(harnessRoot),
51167
51343
  profile: manifest?.profile,
@@ -51172,13 +51348,13 @@ function collectEnvironmentStatus(repoPath) {
51172
51348
 
51173
51349
  // src/core/validations.ts
51174
51350
  var crypto3 = __toESM(require("crypto"));
51175
- var fs34 = __toESM(require("fs"));
51176
- var path34 = __toESM(require("path"));
51351
+ var fs35 = __toESM(require("fs"));
51352
+ var path35 = __toESM(require("path"));
51177
51353
 
51178
51354
  // src/core/change-batch.ts
51179
- var fs33 = __toESM(require("fs"));
51180
- var os8 = __toESM(require("os"));
51181
- var path33 = __toESM(require("path"));
51355
+ var fs34 = __toESM(require("fs"));
51356
+ var os9 = __toESM(require("os"));
51357
+ var path34 = __toESM(require("path"));
51182
51358
  function git(checkoutDir, args, env3) {
51183
51359
  const result = run(`git ${args}`, { cwd: checkoutDir, env: env3 });
51184
51360
  if (result.code !== 0) {
@@ -51194,7 +51370,7 @@ function isCheckoutRoot(checkoutDir) {
51194
51370
  const toplevel = tryGit2(checkoutDir, "rev-parse --show-toplevel");
51195
51371
  if (!toplevel) return false;
51196
51372
  try {
51197
- return fs33.realpathSync(toplevel) === fs33.realpathSync(checkoutDir);
51373
+ return fs34.realpathSync(toplevel) === fs34.realpathSync(checkoutDir);
51198
51374
  } catch {
51199
51375
  return false;
51200
51376
  }
@@ -51216,7 +51392,7 @@ function isMergeOrRebaseInProgress(checkoutDir) {
51216
51392
  if (tryGit2(checkoutDir, "rev-parse -q --verify MERGE_HEAD") !== void 0) return true;
51217
51393
  for (const dir of ["rebase-merge", "rebase-apply"]) {
51218
51394
  const gitPath = tryGit2(checkoutDir, `rev-parse --git-path ${dir}`);
51219
- if (gitPath && fs33.existsSync(path33.resolve(checkoutDir, gitPath))) return true;
51395
+ if (gitPath && fs34.existsSync(path34.resolve(checkoutDir, gitPath))) return true;
51220
51396
  }
51221
51397
  return false;
51222
51398
  }
@@ -51239,8 +51415,8 @@ function parseNameStatus(output) {
51239
51415
  return files;
51240
51416
  }
51241
51417
  function computeWorktreeSnapshot(checkoutDir) {
51242
- const tmpDir = fs33.mkdtempSync(path33.join(os8.tmpdir(), "har-idx-"));
51243
- const tmpIndex = path33.join(tmpDir, "index");
51418
+ const tmpDir = fs34.mkdtempSync(path34.join(os9.tmpdir(), "har-idx-"));
51419
+ const tmpIndex = path34.join(tmpDir, "index");
51244
51420
  const env3 = { GIT_INDEX_FILE: tmpIndex };
51245
51421
  try {
51246
51422
  const headTree = getHeadTree(checkoutDir);
@@ -51263,35 +51439,35 @@ function computeWorktreeSnapshot(checkoutDir) {
51263
51439
  changedFiles: parseNameStatus(diffOutput)
51264
51440
  };
51265
51441
  } finally {
51266
- fs33.rmSync(tmpDir, { recursive: true, force: true });
51442
+ fs34.rmSync(tmpDir, { recursive: true, force: true });
51267
51443
  }
51268
51444
  }
51269
51445
 
51270
51446
  // src/core/validations.ts
51271
51447
  var VALIDATIONS_DIR = "validations";
51272
51448
  function getValidationsDir(checkoutDir) {
51273
- return path34.join(checkoutDir, ".har", VALIDATIONS_DIR);
51449
+ return path35.join(checkoutDir, ".har", VALIDATIONS_DIR);
51274
51450
  }
51275
51451
  function validationPath(checkoutDir, treeHash) {
51276
- return path34.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
51452
+ return path35.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
51277
51453
  }
51278
51454
  function writeRecord(checkoutDir, record2) {
51279
51455
  const dir = getValidationsDir(checkoutDir);
51280
- fs34.mkdirSync(dir, { recursive: true });
51281
- fs34.writeFileSync(
51456
+ fs35.mkdirSync(dir, { recursive: true });
51457
+ fs35.writeFileSync(
51282
51458
  validationPath(checkoutDir, record2.treeHash),
51283
51459
  `${JSON.stringify(record2, null, 2)}
51284
51460
  `
51285
51461
  );
51286
51462
  }
51287
51463
  function ensureValidationsIgnored(checkoutDir) {
51288
- const harDir = path34.join(checkoutDir, ".har");
51289
- if (!fs34.existsSync(harDir)) return;
51290
- const gitignorePath = path34.join(harDir, ".gitignore");
51291
- const content = fs34.existsSync(gitignorePath) ? fs34.readFileSync(gitignorePath, "utf8") : "";
51464
+ const harDir = path35.join(checkoutDir, ".har");
51465
+ if (!fs35.existsSync(harDir)) return;
51466
+ const gitignorePath = path35.join(harDir, ".gitignore");
51467
+ const content = fs35.existsSync(gitignorePath) ? fs35.readFileSync(gitignorePath, "utf8") : "";
51292
51468
  if (content.split("\n").some((line) => line.trim() === `${VALIDATIONS_DIR}/`)) return;
51293
51469
  const suffix = content.length === 0 || content.endsWith("\n") ? "" : "\n";
51294
- fs34.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
51470
+ fs35.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
51295
51471
  `);
51296
51472
  }
51297
51473
  function recordValidation(input) {
@@ -51308,8 +51484,8 @@ function recordValidation(input) {
51308
51484
  treeHash: snapshot.treeHash,
51309
51485
  headSha: snapshot.headSha,
51310
51486
  branch: snapshot.branch,
51311
- workDir: path34.resolve(input.checkoutDir),
51312
- harnessRoot: path34.resolve(input.harnessRoot),
51487
+ workDir: path35.resolve(input.checkoutDir),
51488
+ harnessRoot: path35.resolve(input.harnessRoot),
51313
51489
  agentId: input.agentId,
51314
51490
  status: input.status,
51315
51491
  full: input.full,
@@ -51321,16 +51497,16 @@ function recordValidation(input) {
51321
51497
  committedAt: existing?.committedAt
51322
51498
  });
51323
51499
  writeRecord(input.checkoutDir, record2);
51324
- if (path34.resolve(input.harnessRoot) !== path34.resolve(input.checkoutDir)) {
51500
+ if (path35.resolve(input.harnessRoot) !== path35.resolve(input.checkoutDir)) {
51325
51501
  writeRecord(input.harnessRoot, record2);
51326
51502
  }
51327
51503
  return record2;
51328
51504
  }
51329
51505
  function findValidation(checkoutDir, treeHash) {
51330
51506
  const file = validationPath(checkoutDir, treeHash);
51331
- if (!fs34.existsSync(file)) return void 0;
51507
+ if (!fs35.existsSync(file)) return void 0;
51332
51508
  try {
51333
- return ValidationRecordSchema.parse(JSON.parse(fs34.readFileSync(file, "utf8")));
51509
+ return ValidationRecordSchema.parse(JSON.parse(fs35.readFileSync(file, "utf8")));
51334
51510
  } catch {
51335
51511
  return void 0;
51336
51512
  }
@@ -51345,19 +51521,19 @@ function attachCommit(checkoutDir, treeHash, commitSha) {
51345
51521
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
51346
51522
  };
51347
51523
  writeRecord(checkoutDir, updated);
51348
- if (record2.harnessRoot && path34.resolve(record2.harnessRoot) !== path34.resolve(checkoutDir) && fs34.existsSync(path34.join(record2.harnessRoot, ".har"))) {
51524
+ if (record2.harnessRoot && path35.resolve(record2.harnessRoot) !== path35.resolve(checkoutDir) && fs35.existsSync(path35.join(record2.harnessRoot, ".har"))) {
51349
51525
  writeRecord(record2.harnessRoot, updated);
51350
51526
  }
51351
51527
  return updated;
51352
51528
  }
51353
51529
  function listValidations(harnessRoot) {
51354
51530
  const dir = getValidationsDir(harnessRoot);
51355
- if (!fs34.existsSync(dir)) return [];
51531
+ if (!fs35.existsSync(dir)) return [];
51356
51532
  const records = [];
51357
- for (const entry of fs34.readdirSync(dir)) {
51533
+ for (const entry of fs35.readdirSync(dir)) {
51358
51534
  if (!entry.endsWith(".json")) continue;
51359
51535
  try {
51360
- records.push(ValidationRecordSchema.parse(JSON.parse(fs34.readFileSync(path34.join(dir, entry), "utf8"))));
51536
+ records.push(ValidationRecordSchema.parse(JSON.parse(fs35.readFileSync(path35.join(dir, entry), "utf8"))));
51361
51537
  } catch {
51362
51538
  }
51363
51539
  }
@@ -51366,46 +51542,46 @@ function listValidations(harnessRoot) {
51366
51542
 
51367
51543
  // src/core/work-units.ts
51368
51544
  var crypto4 = __toESM(require("crypto"));
51369
- var fs35 = __toESM(require("fs"));
51370
- var path35 = __toESM(require("path"));
51545
+ var fs36 = __toESM(require("fs"));
51546
+ var path36 = __toESM(require("path"));
51371
51547
  var WORK_UNITS_DIR = "work-units";
51372
51548
  var WORK_ATTEMPTS_DIR = "work-attempts";
51373
51549
  var VALIDATION_BINDINGS_DIR = "validation-bindings";
51374
51550
  var EVIDENCE_DIRS = [WORK_UNITS_DIR, WORK_ATTEMPTS_DIR, VALIDATION_BINDINGS_DIR];
51375
51551
  function harEvidenceDir(harnessRoot, name) {
51376
- return path35.join(harnessRoot, ".har", name);
51552
+ return path36.join(harnessRoot, ".har", name);
51377
51553
  }
51378
51554
  function hashedRecordPath(harnessRoot, dir, id) {
51379
51555
  const digest = crypto4.createHash("sha256").update(id).digest("hex");
51380
- return path35.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
51556
+ return path36.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
51381
51557
  }
51382
51558
  function writeRecord2(file, value) {
51383
- fs35.mkdirSync(path35.dirname(file), { recursive: true });
51559
+ fs36.mkdirSync(path36.dirname(file), { recursive: true });
51384
51560
  const temp = `${file}.${process.pid}.tmp`;
51385
- fs35.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
51561
+ fs36.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
51386
51562
  `);
51387
- fs35.renameSync(temp, file);
51563
+ fs36.renameSync(temp, file);
51388
51564
  }
51389
51565
  function ensureWorkEvidenceIgnored(harnessRoot) {
51390
- const harDir = path35.join(harnessRoot, ".har");
51391
- if (!fs35.existsSync(harDir)) return;
51392
- const gitignorePath = path35.join(harDir, ".gitignore");
51393
- const content = fs35.existsSync(gitignorePath) ? fs35.readFileSync(gitignorePath, "utf8") : "";
51566
+ const harDir = path36.join(harnessRoot, ".har");
51567
+ if (!fs36.existsSync(harDir)) return;
51568
+ const gitignorePath = path36.join(harDir, ".gitignore");
51569
+ const content = fs36.existsSync(gitignorePath) ? fs36.readFileSync(gitignorePath, "utf8") : "";
51394
51570
  const lines2 = new Set(content.split("\n").map((line) => line.trim()));
51395
51571
  const missing = EVIDENCE_DIRS.map((dir) => `${dir}/`).filter((dir) => !lines2.has(dir));
51396
51572
  if (missing.length === 0) return;
51397
51573
  const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
51398
- fs35.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
51574
+ fs36.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
51399
51575
  `);
51400
51576
  }
51401
51577
  function listRecords(harnessRoot, dir, parse4) {
51402
51578
  const recordDir = harEvidenceDir(harnessRoot, dir);
51403
- if (!fs35.existsSync(recordDir)) return [];
51579
+ if (!fs36.existsSync(recordDir)) return [];
51404
51580
  const records = [];
51405
- for (const name of fs35.readdirSync(recordDir)) {
51581
+ for (const name of fs36.readdirSync(recordDir)) {
51406
51582
  if (!name.endsWith(".json")) continue;
51407
51583
  try {
51408
- records.push(parse4(JSON.parse(fs35.readFileSync(path35.join(recordDir, name), "utf8"))));
51584
+ records.push(parse4(JSON.parse(fs36.readFileSync(path36.join(recordDir, name), "utf8"))));
51409
51585
  } catch {
51410
51586
  }
51411
51587
  }
@@ -51414,9 +51590,9 @@ function listRecords(harnessRoot, dir, parse4) {
51414
51590
  function findWorkUnit(harnessRoot, workUnitId) {
51415
51591
  const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
51416
51592
  const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
51417
- if (!fs35.existsSync(file)) return void 0;
51593
+ if (!fs36.existsSync(file)) return void 0;
51418
51594
  try {
51419
- return WorkUnitRecordSchema.parse(JSON.parse(fs35.readFileSync(file, "utf8")));
51595
+ return WorkUnitRecordSchema.parse(JSON.parse(fs36.readFileSync(file, "utf8")));
51420
51596
  } catch {
51421
51597
  return void 0;
51422
51598
  }
@@ -51493,10 +51669,10 @@ function bindValidationToAttempt(harnessRoot, input) {
51493
51669
  VALIDATION_BINDINGS_DIR,
51494
51670
  stableKey
51495
51671
  );
51496
- if (fs35.existsSync(existingFile)) {
51672
+ if (fs36.existsSync(existingFile)) {
51497
51673
  try {
51498
51674
  return ValidationBindingRecordSchema.parse(
51499
- JSON.parse(fs35.readFileSync(existingFile, "utf8"))
51675
+ JSON.parse(fs36.readFileSync(existingFile, "utf8"))
51500
51676
  );
51501
51677
  } catch {
51502
51678
  }
@@ -51557,14 +51733,14 @@ function createRemoteExecutor(apiUrl, apiKey) {
51557
51733
  init_telemetry_config();
51558
51734
 
51559
51735
  // src/core/usage-harvest/claude.ts
51560
- var fs38 = __toESM(require("fs"));
51561
- var os10 = __toESM(require("os"));
51562
- var path38 = __toESM(require("path"));
51736
+ var fs39 = __toESM(require("fs"));
51737
+ var os11 = __toESM(require("os"));
51738
+ var path39 = __toESM(require("path"));
51563
51739
  init_telemetry_config();
51564
51740
 
51565
51741
  // src/core/telemetry-env.ts
51566
- var fs37 = __toESM(require("fs"));
51567
- var path37 = __toESM(require("path"));
51742
+ var fs38 = __toESM(require("fs"));
51743
+ var path38 = __toESM(require("path"));
51568
51744
  init_control_config();
51569
51745
  function escapeAttrValue(value) {
51570
51746
  return value.replace(/[,=]/g, "_");
@@ -51610,8 +51786,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
51610
51786
  ${TELEMETRY_MARKER_END}
51611
51787
  `;
51612
51788
  let existing = "";
51613
- if (fs37.existsSync(envFilePath)) {
51614
- existing = fs37.readFileSync(envFilePath, "utf8");
51789
+ if (fs38.existsSync(envFilePath)) {
51790
+ existing = fs38.readFileSync(envFilePath, "utf8");
51615
51791
  const start = existing.indexOf(TELEMETRY_MARKER_START);
51616
51792
  if (start >= 0) {
51617
51793
  const end = existing.indexOf(TELEMETRY_MARKER_END, start);
@@ -51622,28 +51798,28 @@ ${TELEMETRY_MARKER_END}
51622
51798
  }
51623
51799
  }
51624
51800
  }
51625
- fs37.mkdirSync(path37.dirname(envFilePath), { recursive: true });
51801
+ fs38.mkdirSync(path38.dirname(envFilePath), { recursive: true });
51626
51802
  const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
51627
- fs37.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51803
+ fs38.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51628
51804
  }
51629
51805
 
51630
51806
  // src/core/usage-harvest/claude.ts
51631
51807
  function pathsMatch(candidate, targets) {
51632
- const norm = path38.resolve(candidate);
51808
+ const norm = path39.resolve(candidate);
51633
51809
  return targets.some((t2) => {
51634
- const target = path38.resolve(t2);
51635
- return norm === target || norm.startsWith(target + path38.sep) || target.startsWith(norm + path38.sep);
51810
+ const target = path39.resolve(t2);
51811
+ return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
51636
51812
  });
51637
51813
  }
51638
51814
  function claudeProjectsRoot() {
51639
- return process.env.HAR_CLAUDE_PROJECTS_DIR ? path38.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path38.join(os10.homedir(), ".claude", "projects");
51815
+ return process.env.HAR_CLAUDE_PROJECTS_DIR ? path39.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path39.join(os11.homedir(), ".claude", "projects");
51640
51816
  }
51641
51817
  function encodeClaudeProjectDir(cwd) {
51642
51818
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
51643
51819
  }
51644
51820
  function readJsonlRecords(filePath) {
51645
- if (!fs38.existsSync(filePath)) return [];
51646
- const lines2 = fs38.readFileSync(filePath, "utf8").split(/\r?\n/);
51821
+ if (!fs39.existsSync(filePath)) return [];
51822
+ const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
51647
51823
  const out = [];
51648
51824
  for (const line of lines2) {
51649
51825
  const trimmed = line.trim();
@@ -51661,6 +51837,7 @@ function extractClaudeUsageFromRecords(records) {
51661
51837
  let tokensCacheRead = 0;
51662
51838
  let tokensCacheCreation = 0;
51663
51839
  let costUsd = null;
51840
+ const modelBreakdown = {};
51664
51841
  for (const record2 of records) {
51665
51842
  if (!record2 || typeof record2 !== "object") continue;
51666
51843
  const payload = record2;
@@ -51672,30 +51849,50 @@ function extractClaudeUsageFromRecords(records) {
51672
51849
  tokensCacheCreation = Number(usage2.cache_creation_input_tokens ?? 0);
51673
51850
  if (payload.total_cost_usd != null) costUsd = Number(payload.total_cost_usd);
51674
51851
  }
51675
- const nestedUsage = payload.usage ?? payload.message?.usage;
51852
+ const message = payload.message;
51853
+ const nestedUsage = payload.usage ?? message?.usage;
51676
51854
  if (nestedUsage && payload.type !== "result") {
51677
- tokensInput += Number(nestedUsage.input_tokens ?? 0);
51678
- tokensOutput += Number(nestedUsage.output_tokens ?? 0);
51679
- tokensCacheRead += Number(nestedUsage.cache_read_input_tokens ?? 0);
51680
- tokensCacheCreation += Number(nestedUsage.cache_creation_input_tokens ?? 0);
51855
+ const i2 = Number(nestedUsage.input_tokens ?? 0);
51856
+ const o2 = Number(nestedUsage.output_tokens ?? 0);
51857
+ const cr2 = Number(nestedUsage.cache_read_input_tokens ?? 0);
51858
+ const cc = Number(nestedUsage.cache_creation_input_tokens ?? 0);
51859
+ tokensInput += i2;
51860
+ tokensOutput += o2;
51861
+ tokensCacheRead += cr2;
51862
+ tokensCacheCreation += cc;
51863
+ const model = typeof message?.model === "string" ? message.model : void 0;
51864
+ if (model && model !== "<synthetic>") {
51865
+ const totals = modelBreakdown[model] ??= {
51866
+ tokensInput: 0,
51867
+ tokensOutput: 0,
51868
+ tokensCacheRead: 0,
51869
+ tokensCacheCreation: 0,
51870
+ tokensTotal: 0
51871
+ };
51872
+ totals.tokensInput += i2;
51873
+ totals.tokensOutput += o2;
51874
+ totals.tokensCacheRead += cr2;
51875
+ totals.tokensCacheCreation += cc;
51876
+ totals.tokensTotal += i2 + o2 + cr2 + cc;
51877
+ }
51681
51878
  }
51682
51879
  }
51683
- return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd };
51880
+ return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd, modelBreakdown };
51684
51881
  }
51685
51882
  function findMatchingClaudeTranscripts(slot) {
51686
51883
  const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
51687
51884
  if (targets.length === 0) return [];
51688
51885
  const root = claudeProjectsRoot();
51689
- if (!fs38.existsSync(root)) return [];
51886
+ if (!fs39.existsSync(root)) return [];
51690
51887
  const matches = [];
51691
- for (const entry of fs38.readdirSync(root, { withFileTypes: true })) {
51888
+ for (const entry of fs39.readdirSync(root, { withFileTypes: true })) {
51692
51889
  if (!entry.isDirectory()) continue;
51693
- const projectDir = path38.join(root, entry.name);
51890
+ const projectDir = path39.join(root, entry.name);
51694
51891
  const encodedHit = targets.some((t2) => entry.name.includes(encodeClaudeProjectDir(t2).slice(0, 40)));
51695
- for (const file of fs38.readdirSync(projectDir)) {
51892
+ for (const file of fs39.readdirSync(projectDir)) {
51696
51893
  if (!file.endsWith(".jsonl")) continue;
51697
- const filePath = path38.join(projectDir, file);
51698
- const stat = fs38.statSync(filePath);
51894
+ const filePath = path39.join(projectDir, file);
51895
+ const stat = fs39.statSync(filePath);
51699
51896
  const records = readJsonlRecords(filePath);
51700
51897
  let cwdHit = encodedHit;
51701
51898
  for (const record2 of records) {
@@ -51787,6 +51984,7 @@ function harvestClaudeUsage(slot) {
51787
51984
  tokensCacheCreation: best.tokensCacheCreation,
51788
51985
  tokensTotal,
51789
51986
  costUsd: best.costUsd,
51987
+ ...Object.keys(best.modelBreakdown).length > 0 ? { modelBreakdown: best.modelBreakdown } : {},
51790
51988
  sources: ["harvest"],
51791
51989
  firstSeenAt: slot.sessionCreatedAt ?? now,
51792
51990
  lastSeenAt: now
@@ -51806,30 +52004,30 @@ function harvestClaudeEvents(slot) {
51806
52004
  }
51807
52005
 
51808
52006
  // src/core/usage-harvest/codex.ts
51809
- var fs39 = __toESM(require("fs"));
51810
- var os11 = __toESM(require("os"));
51811
- var path39 = __toESM(require("path"));
52007
+ var fs40 = __toESM(require("fs"));
52008
+ var os12 = __toESM(require("os"));
52009
+ var path40 = __toESM(require("path"));
51812
52010
  function pathsMatch2(candidate, targets) {
51813
- const norm = path39.resolve(candidate);
52011
+ const norm = path40.resolve(candidate);
51814
52012
  return targets.some((t2) => {
51815
- const target = path39.resolve(t2);
51816
- return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
52013
+ const target = path40.resolve(t2);
52014
+ return norm === target || norm.startsWith(target + path40.sep) || target.startsWith(norm + path40.sep);
51817
52015
  });
51818
52016
  }
51819
52017
  function codexSessionsRoot() {
51820
- return process.env.HAR_CODEX_SESSIONS_DIR ? path39.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path39.join(os11.homedir(), ".codex", "sessions");
52018
+ return process.env.HAR_CODEX_SESSIONS_DIR ? path40.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path40.join(os12.homedir(), ".codex", "sessions");
51821
52019
  }
51822
52020
  function walkJsonlFiles(dir, out = []) {
51823
- if (!fs39.existsSync(dir)) return out;
51824
- for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
51825
- const full = path39.join(dir, entry.name);
52021
+ if (!fs40.existsSync(dir)) return out;
52022
+ for (const entry of fs40.readdirSync(dir, { withFileTypes: true })) {
52023
+ const full = path40.join(dir, entry.name);
51826
52024
  if (entry.isDirectory()) walkJsonlFiles(full, out);
51827
52025
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
51828
52026
  }
51829
52027
  return out;
51830
52028
  }
51831
52029
  function readJsonl(filePath) {
51832
- const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
52030
+ const lines2 = fs40.readFileSync(filePath, "utf8").split(/\r?\n/);
51833
52031
  const out = [];
51834
52032
  for (const line of lines2) {
51835
52033
  const trimmed = line.trim();
@@ -51893,7 +52091,7 @@ function harvestCodexUsage(slot) {
51893
52091
  const extracted = extractCodexTokens(records);
51894
52092
  if (!extracted.cwd || !pathsMatch2(extracted.cwd, targets)) continue;
51895
52093
  if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
51896
- const mtime = fs39.statSync(file).mtimeMs;
52094
+ const mtime = fs40.statSync(file).mtimeMs;
51897
52095
  if (mtime >= bestMtime) {
51898
52096
  bestMtime = mtime;
51899
52097
  best = extracted;
@@ -51948,6 +52146,119 @@ async function postJson(url, body, dryRun) {
51948
52146
  }
51949
52147
  return await response.json();
51950
52148
  }
52149
+ async function postPortal(target, endpoint, body, dryRun) {
52150
+ if (dryRun) return;
52151
+ const response = await fetch(`${target.url}${endpoint}`, {
52152
+ method: "POST",
52153
+ headers: {
52154
+ "Content-Type": "application/json",
52155
+ Authorization: `Bearer ${target.token}`
52156
+ },
52157
+ body: JSON.stringify(body)
52158
+ });
52159
+ if (!response.ok) {
52160
+ if (response.status === 401 || response.status === 403) {
52161
+ throw new Error(
52162
+ `har-portal rejected the ingest token (HTTP ${response.status}) \u2014 check HAR_PORTAL_TOKEN.`
52163
+ );
52164
+ }
52165
+ const text = await response.text().catch(() => "");
52166
+ throw new Error(`har-portal sync failed: HTTP ${response.status}${text ? ` \u2014 ${text}` : ""}`);
52167
+ }
52168
+ }
52169
+ function resolvePortalUserEmail() {
52170
+ return readPortalCredentials()?.email || void 0;
52171
+ }
52172
+ function dropNullFields(record2) {
52173
+ return Object.fromEntries(Object.entries(record2).filter(([, value]) => value !== null));
52174
+ }
52175
+ function modelsFromBreakdown(breakdown) {
52176
+ if (!breakdown) return [];
52177
+ return Object.entries(breakdown).map(([model, totals]) => ({
52178
+ model,
52179
+ ...totals && typeof totals === "object" ? totals : {}
52180
+ }));
52181
+ }
52182
+ function collectPortalTelemetry(repoPath, slots) {
52183
+ if (!isTelemetryEnabled()) return { usage: [], events: [] };
52184
+ try {
52185
+ const userEmail = resolvePortalUserEmail();
52186
+ const usage2 = slots.flatMap(
52187
+ (slot) => harvestUsageForSlot({
52188
+ agentId: slot.agentId,
52189
+ workDir: slot.workDir,
52190
+ worktreePath: slot.worktreePath,
52191
+ branch: slot.branch,
52192
+ suffix: slot.suffix,
52193
+ sessionCreatedAt: slot.sessionCreatedAt,
52194
+ repoPath
52195
+ }).map((row) => {
52196
+ const models = modelsFromBreakdown(
52197
+ row.modelBreakdown
52198
+ );
52199
+ return {
52200
+ ...row,
52201
+ workUnitId: slot.workUnitId ?? row.workUnitId,
52202
+ attemptId: slot.attemptId ?? row.attemptId,
52203
+ sessionKey: row.sessionKey || buildSessionKey({
52204
+ branch: slot.branch,
52205
+ agentId: slot.agentId,
52206
+ suffix: slot.suffix,
52207
+ createdAt: slot.sessionCreatedAt
52208
+ }),
52209
+ ...userEmail ? { userEmail } : {},
52210
+ ...models.length > 0 ? { models } : {}
52211
+ };
52212
+ })
52213
+ );
52214
+ const events = slots.flatMap(
52215
+ (slot) => harvestEventsForSlot({
52216
+ agentId: slot.agentId,
52217
+ workDir: slot.workDir,
52218
+ worktreePath: slot.worktreePath,
52219
+ branch: slot.branch,
52220
+ suffix: slot.suffix,
52221
+ sessionCreatedAt: slot.sessionCreatedAt,
52222
+ repoPath
52223
+ }).map(
52224
+ (event) => dropNullFields({
52225
+ ...event,
52226
+ workUnitId: slot.workUnitId ?? event.workUnitId,
52227
+ attemptId: slot.attemptId ?? event.attemptId
52228
+ })
52229
+ )
52230
+ );
52231
+ return { usage: usage2, events };
52232
+ } catch {
52233
+ return { usage: [], events: [] };
52234
+ }
52235
+ }
52236
+ function buildPortalPayload(repoPath) {
52237
+ const runs = listRuns(repoPath);
52238
+ const status = collectEnvironmentStatus(repoPath);
52239
+ const manifest = readManifest(repoPath);
52240
+ const stagesRegistry = readStageRegistry(repoPath);
52241
+ const harnessRoot = resolveHarnessRoot(repoPath);
52242
+ const validations = listValidations(harnessRoot);
52243
+ const workUnits = listWorkUnits(harnessRoot);
52244
+ const attempts = listWorkAttempts(harnessRoot);
52245
+ const validationBindings = listValidationBindings(harnessRoot);
52246
+ const { usage: usage2, events } = collectPortalTelemetry(repoPath, status.slots);
52247
+ const syncBody = {
52248
+ path: repoPath,
52249
+ ...manifest ? { manifest } : {},
52250
+ ...stagesRegistry ? { stagesRegistry } : {},
52251
+ runs,
52252
+ slots: status.slots,
52253
+ generatedAt: status.generatedAt,
52254
+ ...validations.length > 0 ? { validations } : {},
52255
+ ...workUnits.length > 0 ? { workUnits } : {},
52256
+ ...attempts.length > 0 ? { attempts } : {},
52257
+ ...validationBindings.length > 0 ? { validationBindings } : {},
52258
+ ...usage2.length > 0 ? { usage: usage2 } : {}
52259
+ };
52260
+ return { syncBody, events };
52261
+ }
51951
52262
  async function isControlApiReachable(apiUrl = getControlApiUrl()) {
51952
52263
  try {
51953
52264
  const response = await fetch(`${apiUrl}/api/health`, {
@@ -51963,14 +52274,15 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
51963
52274
  const deadline = Date.now() + timeoutMs;
51964
52275
  while (Date.now() < deadline) {
51965
52276
  if (await isControlApiReachable(apiUrl)) return true;
51966
- await new Promise((resolve37) => setTimeout(resolve37, intervalMs));
52277
+ await new Promise((resolve38) => setTimeout(resolve38, intervalMs));
51967
52278
  }
51968
52279
  return false;
51969
52280
  }
51970
52281
  async function syncAllKnownReposWithControl(options) {
51971
52282
  if (!isControlEnabled()) return { synced: 0, failed: 0 };
51972
52283
  const apiUrl = options?.apiUrl ?? getControlApiUrl();
51973
- if (!await isControlApiReachable(apiUrl)) {
52284
+ const portal = getPortalTarget();
52285
+ if (!await isControlApiReachable(portal ? portal.url : apiUrl)) {
51974
52286
  return { synced: 0, failed: 0 };
51975
52287
  }
51976
52288
  const repoPaths = new Set(listRegisteredRepos());
@@ -52061,13 +52373,27 @@ async function syncRepoWithControl(options) {
52061
52373
  }
52062
52374
  return;
52063
52375
  }
52376
+ const portal = getPortalTarget();
52377
+ if (portal) {
52378
+ const { syncBody, events } = buildPortalPayload(repoPath);
52379
+ await postPortal(portal, "/api/sync", syncBody, options.dryRun);
52380
+ if (events.length > 0) {
52381
+ await postPortal(
52382
+ portal,
52383
+ "/api/otel",
52384
+ { path: repoPath, events, spans: [] },
52385
+ options.dryRun
52386
+ );
52387
+ }
52388
+ return;
52389
+ }
52064
52390
  const registerResult = await registerRepoWithControl({ ...options, repoPath });
52065
52391
  const repoId = registerResult?.id;
52066
52392
  if (!repoId && !options.dryRun) {
52067
52393
  const listResponse = await fetch(`${apiUrl}/api/repos`);
52068
52394
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
52069
52395
  const repos = await listResponse.json();
52070
- const existing = repos.find((r2) => path40.resolve(r2.path) === repoPath);
52396
+ const existing = repos.find((r2) => path41.resolve(r2.path) === repoPath);
52071
52397
  if (!existing) {
52072
52398
  return;
52073
52399
  }
@@ -52175,17 +52501,18 @@ async function syncRepoWithControlAsync(repoPath) {
52175
52501
  if (process.env.HAR_CONTROL_DISABLED === "true" || process.env.NODE_ENV === "test") return;
52176
52502
  const verbose = process.env.HAR_CONTROL_VERBOSE === "true";
52177
52503
  try {
52178
- const apiUrl = getControlApiUrl();
52179
- if (!await isControlApiReachable(apiUrl)) {
52504
+ const portal = getPortalTarget();
52505
+ const healthUrl = portal ? portal.url : getControlApiUrl();
52506
+ if (!await isControlApiReachable(healthUrl)) {
52180
52507
  if (verbose) {
52181
- process.stderr.write(`[har control] sync skipped: control API not reachable at ${apiUrl}
52508
+ process.stderr.write(`[har control] sync skipped: not reachable at ${healthUrl}
52182
52509
  `);
52183
52510
  }
52184
52511
  return;
52185
52512
  }
52186
52513
  const canonical = canonicalizeControlRepoPath(repoPath);
52187
52514
  await withTimeout(
52188
- syncRepoWithControl({ repoPath: canonical, apiUrl }),
52515
+ syncRepoWithControl({ repoPath: canonical }),
52189
52516
  SYNC_TIMEOUT_MS,
52190
52517
  "control sync"
52191
52518
  );
@@ -52218,8 +52545,8 @@ function checkLaunchGuard2(repoPath, agentId, options = {}) {
52218
52545
  init_control_config();
52219
52546
 
52220
52547
  // src/core/control-lifecycle.ts
52221
- var import_child_process8 = require("child_process");
52222
- var path41 = __toESM(require("path"));
52548
+ var import_child_process9 = require("child_process");
52549
+ var path42 = __toESM(require("path"));
52223
52550
 
52224
52551
  // src/core/control-image.ts
52225
52552
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -52243,10 +52570,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
52243
52570
  var CONTROL_CONTAINER_PORT = 3847;
52244
52571
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
52245
52572
  function resolveControlDir() {
52246
- return path41.resolve(__dirname, "..", "control");
52573
+ return path42.resolve(__dirname, "..", "control");
52247
52574
  }
52248
52575
  function resolveControlBuildContext() {
52249
- return path41.resolve(resolveControlDir(), "..");
52576
+ return path42.resolve(resolveControlDir(), "..");
52250
52577
  }
52251
52578
  function buildDockerRunArgs(options) {
52252
52579
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -52269,7 +52596,7 @@ function buildDockerRunArgs(options) {
52269
52596
  return args;
52270
52597
  }
52271
52598
  function runDocker(args) {
52272
- const result = (0, import_child_process8.spawnSync)("docker", args, {
52599
+ const result = (0, import_child_process9.spawnSync)("docker", args, {
52273
52600
  stdio: "inherit",
52274
52601
  env: process.env
52275
52602
  });
@@ -52279,7 +52606,7 @@ function runDocker(args) {
52279
52606
  return result.status ?? 1;
52280
52607
  }
52281
52608
  function controlContainerExists(name = CONTROL_CONTAINER_NAME) {
52282
- const result = (0, import_child_process8.spawnSync)("docker", ["ps", "-aq", "-f", `name=^${name}$`], {
52609
+ const result = (0, import_child_process9.spawnSync)("docker", ["ps", "-aq", "-f", `name=^${name}$`], {
52283
52610
  encoding: "utf8",
52284
52611
  stdio: ["pipe", "pipe", "ignore"]
52285
52612
  });
@@ -52302,7 +52629,7 @@ async function startMissionControl(options) {
52302
52629
  "-t",
52303
52630
  imageRef,
52304
52631
  "-f",
52305
- path41.join(resolveControlDir(), "Dockerfile"),
52632
+ path42.join(resolveControlDir(), "Dockerfile"),
52306
52633
  resolveControlBuildContext()
52307
52634
  ]);
52308
52635
  if (buildCode !== 0) {
@@ -52446,7 +52773,7 @@ async function ensureTelemetryInfrastructure(options) {
52446
52773
 
52447
52774
  // src/core/run-service.ts
52448
52775
  init_telemetry_config();
52449
- var path43 = __toESM(require("path"));
52776
+ var path44 = __toESM(require("path"));
52450
52777
  function extractShellOutput(result) {
52451
52778
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
52452
52779
  const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
@@ -52656,12 +52983,12 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52656
52983
  suffix: session.suffix,
52657
52984
  createdAt: session.createdAt
52658
52985
  });
52659
- const envFile = path43.join(session.workDir, `.env.agent.${options.agentId}`);
52986
+ const envFile = path44.join(session.workDir, `.env.agent.${options.agentId}`);
52660
52987
  try {
52661
52988
  appendTelemetryEnvToFile(envFile, {
52662
52989
  sessionKey,
52663
52990
  agentId: options.agentId,
52664
- repoPath: path43.resolve(options.repoPath),
52991
+ repoPath: path44.resolve(options.repoPath),
52665
52992
  workDir: session.workDir,
52666
52993
  branch: session.branch,
52667
52994
  suffix: session.suffix,
@@ -52890,12 +53217,12 @@ var getEnvironmentStatus = defaultRunService.getEnvironmentStatus.bind(defaultRu
52890
53217
  var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunService);
52891
53218
 
52892
53219
  // src/core/commit-gate-onboarding.ts
52893
- var readline5 = __toESM(require("readline"));
53220
+ var readline6 = __toESM(require("readline"));
52894
53221
 
52895
53222
  // src/core/hooks.ts
52896
- var fs41 = __toESM(require("fs"));
52897
- var os13 = __toESM(require("os"));
52898
- var path44 = __toESM(require("path"));
53223
+ var fs42 = __toESM(require("fs"));
53224
+ var os14 = __toESM(require("os"));
53225
+ var path45 = __toESM(require("path"));
52899
53226
  var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
52900
53227
  var MARKER_END = "# <<< har commit gate <<<";
52901
53228
  var PRE_COMMIT_BLOCK = [
@@ -52920,7 +53247,7 @@ function resolveCheckoutRoot(cwd) {
52920
53247
  function resolveHooksDir(checkoutDir) {
52921
53248
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
52922
53249
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
52923
- return path44.resolve(checkoutDir, hooksPath);
53250
+ return path45.resolve(checkoutDir, hooksPath);
52924
53251
  }
52925
53252
  function getConfiguredHooksPath(checkoutDir) {
52926
53253
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -52928,9 +53255,9 @@ function getConfiguredHooksPath(checkoutDir) {
52928
53255
  function defaultHarInvocation() {
52929
53256
  const entry = process.argv[1];
52930
53257
  if (entry && entry.endsWith(".js")) {
52931
- return `"${process.execPath}" "${path44.resolve(entry)}"`;
53258
+ return `"${process.execPath}" "${path45.resolve(entry)}"`;
52932
53259
  }
52933
- if (entry) return `"${path44.resolve(entry)}"`;
53260
+ if (entry) return `"${path45.resolve(entry)}"`;
52934
53261
  return "har";
52935
53262
  }
52936
53263
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -52951,40 +53278,40 @@ exit 0
52951
53278
  `;
52952
53279
  }
52953
53280
  function upsertMarkedBlock(filePath, block) {
52954
- if (!fs41.existsSync(filePath)) {
52955
- fs41.writeFileSync(filePath, `#!/bin/sh
53281
+ if (!fs42.existsSync(filePath)) {
53282
+ fs42.writeFileSync(filePath, `#!/bin/sh
52956
53283
  ${block}
52957
53284
  `, { mode: 493 });
52958
53285
  return "created";
52959
53286
  }
52960
- const content = fs41.readFileSync(filePath, "utf8");
53287
+ const content = fs42.readFileSync(filePath, "utf8");
52961
53288
  if (content.includes(MARKER_START)) {
52962
53289
  const pattern = new RegExp(
52963
53290
  `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
52964
53291
  );
52965
- fs41.writeFileSync(filePath, content.replace(pattern, block));
52966
- fs41.chmodSync(filePath, 493);
53292
+ fs42.writeFileSync(filePath, content.replace(pattern, block));
53293
+ fs42.chmodSync(filePath, 493);
52967
53294
  return "updated";
52968
53295
  }
52969
53296
  const suffix = content.endsWith("\n") ? "" : "\n";
52970
- fs41.writeFileSync(filePath, `${content}${suffix}
53297
+ fs42.writeFileSync(filePath, `${content}${suffix}
52971
53298
  ${block}
52972
53299
  `);
52973
- fs41.chmodSync(filePath, 493);
53300
+ fs42.chmodSync(filePath, 493);
52974
53301
  return "appended";
52975
53302
  }
52976
53303
  function removeMarkedBlock(filePath) {
52977
- if (!fs41.existsSync(filePath)) return false;
52978
- const content = fs41.readFileSync(filePath, "utf8");
53304
+ if (!fs42.existsSync(filePath)) return false;
53305
+ const content = fs42.readFileSync(filePath, "utf8");
52979
53306
  if (!content.includes(MARKER_START)) return false;
52980
53307
  const pattern = new RegExp(
52981
53308
  `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
52982
53309
  );
52983
53310
  const stripped = content.replace(pattern, "\n");
52984
53311
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
52985
- fs41.rmSync(filePath);
53312
+ fs42.rmSync(filePath);
52986
53313
  } else {
52987
- fs41.writeFileSync(filePath, stripped);
53314
+ fs42.writeFileSync(filePath, stripped);
52988
53315
  }
52989
53316
  return true;
52990
53317
  }
@@ -53006,20 +53333,20 @@ Or re-run with --force to write into that directory anyway.`
53006
53333
  );
53007
53334
  }
53008
53335
  const hooksDir = resolveHooksDir(checkout);
53009
- fs41.mkdirSync(hooksDir, { recursive: true });
53336
+ fs42.mkdirSync(hooksDir, { recursive: true });
53010
53337
  const invocation = options.harInvocation ?? defaultHarInvocation();
53011
- fs41.writeFileSync(
53012
- path44.join(hooksDir, "har-pre-commit"),
53338
+ fs42.writeFileSync(
53339
+ path45.join(hooksDir, "har-pre-commit"),
53013
53340
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
53014
53341
  { mode: 493 }
53015
53342
  );
53016
- fs41.writeFileSync(
53017
- path44.join(hooksDir, "har-post-commit"),
53343
+ fs42.writeFileSync(
53344
+ path45.join(hooksDir, "har-post-commit"),
53018
53345
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
53019
53346
  { mode: 493 }
53020
53347
  );
53021
- const preCommit = upsertMarkedBlock(path44.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
53022
- const postCommit = upsertMarkedBlock(path44.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
53348
+ const preCommit = upsertMarkedBlock(path45.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
53349
+ const postCommit = upsertMarkedBlock(path45.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
53023
53350
  ensureValidationsIgnored(checkout);
53024
53351
  return { hooksDir, preCommit, postCommit };
53025
53352
  }
@@ -53028,12 +53355,12 @@ function uninstallHooks(repoPath) {
53028
53355
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
53029
53356
  const hooksDir = resolveHooksDir(checkout);
53030
53357
  let removed = false;
53031
- removed = removeMarkedBlock(path44.join(hooksDir, "pre-commit")) || removed;
53032
- removed = removeMarkedBlock(path44.join(hooksDir, "post-commit")) || removed;
53358
+ removed = removeMarkedBlock(path45.join(hooksDir, "pre-commit")) || removed;
53359
+ removed = removeMarkedBlock(path45.join(hooksDir, "post-commit")) || removed;
53033
53360
  for (const file of ["har-pre-commit", "har-post-commit"]) {
53034
- const full = path44.join(hooksDir, file);
53035
- if (fs41.existsSync(full)) {
53036
- fs41.rmSync(full);
53361
+ const full = path45.join(hooksDir, file);
53362
+ if (fs42.existsSync(full)) {
53363
+ fs42.rmSync(full);
53037
53364
  removed = true;
53038
53365
  }
53039
53366
  }
@@ -53052,10 +53379,10 @@ function isAgentWorktree(checkoutDir) {
53052
53379
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
53053
53380
  return true;
53054
53381
  }
53055
- const worktreesRoot = path44.join(os13.homedir(), "worktrees");
53056
- const resolved = path44.resolve(checkoutDir);
53057
- const name = path44.basename(resolved);
53058
- return resolved.startsWith(`${worktreesRoot}${path44.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
53382
+ const worktreesRoot = path45.join(os14.homedir(), "worktrees");
53383
+ const resolved = path45.resolve(checkoutDir);
53384
+ const name = path45.basename(resolved);
53385
+ return resolved.startsWith(`${worktreesRoot}${path45.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
53059
53386
  }
53060
53387
  function resolveEffectiveMode(checkoutDir, gate) {
53061
53388
  if (!gate.enabled) return "off";
@@ -53068,15 +53395,15 @@ function getHooksStatus(repoPath) {
53068
53395
  const hooksDir = resolveHooksDir(checkout);
53069
53396
  const gate = getCommitGateConfig(checkout);
53070
53397
  const hasBlock = (name) => {
53071
- const file = path44.join(hooksDir, name);
53072
- return fs41.existsSync(file) && fs41.readFileSync(file, "utf8").includes(MARKER_START);
53398
+ const file = path45.join(hooksDir, name);
53399
+ return fs42.existsSync(file) && fs42.readFileSync(file, "utf8").includes(MARKER_START);
53073
53400
  };
53074
53401
  return {
53075
53402
  checkout,
53076
53403
  hooksDir,
53077
53404
  configuredHooksPath: getConfiguredHooksPath(checkout),
53078
- preCommitInstalled: hasBlock("pre-commit") && fs41.existsSync(path44.join(hooksDir, "har-pre-commit")),
53079
- postCommitInstalled: hasBlock("post-commit") && fs41.existsSync(path44.join(hooksDir, "har-post-commit")),
53405
+ preCommitInstalled: hasBlock("pre-commit") && fs42.existsSync(path45.join(hooksDir, "har-pre-commit")),
53406
+ postCommitInstalled: hasBlock("post-commit") && fs42.existsSync(path45.join(hooksDir, "har-post-commit")),
53080
53407
  gate,
53081
53408
  effectiveMode: resolveEffectiveMode(checkout, gate)
53082
53409
  };
@@ -53087,7 +53414,7 @@ function checkCommitGate(cwd) {
53087
53414
  }
53088
53415
  const checkout = resolveCheckoutRoot(cwd);
53089
53416
  if (!checkout) return { exitCode: 0, messages: [] };
53090
- if (!fs41.existsSync(path44.join(checkout, ".har", "stages.json"))) {
53417
+ if (!fs42.existsSync(path45.join(checkout, ".har", "stages.json"))) {
53091
53418
  return { exitCode: 0, messages: [] };
53092
53419
  }
53093
53420
  const gate = getCommitGateConfig(checkout);
@@ -53158,14 +53485,14 @@ async function recordCommitAssociation(cwd) {
53158
53485
  }
53159
53486
 
53160
53487
  // src/core/commit-gate-onboarding.ts
53161
- function askYesNo4(question) {
53162
- const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
53163
- return new Promise((resolve37) => {
53488
+ function askYesNo5(question) {
53489
+ const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
53490
+ return new Promise((resolve38) => {
53164
53491
  process.stderr.write(`${question} `);
53165
53492
  rl.once("line", (answer) => {
53166
53493
  rl.close();
53167
53494
  const trimmed = answer.trim();
53168
- resolve37(trimmed === "" || /^y(es)?$/i.test(trimmed));
53495
+ resolve38(trimmed === "" || /^y(es)?$/i.test(trimmed));
53169
53496
  });
53170
53497
  });
53171
53498
  }
@@ -53190,7 +53517,7 @@ async function handleCommitGateOnboarding(options) {
53190
53517
  const status = getHooksStatus(options.repoPath);
53191
53518
  let shouldInstall = status.preCommitInstalled || status.postCommitInstalled || options.install === "always" || options.autoYes === true;
53192
53519
  if (!shouldInstall && options.install === "prompt" && process.stdin.isTTY && process.stdout.isTTY) {
53193
- shouldInstall = await askYesNo4("Install the HAR commit gate for this repository? [Y/n]");
53520
+ shouldInstall = await askYesNo5("Install the HAR commit gate for this repository? [Y/n]");
53194
53521
  }
53195
53522
  if (!shouldInstall) {
53196
53523
  info("Commit gate is not installed; run `har hooks install` when ready.");
@@ -53207,20 +53534,20 @@ async function handleCommitGateOnboarding(options) {
53207
53534
  }
53208
53535
 
53209
53536
  // src/core/onboarding-preferences.ts
53210
- var fs42 = __toESM(require("fs"));
53211
- var os14 = __toESM(require("os"));
53212
- var path45 = __toESM(require("path"));
53537
+ var fs43 = __toESM(require("fs"));
53538
+ var os15 = __toESM(require("os"));
53539
+ var path46 = __toESM(require("path"));
53213
53540
  function getOnboardingPreferencesPath() {
53214
53541
  if (process.env.HAR_PREFERENCES_PATH) {
53215
- return path45.resolve(process.env.HAR_PREFERENCES_PATH);
53542
+ return path46.resolve(process.env.HAR_PREFERENCES_PATH);
53216
53543
  }
53217
- return path45.join(os14.homedir(), ".har", "preferences.json");
53544
+ return path46.join(os15.homedir(), ".har", "preferences.json");
53218
53545
  }
53219
53546
  function readOnboardingPreferences() {
53220
53547
  const preferencePath = getOnboardingPreferencesPath();
53221
53548
  try {
53222
- if (!fs42.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
53223
- return OnboardingPreferencesSchema.parse(JSON.parse(fs42.readFileSync(preferencePath, "utf8")));
53549
+ if (!fs43.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
53550
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs43.readFileSync(preferencePath, "utf8")));
53224
53551
  } catch {
53225
53552
  return OnboardingPreferencesSchema.parse({});
53226
53553
  }
@@ -53245,8 +53572,8 @@ function writeOnboardingPreferences(overrides) {
53245
53572
  };
53246
53573
  const parsed = OnboardingPreferencesSchema.parse(preference);
53247
53574
  const preferencePath = getOnboardingPreferencesPath();
53248
- fs42.mkdirSync(path45.dirname(preferencePath), { recursive: true });
53249
- fs42.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
53575
+ fs43.mkdirSync(path46.dirname(preferencePath), { recursive: true });
53576
+ fs43.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
53250
53577
  `);
53251
53578
  return parsed;
53252
53579
  }
@@ -53526,7 +53853,7 @@ var envCommand = {
53526
53853
  }
53527
53854
  };
53528
53855
  async function handleInit(argv) {
53529
- const repoPath = path46.resolve(argv.repo);
53856
+ const repoPath = path47.resolve(argv.repo);
53530
53857
  const onboarding = resolveOnboardingOptions(argv);
53531
53858
  header("har env init");
53532
53859
  info(`Repository: ${repoPath}`);
@@ -53560,7 +53887,7 @@ async function handleInit(argv) {
53560
53887
  if (argv.auto) {
53561
53888
  await handleAgentMdProposal(repoPath, argv.yes);
53562
53889
  } else {
53563
- emitManualAdaptationPrompt(repoPath, "init", argv.profile);
53890
+ await emitManualAdaptationPrompt(repoPath, "init", argv.profile, void 0, argv.yes);
53564
53891
  }
53565
53892
  divider();
53566
53893
  success("Harness initialized!");
@@ -53590,7 +53917,7 @@ async function handleInit(argv) {
53590
53917
  }
53591
53918
  }
53592
53919
  async function handleMaintain(argv) {
53593
- const repoPath = path46.resolve(argv.repo);
53920
+ const repoPath = path47.resolve(argv.repo);
53594
53921
  const onboarding = resolveOnboardingOptions(argv);
53595
53922
  header("har env maintain");
53596
53923
  info(`Repository: ${repoPath}`);
@@ -53632,7 +53959,13 @@ async function handleMaintain(argv) {
53632
53959
  if (!result.validation.pass) {
53633
53960
  warn("Harness has validation errors \u2014 fix them before running --finalize.");
53634
53961
  }
53635
- emitManualAdaptationPrompt(repoPath, "maintain", "default", result.bundle?.report);
53962
+ await emitManualAdaptationPrompt(
53963
+ repoPath,
53964
+ "maintain",
53965
+ "default",
53966
+ result.bundle?.report,
53967
+ argv.yes
53968
+ );
53636
53969
  info("After your coding agent finishes adapting, record it with: har env maintain --finalize");
53637
53970
  }
53638
53971
  divider();
@@ -53684,7 +54017,7 @@ function resolveOnboardingOptions(argv) {
53684
54017
  }
53685
54018
  };
53686
54019
  }
53687
- function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleReport) {
54020
+ async function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleReport, autoYes = false) {
53688
54021
  const prompt2 = mode === "init" ? buildInitAdaptationPrompt(repoPath, profile) : buildMaintainAdaptationPrompt(repoPath, bundleReport);
53689
54022
  writeAdaptationPrompt(repoPath, prompt2);
53690
54023
  process.stderr.write("\n");
@@ -53700,12 +54033,13 @@ function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleR
53700
54033
  info(" Reference templates are in .har/maintain/templates/");
53701
54034
  }
53702
54035
  printAdaptationPrompt(prompt2);
54036
+ await offerAdaptationPromptClipboard(prompt2, { autoYes });
53703
54037
  }
53704
54038
  async function handleAgentMdProposal(repoPath, autoYes) {
53705
54039
  if (autoYes) {
53706
54040
  const proposal = readAgentMdProposal(repoPath);
53707
54041
  if (proposal) {
53708
- writeFileSafe(path46.join(repoPath, "AGENT.md"), proposal.content);
54042
+ writeFileSafe(path47.join(repoPath, "AGENT.md"), proposal.content);
53709
54043
  clearAgentMdProposal(repoPath);
53710
54044
  info("Applied AGENT.md proposal (--yes)");
53711
54045
  }
@@ -53714,7 +54048,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
53714
54048
  await promptApplyAgentMdProposal(repoPath);
53715
54049
  }
53716
54050
  async function handleAddStage(argv) {
53717
- const repoPath = path46.resolve(argv.repo);
54051
+ const repoPath = path47.resolve(argv.repo);
53718
54052
  const available = listStageTemplateIds();
53719
54053
  if (argv.list) {
53720
54054
  for (const id of available) {
@@ -53791,7 +54125,7 @@ async function handleAddStage(argv) {
53791
54125
  }
53792
54126
  }
53793
54127
  async function handlePreflight(argv) {
53794
- const repo = path46.resolve(argv.repo);
54128
+ const repo = path47.resolve(argv.repo);
53795
54129
  const agentId = validateAgentId(argv.id, repo);
53796
54130
  const result = await preflightEnvironment({
53797
54131
  repoPath: repo,
@@ -53809,7 +54143,7 @@ async function handlePreflight(argv) {
53809
54143
  process.exit(result.code);
53810
54144
  }
53811
54145
  async function handleLaunch(argv) {
53812
- const repo = path46.resolve(argv.repo);
54146
+ const repo = path47.resolve(argv.repo);
53813
54147
  const agentId = validateAgentId(argv.id, repo);
53814
54148
  let confirmReplace = argv.replace;
53815
54149
  let force = argv.force;
@@ -53819,10 +54153,10 @@ async function handleLaunch(argv) {
53819
54153
  if (!confirmReplace && process.stdin.isTTY && process.stdout.isTTY) {
53820
54154
  warn("Occupied slot \u2014 review before replacing:");
53821
54155
  console.error(guard.reason ?? "");
53822
- const readline9 = await import("readline");
53823
- const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
53824
- const answer = await new Promise((resolve37) => {
53825
- rl.question("Replace this slot? [y/N] ", resolve37);
54156
+ const readline10 = await import("readline");
54157
+ const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
54158
+ const answer = await new Promise((resolve38) => {
54159
+ rl.question("Replace this slot? [y/N] ", resolve38);
53826
54160
  });
53827
54161
  rl.close();
53828
54162
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -53836,10 +54170,10 @@ async function handleLaunch(argv) {
53836
54170
  if (!guardAfterConfirm.allowed && guardAfterConfirm.blocked && guardAfterConfirm.slot?.dirty) {
53837
54171
  if (!force && process.stdin.isTTY && process.stdout.isTTY) {
53838
54172
  warn("Worktree has uncommitted changes.");
53839
- const readline9 = await import("readline");
53840
- const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
53841
- const answer = await new Promise((resolve37) => {
53842
- rl.question("Discard uncommitted changes? [y/N] ", resolve37);
54173
+ const readline10 = await import("readline");
54174
+ const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
54175
+ const answer = await new Promise((resolve38) => {
54176
+ rl.question("Discard uncommitted changes? [y/N] ", resolve38);
53843
54177
  });
53844
54178
  rl.close();
53845
54179
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -53903,7 +54237,7 @@ async function handleRecover(argv) {
53903
54237
  });
53904
54238
  }
53905
54239
  async function handleVerify(argv) {
53906
- const repo = path46.resolve(argv.repo);
54240
+ const repo = path47.resolve(argv.repo);
53907
54241
  const agentId = validateAgentId(argv.id, repo);
53908
54242
  const result = await runVerification({
53909
54243
  repoPath: repo,
@@ -53915,7 +54249,7 @@ async function handleVerify(argv) {
53915
54249
  process.exit(result.code);
53916
54250
  }
53917
54251
  async function handleTeardown(argv) {
53918
- const repo = path46.resolve(argv.repo);
54252
+ const repo = path47.resolve(argv.repo);
53919
54253
  const agentId = validateAgentId(argv.id, repo);
53920
54254
  const result = await teardownEnvironment({
53921
54255
  repoPath: repo,
@@ -53926,7 +54260,7 @@ async function handleTeardown(argv) {
53926
54260
  process.exit(result.code);
53927
54261
  }
53928
54262
  async function handleComplete(argv) {
53929
- const repo = path46.resolve(argv.repo);
54263
+ const repo = path47.resolve(argv.repo);
53930
54264
  const agentId = validateAgentId(argv.id, repo);
53931
54265
  const result = await completeEnvironment({
53932
54266
  repoPath: repo,
@@ -53947,7 +54281,7 @@ async function handleComplete(argv) {
53947
54281
  process.exit(result.code);
53948
54282
  }
53949
54283
  async function handleStatus(argv) {
53950
- const repoPath = path46.resolve(argv.repo);
54284
+ const repoPath = path47.resolve(argv.repo);
53951
54285
  if (argv.json) {
53952
54286
  const status = collectEnvironmentStatus(repoPath);
53953
54287
  const output = EnvironmentStatusSchema.parse(status);
@@ -53960,7 +54294,7 @@ async function handleStatus(argv) {
53960
54294
  });
53961
54295
  }
53962
54296
  async function handleRunsList(argv) {
53963
- const repoPath = path46.resolve(argv.repo);
54297
+ const repoPath = path47.resolve(argv.repo);
53964
54298
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
53965
54299
  if (argv.json) {
53966
54300
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -53977,7 +54311,7 @@ async function handleRunsList(argv) {
53977
54311
  }
53978
54312
  }
53979
54313
  async function handleRunsGet(argv) {
53980
- const run2 = getRun(path46.resolve(argv.repo), argv.runId);
54314
+ const run2 = getRun(path47.resolve(argv.repo), argv.runId);
53981
54315
  if (!run2) {
53982
54316
  error(`Run not found: ${argv.runId}`);
53983
54317
  process.exit(1);
@@ -54042,7 +54376,7 @@ function printNextSteps(auto2) {
54042
54376
  console.error("");
54043
54377
  console.error(" Read: .har/README.md");
54044
54378
  if (!auto2) {
54045
- console.error(" Adapt: paste prompt above into your coding agent");
54379
+ console.error(" Adapt: paste clipboard / prompt above into your coding agent");
54046
54380
  console.error(" Prompt file: .har/ADAPT-PROMPT.md");
54047
54381
  } else {
54048
54382
  console.error(" Agent guide: AGENT.md (repo root, if applied)");
@@ -54056,20 +54390,88 @@ function printNextSteps(auto2) {
54056
54390
  }
54057
54391
 
54058
54392
  // src/cli/commands/control.ts
54059
- var path48 = __toESM(require("path"));
54393
+ var path49 = __toESM(require("path"));
54060
54394
  init_control_config();
54395
+ init_portal_credentials();
54396
+
54397
+ // src/core/portal-login.ts
54398
+ var http = __toESM(require("http"));
54399
+ var import_crypto = require("crypto");
54400
+ var import_child_process11 = require("child_process");
54401
+ var CALLBACK_PATH = "/callback";
54402
+ var LOGIN_TIMEOUT_MS = 3 * 6e4;
54403
+ function openBrowser(url) {
54404
+ const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
54405
+ try {
54406
+ const child = (0, import_child_process11.spawn)(cmd, args, { stdio: "ignore", detached: true });
54407
+ child.on("error", () => {
54408
+ });
54409
+ child.unref();
54410
+ } catch {
54411
+ }
54412
+ }
54413
+ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
54414
+ const state = (0, import_crypto.randomUUID)();
54415
+ return new Promise((resolve38, reject) => {
54416
+ let timer;
54417
+ const server = http.createServer((req, res) => {
54418
+ const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
54419
+ if (requestUrl.pathname !== CALLBACK_PATH) {
54420
+ res.writeHead(404);
54421
+ res.end("Not found");
54422
+ return;
54423
+ }
54424
+ const token = requestUrl.searchParams.get("token");
54425
+ const returnedState = requestUrl.searchParams.get("state");
54426
+ const workspace = requestUrl.searchParams.get("workspace") ?? void 0;
54427
+ const email2 = requestUrl.searchParams.get("email") ?? void 0;
54428
+ if (returnedState !== state || !token) {
54429
+ res.writeHead(400, { "Content-Type": "text/html" });
54430
+ res.end("<h1>Login failed</h1><p>You can close this tab and try again.</p>");
54431
+ cleanup();
54432
+ reject(new Error("state mismatch or missing token"));
54433
+ return;
54434
+ }
54435
+ res.writeHead(200, { "Content-Type": "text/html" });
54436
+ res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
54437
+ cleanup();
54438
+ resolve38({ portalUrl, token, workspace, email: email2, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
54439
+ });
54440
+ const cleanup = () => {
54441
+ clearTimeout(timer);
54442
+ server.close();
54443
+ };
54444
+ server.on("error", (err) => {
54445
+ cleanup();
54446
+ reject(err);
54447
+ });
54448
+ server.listen(0, "127.0.0.1", () => {
54449
+ const { port } = server.address();
54450
+ const callback = `http://127.0.0.1:${port}${CALLBACK_PATH}`;
54451
+ const loginUrl = `${portalUrl}/cli/login?callback=${encodeURIComponent(callback)}&state=${state}`;
54452
+ openUrl(loginUrl);
54453
+ process.stderr.write(`Opening ${loginUrl}
54454
+ If your browser did not open, paste that URL.
54455
+ `);
54456
+ timer = setTimeout(() => {
54457
+ cleanup();
54458
+ reject(new Error("timed out"));
54459
+ }, LOGIN_TIMEOUT_MS);
54460
+ });
54461
+ });
54462
+ }
54061
54463
 
54062
54464
  // src/core/control-unregister.ts
54063
- var fs43 = __toESM(require("fs"));
54064
- var path47 = __toESM(require("path"));
54465
+ var fs44 = __toESM(require("fs"));
54466
+ var path48 = __toESM(require("path"));
54065
54467
  init_control_config();
54066
54468
  function listUnregisterWorktreeCandidates(repoPath) {
54067
54469
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
54068
54470
  const byPath = /* @__PURE__ */ new Map();
54069
54471
  const add = (partial2) => {
54070
- const resolved = path47.resolve(partial2.worktreePath);
54472
+ const resolved = path48.resolve(partial2.worktreePath);
54071
54473
  if (!resolved || resolved === harnessRoot) return;
54072
- const exists = partial2.exists ?? fs43.existsSync(resolved);
54474
+ const exists = partial2.exists ?? fs44.existsSync(resolved);
54073
54475
  const prev = byPath.get(resolved);
54074
54476
  if (prev) {
54075
54477
  byPath.set(resolved, {
@@ -54116,12 +54518,12 @@ function listUnregisterWorktreeCandidates(repoPath) {
54116
54518
  }
54117
54519
  return [...byPath.values()].sort((a2, b2) => a2.agentId - b2.agentId);
54118
54520
  }
54119
- async function askYesNo5(question) {
54521
+ async function askYesNo6(question) {
54120
54522
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
54121
- const readline9 = await import("readline");
54122
- const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
54123
- const answer = await new Promise((resolve37) => {
54124
- rl.question(question, resolve37);
54523
+ const readline10 = await import("readline");
54524
+ const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
54525
+ const answer = await new Promise((resolve38) => {
54526
+ rl.question(question, resolve38);
54125
54527
  });
54126
54528
  rl.close();
54127
54529
  return /^[Yy]$/.test(answer.trim());
@@ -54133,7 +54535,7 @@ async function confirmUnregister(options) {
54133
54535
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
54134
54536
  throw new Error("Non-interactive terminal \u2014 pass --yes (and optionally --delete-worktrees)");
54135
54537
  }
54136
- const proceed = await askYesNo5("Unregister this repository from Mission Control? [y/N] ");
54538
+ const proceed = await askYesNo6("Unregister this repository from Mission Control? [y/N] ");
54137
54539
  if (!proceed) return { proceed: false, deleteWorktrees: false };
54138
54540
  const existing = options.worktrees.filter((w2) => w2.exists);
54139
54541
  if (existing.length === 0) {
@@ -54145,7 +54547,7 @@ async function confirmUnregister(options) {
54145
54547
  process.stderr.write(` agent-${wt2.agentId}: ${wt2.worktreePath}${dirty}
54146
54548
  `);
54147
54549
  }
54148
- const deleteWorktrees = await askYesNo5(
54550
+ const deleteWorktrees = await askYesNo6(
54149
54551
  `Also delete ${existing.length} session worktree(s) on disk? [y/N] `
54150
54552
  );
54151
54553
  return { proceed: true, deleteWorktrees };
@@ -54183,28 +54585,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
54183
54585
  trigger: "cli"
54184
54586
  });
54185
54587
  if (result.code !== 0) {
54186
- if (fs43.existsSync(candidate.worktreePath)) {
54187
- fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
54588
+ if (fs44.existsSync(candidate.worktreePath)) {
54589
+ fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
54188
54590
  }
54189
54591
  }
54190
54592
  outcomes.push({
54191
54593
  path: candidate.worktreePath,
54192
54594
  agentId: candidate.agentId,
54193
- deleted: !fs43.existsSync(candidate.worktreePath),
54194
- error: result.code !== 0 && fs43.existsSync(candidate.worktreePath) ? result.stderr : void 0
54595
+ deleted: !fs44.existsSync(candidate.worktreePath),
54596
+ error: result.code !== 0 && fs44.existsSync(candidate.worktreePath) ? result.stderr : void 0
54195
54597
  });
54196
54598
  } catch (err) {
54197
54599
  const message = err instanceof Error ? err.message : String(err);
54198
54600
  try {
54199
- if (fs43.existsSync(candidate.worktreePath)) {
54200
- fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
54601
+ if (fs44.existsSync(candidate.worktreePath)) {
54602
+ fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
54201
54603
  }
54202
54604
  } catch {
54203
54605
  }
54204
54606
  outcomes.push({
54205
54607
  path: candidate.worktreePath,
54206
54608
  agentId: candidate.agentId,
54207
- deleted: !fs43.existsSync(candidate.worktreePath),
54609
+ deleted: !fs44.existsSync(candidate.worktreePath),
54208
54610
  error: message
54209
54611
  });
54210
54612
  }
@@ -54320,8 +54722,11 @@ var controlCommand = {
54320
54722
  handleWatch
54321
54723
  ).command(
54322
54724
  "login",
54323
- "Configure HAR Cloud API credentials (hosted sync)",
54324
- (y2) => y2.option("api-key", { type: "string", describe: "HAR Cloud API key" }),
54725
+ "Log in to a har-portal (browser SSO) and store an ingest token",
54726
+ (y2) => y2.option("portal", { type: "string", describe: "Portal base URL (or set HAR_PORTAL_URL)" }).option("api-key", {
54727
+ type: "string",
54728
+ describe: "Store this ingest token directly instead of browser login"
54729
+ }),
54325
54730
  handleLogin
54326
54731
  ).demandCommand(
54327
54732
  1,
@@ -54386,7 +54791,7 @@ async function handleDown() {
54386
54791
  process.exit(code);
54387
54792
  }
54388
54793
  async function handleRegister(argv) {
54389
- const repoPath = path48.resolve(argv.repo);
54794
+ const repoPath = path49.resolve(argv.repo);
54390
54795
  header("har control register");
54391
54796
  info(`Repository: ${repoPath}`);
54392
54797
  try {
@@ -54410,7 +54815,7 @@ async function handleRegister(argv) {
54410
54815
  }
54411
54816
  }
54412
54817
  async function handleUnregister(argv) {
54413
- const repoPath = path48.resolve(argv.repo);
54818
+ const repoPath = path49.resolve(argv.repo);
54414
54819
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
54415
54820
  try {
54416
54821
  let deleteWorktrees = argv.deleteWorktrees;
@@ -54479,7 +54884,7 @@ async function handleUnregister(argv) {
54479
54884
  }
54480
54885
  }
54481
54886
  async function handleSync(argv) {
54482
- const repoPath = path48.resolve(argv.repo);
54887
+ const repoPath = path49.resolve(argv.repo);
54483
54888
  try {
54484
54889
  await syncRepoWithControl({
54485
54890
  repoPath,
@@ -54518,7 +54923,7 @@ async function handleWatch(argv) {
54518
54923
  };
54519
54924
  const tick = async () => {
54520
54925
  if (argv.repo) {
54521
- await syncOne(path48.resolve(argv.repo));
54926
+ await syncOne(path49.resolve(argv.repo));
54522
54927
  return;
54523
54928
  }
54524
54929
  try {
@@ -54539,21 +54944,40 @@ async function handleWatch(argv) {
54539
54944
  }
54540
54945
  async function handleLogin(argv) {
54541
54946
  header("har control login");
54542
- if (!argv.apiKey) {
54543
- error("Provide --api-key (HAR Cloud API key)");
54947
+ const portalUrl = (argv.portal ?? process.env.HAR_PORTAL_URL ?? "").replace(/\/+$/, "");
54948
+ if (!portalUrl) {
54949
+ error("Provide --portal <url> (or set HAR_PORTAL_URL)");
54950
+ process.exit(1);
54951
+ }
54952
+ if (argv.apiKey) {
54953
+ writePortalCredentials({
54954
+ portalUrl,
54955
+ token: argv.apiKey,
54956
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
54957
+ });
54958
+ success(`Saved ingest token for ${portalUrl}`);
54959
+ info("Sync: har control sync");
54960
+ return;
54961
+ }
54962
+ try {
54963
+ const creds = await loginViaBrowser(portalUrl);
54964
+ writePortalCredentials(creds);
54965
+ success(
54966
+ `Logged in to ${portalUrl}${creds.workspace ? ` (workspace: ${creds.workspace})` : ""}`
54967
+ );
54968
+ info("Sync: har control sync");
54969
+ } catch (err) {
54970
+ error(`Login failed: ${err.message}`);
54544
54971
  process.exit(1);
54545
54972
  }
54546
- process.env.HAR_CLOUD_API_KEY = argv.apiKey;
54547
- success("HAR_CLOUD_API_KEY set for this process. Export it in your shell for persistence.");
54548
- info("Sync to cloud: har control sync --cloud");
54549
54973
  }
54550
54974
 
54551
54975
  // src/cli/commands/hooks.ts
54552
- var path50 = __toESM(require("path"));
54976
+ var path51 = __toESM(require("path"));
54553
54977
 
54554
54978
  // src/core/claude-hooks.ts
54555
- var fs44 = __toESM(require("fs"));
54556
- var path49 = __toESM(require("path"));
54979
+ var fs45 = __toESM(require("fs"));
54980
+ var path50 = __toESM(require("path"));
54557
54981
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
54558
54982
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
54559
54983
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -54564,8 +54988,8 @@ function isHarGuardEntry(entry) {
54564
54988
  );
54565
54989
  }
54566
54990
  function readSettings(settingsPath) {
54567
- if (!fs44.existsSync(settingsPath)) return {};
54568
- const raw = fs44.readFileSync(settingsPath, "utf8").trim();
54991
+ if (!fs45.existsSync(settingsPath)) return {};
54992
+ const raw = fs45.readFileSync(settingsPath, "utf8").trim();
54569
54993
  if (raw === "") return {};
54570
54994
  const parsed = JSON.parse(raw);
54571
54995
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -54574,19 +54998,19 @@ function readSettings(settingsPath) {
54574
54998
  return parsed;
54575
54999
  }
54576
55000
  function writeSettings(settingsPath, settings) {
54577
- fs44.mkdirSync(path49.dirname(settingsPath), { recursive: true });
54578
- fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
55001
+ fs45.mkdirSync(path50.dirname(settingsPath), { recursive: true });
55002
+ fs45.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
54579
55003
  }
54580
55004
  function installClaudeGuard(repoPath) {
54581
55005
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
54582
55006
  if (!templatePath) {
54583
55007
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
54584
55008
  }
54585
- const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54586
- fs44.mkdirSync(path49.dirname(guardScript), { recursive: true });
54587
- fs44.copyFileSync(templatePath, guardScript);
54588
- fs44.chmodSync(guardScript, 493);
54589
- const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
55009
+ const guardScript = path50.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
55010
+ fs45.mkdirSync(path50.dirname(guardScript), { recursive: true });
55011
+ fs45.copyFileSync(templatePath, guardScript);
55012
+ fs45.chmodSync(guardScript, 493);
55013
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54590
55014
  const settings = readSettings(settingsPath);
54591
55015
  const hooks = settings.hooks ?? {};
54592
55016
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -54600,15 +55024,15 @@ function installClaudeGuard(repoPath) {
54600
55024
  }
54601
55025
  function uninstallClaudeGuard(repoPath) {
54602
55026
  let removed = false;
54603
- const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54604
- if (fs44.existsSync(guardScript)) {
54605
- fs44.rmSync(guardScript);
55027
+ const guardScript = path50.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
55028
+ if (fs45.existsSync(guardScript)) {
55029
+ fs45.rmSync(guardScript);
54606
55030
  removed = true;
54607
- const parent = path49.dirname(guardScript);
54608
- if (fs44.existsSync(parent) && fs44.readdirSync(parent).length === 0) fs44.rmdirSync(parent);
55031
+ const parent = path50.dirname(guardScript);
55032
+ if (fs45.existsSync(parent) && fs45.readdirSync(parent).length === 0) fs45.rmdirSync(parent);
54609
55033
  }
54610
- const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54611
- if (fs44.existsSync(settingsPath)) {
55034
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
55035
+ if (fs45.existsSync(settingsPath)) {
54612
55036
  const settings = readSettings(settingsPath);
54613
55037
  const preToolUse = settings.hooks?.PreToolUse;
54614
55038
  if (preToolUse) {
@@ -54633,8 +55057,8 @@ function uninstallClaudeGuard(repoPath) {
54633
55057
  return { removed };
54634
55058
  }
54635
55059
  function claudeGuardInstalled(repoPath) {
54636
- const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54637
- if (!fs44.existsSync(settingsPath)) return false;
55060
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
55061
+ if (!fs45.existsSync(settingsPath)) return false;
54638
55062
  try {
54639
55063
  const settings = readSettings(settingsPath);
54640
55064
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -54650,7 +55074,7 @@ function repoOption(y2) {
54650
55074
  function handleInstall2(argv) {
54651
55075
  try {
54652
55076
  if (argv.claude) {
54653
- const result2 = installClaudeGuard(path50.resolve(argv.repo));
55077
+ const result2 = installClaudeGuard(path51.resolve(argv.repo));
54654
55078
  success("Claude Code worktree guard installed.");
54655
55079
  info(`Guard script: ${result2.guardScript}`);
54656
55080
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -54658,7 +55082,7 @@ function handleInstall2(argv) {
54658
55082
  info("Commit both files so the guard travels with the repo.");
54659
55083
  return;
54660
55084
  }
54661
- const result = installHooks({ repoPath: path50.resolve(argv.repo), force: argv.force });
55085
+ const result = installHooks({ repoPath: path51.resolve(argv.repo), force: argv.force });
54662
55086
  success(`Commit gate installed in ${result.hooksDir}`);
54663
55087
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
54664
55088
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -54671,7 +55095,7 @@ function handleInstall2(argv) {
54671
55095
  function handleUninstall(argv) {
54672
55096
  try {
54673
55097
  if (argv.claude) {
54674
- const result2 = uninstallClaudeGuard(path50.resolve(argv.repo));
55098
+ const result2 = uninstallClaudeGuard(path51.resolve(argv.repo));
54675
55099
  if (result2.removed) {
54676
55100
  success("Claude Code worktree guard removed.");
54677
55101
  } else {
@@ -54679,7 +55103,7 @@ function handleUninstall(argv) {
54679
55103
  }
54680
55104
  return;
54681
55105
  }
54682
- const result = uninstallHooks(path50.resolve(argv.repo));
55106
+ const result = uninstallHooks(path51.resolve(argv.repo));
54683
55107
  if (result.removed) {
54684
55108
  success(`Commit gate removed from ${result.hooksDir}`);
54685
55109
  } else {
@@ -54692,7 +55116,7 @@ function handleUninstall(argv) {
54692
55116
  }
54693
55117
  function handleStatus2(argv) {
54694
55118
  try {
54695
- const status = getHooksStatus(path50.resolve(argv.repo));
55119
+ const status = getHooksStatus(path51.resolve(argv.repo));
54696
55120
  if (argv.json) {
54697
55121
  process.stdout.write(`${JSON.stringify(status, null, 2)}
54698
55122
  `);
@@ -54710,7 +55134,7 @@ function handleStatus2(argv) {
54710
55134
  );
54711
55135
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
54712
55136
  info(
54713
- `Claude guard: ${claudeGuardInstalled(path50.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
55137
+ `Claude guard: ${claudeGuardInstalled(path51.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
54714
55138
  );
54715
55139
  } catch (err) {
54716
55140
  error(err instanceof Error ? err.message : String(err));
@@ -54971,10 +55395,10 @@ function assignProp(target, prop, value) {
54971
55395
  configurable: true
54972
55396
  });
54973
55397
  }
54974
- function getElementAtPath(obj, path53) {
54975
- if (!path53)
55398
+ function getElementAtPath(obj, path54) {
55399
+ if (!path54)
54976
55400
  return obj;
54977
- return path53.reduce((acc, key) => acc?.[key], obj);
55401
+ return path54.reduce((acc, key) => acc?.[key], obj);
54978
55402
  }
54979
55403
  function promiseAllObject(promisesObj) {
54980
55404
  const keys = Object.keys(promisesObj);
@@ -55294,11 +55718,11 @@ function aborted(x2, startIndex = 0) {
55294
55718
  }
55295
55719
  return false;
55296
55720
  }
55297
- function prefixIssues(path53, issues) {
55721
+ function prefixIssues(path54, issues) {
55298
55722
  return issues.map((iss) => {
55299
55723
  var _a3;
55300
55724
  (_a3 = iss).path ?? (_a3.path = []);
55301
- iss.path.unshift(path53);
55725
+ iss.path.unshift(path54);
55302
55726
  return iss;
55303
55727
  });
55304
55728
  }
@@ -60621,7 +61045,7 @@ var Protocol = class {
60621
61045
  return;
60622
61046
  }
60623
61047
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
60624
- await new Promise((resolve37) => setTimeout(resolve37, pollInterval));
61048
+ await new Promise((resolve38) => setTimeout(resolve38, pollInterval));
60625
61049
  options?.signal?.throwIfAborted();
60626
61050
  }
60627
61051
  } catch (error3) {
@@ -60638,7 +61062,7 @@ var Protocol = class {
60638
61062
  */
60639
61063
  request(request, resultSchema, options) {
60640
61064
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
60641
- return new Promise((resolve37, reject) => {
61065
+ return new Promise((resolve38, reject) => {
60642
61066
  const earlyReject = (error3) => {
60643
61067
  reject(error3);
60644
61068
  };
@@ -60716,7 +61140,7 @@ var Protocol = class {
60716
61140
  if (!parseResult.success) {
60717
61141
  reject(parseResult.error);
60718
61142
  } else {
60719
- resolve37(parseResult.data);
61143
+ resolve38(parseResult.data);
60720
61144
  }
60721
61145
  } catch (error3) {
60722
61146
  reject(error3);
@@ -60977,12 +61401,12 @@ var Protocol = class {
60977
61401
  }
60978
61402
  } catch {
60979
61403
  }
60980
- return new Promise((resolve37, reject) => {
61404
+ return new Promise((resolve38, reject) => {
60981
61405
  if (signal.aborted) {
60982
61406
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
60983
61407
  return;
60984
61408
  }
60985
- const timeoutId = setTimeout(resolve37, interval);
61409
+ const timeoutId = setTimeout(resolve38, interval);
60986
61410
  signal.addEventListener("abort", () => {
60987
61411
  clearTimeout(timeoutId);
60988
61412
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -61772,7 +62196,7 @@ var Server = class extends Protocol {
61772
62196
  };
61773
62197
 
61774
62198
  // src/mcp/server.ts
61775
- var path51 = __toESM(require("path"));
62199
+ var path52 = __toESM(require("path"));
61776
62200
 
61777
62201
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
61778
62202
  var import_node_process2 = __toESM(require("node:process"), 1);
@@ -61855,12 +62279,12 @@ var StdioServerTransport = class {
61855
62279
  this.onclose?.();
61856
62280
  }
61857
62281
  send(message) {
61858
- return new Promise((resolve37) => {
62282
+ return new Promise((resolve38) => {
61859
62283
  const json = serializeMessage(message);
61860
62284
  if (this._stdout.write(json)) {
61861
- resolve37();
62285
+ resolve38();
61862
62286
  } else {
61863
- this._stdout.once("drain", resolve37);
62287
+ this._stdout.once("drain", resolve38);
61864
62288
  }
61865
62289
  });
61866
62290
  }
@@ -62432,7 +62856,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
62432
62856
  const input = ControlUpInputSchema.parse({ ...args, repo });
62433
62857
  const result = await startControlAndSync({
62434
62858
  detach: input.detach,
62435
- cwd: path51.resolve(input.repo)
62859
+ cwd: path52.resolve(input.repo)
62436
62860
  });
62437
62861
  if (result.code !== 0) {
62438
62862
  return {
@@ -62573,7 +62997,7 @@ function getStore() {
62573
62997
  }
62574
62998
  return store;
62575
62999
  }
62576
- function readline6() {
63000
+ function readline7() {
62577
63001
  return getStore().rl;
62578
63002
  }
62579
63003
  function withUpdates(fn) {
@@ -62618,7 +63042,7 @@ var effectScheduler = {
62618
63042
  const { index } = store;
62619
63043
  store.hooksEffect.push(() => {
62620
63044
  store.hooksCleanup[index]?.();
62621
- const cleanFn = cb(readline6());
63045
+ const cleanFn = cb(readline7());
62622
63046
  if (cleanFn != null && typeof cleanFn !== "function") {
62623
63047
  throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
62624
63048
  }
@@ -63094,7 +63518,7 @@ function breakLines(content, width) {
63094
63518
  return content.split("\n").flatMap((line) => (0, import_wrap_ansi.default)(line, width, { trim: false, hard: true }).split("\n").map((str) => str.trimEnd())).join("\n");
63095
63519
  }
63096
63520
  function readlineWidth() {
63097
- return (0, import_cli_width.default)({ defaultWidth: 80, output: readline6().output });
63521
+ return (0, import_cli_width.default)({ defaultWidth: 80, output: readline7().output });
63098
63522
  }
63099
63523
 
63100
63524
  // node_modules/@inquirer/core/dist/esm/lib/pagination/lines.mjs
@@ -63186,7 +63610,7 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
63186
63610
  }
63187
63611
 
63188
63612
  // node_modules/@inquirer/core/dist/esm/lib/create-prompt.mjs
63189
- var readline7 = __toESM(require("node:readline"), 1);
63613
+ var readline8 = __toESM(require("node:readline"), 1);
63190
63614
  var import_node_async_hooks3 = require("node:async_hooks");
63191
63615
  var import_mute_stream = __toESM(require_lib3(), 1);
63192
63616
 
@@ -63512,13 +63936,13 @@ var PromisePolyfill = class extends Promise {
63512
63936
  // Available starting from Node 22
63513
63937
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
63514
63938
  static withResolver() {
63515
- let resolve37;
63939
+ let resolve38;
63516
63940
  let reject;
63517
63941
  const promise = new Promise((res, rej) => {
63518
- resolve37 = res;
63942
+ resolve38 = res;
63519
63943
  reject = rej;
63520
63944
  });
63521
- return { promise, resolve: resolve37, reject };
63945
+ return { promise, resolve: resolve38, reject };
63522
63946
  }
63523
63947
  };
63524
63948
 
@@ -63529,13 +63953,13 @@ function createPrompt(view) {
63529
63953
  const cleanups = /* @__PURE__ */ new Set();
63530
63954
  const output = new import_mute_stream.default();
63531
63955
  output.pipe(context.output ?? process.stdout);
63532
- const rl = readline7.createInterface({
63956
+ const rl = readline8.createInterface({
63533
63957
  terminal: true,
63534
63958
  input,
63535
63959
  output
63536
63960
  });
63537
63961
  const screen = new ScreenManager(rl);
63538
- const { promise, resolve: resolve37, reject } = PromisePolyfill.withResolver();
63962
+ const { promise, resolve: resolve38, reject } = PromisePolyfill.withResolver();
63539
63963
  const cancel = () => reject(new CancelPromptError());
63540
63964
  if (signal) {
63541
63965
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -63559,7 +63983,7 @@ function createPrompt(view) {
63559
63983
  cycle(() => {
63560
63984
  try {
63561
63985
  const nextView = view(config2, (value) => {
63562
- setImmediate(() => resolve37(value));
63986
+ setImmediate(() => resolve38(value));
63563
63987
  });
63564
63988
  const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
63565
63989
  screen.render(content, bottomContent);
@@ -64546,9 +64970,9 @@ var import_run_async = __toESM(require_run_async(), 1);
64546
64970
  var import_mute_stream2 = __toESM(require_lib3(), 1);
64547
64971
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
64548
64972
  var _2 = {
64549
- set: (obj, path53 = "", value) => {
64973
+ set: (obj, path54 = "", value) => {
64550
64974
  let pointer = obj;
64551
- path53.split(".").forEach((key, index, arr) => {
64975
+ path54.split(".").forEach((key, index, arr) => {
64552
64976
  if (key === "__proto__" || key === "constructor")
64553
64977
  return;
64554
64978
  if (index === arr.length - 1) {
@@ -64559,8 +64983,8 @@ var _2 = {
64559
64983
  pointer = pointer[key];
64560
64984
  });
64561
64985
  },
64562
- get: (obj, path53 = "", defaultValue) => {
64563
- const travel = (regexp) => String.prototype.split.call(path53, regexp).filter(Boolean).reduce(
64986
+ get: (obj, path54 = "", defaultValue) => {
64987
+ const travel = (regexp) => String.prototype.split.call(path54, regexp).filter(Boolean).reduce(
64564
64988
  // @ts-expect-error implicit any on res[key]
64565
64989
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
64566
64990
  obj
@@ -64674,7 +65098,7 @@ var PromptsRunner = class {
64674
65098
  throw new Error(`Prompt for type ${question.type} not found`);
64675
65099
  }
64676
65100
  let cleanupSignal;
64677
- const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve37, reject) => {
65101
+ const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve38, reject) => {
64678
65102
  const rl = import_node_readline.default.createInterface(setupReadlineOptions(this.opt));
64679
65103
  rl.resume();
64680
65104
  const onClose = () => {
@@ -64710,7 +65134,7 @@ var PromptsRunner = class {
64710
65134
  cleanupSignal = void 0;
64711
65135
  };
64712
65136
  }
64713
- activePrompt.run().then(resolve37, reject).finally(cleanup);
65137
+ activePrompt.run().then(resolve38, reject).finally(cleanup);
64714
65138
  }) : prompt2;
64715
65139
  const { signal: moduleSignal } = this.opt;
64716
65140
  if (moduleSignal?.aborted) {
@@ -64924,7 +65348,7 @@ var preferencesCommand = {
64924
65348
  };
64925
65349
 
64926
65350
  // src/cli/commands/telemetry.ts
64927
- var path52 = __toESM(require("path"));
65351
+ var path53 = __toESM(require("path"));
64928
65352
  init_control_config();
64929
65353
  init_otel_hooks();
64930
65354
  init_telemetry_config();
@@ -65009,7 +65433,7 @@ async function handleOff() {
65009
65433
  info("Mission Control will not auto-start. Existing usage rows are kept.");
65010
65434
  }
65011
65435
  async function handleWriteEnv(argv) {
65012
- const repoPath = path52.resolve(argv.repo);
65436
+ const repoPath = path53.resolve(argv.repo);
65013
65437
  const harnessRoot = resolveHarnessRoot(repoPath);
65014
65438
  const session = readSlotRegistry(harnessRoot, argv.agentId);
65015
65439
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -65021,7 +65445,7 @@ async function handleWriteEnv(argv) {
65021
65445
  suffix,
65022
65446
  createdAt: session?.createdAt
65023
65447
  });
65024
- const envFile = argv.envFile ?? path52.join(workDir, `.env.agent.${argv.agentId}`);
65448
+ const envFile = argv.envFile ?? path53.join(workDir, `.env.agent.${argv.agentId}`);
65025
65449
  const attrs = {
65026
65450
  sessionKey,
65027
65451
  agentId: argv.agentId,
@@ -65040,7 +65464,7 @@ async function handleWriteEnv(argv) {
65040
65464
  success(`Wrote session attribution to ${envFile}`);
65041
65465
  }
65042
65466
  function handlePrintEnv(argv) {
65043
- const repoPath = path52.resolve(argv.repo);
65467
+ const repoPath = path53.resolve(argv.repo);
65044
65468
  const workDir = argv.workDir ?? repoPath;
65045
65469
  const sessionKey = buildSessionKey({
65046
65470
  branch: argv.branch,