@osfactory/har 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -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 path52 = url.path;
769
- if (path52.length === 0) {
768
+ const path54 = url.path;
769
+ if (path54.length === 0) {
770
770
  return;
771
771
  }
772
- if (url.scheme === "file" && path52.length === 1 && isNormalizedWindowsDriveLetter(path52[0])) {
772
+ if (url.scheme === "file" && path54.length === 1 && isNormalizedWindowsDriveLetter(path54[0])) {
773
773
  return;
774
774
  }
775
- path52.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(path52, { 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: path52, 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(path52, { mtimeMs, size }, filenameOrOptions, option
6367
6367
  lastModified: file.lastModified
6368
6368
  });
6369
6369
  }
6370
- function fileFromPathSync(path52, filenameOrOptions, options = {}) {
6371
- const stats = (0, import_fs5.statSync)(path52);
6372
- return createFileFromPath(path52, 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(path52, filenameOrOptions, options) {
6375
- const stats = await import_fs5.promises.stat(path52);
6376
- return createFileFromPath(path52, 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,44 @@ 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
+ createdAt: parsed.createdAt ?? ""
6453
+ };
6454
+ } catch {
6455
+ return null;
6456
+ }
6457
+ }
6458
+ function writePortalCredentials(creds) {
6459
+ const file = portalCredentialsPath();
6460
+ fs26.mkdirSync(path25.dirname(file), { recursive: true });
6461
+ fs26.writeFileSync(file, JSON.stringify(creds, null, 2), { mode: 384 });
6462
+ fs26.chmodSync(file, 384);
6463
+ }
6464
+ var fs26, os4, path25;
6465
+ var init_portal_credentials = __esm({
6466
+ "src/core/portal-credentials.ts"() {
6467
+ "use strict";
6468
+ fs26 = __toESM(require("fs"));
6469
+ os4 = __toESM(require("os"));
6470
+ path25 = __toESM(require("path"));
6471
+ }
6472
+ });
6473
+
6436
6474
  // src/core/control-config.ts
6437
6475
  function getControlApiUrl() {
6438
6476
  return process.env.HAR_CONTROL_API_URL ?? DEFAULT_CONTROL_API_URL;
@@ -6440,10 +6478,33 @@ function getControlApiUrl() {
6440
6478
  function isControlEnabled() {
6441
6479
  return process.env.HAR_CONTROL_DISABLED !== "true";
6442
6480
  }
6481
+ function normalizeUrl(url) {
6482
+ return url.replace(/\/+$/, "");
6483
+ }
6484
+ function getPortalTarget() {
6485
+ if (process.env.HAR_PORTAL_URL && process.env.HAR_PORTAL_TOKEN) {
6486
+ return {
6487
+ url: normalizeUrl(process.env.HAR_PORTAL_URL),
6488
+ token: process.env.HAR_PORTAL_TOKEN
6489
+ };
6490
+ }
6491
+ const stored = readPortalCredentials();
6492
+ if (stored) {
6493
+ return { url: normalizeUrl(stored.portalUrl), token: stored.token };
6494
+ }
6495
+ if (process.env.HAR_CLOUD_API_URL && process.env.HAR_CLOUD_API_KEY) {
6496
+ return {
6497
+ url: normalizeUrl(process.env.HAR_CLOUD_API_URL),
6498
+ token: process.env.HAR_CLOUD_API_KEY
6499
+ };
6500
+ }
6501
+ return null;
6502
+ }
6443
6503
  var DEFAULT_CONTROL_API_URL;
6444
6504
  var init_control_config = __esm({
6445
6505
  "src/core/control-config.ts"() {
6446
6506
  "use strict";
6507
+ init_portal_credentials();
6447
6508
  DEFAULT_CONTROL_API_URL = "http://localhost:3847";
6448
6509
  }
6449
6510
  });
@@ -6451,9 +6512,9 @@ var init_control_config = __esm({
6451
6512
  // src/core/telemetry-config.ts
6452
6513
  function getPreferencePath() {
6453
6514
  if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
6454
- return path35.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6515
+ return path37.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6455
6516
  }
6456
- return path35.join(os9.homedir(), ".har", "telemetry.json");
6517
+ return path37.join(os10.homedir(), ".har", "telemetry.json");
6457
6518
  }
6458
6519
  function parseEnvOverride(raw) {
6459
6520
  if (raw === void 0 || raw === "") return void 0;
@@ -6474,10 +6535,10 @@ function normalizeSignals(enabled, raw) {
6474
6535
  function readTelemetryPreference() {
6475
6536
  const preferencePath = getPreferencePath();
6476
6537
  try {
6477
- if (!fs35.existsSync(preferencePath)) {
6538
+ if (!fs37.existsSync(preferencePath)) {
6478
6539
  return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
6479
6540
  }
6480
- const parsed = JSON.parse(fs35.readFileSync(preferencePath, "utf8"));
6541
+ const parsed = JSON.parse(fs37.readFileSync(preferencePath, "utf8"));
6481
6542
  const enabled = parsed.enabled !== false;
6482
6543
  return {
6483
6544
  enabled,
@@ -6500,8 +6561,8 @@ function writeTelemetryPreference(enabled, signals2) {
6500
6561
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6501
6562
  };
6502
6563
  const preferencePath = getPreferencePath();
6503
- fs35.mkdirSync(path35.dirname(preferencePath), { recursive: true });
6504
- fs35.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6564
+ fs37.mkdirSync(path37.dirname(preferencePath), { recursive: true });
6565
+ fs37.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6505
6566
  return preference;
6506
6567
  }
6507
6568
  function isTelemetryEnabled() {
@@ -6516,13 +6577,13 @@ function getTelemetrySignals() {
6516
6577
  function getTelemetryPreferencePath() {
6517
6578
  return getPreferencePath();
6518
6579
  }
6519
- var fs35, os9, path35, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6580
+ var fs37, os10, path37, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6520
6581
  var init_telemetry_config = __esm({
6521
6582
  "src/core/telemetry-config.ts"() {
6522
6583
  "use strict";
6523
- fs35 = __toESM(require("fs"));
6524
- os9 = __toESM(require("os"));
6525
- path35 = __toESM(require("path"));
6584
+ fs37 = __toESM(require("fs"));
6585
+ os10 = __toESM(require("os"));
6586
+ path37 = __toESM(require("path"));
6526
6587
  DEFAULT_SIGNALS_ON = {
6527
6588
  metrics: true,
6528
6589
  logs: true,
@@ -6563,15 +6624,15 @@ __export(otel_hooks_exports, {
6563
6624
  });
6564
6625
  function getOtelHooksHome() {
6565
6626
  if (process.env.HAR_OTEL_HOOKS_HOME) {
6566
- return path41.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6627
+ return path43.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6567
6628
  }
6568
- return path41.join(os12.homedir(), ".har", "otel-hooks");
6629
+ return path43.join(os13.homedir(), ".har", "otel-hooks");
6569
6630
  }
6570
6631
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
6571
- return path41.join(hooksHome, "otel_config.json");
6632
+ return path43.join(hooksHome, "otel_config.json");
6572
6633
  }
6573
6634
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
6574
- return path41.join(hooksHome, "run-otel-hook.sh");
6635
+ return path43.join(hooksHome, "run-otel-hook.sh");
6575
6636
  }
6576
6637
  function buildOtelHooksConfig(options) {
6577
6638
  const enabled = options?.enabled ?? isTelemetryEnabled();
@@ -6590,18 +6651,18 @@ function buildOtelHooksConfig(options) {
6590
6651
  };
6591
6652
  }
6592
6653
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
6593
- fs39.mkdirSync(hooksHome, { recursive: true });
6654
+ fs41.mkdirSync(hooksHome, { recursive: true });
6594
6655
  const configPath = getOtelHooksConfigPath(hooksHome);
6595
6656
  const payload = {
6596
6657
  _comment: "Managed by har telemetry \u2014 do not edit by hand; use: har telemetry on|off",
6597
6658
  ...config2
6598
6659
  };
6599
- fs39.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6660
+ fs41.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6600
6661
  `);
6601
6662
  return configPath;
6602
6663
  }
6603
6664
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
6604
- fs39.mkdirSync(hooksHome, { recursive: true });
6665
+ fs41.mkdirSync(hooksHome, { recursive: true });
6605
6666
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
6606
6667
  const script = `#!/usr/bin/env bash
6607
6668
  # Managed by har telemetry \u2014 invokes opentelemetry-hooks with HAR config home.
@@ -6609,9 +6670,9 @@ set -euo pipefail
6609
6670
  export IDE_OTEL_HOOK_HOME="${hooksHome}"
6610
6671
  exec "${otelHookCommand}" "$@"
6611
6672
  `;
6612
- fs39.writeFileSync(wrapperPath, script, { mode: 493 });
6673
+ fs41.writeFileSync(wrapperPath, script, { mode: 493 });
6613
6674
  try {
6614
- fs39.chmodSync(wrapperPath, 493);
6675
+ fs41.chmodSync(wrapperPath, 493);
6615
6676
  } catch {
6616
6677
  }
6617
6678
  return wrapperPath;
@@ -6691,10 +6752,10 @@ function runSetupAgent(agent, otelHookCommand, hooksHome) {
6691
6752
  };
6692
6753
  }
6693
6754
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6694
- if (!fs39.existsSync(filePath)) return false;
6755
+ if (!fs41.existsSync(filePath)) return false;
6695
6756
  let raw;
6696
6757
  try {
6697
- raw = fs39.readFileSync(filePath, "utf8");
6758
+ raw = fs41.readFileSync(filePath, "utf8");
6698
6759
  } catch {
6699
6760
  return false;
6700
6761
  }
@@ -6733,16 +6794,16 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6733
6794
  return changed;
6734
6795
  };
6735
6796
  if (!walk(parsed)) return false;
6736
- fs39.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6797
+ fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6737
6798
  `);
6738
6799
  return true;
6739
6800
  }
6740
6801
  function rewriteKnownHookRegistrations(wrapperPath) {
6741
- const home = os12.homedir();
6802
+ const home = os13.homedir();
6742
6803
  const candidates = [
6743
- path41.join(home, ".cursor", "hooks.json"),
6744
- path41.join(home, ".claude", "settings.json"),
6745
- path41.join(home, ".codex", "hooks.json")
6804
+ path43.join(home, ".cursor", "hooks.json"),
6805
+ path43.join(home, ".claude", "settings.json"),
6806
+ path43.join(home, ".codex", "hooks.json")
6746
6807
  ];
6747
6808
  for (const filePath of candidates) {
6748
6809
  try {
@@ -6755,7 +6816,7 @@ function ensureOtelHooks(options) {
6755
6816
  const hooksHome = getOtelHooksHome();
6756
6817
  const errors = [];
6757
6818
  const agentsSetup = [];
6758
- fs39.mkdirSync(hooksHome, { recursive: true });
6819
+ fs41.mkdirSync(hooksHome, { recursive: true });
6759
6820
  let otelHookCommand = resolveOtelHookCommand();
6760
6821
  if (!otelHookCommand) {
6761
6822
  const installed = tryInstallPackage();
@@ -6824,14 +6885,14 @@ function ensureOtelHooks(options) {
6824
6885
  function disableOtelHooksExport() {
6825
6886
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
6826
6887
  }
6827
- var import_child_process9, fs39, os12, path41, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6888
+ var import_child_process9, fs41, os13, path43, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6828
6889
  var init_otel_hooks = __esm({
6829
6890
  "src/core/otel-hooks.ts"() {
6830
6891
  "use strict";
6831
6892
  import_child_process9 = require("child_process");
6832
- fs39 = __toESM(require("fs"));
6833
- os12 = __toESM(require("os"));
6834
- path41 = __toESM(require("path"));
6893
+ fs41 = __toESM(require("fs"));
6894
+ os13 = __toESM(require("os"));
6895
+ path43 = __toESM(require("path"));
6835
6896
  init_control_config();
6836
6897
  init_telemetry_config();
6837
6898
  OTEL_HOOKS_PACKAGE = "opentelemetry-hooks==0.14.0";
@@ -9790,7 +9851,7 @@ var require_compile = __commonJS({
9790
9851
  const schOrFunc = root.refs[ref];
9791
9852
  if (schOrFunc)
9792
9853
  return schOrFunc;
9793
- let _sch = resolve37.call(this, root, ref);
9854
+ let _sch = resolve38.call(this, root, ref);
9794
9855
  if (_sch === void 0) {
9795
9856
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
9796
9857
  const { schemaId } = this.opts;
@@ -9817,7 +9878,7 @@ var require_compile = __commonJS({
9817
9878
  function sameSchemaEnv(s1, s2) {
9818
9879
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
9819
9880
  }
9820
- function resolve37(root, ref) {
9881
+ function resolve38(root, ref) {
9821
9882
  let sch;
9822
9883
  while (typeof (sch = this.refs[ref]) == "string")
9823
9884
  ref = sch;
@@ -10035,8 +10096,8 @@ var require_utils2 = __commonJS({
10035
10096
  }
10036
10097
  return ind;
10037
10098
  }
10038
- function removeDotSegments(path52) {
10039
- let input = path52;
10099
+ function removeDotSegments(path54) {
10100
+ let input = path54;
10040
10101
  const output = [];
10041
10102
  let nextSlash = -1;
10042
10103
  let len = 0;
@@ -10288,8 +10349,8 @@ var require_schemes = __commonJS({
10288
10349
  wsComponent.secure = void 0;
10289
10350
  }
10290
10351
  if (wsComponent.resourceName) {
10291
- const [path52, query] = wsComponent.resourceName.split("?");
10292
- wsComponent.path = path52 && path52 !== "/" ? path52 : void 0;
10352
+ const [path54, query] = wsComponent.resourceName.split("?");
10353
+ wsComponent.path = path54 && path54 !== "/" ? path54 : void 0;
10293
10354
  wsComponent.query = query;
10294
10355
  wsComponent.resourceName = void 0;
10295
10356
  }
@@ -10348,7 +10409,7 @@ var require_schemes = __commonJS({
10348
10409
  urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
10349
10410
  return urnComponent;
10350
10411
  }
10351
- var http = (
10412
+ var http2 = (
10352
10413
  /** @type {SchemeHandler} */
10353
10414
  {
10354
10415
  scheme: "http",
@@ -10361,7 +10422,7 @@ var require_schemes = __commonJS({
10361
10422
  /** @type {SchemeHandler} */
10362
10423
  {
10363
10424
  scheme: "https",
10364
- domainHost: http.domainHost,
10425
+ domainHost: http2.domainHost,
10365
10426
  parse: httpParse,
10366
10427
  serialize: httpSerialize
10367
10428
  }
@@ -10405,7 +10466,7 @@ var require_schemes = __commonJS({
10405
10466
  var SCHEMES = (
10406
10467
  /** @type {Record<SchemeName, SchemeHandler>} */
10407
10468
  {
10408
- http,
10469
+ http: http2,
10409
10470
  https,
10410
10471
  ws,
10411
10472
  wss,
@@ -10448,7 +10509,7 @@ var require_fast_uri = __commonJS({
10448
10509
  }
10449
10510
  return uri;
10450
10511
  }
10451
- function resolve37(baseURI, relativeURI, options) {
10512
+ function resolve38(baseURI, relativeURI, options) {
10452
10513
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
10453
10514
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
10454
10515
  schemelessOptions.skipEscape = true;
@@ -10706,7 +10767,7 @@ var require_fast_uri = __commonJS({
10706
10767
  var fastUri = {
10707
10768
  SCHEMES,
10708
10769
  normalize: normalize3,
10709
- resolve: resolve37,
10770
+ resolve: resolve38,
10710
10771
  resolveComponent,
10711
10772
  equal,
10712
10773
  serialize,
@@ -13682,12 +13743,12 @@ var require_dist = __commonJS({
13682
13743
  throw new Error(`Unknown format "${name}"`);
13683
13744
  return f2;
13684
13745
  };
13685
- function addFormats(ajv, list, fs44, exportName) {
13746
+ function addFormats(ajv, list, fs46, exportName) {
13686
13747
  var _a3;
13687
13748
  var _b2;
13688
13749
  (_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
13689
13750
  for (const f2 of list)
13690
- ajv.addFormat(f2, fs44[f2]);
13751
+ ajv.addFormat(f2, fs46[f2]);
13691
13752
  }
13692
13753
  module2.exports = exports2 = formatsPlugin;
13693
13754
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -14787,15 +14848,15 @@ var require_route = __commonJS({
14787
14848
  };
14788
14849
  }
14789
14850
  function wrapConversion(toModel, graph) {
14790
- const path52 = [graph[toModel].parent, toModel];
14851
+ const path54 = [graph[toModel].parent, toModel];
14791
14852
  let fn = conversions[graph[toModel].parent][toModel];
14792
14853
  let cur = graph[toModel].parent;
14793
14854
  while (graph[cur].parent) {
14794
- path52.unshift(graph[cur].parent);
14855
+ path54.unshift(graph[cur].parent);
14795
14856
  fn = link(conversions[graph[cur].parent][cur], fn);
14796
14857
  cur = graph[cur].parent;
14797
14858
  }
14798
- fn.conversion = path52;
14859
+ fn.conversion = path54;
14799
14860
  return fn;
14800
14861
  }
14801
14862
  module2.exports = function(fromModel) {
@@ -20725,7 +20786,7 @@ var require_iso2022 = __commonJS({
20725
20786
  // node_modules/chardet/index.js
20726
20787
  var require_chardet = __commonJS({
20727
20788
  "node_modules/chardet/index.js"(exports2, module2) {
20728
- var fs44 = require("fs");
20789
+ var fs46 = require("fs");
20729
20790
  var utf8 = require_utf8();
20730
20791
  var unicode = require_unicode();
20731
20792
  var mbcs = require_mbcs();
@@ -20799,28 +20860,28 @@ var require_chardet = __commonJS({
20799
20860
  var fd;
20800
20861
  var handler = function(err, buffer) {
20801
20862
  if (fd) {
20802
- fs44.closeSync(fd);
20863
+ fs46.closeSync(fd);
20803
20864
  }
20804
20865
  if (err) return cb(err, null);
20805
20866
  cb(null, self.detect(buffer, opts));
20806
20867
  };
20807
20868
  if (opts && opts.sampleSize) {
20808
- fd = fs44.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
20809
- fs44.read(fd, sample, 0, opts.sampleSize, null, function(err) {
20869
+ fd = fs46.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
20870
+ fs46.read(fd, sample, 0, opts.sampleSize, null, function(err) {
20810
20871
  handler(err, sample);
20811
20872
  });
20812
20873
  return;
20813
20874
  }
20814
- fs44.readFile(filepath, handler);
20875
+ fs46.readFile(filepath, handler);
20815
20876
  };
20816
20877
  module2.exports.detectFileSync = function(filepath, opts) {
20817
20878
  if (opts && opts.sampleSize) {
20818
- var fd = fs44.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
20819
- fs44.readSync(fd, sample2, 0, opts.sampleSize);
20820
- fs44.closeSync(fd);
20879
+ var fd = fs46.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
20880
+ fs46.readSync(fd, sample2, 0, opts.sampleSize);
20881
+ fs46.closeSync(fd);
20821
20882
  return self.detect(sample2, opts);
20822
20883
  }
20823
- return self.detect(fs44.readFileSync(filepath), opts);
20884
+ return self.detect(fs46.readFileSync(filepath), opts);
20824
20885
  };
20825
20886
  module2.exports.detectAll = function(buffer, opts) {
20826
20887
  if (typeof opts !== "object") {
@@ -24285,16 +24346,16 @@ var require_os_tmpdir = __commonJS({
24285
24346
  var isWindows = process.platform === "win32";
24286
24347
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
24287
24348
  module2.exports = function() {
24288
- var path52;
24349
+ var path54;
24289
24350
  if (isWindows) {
24290
- path52 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24351
+ path54 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24291
24352
  } else {
24292
- path52 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24353
+ path54 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24293
24354
  }
24294
- if (trailingSlashRe.test(path52)) {
24295
- path52 = path52.slice(0, -1);
24355
+ if (trailingSlashRe.test(path54)) {
24356
+ path54 = path54.slice(0, -1);
24296
24357
  }
24297
- return path52;
24358
+ return path54;
24298
24359
  };
24299
24360
  }
24300
24361
  });
@@ -24302,9 +24363,9 @@ var require_os_tmpdir = __commonJS({
24302
24363
  // node_modules/tmp/lib/tmp.js
24303
24364
  var require_tmp = __commonJS({
24304
24365
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
24305
- var fs44 = require("fs");
24306
- var path52 = require("path");
24307
- var crypto4 = require("crypto");
24366
+ var fs46 = require("fs");
24367
+ var path54 = require("path");
24368
+ var crypto6 = require("crypto");
24308
24369
  var osTmpDir = require_os_tmpdir();
24309
24370
  var _c2 = process.binding("constants");
24310
24371
  var tmpDir = osTmpDir();
@@ -24322,9 +24383,9 @@ var require_tmp = __commonJS({
24322
24383
  function _randomChars(howMany) {
24323
24384
  var value = [], rnd = null;
24324
24385
  try {
24325
- rnd = crypto4.randomBytes(howMany);
24386
+ rnd = crypto6.randomBytes(howMany);
24326
24387
  } catch (e2) {
24327
- rnd = crypto4.pseudoRandomBytes(howMany);
24388
+ rnd = crypto6.pseudoRandomBytes(howMany);
24328
24389
  }
24329
24390
  for (var i2 = 0; i2 < howMany; i2++) {
24330
24391
  value.push(RANDOM_CHARS[rnd[i2] % RANDOM_CHARS.length]);
@@ -24345,7 +24406,7 @@ var require_tmp = __commonJS({
24345
24406
  }
24346
24407
  function _generateTmpName(opts) {
24347
24408
  if (opts.name) {
24348
- return path52.join(opts.dir || tmpDir, opts.name);
24409
+ return path54.join(opts.dir || tmpDir, opts.name);
24349
24410
  }
24350
24411
  if (opts.template) {
24351
24412
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -24356,7 +24417,7 @@ var require_tmp = __commonJS({
24356
24417
  _randomChars(12),
24357
24418
  opts.postfix || ""
24358
24419
  ].join("");
24359
- return path52.join(opts.dir || tmpDir, name);
24420
+ return path54.join(opts.dir || tmpDir, name);
24360
24421
  }
24361
24422
  function tmpName(options, callback) {
24362
24423
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -24366,7 +24427,7 @@ var require_tmp = __commonJS({
24366
24427
  return cb(new Error("Invalid template provided"));
24367
24428
  (function _getUniqueName() {
24368
24429
  const name = _generateTmpName(opts);
24369
- fs44.stat(name, function(err) {
24430
+ fs46.stat(name, function(err) {
24370
24431
  if (!err) {
24371
24432
  if (tries-- > 0) return _getUniqueName();
24372
24433
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -24384,7 +24445,7 @@ var require_tmp = __commonJS({
24384
24445
  do {
24385
24446
  const name = _generateTmpName(opts);
24386
24447
  try {
24387
- fs44.statSync(name);
24448
+ fs46.statSync(name);
24388
24449
  } catch (e2) {
24389
24450
  return name;
24390
24451
  }
@@ -24396,13 +24457,13 @@ var require_tmp = __commonJS({
24396
24457
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
24397
24458
  tmpName(opts, function _tmpNameCreated(err, name) {
24398
24459
  if (err) return cb(err);
24399
- fs44.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24460
+ fs46.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24400
24461
  if (err2) return cb(err2);
24401
24462
  if (opts.discardDescriptor) {
24402
- return fs44.close(fd, function _discardCallback(err3) {
24463
+ return fs46.close(fd, function _discardCallback(err3) {
24403
24464
  if (err3) {
24404
24465
  try {
24405
- fs44.unlinkSync(name);
24466
+ fs46.unlinkSync(name);
24406
24467
  } catch (e2) {
24407
24468
  if (!isENOENT(e2)) {
24408
24469
  err3 = e2;
@@ -24425,9 +24486,9 @@ var require_tmp = __commonJS({
24425
24486
  opts.postfix = opts.postfix || ".tmp";
24426
24487
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
24427
24488
  const name = tmpNameSync(opts);
24428
- var fd = fs44.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24489
+ var fd = fs46.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24429
24490
  if (opts.discardDescriptor) {
24430
- fs44.closeSync(fd);
24491
+ fs46.closeSync(fd);
24431
24492
  fd = void 0;
24432
24493
  }
24433
24494
  return {
@@ -24439,9 +24500,9 @@ var require_tmp = __commonJS({
24439
24500
  function _rmdirRecursiveSync(root) {
24440
24501
  const dirs = [root];
24441
24502
  do {
24442
- var dir2 = dirs.pop(), deferred = false, files = fs44.readdirSync(dir2);
24503
+ var dir2 = dirs.pop(), deferred = false, files = fs46.readdirSync(dir2);
24443
24504
  for (var i2 = 0, length = files.length; i2 < length; i2++) {
24444
- var file2 = path52.join(dir2, files[i2]), stat = fs44.lstatSync(file2);
24505
+ var file2 = path54.join(dir2, files[i2]), stat = fs46.lstatSync(file2);
24445
24506
  if (stat.isDirectory()) {
24446
24507
  if (!deferred) {
24447
24508
  deferred = true;
@@ -24449,11 +24510,11 @@ var require_tmp = __commonJS({
24449
24510
  }
24450
24511
  dirs.push(file2);
24451
24512
  } else {
24452
- fs44.unlinkSync(file2);
24513
+ fs46.unlinkSync(file2);
24453
24514
  }
24454
24515
  }
24455
24516
  if (!deferred) {
24456
- fs44.rmdirSync(dir2);
24517
+ fs46.rmdirSync(dir2);
24457
24518
  }
24458
24519
  } while (dirs.length !== 0);
24459
24520
  }
@@ -24461,7 +24522,7 @@ var require_tmp = __commonJS({
24461
24522
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
24462
24523
  tmpName(opts, function _tmpNameCreated(err, name) {
24463
24524
  if (err) return cb(err);
24464
- fs44.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24525
+ fs46.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24465
24526
  if (err2) return cb(err2);
24466
24527
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
24467
24528
  });
@@ -24470,7 +24531,7 @@ var require_tmp = __commonJS({
24470
24531
  function dirSync(options) {
24471
24532
  var args = _parseArguments(options), opts = args[0];
24472
24533
  const name = tmpNameSync(opts);
24473
- fs44.mkdirSync(name, opts.mode || DIR_MODE);
24534
+ fs46.mkdirSync(name, opts.mode || DIR_MODE);
24474
24535
  return {
24475
24536
  name,
24476
24537
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -24480,7 +24541,7 @@ var require_tmp = __commonJS({
24480
24541
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
24481
24542
  try {
24482
24543
  if (0 <= fdPath[0]) {
24483
- fs44.closeSync(fdPath[0]);
24544
+ fs46.closeSync(fdPath[0]);
24484
24545
  }
24485
24546
  } catch (e2) {
24486
24547
  if (!isEBADF(e2) && !isENOENT(e2)) {
@@ -24488,7 +24549,7 @@ var require_tmp = __commonJS({
24488
24549
  }
24489
24550
  }
24490
24551
  try {
24491
- fs44.unlinkSync(fdPath[1]);
24552
+ fs46.unlinkSync(fdPath[1]);
24492
24553
  } catch (e2) {
24493
24554
  if (!isENOENT(e2)) {
24494
24555
  throw e2;
@@ -24501,7 +24562,7 @@ var require_tmp = __commonJS({
24501
24562
  return removeCallback;
24502
24563
  }
24503
24564
  function _prepareTmpDirRemoveCallback(name, opts) {
24504
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs44.rmdirSync.bind(fs44);
24565
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs46.rmdirSync.bind(fs46);
24505
24566
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
24506
24567
  if (!opts.keep) {
24507
24568
  _removeObjects.unshift(removeCallback);
@@ -25652,7 +25713,7 @@ var require_Observable = __commonJS({
25652
25713
  Observable2.prototype.forEach = function(next, promiseCtor) {
25653
25714
  var _this = this;
25654
25715
  promiseCtor = getPromiseCtor(promiseCtor);
25655
- return new promiseCtor(function(resolve37, reject) {
25716
+ return new promiseCtor(function(resolve38, reject) {
25656
25717
  var subscriber = new Subscriber_1.SafeSubscriber({
25657
25718
  next: function(value) {
25658
25719
  try {
@@ -25663,7 +25724,7 @@ var require_Observable = __commonJS({
25663
25724
  }
25664
25725
  },
25665
25726
  error: reject,
25666
- complete: resolve37
25727
+ complete: resolve38
25667
25728
  });
25668
25729
  _this.subscribe(subscriber);
25669
25730
  });
@@ -25685,14 +25746,14 @@ var require_Observable = __commonJS({
25685
25746
  Observable2.prototype.toPromise = function(promiseCtor) {
25686
25747
  var _this = this;
25687
25748
  promiseCtor = getPromiseCtor(promiseCtor);
25688
- return new promiseCtor(function(resolve37, reject) {
25749
+ return new promiseCtor(function(resolve38, reject) {
25689
25750
  var value;
25690
25751
  _this.subscribe(function(x2) {
25691
25752
  return value = x2;
25692
25753
  }, function(err) {
25693
25754
  return reject(err);
25694
25755
  }, function() {
25695
- return resolve37(value);
25756
+ return resolve38(value);
25696
25757
  });
25697
25758
  });
25698
25759
  };
@@ -27788,11 +27849,11 @@ var require_innerFrom = __commonJS({
27788
27849
  "use strict";
27789
27850
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
27790
27851
  function adopt(value) {
27791
- return value instanceof P2 ? value : new P2(function(resolve37) {
27792
- resolve37(value);
27852
+ return value instanceof P2 ? value : new P2(function(resolve38) {
27853
+ resolve38(value);
27793
27854
  });
27794
27855
  }
27795
- return new (P2 || (P2 = Promise))(function(resolve37, reject) {
27856
+ return new (P2 || (P2 = Promise))(function(resolve38, reject) {
27796
27857
  function fulfilled(value) {
27797
27858
  try {
27798
27859
  step(generator.next(value));
@@ -27808,7 +27869,7 @@ var require_innerFrom = __commonJS({
27808
27869
  }
27809
27870
  }
27810
27871
  function step(result) {
27811
- result.done ? resolve37(result.value) : adopt(result.value).then(fulfilled, rejected);
27872
+ result.done ? resolve38(result.value) : adopt(result.value).then(fulfilled, rejected);
27812
27873
  }
27813
27874
  step((generator = generator.apply(thisArg, _arguments || [])).next());
27814
27875
  });
@@ -27890,14 +27951,14 @@ var require_innerFrom = __commonJS({
27890
27951
  }, i2);
27891
27952
  function verb(n2) {
27892
27953
  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);
27954
+ return new Promise(function(resolve38, reject) {
27955
+ v2 = o2[n2](v2), settle(resolve38, reject, v2.done, v2.value);
27895
27956
  });
27896
27957
  };
27897
27958
  }
27898
- function settle(resolve37, reject, d2, v2) {
27959
+ function settle(resolve38, reject, d2, v2) {
27899
27960
  Promise.resolve(v2).then(function(v3) {
27900
- resolve37({ value: v3, done: d2 });
27961
+ resolve38({ value: v3, done: d2 });
27901
27962
  }, reject);
27902
27963
  }
27903
27964
  };
@@ -28516,7 +28577,7 @@ var require_lastValueFrom = __commonJS({
28516
28577
  var EmptyError_1 = require_EmptyError();
28517
28578
  function lastValueFrom2(source, config2) {
28518
28579
  var hasConfig = typeof config2 === "object";
28519
- return new Promise(function(resolve37, reject) {
28580
+ return new Promise(function(resolve38, reject) {
28520
28581
  var _hasValue = false;
28521
28582
  var _value;
28522
28583
  source.subscribe({
@@ -28527,9 +28588,9 @@ var require_lastValueFrom = __commonJS({
28527
28588
  error: reject,
28528
28589
  complete: function() {
28529
28590
  if (_hasValue) {
28530
- resolve37(_value);
28591
+ resolve38(_value);
28531
28592
  } else if (hasConfig) {
28532
- resolve37(config2.defaultValue);
28593
+ resolve38(config2.defaultValue);
28533
28594
  } else {
28534
28595
  reject(new EmptyError_1.EmptyError());
28535
28596
  }
@@ -28551,16 +28612,16 @@ var require_firstValueFrom = __commonJS({
28551
28612
  var Subscriber_1 = require_Subscriber();
28552
28613
  function firstValueFrom(source, config2) {
28553
28614
  var hasConfig = typeof config2 === "object";
28554
- return new Promise(function(resolve37, reject) {
28615
+ return new Promise(function(resolve38, reject) {
28555
28616
  var subscriber = new Subscriber_1.SafeSubscriber({
28556
28617
  next: function(value) {
28557
- resolve37(value);
28618
+ resolve38(value);
28558
28619
  subscriber.unsubscribe();
28559
28620
  },
28560
28621
  error: reject,
28561
28622
  complete: function() {
28562
28623
  if (hasConfig) {
28563
- resolve37(config2.defaultValue);
28624
+ resolve38(config2.defaultValue);
28564
28625
  } else {
28565
28626
  reject(new EmptyError_1.EmptyError());
28566
28627
  }
@@ -34353,14 +34414,14 @@ var require_run_async = __commonJS({
34353
34414
  return function() {
34354
34415
  var args = arguments;
34355
34416
  var originalThis = this;
34356
- var promise = new Promise(function(resolve37, reject) {
34417
+ var promise = new Promise(function(resolve38, reject) {
34357
34418
  var resolved = false;
34358
34419
  const wrappedResolve = function(value) {
34359
34420
  if (resolved) {
34360
34421
  console.warn("Run-async promise already resolved.");
34361
34422
  }
34362
34423
  resolved = true;
34363
- resolve37(value);
34424
+ resolve38(value);
34364
34425
  };
34365
34426
  var rejected = false;
34366
34427
  const wrappedReject = function(value) {
@@ -35714,11 +35775,11 @@ var parser = new YargsParser({
35714
35775
  resolve: import_path2.resolve,
35715
35776
  // TODO: figure out a way to combine ESM and CJS coverage, such that
35716
35777
  // we can exercise all the lines below:
35717
- require: (path52) => {
35778
+ require: (path54) => {
35718
35779
  if (typeof require !== "undefined") {
35719
- return require(path52);
35720
- } else if (path52.match(/\.json$/)) {
35721
- return JSON.parse((0, import_fs2.readFileSync)(path52, "utf8"));
35780
+ return require(path54);
35781
+ } else if (path54.match(/\.json$/)) {
35782
+ return JSON.parse((0, import_fs2.readFileSync)(path54, "utf8"));
35722
35783
  } else {
35723
35784
  throw Error("only .json config files are supported in ESM");
35724
35785
  }
@@ -38244,12 +38305,12 @@ var YargsInstance = class {
38244
38305
  async getCompletion(args, done) {
38245
38306
  argsert("<array> [function]", [args, done], arguments.length);
38246
38307
  if (!done) {
38247
- return new Promise((resolve37, reject) => {
38308
+ return new Promise((resolve38, reject) => {
38248
38309
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
38249
38310
  if (err)
38250
38311
  reject(err);
38251
38312
  else
38252
- resolve37(completions);
38313
+ resolve38(completions);
38253
38314
  });
38254
38315
  });
38255
38316
  } else {
@@ -40399,8 +40460,8 @@ function getErrorMap() {
40399
40460
 
40400
40461
  // node_modules/zod/v3/helpers/parseUtil.js
40401
40462
  var makeIssue = (params) => {
40402
- const { data, path: path52, errorMaps, issueData } = params;
40403
- const fullPath = [...path52, ...issueData.path || []];
40463
+ const { data, path: path54, errorMaps, issueData } = params;
40464
+ const fullPath = [...path54, ...issueData.path || []];
40404
40465
  const fullIssue = {
40405
40466
  ...issueData,
40406
40467
  path: fullPath
@@ -40516,11 +40577,11 @@ var errorUtil;
40516
40577
 
40517
40578
  // node_modules/zod/v3/types.js
40518
40579
  var ParseInputLazyPath = class {
40519
- constructor(parent, value, path52, key) {
40580
+ constructor(parent, value, path54, key) {
40520
40581
  this._cachedPath = [];
40521
40582
  this.parent = parent;
40522
40583
  this.data = value;
40523
- this._path = path52;
40584
+ this._path = path54;
40524
40585
  this._key = key;
40525
40586
  }
40526
40587
  get path() {
@@ -44117,6 +44178,51 @@ var StageKindSchema = HarnessStageKindSchema;
44117
44178
  var VerificationResultSchema = HarnessVerificationResultSchema;
44118
44179
  var StageResultSchema = HarnessStageRunResultSchema;
44119
44180
  var RunRecordTriggerSchema = external_exports.enum(["cli", "mcp", "script"]);
44181
+ var WorkUnitIdSchema = external_exports.string().min(1).max(128).regex(
44182
+ /^[A-Za-z0-9][A-Za-z0-9._:/#@-]*$/,
44183
+ "work unit id must start with an alphanumeric character and contain only stable identifier characters"
44184
+ );
44185
+ var WorkAttemptIdSchema = external_exports.string().uuid();
44186
+ var WorkUnitMetadataSchema = external_exports.object({
44187
+ workUnitId: WorkUnitIdSchema,
44188
+ source: external_exports.string().min(1).max(64).optional(),
44189
+ sourceUrl: external_exports.string().url().optional(),
44190
+ title: external_exports.string().min(1).max(256).optional(),
44191
+ parentWorkUnitId: WorkUnitIdSchema.optional()
44192
+ });
44193
+ var WorkUnitOutcomeSchema = external_exports.object({
44194
+ decision: external_exports.enum(["completed", "abandoned"]),
44195
+ decidedAt: external_exports.string(),
44196
+ attemptId: WorkAttemptIdSchema.optional(),
44197
+ validationId: external_exports.string().uuid().optional(),
44198
+ treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/).optional(),
44199
+ reason: external_exports.string().max(2e3).optional()
44200
+ }).superRefine((outcome, ctx) => {
44201
+ if (outcome.decision === "completed" && (!outcome.attemptId || !outcome.validationId || !outcome.treeHash)) {
44202
+ ctx.addIssue({
44203
+ code: external_exports.ZodIssueCode.custom,
44204
+ message: "completed work must reference an attempt and exact-tree validation"
44205
+ });
44206
+ }
44207
+ });
44208
+ var WorkUnitRecordSchema = WorkUnitMetadataSchema.extend({
44209
+ version: external_exports.number().int().default(1),
44210
+ createdAt: external_exports.string(),
44211
+ updatedAt: external_exports.string(),
44212
+ outcome: WorkUnitOutcomeSchema.optional()
44213
+ }).passthrough();
44214
+ var WorkAttemptRecordSchema = external_exports.object({
44215
+ version: external_exports.number().int().default(1),
44216
+ attemptId: WorkAttemptIdSchema,
44217
+ workUnitId: WorkUnitIdSchema,
44218
+ agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
44219
+ sessionKey: external_exports.string().min(1).optional(),
44220
+ workDir: external_exports.string().optional(),
44221
+ worktreePath: external_exports.string().optional(),
44222
+ branch: external_exports.string().optional(),
44223
+ baseCommit: external_exports.string().optional(),
44224
+ createdAt: external_exports.string()
44225
+ }).passthrough();
44120
44226
  var RunRecordSchema = external_exports.object({
44121
44227
  runId: external_exports.string().uuid(),
44122
44228
  repoPath: external_exports.string(),
@@ -44132,7 +44238,9 @@ var RunRecordSchema = external_exports.object({
44132
44238
  relativePath: external_exports.string().optional(),
44133
44239
  command: external_exports.string().optional(),
44134
44240
  workDir: external_exports.string().optional(),
44135
- harnessRoot: external_exports.string().optional()
44241
+ harnessRoot: external_exports.string().optional(),
44242
+ workUnitId: WorkUnitIdSchema.optional(),
44243
+ attemptId: WorkAttemptIdSchema.optional()
44136
44244
  }).passthrough();
44137
44245
  var SlotRegistryEntrySchema = external_exports.object({
44138
44246
  version: external_exports.number().int().default(1),
@@ -44154,6 +44262,8 @@ var SlotRegistryEntrySchema = external_exports.object({
44154
44262
  createdAt: external_exports.string(),
44155
44263
  ports: external_exports.record(external_exports.number()).optional(),
44156
44264
  previewUrls: external_exports.record(external_exports.string()).optional(),
44265
+ workUnitId: WorkUnitIdSchema.optional(),
44266
+ attemptId: WorkAttemptIdSchema.optional(),
44157
44267
  status: external_exports.enum(["starting", "active", "failed", "completed"]).default("active"),
44158
44268
  lastError: external_exports.string().optional()
44159
44269
  }).passthrough();
@@ -44199,6 +44309,8 @@ var AgentSlotStatusSchema = external_exports.object({
44199
44309
  sessionCreatedAt: external_exports.string().optional(),
44200
44310
  /** Derived from first captured user prompt (OTEL hooks); not set at launch. */
44201
44311
  purpose: external_exports.string().optional(),
44312
+ workUnitId: WorkUnitIdSchema.optional(),
44313
+ attemptId: WorkAttemptIdSchema.optional(),
44202
44314
  sessionStatus: external_exports.enum(["starting", "active", "failed", "completed"]).optional(),
44203
44315
  lastError: external_exports.string().optional(),
44204
44316
  /** Set when a failed/starting session can be resumed without --replace. */
@@ -44259,6 +44371,10 @@ var SyncSlotsInputSchema = external_exports.object({
44259
44371
  slots: external_exports.array(AgentSlotStatusSchema),
44260
44372
  generatedAt: external_exports.string()
44261
44373
  });
44374
+ var SyncWorkUnitsInputSchema = external_exports.object({
44375
+ workUnits: external_exports.array(WorkUnitRecordSchema),
44376
+ attempts: external_exports.array(WorkAttemptRecordSchema)
44377
+ });
44262
44378
  var ChangedFileStatusSchema = external_exports.enum(["A", "M", "D", "R", "C", "T", "U"]);
44263
44379
  var ChangedFileSchema = external_exports.object({
44264
44380
  path: external_exports.string(),
@@ -44285,6 +44401,17 @@ var ValidationRecordSchema = external_exports.object({
44285
44401
  var SyncValidationsInputSchema = external_exports.object({
44286
44402
  validations: external_exports.array(ValidationRecordSchema)
44287
44403
  });
44404
+ var ValidationBindingRecordSchema = external_exports.object({
44405
+ bindingId: external_exports.string().uuid(),
44406
+ workUnitId: WorkUnitIdSchema,
44407
+ attemptId: WorkAttemptIdSchema,
44408
+ validationId: external_exports.string().uuid(),
44409
+ treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/),
44410
+ createdAt: external_exports.string()
44411
+ });
44412
+ var SyncValidationBindingsInputSchema = external_exports.object({
44413
+ bindings: external_exports.array(ValidationBindingRecordSchema)
44414
+ });
44288
44415
  var AgentToolSchema = external_exports.enum(["claude_code", "codex", "cursor"]);
44289
44416
  var UsageSourceSchema = external_exports.enum(["otel", "harvest"]);
44290
44417
  var AgentSessionUsageSchema = external_exports.object({
@@ -44294,6 +44421,8 @@ var AgentSessionUsageSchema = external_exports.object({
44294
44421
  workDir: external_exports.string().optional(),
44295
44422
  branch: external_exports.string().optional(),
44296
44423
  suffix: external_exports.string().optional(),
44424
+ workUnitId: WorkUnitIdSchema.optional(),
44425
+ attemptId: WorkAttemptIdSchema.optional(),
44297
44426
  tokensInput: external_exports.number().nonnegative().default(0),
44298
44427
  tokensOutput: external_exports.number().nonnegative().default(0),
44299
44428
  tokensCacheRead: external_exports.number().nonnegative().default(0),
@@ -44315,6 +44444,8 @@ var AgentSessionEventSchema = external_exports.object({
44315
44444
  eventName: external_exports.string().min(1),
44316
44445
  sequence: external_exports.number().int().nonnegative().default(0),
44317
44446
  timestamp: external_exports.string(),
44447
+ workUnitId: WorkUnitIdSchema.optional(),
44448
+ attemptId: WorkAttemptIdSchema.optional(),
44318
44449
  attributes: external_exports.record(external_exports.unknown()).optional(),
44319
44450
  promptText: external_exports.string().nullable().optional(),
44320
44451
  responseText: external_exports.string().nullable().optional(),
@@ -44589,16 +44720,16 @@ async function handleAgentSkills(options) {
44589
44720
  }
44590
44721
  async function askYesNo(question) {
44591
44722
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
44592
- return new Promise((resolve37) => {
44723
+ return new Promise((resolve38) => {
44593
44724
  process.stderr.write(`${question} `);
44594
44725
  rl.once("line", (answer) => {
44595
44726
  rl.close();
44596
44727
  const trimmed = answer.trim();
44597
44728
  if (trimmed === "") {
44598
- resolve37(true);
44729
+ resolve38(true);
44599
44730
  return;
44600
44731
  }
44601
- resolve37(/^y(es)?$/i.test(trimmed));
44732
+ resolve38(/^y(es)?$/i.test(trimmed));
44602
44733
  });
44603
44734
  });
44604
44735
  }
@@ -44677,7 +44808,7 @@ function handleRemove(argv) {
44677
44808
  }
44678
44809
 
44679
44810
  // src/cli/commands/env.ts
44680
- var path45 = __toESM(require("path"));
44811
+ var path47 = __toESM(require("path"));
44681
44812
 
44682
44813
  // src/core/harness.ts
44683
44814
  var fs20 = __toESM(require("fs"));
@@ -45456,13 +45587,13 @@ var MultipartBody = class {
45456
45587
  // node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
45457
45588
  var import_web = require("node:stream/web");
45458
45589
  var fileFromPathWarned = false;
45459
- async function fileFromPath3(path52, ...args) {
45590
+ async function fileFromPath3(path54, ...args) {
45460
45591
  const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
45461
45592
  if (!fileFromPathWarned) {
45462
- console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path52)}) instead`);
45593
+ console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path54)}) instead`);
45463
45594
  fileFromPathWarned = true;
45464
45595
  }
45465
- return await _fileFromPath(path52, ...args);
45596
+ return await _fileFromPath(path54, ...args);
45466
45597
  }
45467
45598
  var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
45468
45599
  var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
@@ -45958,8 +46089,8 @@ async function defaultParseResponse(props) {
45958
46089
  }
45959
46090
  var APIPromise = class _APIPromise extends Promise {
45960
46091
  constructor(responsePromise, parseResponse = defaultParseResponse) {
45961
- super((resolve37) => {
45962
- resolve37(null);
46092
+ super((resolve38) => {
46093
+ resolve38(null);
45963
46094
  });
45964
46095
  this.responsePromise = responsePromise;
45965
46096
  this.parseResponse = parseResponse;
@@ -46059,29 +46190,29 @@ var APIClient = class {
46059
46190
  defaultIdempotencyKey() {
46060
46191
  return `stainless-node-retry-${uuid4()}`;
46061
46192
  }
46062
- get(path52, opts) {
46063
- return this.methodRequest("get", path52, opts);
46193
+ get(path54, opts) {
46194
+ return this.methodRequest("get", path54, opts);
46064
46195
  }
46065
- post(path52, opts) {
46066
- return this.methodRequest("post", path52, opts);
46196
+ post(path54, opts) {
46197
+ return this.methodRequest("post", path54, opts);
46067
46198
  }
46068
- patch(path52, opts) {
46069
- return this.methodRequest("patch", path52, opts);
46199
+ patch(path54, opts) {
46200
+ return this.methodRequest("patch", path54, opts);
46070
46201
  }
46071
- put(path52, opts) {
46072
- return this.methodRequest("put", path52, opts);
46202
+ put(path54, opts) {
46203
+ return this.methodRequest("put", path54, opts);
46073
46204
  }
46074
- delete(path52, opts) {
46075
- return this.methodRequest("delete", path52, opts);
46205
+ delete(path54, opts) {
46206
+ return this.methodRequest("delete", path54, opts);
46076
46207
  }
46077
- methodRequest(method, path52, opts) {
46208
+ methodRequest(method, path54, opts) {
46078
46209
  return this.request(Promise.resolve(opts).then(async (opts2) => {
46079
46210
  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;
46080
- return { method, path: path52, ...opts2, body };
46211
+ return { method, path: path54, ...opts2, body };
46081
46212
  }));
46082
46213
  }
46083
- getAPIList(path52, Page, opts) {
46084
- return this.requestAPIList(Page, { method: "get", path: path52, ...opts });
46214
+ getAPIList(path54, Page, opts) {
46215
+ return this.requestAPIList(Page, { method: "get", path: path54, ...opts });
46085
46216
  }
46086
46217
  calculateContentLength(body) {
46087
46218
  if (typeof body === "string") {
@@ -46099,10 +46230,10 @@ var APIClient = class {
46099
46230
  return null;
46100
46231
  }
46101
46232
  buildRequest(options) {
46102
- const { method, path: path52, query, headers = {} } = options;
46233
+ const { method, path: path54, query, headers = {} } = options;
46103
46234
  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;
46104
46235
  const contentLength = this.calculateContentLength(body);
46105
- const url = this.buildURL(path52, query);
46236
+ const url = this.buildURL(path54, query);
46106
46237
  if ("timeout" in options)
46107
46238
  validatePositiveInteger("timeout", options.timeout);
46108
46239
  const timeout = options.timeout ?? this.timeout;
@@ -46211,8 +46342,8 @@ var APIClient = class {
46211
46342
  const request = this.makeRequest(options, null);
46212
46343
  return new PagePromise(this, request, Page);
46213
46344
  }
46214
- buildURL(path52, query) {
46215
- const url = isAbsoluteURL(path52) ? new URL(path52) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path52.startsWith("/") ? path52.slice(1) : path52));
46345
+ buildURL(path54, query) {
46346
+ const url = isAbsoluteURL(path54) ? new URL(path54) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path54.startsWith("/") ? path54.slice(1) : path54));
46216
46347
  const defaultQuery = this.defaultQuery();
46217
46348
  if (!isEmptyObj(defaultQuery)) {
46218
46349
  query = { ...defaultQuery, ...query };
@@ -46497,7 +46628,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
46497
46628
  var isAbsoluteURL = (url) => {
46498
46629
  return startsWithSchemeRegexp.test(url);
46499
46630
  };
46500
- var sleep = (ms) => new Promise((resolve37) => setTimeout(resolve37, ms));
46631
+ var sleep = (ms) => new Promise((resolve38) => setTimeout(resolve38, ms));
46501
46632
  var validatePositiveInteger = (name, n2) => {
46502
46633
  if (typeof n2 !== "number" || !Number.isInteger(n2)) {
46503
46634
  throw new AnthropicError(`${name} must be an integer`);
@@ -46988,12 +47119,12 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
46988
47119
  }
46989
47120
  return this._emit("error", new AnthropicError(String(error3)));
46990
47121
  });
46991
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve37, reject) => {
46992
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve37, "f");
47122
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve38, reject) => {
47123
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve38, "f");
46993
47124
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
46994
47125
  }), "f");
46995
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve37, reject) => {
46996
- __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve37, "f");
47126
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve38, reject) => {
47127
+ __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve38, "f");
46997
47128
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
46998
47129
  }), "f");
46999
47130
  __classPrivateFieldGet8(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {
@@ -47122,11 +47253,11 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
47122
47253
  * const message = await stream.emitted('message') // rejects if the stream errors
47123
47254
  */
47124
47255
  emitted(event) {
47125
- return new Promise((resolve37, reject) => {
47256
+ return new Promise((resolve38, reject) => {
47126
47257
  __classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
47127
47258
  if (event !== "error")
47128
47259
  this.once("error", reject);
47129
- this.once(event, resolve37);
47260
+ this.once(event, resolve38);
47130
47261
  });
47131
47262
  }
47132
47263
  async done() {
@@ -47353,7 +47484,7 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
47353
47484
  if (done) {
47354
47485
  return { value: void 0, done: true };
47355
47486
  }
47356
- return new Promise((resolve37, reject) => readQueue.push({ resolve: resolve37, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47487
+ return new Promise((resolve38, reject) => readQueue.push({ resolve: resolve38, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47357
47488
  }
47358
47489
  const chunk = pushQueue.shift();
47359
47490
  return { value: chunk, done: false };
@@ -47501,12 +47632,12 @@ var MessageStream = class _MessageStream {
47501
47632
  }
47502
47633
  return this._emit("error", new AnthropicError(String(error3)));
47503
47634
  });
47504
- __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve37, reject) => {
47505
- __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve37, "f");
47635
+ __classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve38, reject) => {
47636
+ __classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve38, "f");
47506
47637
  __classPrivateFieldSet8(this, _MessageStream_rejectConnectedPromise, reject, "f");
47507
47638
  }), "f");
47508
- __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve37, reject) => {
47509
- __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve37, "f");
47639
+ __classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve38, reject) => {
47640
+ __classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve38, "f");
47510
47641
  __classPrivateFieldSet8(this, _MessageStream_rejectEndPromise, reject, "f");
47511
47642
  }), "f");
47512
47643
  __classPrivateFieldGet9(this, _MessageStream_connectedPromise, "f").catch(() => {
@@ -47635,11 +47766,11 @@ var MessageStream = class _MessageStream {
47635
47766
  * const message = await stream.emitted('message') // rejects if the stream errors
47636
47767
  */
47637
47768
  emitted(event) {
47638
- return new Promise((resolve37, reject) => {
47769
+ return new Promise((resolve38, reject) => {
47639
47770
  __classPrivateFieldSet8(this, _MessageStream_catchingPromiseCreated, true, "f");
47640
47771
  if (event !== "error")
47641
47772
  this.once("error", reject);
47642
- this.once(event, resolve37);
47773
+ this.once(event, resolve38);
47643
47774
  });
47644
47775
  }
47645
47776
  async done() {
@@ -47866,7 +47997,7 @@ var MessageStream = class _MessageStream {
47866
47997
  if (done) {
47867
47998
  return { value: void 0, done: true };
47868
47999
  }
47869
- return new Promise((resolve37, reject) => readQueue.push({ resolve: resolve37, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
48000
+ return new Promise((resolve38, reject) => readQueue.push({ resolve: resolve38, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
47870
48001
  }
47871
48002
  const chunk = pushQueue.shift();
47872
48003
  return { value: chunk, done: false };
@@ -48126,11 +48257,11 @@ async function promptApplyAgentMdProposal(repoPath) {
48126
48257
  }
48127
48258
  async function askYesNo2(question) {
48128
48259
  const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
48129
- return new Promise((resolve37) => {
48260
+ return new Promise((resolve38) => {
48130
48261
  process.stderr.write(`${question} `);
48131
48262
  rl.once("line", (answer) => {
48132
48263
  rl.close();
48133
- resolve37(/^y(es)?$/i.test(answer.trim()));
48264
+ resolve38(/^y(es)?$/i.test(answer.trim()));
48134
48265
  });
48135
48266
  });
48136
48267
  }
@@ -48360,7 +48491,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
48360
48491
  }
48361
48492
  async function askUser(question, options) {
48362
48493
  const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
48363
- return new Promise((resolve37) => {
48494
+ return new Promise((resolve38) => {
48364
48495
  process.stderr.write("\n");
48365
48496
  process.stderr.write(`\u2753 ${question}
48366
48497
  `);
@@ -48371,7 +48502,7 @@ async function askUser(question, options) {
48371
48502
  process.stderr.write("> ");
48372
48503
  rl.once("line", (answer) => {
48373
48504
  rl.close();
48374
- resolve37(answer.trim());
48505
+ resolve38(answer.trim());
48375
48506
  });
48376
48507
  });
48377
48508
  }
@@ -48515,7 +48646,7 @@ function runScript(scriptPath, args = [], options = {}) {
48515
48646
  function runScriptCapture(scriptPath, args = [], options = {}) {
48516
48647
  const stream = options.stream ?? false;
48517
48648
  const { stream: _stream, ...spawnOptions } = options;
48518
- return new Promise((resolve37) => {
48649
+ return new Promise((resolve38) => {
48519
48650
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
48520
48651
  ...spawnOptions,
48521
48652
  stdio: ["inherit", "pipe", "pipe"]
@@ -48530,13 +48661,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
48530
48661
  stderr += d2;
48531
48662
  if (stream) process.stderr.write(d2);
48532
48663
  });
48533
- proc.on("close", (code) => resolve37({ stdout, stderr, code: code ?? 0 }));
48664
+ proc.on("close", (code) => resolve38({ stdout, stderr, code: code ?? 0 }));
48534
48665
  });
48535
48666
  }
48536
48667
  function runShellCommand(command2, options = {}) {
48537
48668
  const stream = options.stream ?? false;
48538
48669
  const { stream: _stream, ...spawnOptions } = options;
48539
- return new Promise((resolve37) => {
48670
+ return new Promise((resolve38) => {
48540
48671
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
48541
48672
  ...spawnOptions,
48542
48673
  stdio: ["inherit", "pipe", "pipe"]
@@ -48551,7 +48682,7 @@ function runShellCommand(command2, options = {}) {
48551
48682
  stderr += d2;
48552
48683
  if (stream) process.stderr.write(d2);
48553
48684
  });
48554
- proc.on("close", (code) => resolve37({ stdout, stderr, code: code ?? 0 }));
48685
+ proc.on("close", (code) => resolve38({ stdout, stderr, code: code ?? 0 }));
48555
48686
  });
48556
48687
  }
48557
48688
 
@@ -49715,16 +49846,16 @@ async function promptScaffoldCursorRule(exists) {
49715
49846
  }
49716
49847
  async function askYesNo3(question) {
49717
49848
  const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
49718
- return new Promise((resolve37) => {
49849
+ return new Promise((resolve38) => {
49719
49850
  process.stderr.write(`${question} `);
49720
49851
  rl.once("line", (answer) => {
49721
49852
  rl.close();
49722
49853
  const trimmed = answer.trim();
49723
49854
  if (trimmed === "") {
49724
- resolve37(true);
49855
+ resolve38(true);
49725
49856
  return;
49726
49857
  }
49727
- resolve37(/^y(es)?$/i.test(trimmed));
49858
+ resolve38(/^y(es)?$/i.test(trimmed));
49728
49859
  });
49729
49860
  });
49730
49861
  }
@@ -49802,6 +49933,9 @@ function buildStageResult(input) {
49802
49933
  });
49803
49934
  }
49804
49935
 
49936
+ // src/core/run-service.ts
49937
+ var crypto5 = __toESM(require("crypto"));
49938
+
49805
49939
  // src/core/local-executor.ts
49806
49940
  var fs25 = __toESM(require("fs"));
49807
49941
  var path24 = __toESM(require("path"));
@@ -49854,6 +49988,8 @@ function buildLaunchFlagArgs(flags) {
49854
49988
  if (flags.confirmReplace) args.push("--replace");
49855
49989
  if (flags.force) args.push("--force");
49856
49990
  if (flags.resume) args.push("--resume");
49991
+ if (flags.workUnitId) args.push(`--work-id=${flags.workUnitId}`);
49992
+ if (flags.attemptId) args.push(`--attempt-id=${flags.attemptId}`);
49857
49993
  return args;
49858
49994
  }
49859
49995
  function resolveRepoPath(repoPath) {
@@ -50029,19 +50165,19 @@ var LocalScriptExecutor = class {
50029
50165
  var localScriptExecutor = new LocalScriptExecutor();
50030
50166
 
50031
50167
  // src/core/control-sync.ts
50032
- var path39 = __toESM(require("path"));
50168
+ var path41 = __toESM(require("path"));
50033
50169
  init_control_config();
50034
50170
 
50035
50171
  // src/core/control-registry.ts
50036
- var fs27 = __toESM(require("fs"));
50037
- var os4 = __toESM(require("os"));
50038
- var path26 = __toESM(require("path"));
50172
+ var fs28 = __toESM(require("fs"));
50173
+ var os5 = __toESM(require("os"));
50174
+ var path27 = __toESM(require("path"));
50039
50175
 
50040
50176
  // src/core/control-repo-path.ts
50041
- var fs26 = __toESM(require("fs"));
50042
- var path25 = __toESM(require("path"));
50177
+ var fs27 = __toESM(require("fs"));
50178
+ var path26 = __toESM(require("path"));
50043
50179
  function tryGit(cwd, args) {
50044
- if (!fs26.existsSync(cwd)) return void 0;
50180
+ if (!fs27.existsSync(cwd)) return void 0;
50045
50181
  const result = run(`git ${args}`, { cwd });
50046
50182
  return result.code === 0 ? result.stdout.trim() : void 0;
50047
50183
  }
@@ -50049,58 +50185,58 @@ function resolveMainWorkingTree(cwd) {
50049
50185
  const toplevel = tryGit(cwd, "rev-parse --show-toplevel");
50050
50186
  if (!toplevel) return void 0;
50051
50187
  const commonDirRaw = tryGit(cwd, "rev-parse --git-common-dir");
50052
- const commonDir = commonDirRaw ? path25.resolve(cwd, commonDirRaw) : void 0;
50053
- if (!commonDir) return path25.resolve(toplevel);
50054
- if (path25.basename(commonDir) === ".git") {
50055
- return path25.dirname(commonDir);
50188
+ const commonDir = commonDirRaw ? path26.resolve(cwd, commonDirRaw) : void 0;
50189
+ if (!commonDir) return path26.resolve(toplevel);
50190
+ if (path26.basename(commonDir) === ".git") {
50191
+ return path26.dirname(commonDir);
50056
50192
  }
50057
50193
  const porcelain = tryGit(cwd, "worktree list --porcelain");
50058
50194
  if (porcelain) {
50059
50195
  for (const line of porcelain.split("\n")) {
50060
50196
  if (line.startsWith("worktree ")) {
50061
- return path25.resolve(line.slice("worktree ".length));
50197
+ return path26.resolve(line.slice("worktree ".length));
50062
50198
  }
50063
50199
  }
50064
50200
  }
50065
- return path25.resolve(toplevel);
50201
+ return path26.resolve(toplevel);
50066
50202
  }
50067
50203
  function canonicalizeControlRepoPath(repoPath) {
50068
- const resolved = path25.resolve(repoPath);
50204
+ const resolved = path26.resolve(repoPath);
50069
50205
  const toplevel = tryGit(resolved, "rev-parse --show-toplevel");
50070
50206
  if (!toplevel) return resolved;
50071
50207
  const mainRoot = resolveMainWorkingTree(resolved);
50072
50208
  if (!mainRoot) return resolved;
50073
- const top2 = path25.resolve(toplevel);
50074
- const main = path25.resolve(mainRoot);
50209
+ const top2 = path26.resolve(toplevel);
50210
+ const main = path26.resolve(mainRoot);
50075
50211
  if (top2 === main) return resolved;
50076
- const rel = path25.relative(top2, resolved);
50212
+ const rel = path26.relative(top2, resolved);
50077
50213
  if (!rel || rel === ".") return main;
50078
- if (rel.startsWith(`..${path25.sep}`) || rel === ".." || path25.isAbsolute(rel)) {
50214
+ if (rel.startsWith(`..${path26.sep}`) || rel === ".." || path26.isAbsolute(rel)) {
50079
50215
  return resolved;
50080
50216
  }
50081
- return path25.resolve(main, rel);
50217
+ return path26.resolve(main, rel);
50082
50218
  }
50083
50219
 
50084
50220
  // src/core/control-registry.ts
50085
50221
  function getRegistryPath() {
50086
50222
  if (process.env.HAR_CONTROL_REGISTRY_PATH) {
50087
- return path26.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
50223
+ return path27.resolve(process.env.HAR_CONTROL_REGISTRY_PATH);
50088
50224
  }
50089
- return path26.join(os4.homedir(), ".har", "repos.json");
50225
+ return path27.join(os5.homedir(), ".har", "repos.json");
50090
50226
  }
50091
50227
  function readRegistry() {
50092
50228
  const registryPath = getRegistryPath();
50093
50229
  try {
50094
- if (!fs27.existsSync(registryPath)) return { repos: [] };
50095
- return JSON.parse(fs27.readFileSync(registryPath, "utf8"));
50230
+ if (!fs28.existsSync(registryPath)) return { repos: [] };
50231
+ return JSON.parse(fs28.readFileSync(registryPath, "utf8"));
50096
50232
  } catch {
50097
50233
  return { repos: [] };
50098
50234
  }
50099
50235
  }
50100
50236
  function writeRegistry(registry2) {
50101
50237
  const registryPath = getRegistryPath();
50102
- fs27.mkdirSync(path26.dirname(registryPath), { recursive: true });
50103
- fs27.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
50238
+ fs28.mkdirSync(path27.dirname(registryPath), { recursive: true });
50239
+ fs28.writeFileSync(registryPath, JSON.stringify(registry2, null, 2) + "\n");
50104
50240
  }
50105
50241
  function registryChanged(before, after) {
50106
50242
  if (before.length !== after.length) return true;
@@ -50122,7 +50258,7 @@ function removeRegisteredRepo(repoPath) {
50122
50258
  try {
50123
50259
  return canonicalizeControlRepoPath(entry) !== resolved;
50124
50260
  } catch {
50125
- return path26.resolve(entry) !== resolved;
50261
+ return path27.resolve(entry) !== resolved;
50126
50262
  }
50127
50263
  });
50128
50264
  if (next.length === registry2.repos.length) return false;
@@ -50134,9 +50270,9 @@ function listRegisteredRepos() {
50134
50270
  const kept = [];
50135
50271
  const seen = /* @__PURE__ */ new Set();
50136
50272
  for (const repoPath of registry2.repos) {
50137
- if (!fs27.existsSync(repoPath)) continue;
50273
+ if (!fs28.existsSync(repoPath)) continue;
50138
50274
  const canonical = canonicalizeControlRepoPath(repoPath);
50139
- if (!fs27.existsSync(canonical) || !readManifest(canonical)) continue;
50275
+ if (!fs28.existsSync(canonical) || !readManifest(canonical)) continue;
50140
50276
  if (seen.has(canonical)) continue;
50141
50277
  seen.add(canonical);
50142
50278
  kept.push(canonical);
@@ -50148,17 +50284,17 @@ function listRegisteredRepos() {
50148
50284
  }
50149
50285
 
50150
50286
  // src/core/slot-status.ts
50151
- var fs32 = __toESM(require("fs"));
50152
- var os7 = __toESM(require("os"));
50153
- var path32 = __toESM(require("path"));
50287
+ var fs33 = __toESM(require("fs"));
50288
+ var os8 = __toESM(require("os"));
50289
+ var path33 = __toESM(require("path"));
50154
50290
  var import_child_process7 = require("child_process");
50155
50291
 
50156
50292
  // src/core/runs.ts
50157
50293
  var crypto2 = __toESM(require("crypto"));
50158
50294
  var import_child_process2 = require("child_process");
50159
- var fs28 = __toESM(require("fs"));
50160
- var os5 = __toESM(require("os"));
50161
- var path27 = __toESM(require("path"));
50295
+ var fs29 = __toESM(require("fs"));
50296
+ var os6 = __toESM(require("os"));
50297
+ var path28 = __toESM(require("path"));
50162
50298
  var RUNS_DIR = "runs";
50163
50299
  function gitCommonDir(cwd) {
50164
50300
  try {
@@ -50167,7 +50303,7 @@ function gitCommonDir(cwd) {
50167
50303
  encoding: "utf8",
50168
50304
  stdio: ["pipe", "pipe", "ignore"]
50169
50305
  }).trim();
50170
- return out ? path27.resolve(cwd, out) : void 0;
50306
+ return out ? path28.resolve(cwd, out) : void 0;
50171
50307
  } catch {
50172
50308
  return void 0;
50173
50309
  }
@@ -50189,7 +50325,7 @@ function gitPrefix(cwd) {
50189
50325
  }
50190
50326
  }
50191
50327
  function getRunsDir(harnessRoot) {
50192
- return path27.join(getHarnessDir(harnessRoot), RUNS_DIR);
50328
+ return path28.join(getHarnessDir(harnessRoot), RUNS_DIR);
50193
50329
  }
50194
50330
  function formatLocalDate(d2) {
50195
50331
  const y2 = d2.getFullYear();
@@ -50209,24 +50345,24 @@ function buildRunRelativePath(stageId, agentId, startedAt, runId, runsDir) {
50209
50345
  const timePart = formatLocalTime(started);
50210
50346
  const agentPart = agentId !== void 0 ? `_agent-${agentId}` : "";
50211
50347
  let filename = `${timePart}_${stageId}${agentPart}.json`;
50212
- const fullPath = path27.join(runsDir, dateFolder, filename);
50213
- if (fs28.existsSync(fullPath)) {
50348
+ const fullPath = path28.join(runsDir, dateFolder, filename);
50349
+ if (fs29.existsSync(fullPath)) {
50214
50350
  filename = `${timePart}_${stageId}${agentPart}-${runId.slice(0, 8)}.json`;
50215
50351
  }
50216
- return path27.join(dateFolder, filename);
50352
+ return path28.join(dateFolder, filename);
50217
50353
  }
50218
50354
  function resolveRunFilePath(harnessRoot, run2) {
50219
50355
  if (run2.relativePath) {
50220
- return path27.join(getRunsDir(harnessRoot), run2.relativePath);
50356
+ return path28.join(getRunsDir(harnessRoot), run2.relativePath);
50221
50357
  }
50222
- return path27.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
50358
+ return path28.join(getRunsDir(harnessRoot), `${run2.runId}.json`);
50223
50359
  }
50224
50360
  function collectRunFiles(runsDir) {
50225
- if (!fs28.existsSync(runsDir)) return [];
50361
+ if (!fs29.existsSync(runsDir)) return [];
50226
50362
  const files = [];
50227
50363
  const walk = (dir) => {
50228
- for (const entry of fs28.readdirSync(dir, { withFileTypes: true })) {
50229
- const full = path27.join(dir, entry.name);
50364
+ for (const entry of fs29.readdirSync(dir, { withFileTypes: true })) {
50365
+ const full = path28.join(dir, entry.name);
50230
50366
  if (entry.isDirectory()) {
50231
50367
  walk(full);
50232
50368
  } else if (entry.name.endsWith(".json")) {
@@ -50240,30 +50376,30 @@ function collectRunFiles(runsDir) {
50240
50376
  function resolveAgentWorkDir(harnessRoot, agentId) {
50241
50377
  if (agentId === void 0) return void 0;
50242
50378
  const entry = readSlotRegistry(harnessRoot, agentId);
50243
- if (entry?.workDir && fs28.existsSync(entry.workDir)) return entry.workDir;
50379
+ if (entry?.workDir && fs29.existsSync(entry.workDir)) return entry.workDir;
50244
50380
  const env3 = readHarnessEnv(harnessRoot);
50245
- const projectName = env3.HARNESS_PROJECT_NAME ?? path27.basename(harnessRoot);
50246
- const worktreeDir = path27.join(os5.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50381
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path28.basename(harnessRoot);
50382
+ const worktreeDir = path28.join(os6.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50247
50383
  const relPrefix = gitPrefix(harnessRoot);
50248
50384
  const sessionEnvFiles = [];
50249
- const worktreesRoot = path27.join(os5.homedir(), "worktrees");
50250
- if (fs28.existsSync(worktreesRoot)) {
50385
+ const worktreesRoot = path28.join(os6.homedir(), "worktrees");
50386
+ if (fs29.existsSync(worktreesRoot)) {
50251
50387
  const suffix = `-har-agent-${agentId}-`;
50252
- for (const entry2 of fs28.readdirSync(worktreesRoot, { withFileTypes: true })) {
50388
+ for (const entry2 of fs29.readdirSync(worktreesRoot, { withFileTypes: true })) {
50253
50389
  if (!entry2.isDirectory() || !entry2.name.includes(suffix)) continue;
50254
- const sessionDir = path27.join(worktreesRoot, entry2.name);
50390
+ const sessionDir = path28.join(worktreesRoot, entry2.name);
50255
50391
  if (!sameGitCheckout(harnessRoot, sessionDir)) continue;
50256
- sessionEnvFiles.push(path27.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
50392
+ sessionEnvFiles.push(path28.join(sessionDir, relPrefix, `.env.agent.${agentId}`));
50257
50393
  }
50258
50394
  }
50259
50395
  const candidates = [
50260
- path27.join(worktreeDir, `.env.agent.${agentId}`),
50261
- path27.join(harnessRoot, `.env.agent.${agentId}`),
50396
+ path28.join(worktreeDir, `.env.agent.${agentId}`),
50397
+ path28.join(harnessRoot, `.env.agent.${agentId}`),
50262
50398
  ...sessionEnvFiles.sort()
50263
50399
  ];
50264
50400
  for (const envFile of candidates) {
50265
- if (!fs28.existsSync(envFile)) continue;
50266
- const content = fs28.readFileSync(envFile, "utf8");
50401
+ if (!fs29.existsSync(envFile)) continue;
50402
+ const content = fs29.readFileSync(envFile, "utf8");
50267
50403
  const match = content.match(/^REPO_ROOT=(.+)$/m);
50268
50404
  if (match) return match[1].trim();
50269
50405
  }
@@ -50275,11 +50411,11 @@ function createRun(ctx, meta) {
50275
50411
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
50276
50412
  const runId = crypto2.randomUUID();
50277
50413
  const relativePath = buildRunRelativePath(meta.stageId, meta.agentId, startedAt, runId, runsDir);
50278
- const runFilePath = path27.join(runsDir, relativePath);
50279
- fs28.mkdirSync(path27.dirname(runFilePath), { recursive: true });
50414
+ const runFilePath = path28.join(runsDir, relativePath);
50415
+ fs29.mkdirSync(path28.dirname(runFilePath), { recursive: true });
50280
50416
  const run2 = RunRecordSchema.parse({
50281
50417
  runId,
50282
- repoPath: path27.resolve(ctx.repoPath),
50418
+ repoPath: path28.resolve(ctx.repoPath),
50283
50419
  harnessRoot,
50284
50420
  stageId: meta.stageId,
50285
50421
  kind: meta.kind,
@@ -50288,9 +50424,11 @@ function createRun(ctx, meta) {
50288
50424
  status: "unknown",
50289
50425
  startedAt,
50290
50426
  relativePath,
50291
- trigger: ctx.trigger ?? "cli"
50427
+ trigger: ctx.trigger ?? "cli",
50428
+ workUnitId: ctx.workUnitId,
50429
+ attemptId: ctx.attemptId
50292
50430
  });
50293
- fs28.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
50431
+ fs29.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
50294
50432
  return run2;
50295
50433
  }
50296
50434
  function finishRun(repoPath, runId, update) {
@@ -50309,13 +50447,13 @@ function finishRun(repoPath, runId, update) {
50309
50447
  finishedAt: (/* @__PURE__ */ new Date()).toISOString()
50310
50448
  });
50311
50449
  const runPath = resolveRunFilePath(harnessRoot, finished);
50312
- fs28.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
50450
+ fs29.writeFileSync(runPath, JSON.stringify(finished, null, 2) + "\n");
50313
50451
  return finished;
50314
50452
  }
50315
50453
  function findRunRecord(harnessRoot, runId) {
50316
50454
  const runsDir = getRunsDir(harnessRoot);
50317
50455
  for (const filePath of collectRunFiles(runsDir)) {
50318
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs28.readFileSync(filePath, "utf8")));
50456
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs29.readFileSync(filePath, "utf8")));
50319
50457
  if (parsed.success && parsed.data.runId === runId) {
50320
50458
  return parsed.data;
50321
50459
  }
@@ -50327,10 +50465,10 @@ function getRun(repoPath, runId) {
50327
50465
  }
50328
50466
  function listRuns(repoPath, filter2 = {}) {
50329
50467
  const runsDir = getRunsDir(resolveHarnessRoot(repoPath));
50330
- if (!fs28.existsSync(runsDir)) return [];
50468
+ if (!fs29.existsSync(runsDir)) return [];
50331
50469
  const runs = [];
50332
50470
  for (const filePath of collectRunFiles(runsDir)) {
50333
- const parsed = RunRecordSchema.safeParse(JSON.parse(fs28.readFileSync(filePath, "utf8")));
50471
+ const parsed = RunRecordSchema.safeParse(JSON.parse(fs29.readFileSync(filePath, "utf8")));
50334
50472
  if (!parsed.success) continue;
50335
50473
  if (filter2.stageId && parsed.data.stageId !== filter2.stageId) continue;
50336
50474
  runs.push(parsed.data);
@@ -50343,18 +50481,18 @@ function listRuns(repoPath, filter2 = {}) {
50343
50481
  }
50344
50482
 
50345
50483
  // src/core/slot-preflight.ts
50346
- var path31 = __toESM(require("path"));
50484
+ var path32 = __toESM(require("path"));
50347
50485
 
50348
50486
  // src/core/control-port.ts
50349
50487
  var import_child_process4 = require("child_process");
50350
- var fs30 = __toESM(require("fs"));
50351
- var path29 = __toESM(require("path"));
50488
+ var fs31 = __toESM(require("fs"));
50489
+ var path30 = __toESM(require("path"));
50352
50490
  init_control_config();
50353
50491
 
50354
50492
  // src/core/slot-ports.ts
50355
50493
  var import_child_process3 = require("child_process");
50356
- var fs29 = __toESM(require("fs"));
50357
- var path28 = __toESM(require("path"));
50494
+ var fs30 = __toESM(require("fs"));
50495
+ var path29 = __toESM(require("path"));
50358
50496
  function portStep(env3) {
50359
50497
  return Number(env3.HARNESS_PORT_STEP ?? 10);
50360
50498
  }
@@ -50410,7 +50548,7 @@ function allocateAppPorts(repoPath, agentId) {
50410
50548
  }
50411
50549
  function harnessUsesPm2(repoPath) {
50412
50550
  const harnessRoot = resolveHarnessRoot(repoPath);
50413
- return fs29.existsSync(path28.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
50551
+ return fs30.existsSync(path29.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
50414
50552
  }
50415
50553
 
50416
50554
  // src/core/control-port.ts
@@ -50465,13 +50603,13 @@ function controlDefaultPortWarnings(containers, defaultFrontendPort, allocatedFr
50465
50603
  return [formatControlDefaultPortWarning(control.name, defaultFrontendPort, allocatedFrontend)];
50466
50604
  }
50467
50605
  function inspectControlUpReadiness(repoPath) {
50468
- const resolved = path29.resolve(repoPath);
50606
+ const resolved = path30.resolve(repoPath);
50469
50607
  const port = parseControlHostPort();
50470
50608
  const containers = listDockerContainers();
50471
50609
  const control = controlContainerOnPort(containers, port);
50472
50610
  const warnings = [];
50473
- const controlHarnessDir = path29.join(resolved, "control", ".har");
50474
- const harnessSlot1Active = fs30.existsSync(controlHarnessDir) && readSlotRegistry(path29.join(resolved, "control"), 1)?.status === "active";
50611
+ const controlHarnessDir = path30.join(resolved, "control", ".har");
50612
+ const harnessSlot1Active = fs31.existsSync(controlHarnessDir) && readSlotRegistry(path30.join(resolved, "control"), 1)?.status === "active";
50475
50613
  if (control) {
50476
50614
  return {
50477
50615
  warnings,
@@ -50502,9 +50640,9 @@ function inspectControlUpReadiness(repoPath) {
50502
50640
  }
50503
50641
 
50504
50642
  // src/core/slot-launch-guard-occupied.ts
50505
- var fs31 = __toESM(require("fs"));
50506
- var os6 = __toESM(require("os"));
50507
- var path30 = __toESM(require("path"));
50643
+ var fs32 = __toESM(require("fs"));
50644
+ var os7 = __toESM(require("os"));
50645
+ var path31 = __toESM(require("path"));
50508
50646
  var import_child_process5 = require("child_process");
50509
50647
  function runGit(cwd, args) {
50510
50648
  try {
@@ -50523,7 +50661,7 @@ function worktreeDirty(worktreePath) {
50523
50661
  }
50524
50662
  function gitCommonDir2(cwd) {
50525
50663
  const out = runGit(cwd, "rev-parse --git-common-dir");
50526
- return out ? path30.resolve(cwd, out) : void 0;
50664
+ return out ? path31.resolve(cwd, out) : void 0;
50527
50665
  }
50528
50666
  function sameGitCheckout2(a2, b2) {
50529
50667
  const left2 = gitCommonDir2(a2);
@@ -50532,20 +50670,20 @@ function sameGitCheckout2(a2, b2) {
50532
50670
  }
50533
50671
  function discoverWorktree(harnessRoot, agentId, projectName) {
50534
50672
  const session = readSlotRegistry(harnessRoot, agentId);
50535
- if (session?.worktreePath && fs31.existsSync(session.worktreePath)) {
50673
+ if (session?.worktreePath && fs32.existsSync(session.worktreePath)) {
50536
50674
  return session.worktreePath;
50537
50675
  }
50538
- const legacy = path30.join(os6.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50539
- if (fs31.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
50540
- const worktreesRoot = path30.join(os6.homedir(), "worktrees");
50541
- if (!fs31.existsSync(worktreesRoot)) return void 0;
50676
+ const legacy = path31.join(os7.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
50677
+ if (fs32.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
50678
+ const worktreesRoot = path31.join(os7.homedir(), "worktrees");
50679
+ if (!fs32.existsSync(worktreesRoot)) return void 0;
50542
50680
  const suffix = `-har-agent-${agentId}-`;
50543
50681
  const relPrefix = runGit(harnessRoot, "rev-parse --show-prefix") ?? "";
50544
- for (const name of fs31.readdirSync(worktreesRoot)) {
50682
+ for (const name of fs32.readdirSync(worktreesRoot)) {
50545
50683
  if (!name.includes(suffix)) continue;
50546
- const candidate = path30.join(worktreesRoot, name);
50684
+ const candidate = path31.join(worktreesRoot, name);
50547
50685
  if (!sameGitCheckout2(harnessRoot, candidate)) continue;
50548
- if (!fs31.existsSync(path30.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
50686
+ if (!fs32.existsSync(path31.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
50549
50687
  return candidate;
50550
50688
  }
50551
50689
  return void 0;
@@ -50553,13 +50691,13 @@ function discoverWorktree(harnessRoot, agentId, projectName) {
50553
50691
  function collectOccupiedSlot(repoPath, agentId) {
50554
50692
  const harnessRoot = resolveHarnessRoot(repoPath);
50555
50693
  const env3 = readHarnessEnv(harnessRoot);
50556
- const projectName = env3.HARNESS_PROJECT_NAME ?? path30.basename(harnessRoot);
50694
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path31.basename(harnessRoot);
50557
50695
  const session = readSlotRegistry(harnessRoot, agentId);
50558
50696
  const worktreePath = discoverWorktree(harnessRoot, agentId, projectName);
50559
50697
  const workDir = session?.workDir;
50560
- const envInWorkDir = workDir ? fs31.existsSync(path30.join(workDir, `.env.agent.${agentId}`)) : false;
50561
- const envInRoot = fs31.existsSync(path30.join(harnessRoot, `.env.agent.${agentId}`));
50562
- const envInWorktree = worktreePath ? fs31.existsSync(path30.join(worktreePath, `.env.agent.${agentId}`)) : false;
50698
+ const envInWorkDir = workDir ? fs32.existsSync(path31.join(workDir, `.env.agent.${agentId}`)) : false;
50699
+ const envInRoot = fs32.existsSync(path31.join(harnessRoot, `.env.agent.${agentId}`));
50700
+ const envInWorktree = worktreePath ? fs32.existsSync(path31.join(worktreePath, `.env.agent.${agentId}`)) : false;
50563
50701
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
50564
50702
  if (!active) return void 0;
50565
50703
  const dirty = worktreePath ? worktreeDirty(worktreePath) : void 0;
@@ -50725,7 +50863,7 @@ function checkInfraPort(env3, varName, defaultPort, scanStart, scanEnd) {
50725
50863
  function inspectSlotReadiness(repoPath, agentId, options = {}) {
50726
50864
  const harnessRoot = resolveHarnessRoot(repoPath);
50727
50865
  const env3 = readHarnessEnv(harnessRoot);
50728
- const projectName = env3.HARNESS_PROJECT_NAME ?? path31.basename(harnessRoot);
50866
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path32.basename(harnessRoot);
50729
50867
  const usesPm2 = harnessUsesPm2(repoPath);
50730
50868
  const blockers = [];
50731
50869
  const remediations = [];
@@ -50927,7 +51065,7 @@ function readWorktreeBranch(worktreePath) {
50927
51065
  }
50928
51066
  function gitCommonDir3(cwd) {
50929
51067
  const out = runGit2(cwd, "rev-parse --git-common-dir");
50930
- return out ? path32.resolve(cwd, out) : void 0;
51068
+ return out ? path33.resolve(cwd, out) : void 0;
50931
51069
  }
50932
51070
  function sameGitCheckout3(a2, b2) {
50933
51071
  const left2 = gitCommonDir3(a2);
@@ -50939,12 +51077,12 @@ function gitPrefix2(cwd) {
50939
51077
  return out ?? "";
50940
51078
  }
50941
51079
  function discoverSessionWorktreePath(harnessRoot, agentId) {
50942
- const worktreesRoot = path32.join(os7.homedir(), "worktrees");
50943
- if (!fs32.existsSync(worktreesRoot)) return void 0;
51080
+ const worktreesRoot = path33.join(os8.homedir(), "worktrees");
51081
+ if (!fs33.existsSync(worktreesRoot)) return void 0;
50944
51082
  const suffix = `-har-agent-${agentId}-`;
50945
51083
  const relPrefix = gitPrefix2(harnessRoot);
50946
- const matches = fs32.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path32.join(worktreesRoot, entry.name)).filter(
50947
- (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs32.existsSync(path32.join(candidate, relPrefix, `.env.agent.${agentId}`))
51084
+ const matches = fs33.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path33.join(worktreesRoot, entry.name)).filter(
51085
+ (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs33.existsSync(path33.join(candidate, relPrefix, `.env.agent.${agentId}`))
50948
51086
  );
50949
51087
  return matches.sort()[0];
50950
51088
  }
@@ -51019,18 +51157,18 @@ function detectPm2Issue(projectName, agentId, session, procs) {
51019
51157
  }
51020
51158
  function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
51021
51159
  const env3 = readHarnessEnv(harnessRoot);
51022
- const projectName = env3.HARNESS_PROJECT_NAME ?? path32.basename(harnessRoot);
51160
+ const projectName = env3.HARNESS_PROJECT_NAME ?? path33.basename(harnessRoot);
51023
51161
  const session = readSlotRegistry(harnessRoot, agentId);
51024
- const legacyWorktreePath = path32.join(
51025
- os7.homedir(),
51162
+ const legacyWorktreePath = path33.join(
51163
+ os8.homedir(),
51026
51164
  "worktrees",
51027
51165
  `${projectName}-agent-${agentId}`
51028
51166
  );
51029
- const worktreePath = session?.worktreePath && fs32.existsSync(session.worktreePath) ? session.worktreePath : fs32.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
51167
+ const worktreePath = session?.worktreePath && fs33.existsSync(session.worktreePath) ? session.worktreePath : fs33.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
51030
51168
  const workDir = resolveAgentWorkDir(harnessRoot, agentId);
51031
- const envInWorkDir = workDir ? fs32.existsSync(path32.join(workDir, `.env.agent.${agentId}`)) : false;
51032
- const envInRoot = fs32.existsSync(path32.join(harnessRoot, `.env.agent.${agentId}`));
51033
- const envInWorktree = worktreePath ? fs32.existsSync(path32.join(worktreePath, `.env.agent.${agentId}`)) : false;
51169
+ const envInWorkDir = workDir ? fs33.existsSync(path33.join(workDir, `.env.agent.${agentId}`)) : false;
51170
+ const envInRoot = fs33.existsSync(path33.join(harnessRoot, `.env.agent.${agentId}`));
51171
+ const envInWorktree = worktreePath ? fs33.existsSync(path33.join(worktreePath, `.env.agent.${agentId}`)) : false;
51034
51172
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
51035
51173
  const latest = latestRunForAgent(runs, agentId);
51036
51174
  const verifyRun = runs.find((r2) => r2.agentId === agentId && r2.stageId === "verify");
@@ -51069,6 +51207,8 @@ function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
51069
51207
  baseBranch: session?.baseBranch,
51070
51208
  baseCommit: session?.baseCommit,
51071
51209
  sessionCreatedAt: session?.createdAt,
51210
+ workUnitId: session?.workUnitId,
51211
+ attemptId: session?.attemptId,
51072
51212
  sessionStatus: session?.status,
51073
51213
  lastError: session?.lastError,
51074
51214
  resumeHint,
@@ -51082,7 +51222,7 @@ function collectEnvironmentStatus(repoPath) {
51082
51222
  const slotIds = getAgentSlotIds(harnessRoot);
51083
51223
  const pm2Procs = listPm2Processes2();
51084
51224
  return {
51085
- repoPath: path32.resolve(repoPath),
51225
+ repoPath: path33.resolve(repoPath),
51086
51226
  harnessRoot,
51087
51227
  gitRemote: readGitRemote(harnessRoot),
51088
51228
  profile: manifest?.profile,
@@ -51093,13 +51233,13 @@ function collectEnvironmentStatus(repoPath) {
51093
51233
 
51094
51234
  // src/core/validations.ts
51095
51235
  var crypto3 = __toESM(require("crypto"));
51096
- var fs34 = __toESM(require("fs"));
51097
- var path34 = __toESM(require("path"));
51236
+ var fs35 = __toESM(require("fs"));
51237
+ var path35 = __toESM(require("path"));
51098
51238
 
51099
51239
  // src/core/change-batch.ts
51100
- var fs33 = __toESM(require("fs"));
51101
- var os8 = __toESM(require("os"));
51102
- var path33 = __toESM(require("path"));
51240
+ var fs34 = __toESM(require("fs"));
51241
+ var os9 = __toESM(require("os"));
51242
+ var path34 = __toESM(require("path"));
51103
51243
  function git(checkoutDir, args, env3) {
51104
51244
  const result = run(`git ${args}`, { cwd: checkoutDir, env: env3 });
51105
51245
  if (result.code !== 0) {
@@ -51115,7 +51255,7 @@ function isCheckoutRoot(checkoutDir) {
51115
51255
  const toplevel = tryGit2(checkoutDir, "rev-parse --show-toplevel");
51116
51256
  if (!toplevel) return false;
51117
51257
  try {
51118
- return fs33.realpathSync(toplevel) === fs33.realpathSync(checkoutDir);
51258
+ return fs34.realpathSync(toplevel) === fs34.realpathSync(checkoutDir);
51119
51259
  } catch {
51120
51260
  return false;
51121
51261
  }
@@ -51137,7 +51277,7 @@ function isMergeOrRebaseInProgress(checkoutDir) {
51137
51277
  if (tryGit2(checkoutDir, "rev-parse -q --verify MERGE_HEAD") !== void 0) return true;
51138
51278
  for (const dir of ["rebase-merge", "rebase-apply"]) {
51139
51279
  const gitPath = tryGit2(checkoutDir, `rev-parse --git-path ${dir}`);
51140
- if (gitPath && fs33.existsSync(path33.resolve(checkoutDir, gitPath))) return true;
51280
+ if (gitPath && fs34.existsSync(path34.resolve(checkoutDir, gitPath))) return true;
51141
51281
  }
51142
51282
  return false;
51143
51283
  }
@@ -51160,8 +51300,8 @@ function parseNameStatus(output) {
51160
51300
  return files;
51161
51301
  }
51162
51302
  function computeWorktreeSnapshot(checkoutDir) {
51163
- const tmpDir = fs33.mkdtempSync(path33.join(os8.tmpdir(), "har-idx-"));
51164
- const tmpIndex = path33.join(tmpDir, "index");
51303
+ const tmpDir = fs34.mkdtempSync(path34.join(os9.tmpdir(), "har-idx-"));
51304
+ const tmpIndex = path34.join(tmpDir, "index");
51165
51305
  const env3 = { GIT_INDEX_FILE: tmpIndex };
51166
51306
  try {
51167
51307
  const headTree = getHeadTree(checkoutDir);
@@ -51184,35 +51324,35 @@ function computeWorktreeSnapshot(checkoutDir) {
51184
51324
  changedFiles: parseNameStatus(diffOutput)
51185
51325
  };
51186
51326
  } finally {
51187
- fs33.rmSync(tmpDir, { recursive: true, force: true });
51327
+ fs34.rmSync(tmpDir, { recursive: true, force: true });
51188
51328
  }
51189
51329
  }
51190
51330
 
51191
51331
  // src/core/validations.ts
51192
51332
  var VALIDATIONS_DIR = "validations";
51193
51333
  function getValidationsDir(checkoutDir) {
51194
- return path34.join(checkoutDir, ".har", VALIDATIONS_DIR);
51334
+ return path35.join(checkoutDir, ".har", VALIDATIONS_DIR);
51195
51335
  }
51196
51336
  function validationPath(checkoutDir, treeHash) {
51197
- return path34.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
51337
+ return path35.join(getValidationsDir(checkoutDir), `${treeHash}.json`);
51198
51338
  }
51199
51339
  function writeRecord(checkoutDir, record2) {
51200
51340
  const dir = getValidationsDir(checkoutDir);
51201
- fs34.mkdirSync(dir, { recursive: true });
51202
- fs34.writeFileSync(
51341
+ fs35.mkdirSync(dir, { recursive: true });
51342
+ fs35.writeFileSync(
51203
51343
  validationPath(checkoutDir, record2.treeHash),
51204
51344
  `${JSON.stringify(record2, null, 2)}
51205
51345
  `
51206
51346
  );
51207
51347
  }
51208
51348
  function ensureValidationsIgnored(checkoutDir) {
51209
- const harDir = path34.join(checkoutDir, ".har");
51210
- if (!fs34.existsSync(harDir)) return;
51211
- const gitignorePath = path34.join(harDir, ".gitignore");
51212
- const content = fs34.existsSync(gitignorePath) ? fs34.readFileSync(gitignorePath, "utf8") : "";
51349
+ const harDir = path35.join(checkoutDir, ".har");
51350
+ if (!fs35.existsSync(harDir)) return;
51351
+ const gitignorePath = path35.join(harDir, ".gitignore");
51352
+ const content = fs35.existsSync(gitignorePath) ? fs35.readFileSync(gitignorePath, "utf8") : "";
51213
51353
  if (content.split("\n").some((line) => line.trim() === `${VALIDATIONS_DIR}/`)) return;
51214
51354
  const suffix = content.length === 0 || content.endsWith("\n") ? "" : "\n";
51215
- fs34.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
51355
+ fs35.writeFileSync(gitignorePath, `${content}${suffix}${VALIDATIONS_DIR}/
51216
51356
  `);
51217
51357
  }
51218
51358
  function recordValidation(input) {
@@ -51229,8 +51369,8 @@ function recordValidation(input) {
51229
51369
  treeHash: snapshot.treeHash,
51230
51370
  headSha: snapshot.headSha,
51231
51371
  branch: snapshot.branch,
51232
- workDir: path34.resolve(input.checkoutDir),
51233
- harnessRoot: path34.resolve(input.harnessRoot),
51372
+ workDir: path35.resolve(input.checkoutDir),
51373
+ harnessRoot: path35.resolve(input.harnessRoot),
51234
51374
  agentId: input.agentId,
51235
51375
  status: input.status,
51236
51376
  full: input.full,
@@ -51242,16 +51382,16 @@ function recordValidation(input) {
51242
51382
  committedAt: existing?.committedAt
51243
51383
  });
51244
51384
  writeRecord(input.checkoutDir, record2);
51245
- if (path34.resolve(input.harnessRoot) !== path34.resolve(input.checkoutDir)) {
51385
+ if (path35.resolve(input.harnessRoot) !== path35.resolve(input.checkoutDir)) {
51246
51386
  writeRecord(input.harnessRoot, record2);
51247
51387
  }
51248
51388
  return record2;
51249
51389
  }
51250
51390
  function findValidation(checkoutDir, treeHash) {
51251
51391
  const file = validationPath(checkoutDir, treeHash);
51252
- if (!fs34.existsSync(file)) return void 0;
51392
+ if (!fs35.existsSync(file)) return void 0;
51253
51393
  try {
51254
- return ValidationRecordSchema.parse(JSON.parse(fs34.readFileSync(file, "utf8")));
51394
+ return ValidationRecordSchema.parse(JSON.parse(fs35.readFileSync(file, "utf8")));
51255
51395
  } catch {
51256
51396
  return void 0;
51257
51397
  }
@@ -51266,25 +51406,192 @@ function attachCommit(checkoutDir, treeHash, commitSha) {
51266
51406
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
51267
51407
  };
51268
51408
  writeRecord(checkoutDir, updated);
51269
- if (record2.harnessRoot && path34.resolve(record2.harnessRoot) !== path34.resolve(checkoutDir) && fs34.existsSync(path34.join(record2.harnessRoot, ".har"))) {
51409
+ if (record2.harnessRoot && path35.resolve(record2.harnessRoot) !== path35.resolve(checkoutDir) && fs35.existsSync(path35.join(record2.harnessRoot, ".har"))) {
51270
51410
  writeRecord(record2.harnessRoot, updated);
51271
51411
  }
51272
51412
  return updated;
51273
51413
  }
51274
51414
  function listValidations(harnessRoot) {
51275
51415
  const dir = getValidationsDir(harnessRoot);
51276
- if (!fs34.existsSync(dir)) return [];
51416
+ if (!fs35.existsSync(dir)) return [];
51277
51417
  const records = [];
51278
- for (const entry of fs34.readdirSync(dir)) {
51418
+ for (const entry of fs35.readdirSync(dir)) {
51279
51419
  if (!entry.endsWith(".json")) continue;
51280
51420
  try {
51281
- records.push(ValidationRecordSchema.parse(JSON.parse(fs34.readFileSync(path34.join(dir, entry), "utf8"))));
51421
+ records.push(ValidationRecordSchema.parse(JSON.parse(fs35.readFileSync(path35.join(dir, entry), "utf8"))));
51282
51422
  } catch {
51283
51423
  }
51284
51424
  }
51285
51425
  return records.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
51286
51426
  }
51287
51427
 
51428
+ // src/core/work-units.ts
51429
+ var crypto4 = __toESM(require("crypto"));
51430
+ var fs36 = __toESM(require("fs"));
51431
+ var path36 = __toESM(require("path"));
51432
+ var WORK_UNITS_DIR = "work-units";
51433
+ var WORK_ATTEMPTS_DIR = "work-attempts";
51434
+ var VALIDATION_BINDINGS_DIR = "validation-bindings";
51435
+ var EVIDENCE_DIRS = [WORK_UNITS_DIR, WORK_ATTEMPTS_DIR, VALIDATION_BINDINGS_DIR];
51436
+ function harEvidenceDir(harnessRoot, name) {
51437
+ return path36.join(harnessRoot, ".har", name);
51438
+ }
51439
+ function hashedRecordPath(harnessRoot, dir, id) {
51440
+ const digest = crypto4.createHash("sha256").update(id).digest("hex");
51441
+ return path36.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
51442
+ }
51443
+ function writeRecord2(file, value) {
51444
+ fs36.mkdirSync(path36.dirname(file), { recursive: true });
51445
+ const temp = `${file}.${process.pid}.tmp`;
51446
+ fs36.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
51447
+ `);
51448
+ fs36.renameSync(temp, file);
51449
+ }
51450
+ function ensureWorkEvidenceIgnored(harnessRoot) {
51451
+ const harDir = path36.join(harnessRoot, ".har");
51452
+ if (!fs36.existsSync(harDir)) return;
51453
+ const gitignorePath = path36.join(harDir, ".gitignore");
51454
+ const content = fs36.existsSync(gitignorePath) ? fs36.readFileSync(gitignorePath, "utf8") : "";
51455
+ const lines2 = new Set(content.split("\n").map((line) => line.trim()));
51456
+ const missing = EVIDENCE_DIRS.map((dir) => `${dir}/`).filter((dir) => !lines2.has(dir));
51457
+ if (missing.length === 0) return;
51458
+ const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
51459
+ fs36.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
51460
+ `);
51461
+ }
51462
+ function listRecords(harnessRoot, dir, parse4) {
51463
+ const recordDir = harEvidenceDir(harnessRoot, dir);
51464
+ if (!fs36.existsSync(recordDir)) return [];
51465
+ const records = [];
51466
+ for (const name of fs36.readdirSync(recordDir)) {
51467
+ if (!name.endsWith(".json")) continue;
51468
+ try {
51469
+ records.push(parse4(JSON.parse(fs36.readFileSync(path36.join(recordDir, name), "utf8"))));
51470
+ } catch {
51471
+ }
51472
+ }
51473
+ return records;
51474
+ }
51475
+ function findWorkUnit(harnessRoot, workUnitId) {
51476
+ const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
51477
+ const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
51478
+ if (!fs36.existsSync(file)) return void 0;
51479
+ try {
51480
+ return WorkUnitRecordSchema.parse(JSON.parse(fs36.readFileSync(file, "utf8")));
51481
+ } catch {
51482
+ return void 0;
51483
+ }
51484
+ }
51485
+ function upsertWorkUnit(harnessRoot, input) {
51486
+ const metadata = WorkUnitMetadataSchema.parse(input);
51487
+ ensureWorkEvidenceIgnored(harnessRoot);
51488
+ const existing = findWorkUnit(harnessRoot, metadata.workUnitId);
51489
+ if (existing) {
51490
+ if (existing.outcome) {
51491
+ throw new Error(
51492
+ `Work unit ${metadata.workUnitId} is already ${existing.outcome.decision}; reopening is not supported`
51493
+ );
51494
+ }
51495
+ for (const field of ["source", "sourceUrl", "title", "parentWorkUnitId"]) {
51496
+ if (metadata[field] !== void 0 && existing[field] !== void 0 && metadata[field] !== existing[field]) {
51497
+ throw new Error(
51498
+ `Work unit ${metadata.workUnitId} has immutable ${field}=${existing[field]}`
51499
+ );
51500
+ }
51501
+ }
51502
+ }
51503
+ const now = (/* @__PURE__ */ new Date()).toISOString();
51504
+ const record2 = WorkUnitRecordSchema.parse({
51505
+ ...existing,
51506
+ workUnitId: metadata.workUnitId,
51507
+ source: existing?.source ?? metadata.source,
51508
+ sourceUrl: existing?.sourceUrl ?? metadata.sourceUrl,
51509
+ title: existing?.title ?? metadata.title,
51510
+ parentWorkUnitId: existing?.parentWorkUnitId ?? metadata.parentWorkUnitId,
51511
+ version: 1,
51512
+ createdAt: existing?.createdAt ?? now,
51513
+ updatedAt: now,
51514
+ outcome: existing?.outcome
51515
+ });
51516
+ writeRecord2(
51517
+ hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId),
51518
+ record2
51519
+ );
51520
+ return record2;
51521
+ }
51522
+ function listWorkUnits(harnessRoot) {
51523
+ return listRecords(
51524
+ harnessRoot,
51525
+ WORK_UNITS_DIR,
51526
+ (value) => WorkUnitRecordSchema.parse(value)
51527
+ ).sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
51528
+ }
51529
+ function createWorkAttempt(harnessRoot, input) {
51530
+ const attempt = WorkAttemptRecordSchema.parse({
51531
+ ...input,
51532
+ version: 1,
51533
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
51534
+ });
51535
+ ensureWorkEvidenceIgnored(harnessRoot);
51536
+ writeRecord2(
51537
+ hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt.attemptId),
51538
+ attempt
51539
+ );
51540
+ return attempt;
51541
+ }
51542
+ function listWorkAttempts(harnessRoot) {
51543
+ return listRecords(
51544
+ harnessRoot,
51545
+ WORK_ATTEMPTS_DIR,
51546
+ (value) => WorkAttemptRecordSchema.parse(value)
51547
+ ).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
51548
+ }
51549
+ function bindValidationToAttempt(harnessRoot, input) {
51550
+ const stableKey = `${input.attemptId}:${input.validation.validationId}`;
51551
+ ensureWorkEvidenceIgnored(harnessRoot);
51552
+ const existingFile = hashedRecordPath(
51553
+ harnessRoot,
51554
+ VALIDATION_BINDINGS_DIR,
51555
+ stableKey
51556
+ );
51557
+ if (fs36.existsSync(existingFile)) {
51558
+ try {
51559
+ return ValidationBindingRecordSchema.parse(
51560
+ JSON.parse(fs36.readFileSync(existingFile, "utf8"))
51561
+ );
51562
+ } catch {
51563
+ }
51564
+ }
51565
+ const binding = ValidationBindingRecordSchema.parse({
51566
+ bindingId: crypto4.randomUUID(),
51567
+ workUnitId: input.workUnitId,
51568
+ attemptId: input.attemptId,
51569
+ validationId: input.validation.validationId,
51570
+ treeHash: input.validation.treeHash,
51571
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
51572
+ });
51573
+ writeRecord2(existingFile, binding);
51574
+ return binding;
51575
+ }
51576
+ function listValidationBindings(harnessRoot) {
51577
+ return listRecords(
51578
+ harnessRoot,
51579
+ VALIDATION_BINDINGS_DIR,
51580
+ (value) => ValidationBindingRecordSchema.parse(value)
51581
+ ).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
51582
+ }
51583
+ function decideWorkUnitOutcome(harnessRoot, workUnitId, outcome) {
51584
+ const existing = findWorkUnit(harnessRoot, workUnitId);
51585
+ if (!existing) throw new Error(`Unknown work unit: ${workUnitId}`);
51586
+ const record2 = WorkUnitRecordSchema.parse({
51587
+ ...existing,
51588
+ outcome,
51589
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
51590
+ });
51591
+ writeRecord2(hashedRecordPath(harnessRoot, WORK_UNITS_DIR, workUnitId), record2);
51592
+ return record2;
51593
+ }
51594
+
51288
51595
  // src/core/cloud-executor.ts
51289
51596
  var RemoteExecutor = class {
51290
51597
  constructor(apiUrl, apiKey) {
@@ -51311,14 +51618,14 @@ function createRemoteExecutor(apiUrl, apiKey) {
51311
51618
  init_telemetry_config();
51312
51619
 
51313
51620
  // src/core/usage-harvest/claude.ts
51314
- var fs37 = __toESM(require("fs"));
51315
- var os10 = __toESM(require("os"));
51316
- var path37 = __toESM(require("path"));
51621
+ var fs39 = __toESM(require("fs"));
51622
+ var os11 = __toESM(require("os"));
51623
+ var path39 = __toESM(require("path"));
51317
51624
  init_telemetry_config();
51318
51625
 
51319
51626
  // src/core/telemetry-env.ts
51320
- var fs36 = __toESM(require("fs"));
51321
- var path36 = __toESM(require("path"));
51627
+ var fs38 = __toESM(require("fs"));
51628
+ var path38 = __toESM(require("path"));
51322
51629
  init_control_config();
51323
51630
  function escapeAttrValue(value) {
51324
51631
  return value.replace(/[,=]/g, "_");
@@ -51332,6 +51639,10 @@ function buildOtelResourceAttributes(attrs) {
51332
51639
  ];
51333
51640
  if (attrs.branch) parts.push(`har.branch=${escapeAttrValue(attrs.branch)}`);
51334
51641
  if (attrs.suffix) parts.push(`har.suffix=${escapeAttrValue(attrs.suffix)}`);
51642
+ if (attrs.workUnitId) {
51643
+ parts.push(`har.work_unit_id=${escapeAttrValue(attrs.workUnitId)}`);
51644
+ }
51645
+ if (attrs.attemptId) parts.push(`har.attempt_id=${attrs.attemptId}`);
51335
51646
  return parts.join(",");
51336
51647
  }
51337
51648
  function buildSessionKey(input) {
@@ -51345,6 +51656,8 @@ function buildTelemetryEnvBlock(attrs) {
51345
51656
  "",
51346
51657
  "# HAR session attribution (generated)",
51347
51658
  `HAR_SESSION_KEY=${attrs.sessionKey}`,
51659
+ ...attrs.workUnitId ? [`HAR_WORK_UNIT_ID=${attrs.workUnitId}`] : [],
51660
+ ...attrs.attemptId ? [`HAR_ATTEMPT_ID=${attrs.attemptId}`] : [],
51348
51661
  `HAR_CONTROL_API_URL=${apiUrl}`,
51349
51662
  `OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}`,
51350
51663
  "# Agent telemetry: opentelemetry-hooks \u2192 Mission Control (har telemetry on|off)"
@@ -51358,8 +51671,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
51358
51671
  ${TELEMETRY_MARKER_END}
51359
51672
  `;
51360
51673
  let existing = "";
51361
- if (fs36.existsSync(envFilePath)) {
51362
- existing = fs36.readFileSync(envFilePath, "utf8");
51674
+ if (fs38.existsSync(envFilePath)) {
51675
+ existing = fs38.readFileSync(envFilePath, "utf8");
51363
51676
  const start = existing.indexOf(TELEMETRY_MARKER_START);
51364
51677
  if (start >= 0) {
51365
51678
  const end = existing.indexOf(TELEMETRY_MARKER_END, start);
@@ -51370,28 +51683,28 @@ ${TELEMETRY_MARKER_END}
51370
51683
  }
51371
51684
  }
51372
51685
  }
51373
- fs36.mkdirSync(path36.dirname(envFilePath), { recursive: true });
51686
+ fs38.mkdirSync(path38.dirname(envFilePath), { recursive: true });
51374
51687
  const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
51375
- fs36.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51688
+ fs38.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51376
51689
  }
51377
51690
 
51378
51691
  // src/core/usage-harvest/claude.ts
51379
51692
  function pathsMatch(candidate, targets) {
51380
- const norm = path37.resolve(candidate);
51693
+ const norm = path39.resolve(candidate);
51381
51694
  return targets.some((t2) => {
51382
- const target = path37.resolve(t2);
51383
- return norm === target || norm.startsWith(target + path37.sep) || target.startsWith(norm + path37.sep);
51695
+ const target = path39.resolve(t2);
51696
+ return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
51384
51697
  });
51385
51698
  }
51386
51699
  function claudeProjectsRoot() {
51387
- return process.env.HAR_CLAUDE_PROJECTS_DIR ? path37.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path37.join(os10.homedir(), ".claude", "projects");
51700
+ return process.env.HAR_CLAUDE_PROJECTS_DIR ? path39.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path39.join(os11.homedir(), ".claude", "projects");
51388
51701
  }
51389
51702
  function encodeClaudeProjectDir(cwd) {
51390
51703
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
51391
51704
  }
51392
51705
  function readJsonlRecords(filePath) {
51393
- if (!fs37.existsSync(filePath)) return [];
51394
- const lines2 = fs37.readFileSync(filePath, "utf8").split(/\r?\n/);
51706
+ if (!fs39.existsSync(filePath)) return [];
51707
+ const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
51395
51708
  const out = [];
51396
51709
  for (const line of lines2) {
51397
51710
  const trimmed = line.trim();
@@ -51434,16 +51747,16 @@ function findMatchingClaudeTranscripts(slot) {
51434
51747
  const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
51435
51748
  if (targets.length === 0) return [];
51436
51749
  const root = claudeProjectsRoot();
51437
- if (!fs37.existsSync(root)) return [];
51750
+ if (!fs39.existsSync(root)) return [];
51438
51751
  const matches = [];
51439
- for (const entry of fs37.readdirSync(root, { withFileTypes: true })) {
51752
+ for (const entry of fs39.readdirSync(root, { withFileTypes: true })) {
51440
51753
  if (!entry.isDirectory()) continue;
51441
- const projectDir = path37.join(root, entry.name);
51754
+ const projectDir = path39.join(root, entry.name);
51442
51755
  const encodedHit = targets.some((t2) => entry.name.includes(encodeClaudeProjectDir(t2).slice(0, 40)));
51443
- for (const file of fs37.readdirSync(projectDir)) {
51756
+ for (const file of fs39.readdirSync(projectDir)) {
51444
51757
  if (!file.endsWith(".jsonl")) continue;
51445
- const filePath = path37.join(projectDir, file);
51446
- const stat = fs37.statSync(filePath);
51758
+ const filePath = path39.join(projectDir, file);
51759
+ const stat = fs39.statSync(filePath);
51447
51760
  const records = readJsonlRecords(filePath);
51448
51761
  let cwdHit = encodedHit;
51449
51762
  for (const record2 of records) {
@@ -51554,30 +51867,30 @@ function harvestClaudeEvents(slot) {
51554
51867
  }
51555
51868
 
51556
51869
  // src/core/usage-harvest/codex.ts
51557
- var fs38 = __toESM(require("fs"));
51558
- var os11 = __toESM(require("os"));
51559
- var path38 = __toESM(require("path"));
51870
+ var fs40 = __toESM(require("fs"));
51871
+ var os12 = __toESM(require("os"));
51872
+ var path40 = __toESM(require("path"));
51560
51873
  function pathsMatch2(candidate, targets) {
51561
- const norm = path38.resolve(candidate);
51874
+ const norm = path40.resolve(candidate);
51562
51875
  return targets.some((t2) => {
51563
- const target = path38.resolve(t2);
51564
- return norm === target || norm.startsWith(target + path38.sep) || target.startsWith(norm + path38.sep);
51876
+ const target = path40.resolve(t2);
51877
+ return norm === target || norm.startsWith(target + path40.sep) || target.startsWith(norm + path40.sep);
51565
51878
  });
51566
51879
  }
51567
51880
  function codexSessionsRoot() {
51568
- return process.env.HAR_CODEX_SESSIONS_DIR ? path38.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path38.join(os11.homedir(), ".codex", "sessions");
51881
+ return process.env.HAR_CODEX_SESSIONS_DIR ? path40.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path40.join(os12.homedir(), ".codex", "sessions");
51569
51882
  }
51570
51883
  function walkJsonlFiles(dir, out = []) {
51571
- if (!fs38.existsSync(dir)) return out;
51572
- for (const entry of fs38.readdirSync(dir, { withFileTypes: true })) {
51573
- const full = path38.join(dir, entry.name);
51884
+ if (!fs40.existsSync(dir)) return out;
51885
+ for (const entry of fs40.readdirSync(dir, { withFileTypes: true })) {
51886
+ const full = path40.join(dir, entry.name);
51574
51887
  if (entry.isDirectory()) walkJsonlFiles(full, out);
51575
51888
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
51576
51889
  }
51577
51890
  return out;
51578
51891
  }
51579
51892
  function readJsonl(filePath) {
51580
- const lines2 = fs38.readFileSync(filePath, "utf8").split(/\r?\n/);
51893
+ const lines2 = fs40.readFileSync(filePath, "utf8").split(/\r?\n/);
51581
51894
  const out = [];
51582
51895
  for (const line of lines2) {
51583
51896
  const trimmed = line.trim();
@@ -51641,7 +51954,7 @@ function harvestCodexUsage(slot) {
51641
51954
  const extracted = extractCodexTokens(records);
51642
51955
  if (!extracted.cwd || !pathsMatch2(extracted.cwd, targets)) continue;
51643
51956
  if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
51644
- const mtime = fs38.statSync(file).mtimeMs;
51957
+ const mtime = fs40.statSync(file).mtimeMs;
51645
51958
  if (mtime >= bestMtime) {
51646
51959
  bestMtime = mtime;
51647
51960
  best = extracted;
@@ -51696,6 +52009,42 @@ async function postJson(url, body, dryRun) {
51696
52009
  }
51697
52010
  return await response.json();
51698
52011
  }
52012
+ async function postPortalSync(target, body, dryRun) {
52013
+ if (dryRun) return;
52014
+ const response = await fetch(`${target.url}/api/sync`, {
52015
+ method: "POST",
52016
+ headers: {
52017
+ "Content-Type": "application/json",
52018
+ Authorization: `Bearer ${target.token}`
52019
+ },
52020
+ body: JSON.stringify(body)
52021
+ });
52022
+ if (!response.ok) {
52023
+ if (response.status === 401 || response.status === 403) {
52024
+ throw new Error(
52025
+ `har-portal rejected the ingest token (HTTP ${response.status}) \u2014 check HAR_PORTAL_TOKEN.`
52026
+ );
52027
+ }
52028
+ const text = await response.text().catch(() => "");
52029
+ throw new Error(`har-portal sync failed: HTTP ${response.status}${text ? ` \u2014 ${text}` : ""}`);
52030
+ }
52031
+ }
52032
+ function buildPortalSyncBody(repoPath) {
52033
+ const runs = listRuns(repoPath);
52034
+ const status = collectEnvironmentStatus(repoPath);
52035
+ const manifest = readManifest(repoPath);
52036
+ const stagesRegistry = readStageRegistry(repoPath);
52037
+ const validations = listValidations(resolveHarnessRoot(repoPath));
52038
+ return {
52039
+ path: repoPath,
52040
+ ...manifest ? { manifest } : {},
52041
+ ...stagesRegistry ? { stagesRegistry } : {},
52042
+ runs,
52043
+ slots: status.slots,
52044
+ generatedAt: status.generatedAt,
52045
+ ...validations.length > 0 ? { validations } : {}
52046
+ };
52047
+ }
51699
52048
  async function isControlApiReachable(apiUrl = getControlApiUrl()) {
51700
52049
  try {
51701
52050
  const response = await fetch(`${apiUrl}/api/health`, {
@@ -51711,14 +52060,15 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
51711
52060
  const deadline = Date.now() + timeoutMs;
51712
52061
  while (Date.now() < deadline) {
51713
52062
  if (await isControlApiReachable(apiUrl)) return true;
51714
- await new Promise((resolve37) => setTimeout(resolve37, intervalMs));
52063
+ await new Promise((resolve38) => setTimeout(resolve38, intervalMs));
51715
52064
  }
51716
52065
  return false;
51717
52066
  }
51718
52067
  async function syncAllKnownReposWithControl(options) {
51719
52068
  if (!isControlEnabled()) return { synced: 0, failed: 0 };
51720
52069
  const apiUrl = options?.apiUrl ?? getControlApiUrl();
51721
- if (!await isControlApiReachable(apiUrl)) {
52070
+ const portal = getPortalTarget();
52071
+ if (!await isControlApiReachable(portal ? portal.url : apiUrl)) {
51722
52072
  return { synced: 0, failed: 0 };
51723
52073
  }
51724
52074
  const repoPaths = new Set(listRegisteredRepos());
@@ -51787,26 +52137,40 @@ async function syncRepoWithControl(options) {
51787
52137
  }
51788
52138
  const runs = listRuns(repoPath);
51789
52139
  const status = collectEnvironmentStatus(repoPath);
52140
+ const harnessRoot = resolveHarnessRoot(repoPath);
51790
52141
  const response = await fetch(`${process.env.HAR_CLOUD_API_URL}/api/sync`, {
51791
52142
  method: "POST",
51792
52143
  headers: {
51793
52144
  "Content-Type": "application/json",
51794
52145
  Authorization: `Bearer ${process.env.HAR_CLOUD_API_KEY}`
51795
52146
  },
51796
- body: JSON.stringify({ path: repoPath, runs, slots: status.slots })
52147
+ body: JSON.stringify({
52148
+ path: repoPath,
52149
+ runs,
52150
+ slots: status.slots,
52151
+ workUnits: listWorkUnits(harnessRoot),
52152
+ attempts: listWorkAttempts(harnessRoot),
52153
+ validations: listValidations(harnessRoot),
52154
+ validationBindings: listValidationBindings(harnessRoot)
52155
+ })
51797
52156
  });
51798
52157
  if (!response.ok) {
51799
52158
  throw new Error(`Cloud sync failed: ${response.status}`);
51800
52159
  }
51801
52160
  return;
51802
52161
  }
52162
+ const portal = getPortalTarget();
52163
+ if (portal) {
52164
+ await postPortalSync(portal, buildPortalSyncBody(repoPath), options.dryRun);
52165
+ return;
52166
+ }
51803
52167
  const registerResult = await registerRepoWithControl({ ...options, repoPath });
51804
52168
  const repoId = registerResult?.id;
51805
52169
  if (!repoId && !options.dryRun) {
51806
52170
  const listResponse = await fetch(`${apiUrl}/api/repos`);
51807
52171
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
51808
52172
  const repos = await listResponse.json();
51809
- const existing = repos.find((r2) => path39.resolve(r2.path) === repoPath);
52173
+ const existing = repos.find((r2) => path41.resolve(r2.path) === repoPath);
51810
52174
  if (!existing) {
51811
52175
  return;
51812
52176
  }
@@ -51827,6 +52191,13 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51827
52191
  generatedAt: status.generatedAt
51828
52192
  });
51829
52193
  await postJson(`${apiUrl}/api/repos/${repoId}/slots`, slotsBody, dryRun);
52194
+ const workUnitsBody = SyncWorkUnitsInputSchema.parse({
52195
+ workUnits: listWorkUnits(resolveHarnessRoot(repoPath)),
52196
+ attempts: listWorkAttempts(resolveHarnessRoot(repoPath))
52197
+ });
52198
+ if (workUnitsBody.workUnits.length > 0 || workUnitsBody.attempts.length > 0) {
52199
+ await postJson(`${apiUrl}/api/repos/${repoId}/work-units`, workUnitsBody, dryRun);
52200
+ }
51830
52201
  if (isTelemetryEnabled() && process.env.NODE_ENV !== "test") {
51831
52202
  try {
51832
52203
  const usage2 = status.slots.flatMap(
@@ -51840,6 +52211,8 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51840
52211
  repoPath
51841
52212
  }).map((row) => ({
51842
52213
  ...row,
52214
+ workUnitId: slot.workUnitId,
52215
+ attemptId: slot.attemptId,
51843
52216
  sessionKey: row.sessionKey || buildSessionKey({
51844
52217
  branch: slot.branch,
51845
52218
  agentId: slot.agentId,
@@ -51861,7 +52234,11 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51861
52234
  suffix: slot.suffix,
51862
52235
  sessionCreatedAt: slot.sessionCreatedAt,
51863
52236
  repoPath
51864
- })
52237
+ }).map((event) => ({
52238
+ ...event,
52239
+ workUnitId: slot.workUnitId,
52240
+ attemptId: slot.attemptId
52241
+ }))
51865
52242
  );
51866
52243
  if (events.length > 0) {
51867
52244
  const eventsBody = SyncSessionEventsInputSchema.parse({ events });
@@ -51878,6 +52255,16 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51878
52255
  const validationsBody = SyncValidationsInputSchema.parse({ validations });
51879
52256
  await postJson(`${apiUrl}/api/repos/${repoId}/validations`, validationsBody, dryRun);
51880
52257
  }
52258
+ const bindingsBody = SyncValidationBindingsInputSchema.parse({
52259
+ bindings: listValidationBindings(resolveHarnessRoot(repoPath))
52260
+ });
52261
+ if (bindingsBody.bindings.length > 0) {
52262
+ await postJson(
52263
+ `${apiUrl}/api/repos/${repoId}/validation-bindings`,
52264
+ bindingsBody,
52265
+ dryRun
52266
+ );
52267
+ }
51881
52268
  }
51882
52269
  var SYNC_TIMEOUT_MS = 15e3;
51883
52270
  function withTimeout(promise, ms, label) {
@@ -51891,17 +52278,18 @@ async function syncRepoWithControlAsync(repoPath) {
51891
52278
  if (process.env.HAR_CONTROL_DISABLED === "true" || process.env.NODE_ENV === "test") return;
51892
52279
  const verbose = process.env.HAR_CONTROL_VERBOSE === "true";
51893
52280
  try {
51894
- const apiUrl = getControlApiUrl();
51895
- if (!await isControlApiReachable(apiUrl)) {
52281
+ const portal = getPortalTarget();
52282
+ const healthUrl = portal ? portal.url : getControlApiUrl();
52283
+ if (!await isControlApiReachable(healthUrl)) {
51896
52284
  if (verbose) {
51897
- process.stderr.write(`[har control] sync skipped: control API not reachable at ${apiUrl}
52285
+ process.stderr.write(`[har control] sync skipped: not reachable at ${healthUrl}
51898
52286
  `);
51899
52287
  }
51900
52288
  return;
51901
52289
  }
51902
52290
  const canonical = canonicalizeControlRepoPath(repoPath);
51903
52291
  await withTimeout(
51904
- syncRepoWithControl({ repoPath: canonical, apiUrl }),
52292
+ syncRepoWithControl({ repoPath: canonical }),
51905
52293
  SYNC_TIMEOUT_MS,
51906
52294
  "control sync"
51907
52295
  );
@@ -51935,7 +52323,7 @@ init_control_config();
51935
52323
 
51936
52324
  // src/core/control-lifecycle.ts
51937
52325
  var import_child_process8 = require("child_process");
51938
- var path40 = __toESM(require("path"));
52326
+ var path42 = __toESM(require("path"));
51939
52327
 
51940
52328
  // src/core/control-image.ts
51941
52329
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -51959,10 +52347,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
51959
52347
  var CONTROL_CONTAINER_PORT = 3847;
51960
52348
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
51961
52349
  function resolveControlDir() {
51962
- return path40.resolve(__dirname, "..", "control");
52350
+ return path42.resolve(__dirname, "..", "control");
51963
52351
  }
51964
52352
  function resolveControlBuildContext() {
51965
- return path40.resolve(resolveControlDir(), "..");
52353
+ return path42.resolve(resolveControlDir(), "..");
51966
52354
  }
51967
52355
  function buildDockerRunArgs(options) {
51968
52356
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -52018,7 +52406,7 @@ async function startMissionControl(options) {
52018
52406
  "-t",
52019
52407
  imageRef,
52020
52408
  "-f",
52021
- path40.join(resolveControlDir(), "Dockerfile"),
52409
+ path42.join(resolveControlDir(), "Dockerfile"),
52022
52410
  resolveControlBuildContext()
52023
52411
  ]);
52024
52412
  if (buildCode !== 0) {
@@ -52162,7 +52550,7 @@ async function ensureTelemetryInfrastructure(options) {
52162
52550
 
52163
52551
  // src/core/run-service.ts
52164
52552
  init_telemetry_config();
52165
- var path42 = __toESM(require("path"));
52553
+ var path44 = __toESM(require("path"));
52166
52554
  function extractShellOutput(result) {
52167
52555
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
52168
52556
  const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
@@ -52200,11 +52588,14 @@ var RunService = class {
52200
52588
  this.executor = executor;
52201
52589
  }
52202
52590
  async runStage(options) {
52591
+ const activeSession = options.agentId !== void 0 && options.kind !== "launch" ? readSlotRegistry(resolveHarnessRoot(options.repoPath), options.agentId) : void 0;
52203
52592
  const ctx = {
52204
52593
  repoPath: options.repoPath,
52205
52594
  capture: options.capture,
52206
52595
  agentId: options.agentId,
52207
- trigger: options.trigger
52596
+ trigger: options.trigger,
52597
+ workUnitId: options.workUnitId ?? activeSession?.workUnitId,
52598
+ attemptId: options.attemptId ?? activeSession?.attemptId
52208
52599
  };
52209
52600
  const stageLookup = options.stageId ? { id: options.stageId } : options.kind ? { kind: options.kind } : null;
52210
52601
  if (!stageLookup) {
@@ -52306,47 +52697,96 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52306
52697
  `;
52307
52698
  }
52308
52699
  }
52700
+ const harnessRoot = resolveHarnessRoot(options.repoPath);
52701
+ const resumableSession = options.resume ? readSlotRegistry(harnessRoot, options.agentId) : void 0;
52702
+ const workUnitId = options.workUnitId ?? resumableSession?.workUnitId;
52703
+ const attemptId = workUnitId ? resumableSession?.attemptId ?? crypto5.randomUUID() : void 0;
52704
+ if (workUnitId && attemptId) {
52705
+ const conflictingSession = listSlotRegistryEntries(harnessRoot).find(
52706
+ (entry) => entry.workUnitId === workUnitId && !(entry.agentId === options.agentId && (options.resume || options.confirmReplace))
52707
+ );
52708
+ if (conflictingSession) {
52709
+ return {
52710
+ code: 2,
52711
+ stdout: "",
52712
+ stderr: `Work unit ${workUnitId} is already bound to slot ${conflictingSession.agentId} (attempt ${conflictingSession.attemptId ?? "unknown"}).`,
52713
+ blocked: true
52714
+ };
52715
+ }
52716
+ upsertWorkUnit(harnessRoot, {
52717
+ workUnitId,
52718
+ source: options.source,
52719
+ sourceUrl: options.sourceUrl,
52720
+ title: options.title,
52721
+ parentWorkUnitId: options.parentWorkUnitId
52722
+ });
52723
+ createWorkAttempt(harnessRoot, {
52724
+ attemptId,
52725
+ workUnitId,
52726
+ agentId: options.agentId
52727
+ });
52728
+ }
52309
52729
  const result = await this.runStage({
52310
52730
  repoPath: options.repoPath,
52311
52731
  kind: "launch",
52312
52732
  agentId: options.agentId,
52733
+ workUnitId,
52734
+ attemptId,
52313
52735
  capture: options.capture ?? false,
52314
52736
  launchFlags: {
52315
52737
  worktree: options.worktree,
52316
52738
  claude: options.claude,
52317
52739
  confirmReplace: options.confirmReplace,
52318
52740
  force: options.force,
52319
- resume: options.resume
52741
+ resume: options.resume,
52742
+ workUnitId,
52743
+ attemptId
52320
52744
  },
52321
52745
  trigger: "cli"
52322
52746
  });
52323
52747
  const envResult = toEnvironmentRunResult(result);
52324
52748
  if (envResult.code === 0) {
52325
- const harnessRoot = resolveHarnessRoot(options.repoPath);
52326
52749
  const session = readSlotRegistry(harnessRoot, options.agentId);
52327
52750
  if (session) {
52328
52751
  envResult.workDir = session.workDir;
52329
52752
  envResult.worktreePath = session.worktreePath;
52330
52753
  envResult.branch = session.branch;
52331
52754
  envResult.previewUrls = envResult.previewUrls ?? session.previewUrls;
52755
+ envResult.workUnitId = session.workUnitId;
52756
+ envResult.attemptId = session.attemptId;
52332
52757
  const sessionKey = buildSessionKey({
52333
52758
  branch: session.branch,
52334
52759
  agentId: options.agentId,
52335
52760
  suffix: session.suffix,
52336
52761
  createdAt: session.createdAt
52337
52762
  });
52338
- const envFile = path42.join(session.workDir, `.env.agent.${options.agentId}`);
52763
+ const envFile = path44.join(session.workDir, `.env.agent.${options.agentId}`);
52339
52764
  try {
52340
52765
  appendTelemetryEnvToFile(envFile, {
52341
52766
  sessionKey,
52342
52767
  agentId: options.agentId,
52343
- repoPath: path42.resolve(options.repoPath),
52768
+ repoPath: path44.resolve(options.repoPath),
52344
52769
  workDir: session.workDir,
52345
52770
  branch: session.branch,
52346
- suffix: session.suffix
52771
+ suffix: session.suffix,
52772
+ workUnitId: session.workUnitId,
52773
+ attemptId: session.attemptId
52347
52774
  });
52348
52775
  } catch {
52349
52776
  }
52777
+ if (session.workUnitId && session.attemptId) {
52778
+ createWorkAttempt(harnessRoot, {
52779
+ attemptId: session.attemptId,
52780
+ workUnitId: session.workUnitId,
52781
+ agentId: options.agentId,
52782
+ sessionKey,
52783
+ workDir: session.workDir,
52784
+ worktreePath: session.worktreePath,
52785
+ branch: session.branch,
52786
+ baseCommit: session.baseCommit,
52787
+ createdAt: session.createdAt
52788
+ });
52789
+ }
52350
52790
  }
52351
52791
  if (telemetryBanner) {
52352
52792
  envResult.stderr = `${telemetryBanner}${envResult.stderr ?? ""}`;
@@ -52377,7 +52817,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52377
52817
  const harnessRoot = resolveHarnessRoot(options.repoPath);
52378
52818
  const checkoutDir = resolveAgentWorkDir(harnessRoot, options.agentId) ?? harnessRoot;
52379
52819
  const runId = typeof result.data === "object" && result.data !== null && !Array.isArray(result.data) ? result.data.runId : void 0;
52380
- recordValidation({
52820
+ const validation2 = recordValidation({
52381
52821
  checkoutDir,
52382
52822
  harnessRoot,
52383
52823
  status: verification.status,
@@ -52385,7 +52825,22 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52385
52825
  runId,
52386
52826
  agentId: options.agentId
52387
52827
  });
52828
+ const session = readSlotRegistry(harnessRoot, options.agentId);
52829
+ if (session?.workUnitId && session.attemptId) {
52830
+ bindValidationToAttempt(harnessRoot, {
52831
+ workUnitId: session.workUnitId,
52832
+ attemptId: session.attemptId,
52833
+ validation: validation2
52834
+ });
52835
+ }
52388
52836
  await syncRepoWithControlAsync(options.repoPath);
52837
+ return {
52838
+ code: shell.code,
52839
+ stdout: shell.stdout,
52840
+ stderr: shell.stderr,
52841
+ verification,
52842
+ validation: validation2
52843
+ };
52389
52844
  } catch {
52390
52845
  }
52391
52846
  }
@@ -52423,6 +52878,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52423
52878
  };
52424
52879
  }
52425
52880
  let verification;
52881
+ let validation2;
52426
52882
  if (!options.skipVerify) {
52427
52883
  const verify = await this.runVerification({
52428
52884
  repoPath: options.repoPath,
@@ -52432,6 +52888,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52432
52888
  trigger: options.trigger
52433
52889
  });
52434
52890
  verification = verify.verification;
52891
+ validation2 = verify.validation;
52435
52892
  if (verify.code !== 0 || verification?.status !== "pass") {
52436
52893
  return {
52437
52894
  ...verify,
@@ -52439,6 +52896,24 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52439
52896
  };
52440
52897
  }
52441
52898
  }
52899
+ if (session.workUnitId && session.attemptId && !options.skipVerify && !validation2) {
52900
+ return {
52901
+ code: 1,
52902
+ stdout: "",
52903
+ stderr: "Full verification passed, but HAR could not record exact-tree validation proof. Session NOT completed.",
52904
+ verification
52905
+ };
52906
+ }
52907
+ if (session.workUnitId && session.attemptId && validation2) {
52908
+ decideWorkUnitOutcome(harnessRoot, session.workUnitId, {
52909
+ decision: "completed",
52910
+ decidedAt: (/* @__PURE__ */ new Date()).toISOString(),
52911
+ attemptId: session.attemptId,
52912
+ validationId: validation2.validationId,
52913
+ treeHash: validation2.treeHash
52914
+ });
52915
+ await syncRepoWithControlAsync(options.repoPath);
52916
+ }
52442
52917
  const teardown = await this.teardownEnvironment({
52443
52918
  repoPath: options.repoPath,
52444
52919
  agentId: options.agentId,
@@ -52522,9 +52997,9 @@ var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunSer
52522
52997
  var readline5 = __toESM(require("readline"));
52523
52998
 
52524
52999
  // src/core/hooks.ts
52525
- var fs40 = __toESM(require("fs"));
52526
- var os13 = __toESM(require("os"));
52527
- var path43 = __toESM(require("path"));
53000
+ var fs42 = __toESM(require("fs"));
53001
+ var os14 = __toESM(require("os"));
53002
+ var path45 = __toESM(require("path"));
52528
53003
  var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
52529
53004
  var MARKER_END = "# <<< har commit gate <<<";
52530
53005
  var PRE_COMMIT_BLOCK = [
@@ -52549,7 +53024,7 @@ function resolveCheckoutRoot(cwd) {
52549
53024
  function resolveHooksDir(checkoutDir) {
52550
53025
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
52551
53026
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
52552
- return path43.resolve(checkoutDir, hooksPath);
53027
+ return path45.resolve(checkoutDir, hooksPath);
52553
53028
  }
52554
53029
  function getConfiguredHooksPath(checkoutDir) {
52555
53030
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -52557,9 +53032,9 @@ function getConfiguredHooksPath(checkoutDir) {
52557
53032
  function defaultHarInvocation() {
52558
53033
  const entry = process.argv[1];
52559
53034
  if (entry && entry.endsWith(".js")) {
52560
- return `"${process.execPath}" "${path43.resolve(entry)}"`;
53035
+ return `"${process.execPath}" "${path45.resolve(entry)}"`;
52561
53036
  }
52562
- if (entry) return `"${path43.resolve(entry)}"`;
53037
+ if (entry) return `"${path45.resolve(entry)}"`;
52563
53038
  return "har";
52564
53039
  }
52565
53040
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -52580,40 +53055,40 @@ exit 0
52580
53055
  `;
52581
53056
  }
52582
53057
  function upsertMarkedBlock(filePath, block) {
52583
- if (!fs40.existsSync(filePath)) {
52584
- fs40.writeFileSync(filePath, `#!/bin/sh
53058
+ if (!fs42.existsSync(filePath)) {
53059
+ fs42.writeFileSync(filePath, `#!/bin/sh
52585
53060
  ${block}
52586
53061
  `, { mode: 493 });
52587
53062
  return "created";
52588
53063
  }
52589
- const content = fs40.readFileSync(filePath, "utf8");
53064
+ const content = fs42.readFileSync(filePath, "utf8");
52590
53065
  if (content.includes(MARKER_START)) {
52591
53066
  const pattern = new RegExp(
52592
53067
  `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
52593
53068
  );
52594
- fs40.writeFileSync(filePath, content.replace(pattern, block));
52595
- fs40.chmodSync(filePath, 493);
53069
+ fs42.writeFileSync(filePath, content.replace(pattern, block));
53070
+ fs42.chmodSync(filePath, 493);
52596
53071
  return "updated";
52597
53072
  }
52598
53073
  const suffix = content.endsWith("\n") ? "" : "\n";
52599
- fs40.writeFileSync(filePath, `${content}${suffix}
53074
+ fs42.writeFileSync(filePath, `${content}${suffix}
52600
53075
  ${block}
52601
53076
  `);
52602
- fs40.chmodSync(filePath, 493);
53077
+ fs42.chmodSync(filePath, 493);
52603
53078
  return "appended";
52604
53079
  }
52605
53080
  function removeMarkedBlock(filePath) {
52606
- if (!fs40.existsSync(filePath)) return false;
52607
- const content = fs40.readFileSync(filePath, "utf8");
53081
+ if (!fs42.existsSync(filePath)) return false;
53082
+ const content = fs42.readFileSync(filePath, "utf8");
52608
53083
  if (!content.includes(MARKER_START)) return false;
52609
53084
  const pattern = new RegExp(
52610
53085
  `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
52611
53086
  );
52612
53087
  const stripped = content.replace(pattern, "\n");
52613
53088
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
52614
- fs40.rmSync(filePath);
53089
+ fs42.rmSync(filePath);
52615
53090
  } else {
52616
- fs40.writeFileSync(filePath, stripped);
53091
+ fs42.writeFileSync(filePath, stripped);
52617
53092
  }
52618
53093
  return true;
52619
53094
  }
@@ -52635,20 +53110,20 @@ Or re-run with --force to write into that directory anyway.`
52635
53110
  );
52636
53111
  }
52637
53112
  const hooksDir = resolveHooksDir(checkout);
52638
- fs40.mkdirSync(hooksDir, { recursive: true });
53113
+ fs42.mkdirSync(hooksDir, { recursive: true });
52639
53114
  const invocation = options.harInvocation ?? defaultHarInvocation();
52640
- fs40.writeFileSync(
52641
- path43.join(hooksDir, "har-pre-commit"),
53115
+ fs42.writeFileSync(
53116
+ path45.join(hooksDir, "har-pre-commit"),
52642
53117
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
52643
53118
  { mode: 493 }
52644
53119
  );
52645
- fs40.writeFileSync(
52646
- path43.join(hooksDir, "har-post-commit"),
53120
+ fs42.writeFileSync(
53121
+ path45.join(hooksDir, "har-post-commit"),
52647
53122
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
52648
53123
  { mode: 493 }
52649
53124
  );
52650
- const preCommit = upsertMarkedBlock(path43.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
52651
- const postCommit = upsertMarkedBlock(path43.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
53125
+ const preCommit = upsertMarkedBlock(path45.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
53126
+ const postCommit = upsertMarkedBlock(path45.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
52652
53127
  ensureValidationsIgnored(checkout);
52653
53128
  return { hooksDir, preCommit, postCommit };
52654
53129
  }
@@ -52657,12 +53132,12 @@ function uninstallHooks(repoPath) {
52657
53132
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
52658
53133
  const hooksDir = resolveHooksDir(checkout);
52659
53134
  let removed = false;
52660
- removed = removeMarkedBlock(path43.join(hooksDir, "pre-commit")) || removed;
52661
- removed = removeMarkedBlock(path43.join(hooksDir, "post-commit")) || removed;
53135
+ removed = removeMarkedBlock(path45.join(hooksDir, "pre-commit")) || removed;
53136
+ removed = removeMarkedBlock(path45.join(hooksDir, "post-commit")) || removed;
52662
53137
  for (const file of ["har-pre-commit", "har-post-commit"]) {
52663
- const full = path43.join(hooksDir, file);
52664
- if (fs40.existsSync(full)) {
52665
- fs40.rmSync(full);
53138
+ const full = path45.join(hooksDir, file);
53139
+ if (fs42.existsSync(full)) {
53140
+ fs42.rmSync(full);
52666
53141
  removed = true;
52667
53142
  }
52668
53143
  }
@@ -52681,10 +53156,10 @@ function isAgentWorktree(checkoutDir) {
52681
53156
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
52682
53157
  return true;
52683
53158
  }
52684
- const worktreesRoot = path43.join(os13.homedir(), "worktrees");
52685
- const resolved = path43.resolve(checkoutDir);
52686
- const name = path43.basename(resolved);
52687
- return resolved.startsWith(`${worktreesRoot}${path43.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
53159
+ const worktreesRoot = path45.join(os14.homedir(), "worktrees");
53160
+ const resolved = path45.resolve(checkoutDir);
53161
+ const name = path45.basename(resolved);
53162
+ return resolved.startsWith(`${worktreesRoot}${path45.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
52688
53163
  }
52689
53164
  function resolveEffectiveMode(checkoutDir, gate) {
52690
53165
  if (!gate.enabled) return "off";
@@ -52697,15 +53172,15 @@ function getHooksStatus(repoPath) {
52697
53172
  const hooksDir = resolveHooksDir(checkout);
52698
53173
  const gate = getCommitGateConfig(checkout);
52699
53174
  const hasBlock = (name) => {
52700
- const file = path43.join(hooksDir, name);
52701
- return fs40.existsSync(file) && fs40.readFileSync(file, "utf8").includes(MARKER_START);
53175
+ const file = path45.join(hooksDir, name);
53176
+ return fs42.existsSync(file) && fs42.readFileSync(file, "utf8").includes(MARKER_START);
52702
53177
  };
52703
53178
  return {
52704
53179
  checkout,
52705
53180
  hooksDir,
52706
53181
  configuredHooksPath: getConfiguredHooksPath(checkout),
52707
- preCommitInstalled: hasBlock("pre-commit") && fs40.existsSync(path43.join(hooksDir, "har-pre-commit")),
52708
- postCommitInstalled: hasBlock("post-commit") && fs40.existsSync(path43.join(hooksDir, "har-post-commit")),
53182
+ preCommitInstalled: hasBlock("pre-commit") && fs42.existsSync(path45.join(hooksDir, "har-pre-commit")),
53183
+ postCommitInstalled: hasBlock("post-commit") && fs42.existsSync(path45.join(hooksDir, "har-post-commit")),
52709
53184
  gate,
52710
53185
  effectiveMode: resolveEffectiveMode(checkout, gate)
52711
53186
  };
@@ -52716,7 +53191,7 @@ function checkCommitGate(cwd) {
52716
53191
  }
52717
53192
  const checkout = resolveCheckoutRoot(cwd);
52718
53193
  if (!checkout) return { exitCode: 0, messages: [] };
52719
- if (!fs40.existsSync(path43.join(checkout, ".har", "stages.json"))) {
53194
+ if (!fs42.existsSync(path45.join(checkout, ".har", "stages.json"))) {
52720
53195
  return { exitCode: 0, messages: [] };
52721
53196
  }
52722
53197
  const gate = getCommitGateConfig(checkout);
@@ -52789,12 +53264,12 @@ async function recordCommitAssociation(cwd) {
52789
53264
  // src/core/commit-gate-onboarding.ts
52790
53265
  function askYesNo4(question) {
52791
53266
  const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
52792
- return new Promise((resolve37) => {
53267
+ return new Promise((resolve38) => {
52793
53268
  process.stderr.write(`${question} `);
52794
53269
  rl.once("line", (answer) => {
52795
53270
  rl.close();
52796
53271
  const trimmed = answer.trim();
52797
- resolve37(trimmed === "" || /^y(es)?$/i.test(trimmed));
53272
+ resolve38(trimmed === "" || /^y(es)?$/i.test(trimmed));
52798
53273
  });
52799
53274
  });
52800
53275
  }
@@ -52836,20 +53311,20 @@ async function handleCommitGateOnboarding(options) {
52836
53311
  }
52837
53312
 
52838
53313
  // src/core/onboarding-preferences.ts
52839
- var fs41 = __toESM(require("fs"));
52840
- var os14 = __toESM(require("os"));
52841
- var path44 = __toESM(require("path"));
53314
+ var fs43 = __toESM(require("fs"));
53315
+ var os15 = __toESM(require("os"));
53316
+ var path46 = __toESM(require("path"));
52842
53317
  function getOnboardingPreferencesPath() {
52843
53318
  if (process.env.HAR_PREFERENCES_PATH) {
52844
- return path44.resolve(process.env.HAR_PREFERENCES_PATH);
53319
+ return path46.resolve(process.env.HAR_PREFERENCES_PATH);
52845
53320
  }
52846
- return path44.join(os14.homedir(), ".har", "preferences.json");
53321
+ return path46.join(os15.homedir(), ".har", "preferences.json");
52847
53322
  }
52848
53323
  function readOnboardingPreferences() {
52849
53324
  const preferencePath = getOnboardingPreferencesPath();
52850
53325
  try {
52851
- if (!fs41.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
52852
- return OnboardingPreferencesSchema.parse(JSON.parse(fs41.readFileSync(preferencePath, "utf8")));
53326
+ if (!fs43.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
53327
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs43.readFileSync(preferencePath, "utf8")));
52853
53328
  } catch {
52854
53329
  return OnboardingPreferencesSchema.parse({});
52855
53330
  }
@@ -52874,8 +53349,8 @@ function writeOnboardingPreferences(overrides) {
52874
53349
  };
52875
53350
  const parsed = OnboardingPreferencesSchema.parse(preference);
52876
53351
  const preferencePath = getOnboardingPreferencesPath();
52877
- fs41.mkdirSync(path44.dirname(preferencePath), { recursive: true });
52878
- fs41.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
53352
+ fs43.mkdirSync(path46.dirname(preferencePath), { recursive: true });
53353
+ fs43.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
52879
53354
  `);
52880
53355
  return parsed;
52881
53356
  }
@@ -53070,6 +53545,15 @@ var envCommand = {
53070
53545
  type: "boolean",
53071
53546
  default: false,
53072
53547
  describe: LAUNCH_RESUME_DESCRIBE
53548
+ }).option("work-id", {
53549
+ type: "string",
53550
+ describe: "Bind this session to a durable external work identifier"
53551
+ }).option("work-source", {
53552
+ type: "string",
53553
+ describe: "Optional provider/source name (for example github or linear)"
53554
+ }).option("work-url", { type: "string", describe: "Optional source URL for the work" }).option("work-title", { type: "string", describe: "Optional human-readable title" }).option("parent-work-id", {
53555
+ type: "string",
53556
+ describe: "Optional parent work unit identifier"
53073
53557
  }).epilog(LAUNCH_EPILOG),
53074
53558
  handleLaunch
53075
53559
  ).command(
@@ -53146,7 +53630,7 @@ var envCommand = {
53146
53630
  }
53147
53631
  };
53148
53632
  async function handleInit(argv) {
53149
- const repoPath = path45.resolve(argv.repo);
53633
+ const repoPath = path47.resolve(argv.repo);
53150
53634
  const onboarding = resolveOnboardingOptions(argv);
53151
53635
  header("har env init");
53152
53636
  info(`Repository: ${repoPath}`);
@@ -53210,7 +53694,7 @@ async function handleInit(argv) {
53210
53694
  }
53211
53695
  }
53212
53696
  async function handleMaintain(argv) {
53213
- const repoPath = path45.resolve(argv.repo);
53697
+ const repoPath = path47.resolve(argv.repo);
53214
53698
  const onboarding = resolveOnboardingOptions(argv);
53215
53699
  header("har env maintain");
53216
53700
  info(`Repository: ${repoPath}`);
@@ -53325,7 +53809,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
53325
53809
  if (autoYes) {
53326
53810
  const proposal = readAgentMdProposal(repoPath);
53327
53811
  if (proposal) {
53328
- writeFileSafe(path45.join(repoPath, "AGENT.md"), proposal.content);
53812
+ writeFileSafe(path47.join(repoPath, "AGENT.md"), proposal.content);
53329
53813
  clearAgentMdProposal(repoPath);
53330
53814
  info("Applied AGENT.md proposal (--yes)");
53331
53815
  }
@@ -53334,7 +53818,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
53334
53818
  await promptApplyAgentMdProposal(repoPath);
53335
53819
  }
53336
53820
  async function handleAddStage(argv) {
53337
- const repoPath = path45.resolve(argv.repo);
53821
+ const repoPath = path47.resolve(argv.repo);
53338
53822
  const available = listStageTemplateIds();
53339
53823
  if (argv.list) {
53340
53824
  for (const id of available) {
@@ -53411,7 +53895,7 @@ async function handleAddStage(argv) {
53411
53895
  }
53412
53896
  }
53413
53897
  async function handlePreflight(argv) {
53414
- const repo = path45.resolve(argv.repo);
53898
+ const repo = path47.resolve(argv.repo);
53415
53899
  const agentId = validateAgentId(argv.id, repo);
53416
53900
  const result = await preflightEnvironment({
53417
53901
  repoPath: repo,
@@ -53429,7 +53913,7 @@ async function handlePreflight(argv) {
53429
53913
  process.exit(result.code);
53430
53914
  }
53431
53915
  async function handleLaunch(argv) {
53432
- const repo = path45.resolve(argv.repo);
53916
+ const repo = path47.resolve(argv.repo);
53433
53917
  const agentId = validateAgentId(argv.id, repo);
53434
53918
  let confirmReplace = argv.replace;
53435
53919
  let force = argv.force;
@@ -53441,8 +53925,8 @@ async function handleLaunch(argv) {
53441
53925
  console.error(guard.reason ?? "");
53442
53926
  const readline9 = await import("readline");
53443
53927
  const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
53444
- const answer = await new Promise((resolve37) => {
53445
- rl.question("Replace this slot? [y/N] ", resolve37);
53928
+ const answer = await new Promise((resolve38) => {
53929
+ rl.question("Replace this slot? [y/N] ", resolve38);
53446
53930
  });
53447
53931
  rl.close();
53448
53932
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -53458,8 +53942,8 @@ async function handleLaunch(argv) {
53458
53942
  warn("Worktree has uncommitted changes.");
53459
53943
  const readline9 = await import("readline");
53460
53944
  const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
53461
- const answer = await new Promise((resolve37) => {
53462
- rl.question("Discard uncommitted changes? [y/N] ", resolve37);
53945
+ const answer = await new Promise((resolve38) => {
53946
+ rl.question("Discard uncommitted changes? [y/N] ", resolve38);
53463
53947
  });
53464
53948
  rl.close();
53465
53949
  if (!/^[Yy]$/.test(answer.trim())) {
@@ -53481,6 +53965,11 @@ async function handleLaunch(argv) {
53481
53965
  confirmReplace,
53482
53966
  force,
53483
53967
  resume: argv.resume,
53968
+ workUnitId: argv.workId,
53969
+ source: argv.workSource,
53970
+ sourceUrl: argv.workUrl,
53971
+ title: argv.workTitle,
53972
+ parentWorkUnitId: argv.parentWorkId,
53484
53973
  capture: false
53485
53974
  });
53486
53975
  if (result.blocked) {
@@ -53509,11 +53998,16 @@ async function handleRecover(argv) {
53509
53998
  claude: false,
53510
53999
  replace: false,
53511
54000
  force: false,
53512
- resume: true
54001
+ resume: true,
54002
+ workId: void 0,
54003
+ workSource: void 0,
54004
+ workUrl: void 0,
54005
+ workTitle: void 0,
54006
+ parentWorkId: void 0
53513
54007
  });
53514
54008
  }
53515
54009
  async function handleVerify(argv) {
53516
- const repo = path45.resolve(argv.repo);
54010
+ const repo = path47.resolve(argv.repo);
53517
54011
  const agentId = validateAgentId(argv.id, repo);
53518
54012
  const result = await runVerification({
53519
54013
  repoPath: repo,
@@ -53525,7 +54019,7 @@ async function handleVerify(argv) {
53525
54019
  process.exit(result.code);
53526
54020
  }
53527
54021
  async function handleTeardown(argv) {
53528
- const repo = path45.resolve(argv.repo);
54022
+ const repo = path47.resolve(argv.repo);
53529
54023
  const agentId = validateAgentId(argv.id, repo);
53530
54024
  const result = await teardownEnvironment({
53531
54025
  repoPath: repo,
@@ -53536,7 +54030,7 @@ async function handleTeardown(argv) {
53536
54030
  process.exit(result.code);
53537
54031
  }
53538
54032
  async function handleComplete(argv) {
53539
- const repo = path45.resolve(argv.repo);
54033
+ const repo = path47.resolve(argv.repo);
53540
54034
  const agentId = validateAgentId(argv.id, repo);
53541
54035
  const result = await completeEnvironment({
53542
54036
  repoPath: repo,
@@ -53557,7 +54051,7 @@ async function handleComplete(argv) {
53557
54051
  process.exit(result.code);
53558
54052
  }
53559
54053
  async function handleStatus(argv) {
53560
- const repoPath = path45.resolve(argv.repo);
54054
+ const repoPath = path47.resolve(argv.repo);
53561
54055
  if (argv.json) {
53562
54056
  const status = collectEnvironmentStatus(repoPath);
53563
54057
  const output = EnvironmentStatusSchema.parse(status);
@@ -53570,7 +54064,7 @@ async function handleStatus(argv) {
53570
54064
  });
53571
54065
  }
53572
54066
  async function handleRunsList(argv) {
53573
- const repoPath = path45.resolve(argv.repo);
54067
+ const repoPath = path47.resolve(argv.repo);
53574
54068
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
53575
54069
  if (argv.json) {
53576
54070
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -53587,7 +54081,7 @@ async function handleRunsList(argv) {
53587
54081
  }
53588
54082
  }
53589
54083
  async function handleRunsGet(argv) {
53590
- const run2 = getRun(path45.resolve(argv.repo), argv.runId);
54084
+ const run2 = getRun(path47.resolve(argv.repo), argv.runId);
53591
54085
  if (!run2) {
53592
54086
  error(`Run not found: ${argv.runId}`);
53593
54087
  process.exit(1);
@@ -53666,20 +54160,87 @@ function printNextSteps(auto2) {
53666
54160
  }
53667
54161
 
53668
54162
  // src/cli/commands/control.ts
53669
- var path47 = __toESM(require("path"));
54163
+ var path49 = __toESM(require("path"));
53670
54164
  init_control_config();
54165
+ init_portal_credentials();
54166
+
54167
+ // src/core/portal-login.ts
54168
+ var http = __toESM(require("http"));
54169
+ var import_crypto = require("crypto");
54170
+ var import_child_process10 = require("child_process");
54171
+ var CALLBACK_PATH = "/callback";
54172
+ var LOGIN_TIMEOUT_MS = 3 * 6e4;
54173
+ function openBrowser(url) {
54174
+ const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
54175
+ try {
54176
+ const child = (0, import_child_process10.spawn)(cmd, args, { stdio: "ignore", detached: true });
54177
+ child.on("error", () => {
54178
+ });
54179
+ child.unref();
54180
+ } catch {
54181
+ }
54182
+ }
54183
+ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
54184
+ const state = (0, import_crypto.randomUUID)();
54185
+ return new Promise((resolve38, reject) => {
54186
+ let timer;
54187
+ const server = http.createServer((req, res) => {
54188
+ const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
54189
+ if (requestUrl.pathname !== CALLBACK_PATH) {
54190
+ res.writeHead(404);
54191
+ res.end("Not found");
54192
+ return;
54193
+ }
54194
+ const token = requestUrl.searchParams.get("token");
54195
+ const returnedState = requestUrl.searchParams.get("state");
54196
+ const workspace = requestUrl.searchParams.get("workspace") ?? void 0;
54197
+ if (returnedState !== state || !token) {
54198
+ res.writeHead(400, { "Content-Type": "text/html" });
54199
+ res.end("<h1>Login failed</h1><p>You can close this tab and try again.</p>");
54200
+ cleanup();
54201
+ reject(new Error("state mismatch or missing token"));
54202
+ return;
54203
+ }
54204
+ res.writeHead(200, { "Content-Type": "text/html" });
54205
+ res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
54206
+ cleanup();
54207
+ resolve38({ portalUrl, token, workspace, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
54208
+ });
54209
+ const cleanup = () => {
54210
+ clearTimeout(timer);
54211
+ server.close();
54212
+ };
54213
+ server.on("error", (err) => {
54214
+ cleanup();
54215
+ reject(err);
54216
+ });
54217
+ server.listen(0, "127.0.0.1", () => {
54218
+ const { port } = server.address();
54219
+ const callback = `http://127.0.0.1:${port}${CALLBACK_PATH}`;
54220
+ const loginUrl = `${portalUrl}/cli/login?callback=${encodeURIComponent(callback)}&state=${state}`;
54221
+ openUrl(loginUrl);
54222
+ process.stderr.write(`Opening ${loginUrl}
54223
+ If your browser did not open, paste that URL.
54224
+ `);
54225
+ timer = setTimeout(() => {
54226
+ cleanup();
54227
+ reject(new Error("timed out"));
54228
+ }, LOGIN_TIMEOUT_MS);
54229
+ });
54230
+ });
54231
+ }
53671
54232
 
53672
54233
  // src/core/control-unregister.ts
53673
- var fs42 = __toESM(require("fs"));
53674
- var path46 = __toESM(require("path"));
54234
+ var fs44 = __toESM(require("fs"));
54235
+ var path48 = __toESM(require("path"));
53675
54236
  init_control_config();
53676
54237
  function listUnregisterWorktreeCandidates(repoPath) {
53677
54238
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
53678
54239
  const byPath = /* @__PURE__ */ new Map();
53679
54240
  const add = (partial2) => {
53680
- const resolved = path46.resolve(partial2.worktreePath);
54241
+ const resolved = path48.resolve(partial2.worktreePath);
53681
54242
  if (!resolved || resolved === harnessRoot) return;
53682
- const exists = partial2.exists ?? fs42.existsSync(resolved);
54243
+ const exists = partial2.exists ?? fs44.existsSync(resolved);
53683
54244
  const prev = byPath.get(resolved);
53684
54245
  if (prev) {
53685
54246
  byPath.set(resolved, {
@@ -53730,8 +54291,8 @@ async function askYesNo5(question) {
53730
54291
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
53731
54292
  const readline9 = await import("readline");
53732
54293
  const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
53733
- const answer = await new Promise((resolve37) => {
53734
- rl.question(question, resolve37);
54294
+ const answer = await new Promise((resolve38) => {
54295
+ rl.question(question, resolve38);
53735
54296
  });
53736
54297
  rl.close();
53737
54298
  return /^[Yy]$/.test(answer.trim());
@@ -53793,28 +54354,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
53793
54354
  trigger: "cli"
53794
54355
  });
53795
54356
  if (result.code !== 0) {
53796
- if (fs42.existsSync(candidate.worktreePath)) {
53797
- fs42.rmSync(candidate.worktreePath, { recursive: true, force: true });
54357
+ if (fs44.existsSync(candidate.worktreePath)) {
54358
+ fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
53798
54359
  }
53799
54360
  }
53800
54361
  outcomes.push({
53801
54362
  path: candidate.worktreePath,
53802
54363
  agentId: candidate.agentId,
53803
- deleted: !fs42.existsSync(candidate.worktreePath),
53804
- error: result.code !== 0 && fs42.existsSync(candidate.worktreePath) ? result.stderr : void 0
54364
+ deleted: !fs44.existsSync(candidate.worktreePath),
54365
+ error: result.code !== 0 && fs44.existsSync(candidate.worktreePath) ? result.stderr : void 0
53805
54366
  });
53806
54367
  } catch (err) {
53807
54368
  const message = err instanceof Error ? err.message : String(err);
53808
54369
  try {
53809
- if (fs42.existsSync(candidate.worktreePath)) {
53810
- fs42.rmSync(candidate.worktreePath, { recursive: true, force: true });
54370
+ if (fs44.existsSync(candidate.worktreePath)) {
54371
+ fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
53811
54372
  }
53812
54373
  } catch {
53813
54374
  }
53814
54375
  outcomes.push({
53815
54376
  path: candidate.worktreePath,
53816
54377
  agentId: candidate.agentId,
53817
- deleted: !fs42.existsSync(candidate.worktreePath),
54378
+ deleted: !fs44.existsSync(candidate.worktreePath),
53818
54379
  error: message
53819
54380
  });
53820
54381
  }
@@ -53930,8 +54491,11 @@ var controlCommand = {
53930
54491
  handleWatch
53931
54492
  ).command(
53932
54493
  "login",
53933
- "Configure HAR Cloud API credentials (hosted sync)",
53934
- (y2) => y2.option("api-key", { type: "string", describe: "HAR Cloud API key" }),
54494
+ "Log in to a har-portal (browser SSO) and store an ingest token",
54495
+ (y2) => y2.option("portal", { type: "string", describe: "Portal base URL (or set HAR_PORTAL_URL)" }).option("api-key", {
54496
+ type: "string",
54497
+ describe: "Store this ingest token directly instead of browser login"
54498
+ }),
53935
54499
  handleLogin
53936
54500
  ).demandCommand(
53937
54501
  1,
@@ -53996,7 +54560,7 @@ async function handleDown() {
53996
54560
  process.exit(code);
53997
54561
  }
53998
54562
  async function handleRegister(argv) {
53999
- const repoPath = path47.resolve(argv.repo);
54563
+ const repoPath = path49.resolve(argv.repo);
54000
54564
  header("har control register");
54001
54565
  info(`Repository: ${repoPath}`);
54002
54566
  try {
@@ -54020,7 +54584,7 @@ async function handleRegister(argv) {
54020
54584
  }
54021
54585
  }
54022
54586
  async function handleUnregister(argv) {
54023
- const repoPath = path47.resolve(argv.repo);
54587
+ const repoPath = path49.resolve(argv.repo);
54024
54588
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
54025
54589
  try {
54026
54590
  let deleteWorktrees = argv.deleteWorktrees;
@@ -54089,7 +54653,7 @@ async function handleUnregister(argv) {
54089
54653
  }
54090
54654
  }
54091
54655
  async function handleSync(argv) {
54092
- const repoPath = path47.resolve(argv.repo);
54656
+ const repoPath = path49.resolve(argv.repo);
54093
54657
  try {
54094
54658
  await syncRepoWithControl({
54095
54659
  repoPath,
@@ -54128,7 +54692,7 @@ async function handleWatch(argv) {
54128
54692
  };
54129
54693
  const tick = async () => {
54130
54694
  if (argv.repo) {
54131
- await syncOne(path47.resolve(argv.repo));
54695
+ await syncOne(path49.resolve(argv.repo));
54132
54696
  return;
54133
54697
  }
54134
54698
  try {
@@ -54149,21 +54713,40 @@ async function handleWatch(argv) {
54149
54713
  }
54150
54714
  async function handleLogin(argv) {
54151
54715
  header("har control login");
54152
- if (!argv.apiKey) {
54153
- error("Provide --api-key (HAR Cloud API key)");
54716
+ const portalUrl = (argv.portal ?? process.env.HAR_PORTAL_URL ?? "").replace(/\/+$/, "");
54717
+ if (!portalUrl) {
54718
+ error("Provide --portal <url> (or set HAR_PORTAL_URL)");
54719
+ process.exit(1);
54720
+ }
54721
+ if (argv.apiKey) {
54722
+ writePortalCredentials({
54723
+ portalUrl,
54724
+ token: argv.apiKey,
54725
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
54726
+ });
54727
+ success(`Saved ingest token for ${portalUrl}`);
54728
+ info("Sync: har control sync");
54729
+ return;
54730
+ }
54731
+ try {
54732
+ const creds = await loginViaBrowser(portalUrl);
54733
+ writePortalCredentials(creds);
54734
+ success(
54735
+ `Logged in to ${portalUrl}${creds.workspace ? ` (workspace: ${creds.workspace})` : ""}`
54736
+ );
54737
+ info("Sync: har control sync");
54738
+ } catch (err) {
54739
+ error(`Login failed: ${err.message}`);
54154
54740
  process.exit(1);
54155
54741
  }
54156
- process.env.HAR_CLOUD_API_KEY = argv.apiKey;
54157
- success("HAR_CLOUD_API_KEY set for this process. Export it in your shell for persistence.");
54158
- info("Sync to cloud: har control sync --cloud");
54159
54742
  }
54160
54743
 
54161
54744
  // src/cli/commands/hooks.ts
54162
- var path49 = __toESM(require("path"));
54745
+ var path51 = __toESM(require("path"));
54163
54746
 
54164
54747
  // src/core/claude-hooks.ts
54165
- var fs43 = __toESM(require("fs"));
54166
- var path48 = __toESM(require("path"));
54748
+ var fs45 = __toESM(require("fs"));
54749
+ var path50 = __toESM(require("path"));
54167
54750
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
54168
54751
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
54169
54752
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -54174,8 +54757,8 @@ function isHarGuardEntry(entry) {
54174
54757
  );
54175
54758
  }
54176
54759
  function readSettings(settingsPath) {
54177
- if (!fs43.existsSync(settingsPath)) return {};
54178
- const raw = fs43.readFileSync(settingsPath, "utf8").trim();
54760
+ if (!fs45.existsSync(settingsPath)) return {};
54761
+ const raw = fs45.readFileSync(settingsPath, "utf8").trim();
54179
54762
  if (raw === "") return {};
54180
54763
  const parsed = JSON.parse(raw);
54181
54764
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -54184,19 +54767,19 @@ function readSettings(settingsPath) {
54184
54767
  return parsed;
54185
54768
  }
54186
54769
  function writeSettings(settingsPath, settings) {
54187
- fs43.mkdirSync(path48.dirname(settingsPath), { recursive: true });
54188
- fs43.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
54770
+ fs45.mkdirSync(path50.dirname(settingsPath), { recursive: true });
54771
+ fs45.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
54189
54772
  }
54190
54773
  function installClaudeGuard(repoPath) {
54191
54774
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
54192
54775
  if (!templatePath) {
54193
54776
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
54194
54777
  }
54195
- const guardScript = path48.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54196
- fs43.mkdirSync(path48.dirname(guardScript), { recursive: true });
54197
- fs43.copyFileSync(templatePath, guardScript);
54198
- fs43.chmodSync(guardScript, 493);
54199
- const settingsPath = path48.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54778
+ const guardScript = path50.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54779
+ fs45.mkdirSync(path50.dirname(guardScript), { recursive: true });
54780
+ fs45.copyFileSync(templatePath, guardScript);
54781
+ fs45.chmodSync(guardScript, 493);
54782
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54200
54783
  const settings = readSettings(settingsPath);
54201
54784
  const hooks = settings.hooks ?? {};
54202
54785
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -54210,15 +54793,15 @@ function installClaudeGuard(repoPath) {
54210
54793
  }
54211
54794
  function uninstallClaudeGuard(repoPath) {
54212
54795
  let removed = false;
54213
- const guardScript = path48.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54214
- if (fs43.existsSync(guardScript)) {
54215
- fs43.rmSync(guardScript);
54796
+ const guardScript = path50.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54797
+ if (fs45.existsSync(guardScript)) {
54798
+ fs45.rmSync(guardScript);
54216
54799
  removed = true;
54217
- const parent = path48.dirname(guardScript);
54218
- if (fs43.existsSync(parent) && fs43.readdirSync(parent).length === 0) fs43.rmdirSync(parent);
54800
+ const parent = path50.dirname(guardScript);
54801
+ if (fs45.existsSync(parent) && fs45.readdirSync(parent).length === 0) fs45.rmdirSync(parent);
54219
54802
  }
54220
- const settingsPath = path48.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54221
- if (fs43.existsSync(settingsPath)) {
54803
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54804
+ if (fs45.existsSync(settingsPath)) {
54222
54805
  const settings = readSettings(settingsPath);
54223
54806
  const preToolUse = settings.hooks?.PreToolUse;
54224
54807
  if (preToolUse) {
@@ -54243,8 +54826,8 @@ function uninstallClaudeGuard(repoPath) {
54243
54826
  return { removed };
54244
54827
  }
54245
54828
  function claudeGuardInstalled(repoPath) {
54246
- const settingsPath = path48.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54247
- if (!fs43.existsSync(settingsPath)) return false;
54829
+ const settingsPath = path50.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54830
+ if (!fs45.existsSync(settingsPath)) return false;
54248
54831
  try {
54249
54832
  const settings = readSettings(settingsPath);
54250
54833
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -54260,7 +54843,7 @@ function repoOption(y2) {
54260
54843
  function handleInstall2(argv) {
54261
54844
  try {
54262
54845
  if (argv.claude) {
54263
- const result2 = installClaudeGuard(path49.resolve(argv.repo));
54846
+ const result2 = installClaudeGuard(path51.resolve(argv.repo));
54264
54847
  success("Claude Code worktree guard installed.");
54265
54848
  info(`Guard script: ${result2.guardScript}`);
54266
54849
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -54268,7 +54851,7 @@ function handleInstall2(argv) {
54268
54851
  info("Commit both files so the guard travels with the repo.");
54269
54852
  return;
54270
54853
  }
54271
- const result = installHooks({ repoPath: path49.resolve(argv.repo), force: argv.force });
54854
+ const result = installHooks({ repoPath: path51.resolve(argv.repo), force: argv.force });
54272
54855
  success(`Commit gate installed in ${result.hooksDir}`);
54273
54856
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
54274
54857
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -54281,7 +54864,7 @@ function handleInstall2(argv) {
54281
54864
  function handleUninstall(argv) {
54282
54865
  try {
54283
54866
  if (argv.claude) {
54284
- const result2 = uninstallClaudeGuard(path49.resolve(argv.repo));
54867
+ const result2 = uninstallClaudeGuard(path51.resolve(argv.repo));
54285
54868
  if (result2.removed) {
54286
54869
  success("Claude Code worktree guard removed.");
54287
54870
  } else {
@@ -54289,7 +54872,7 @@ function handleUninstall(argv) {
54289
54872
  }
54290
54873
  return;
54291
54874
  }
54292
- const result = uninstallHooks(path49.resolve(argv.repo));
54875
+ const result = uninstallHooks(path51.resolve(argv.repo));
54293
54876
  if (result.removed) {
54294
54877
  success(`Commit gate removed from ${result.hooksDir}`);
54295
54878
  } else {
@@ -54302,7 +54885,7 @@ function handleUninstall(argv) {
54302
54885
  }
54303
54886
  function handleStatus2(argv) {
54304
54887
  try {
54305
- const status = getHooksStatus(path49.resolve(argv.repo));
54888
+ const status = getHooksStatus(path51.resolve(argv.repo));
54306
54889
  if (argv.json) {
54307
54890
  process.stdout.write(`${JSON.stringify(status, null, 2)}
54308
54891
  `);
@@ -54320,7 +54903,7 @@ function handleStatus2(argv) {
54320
54903
  );
54321
54904
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
54322
54905
  info(
54323
- `Claude guard: ${claudeGuardInstalled(path49.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
54906
+ `Claude guard: ${claudeGuardInstalled(path51.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
54324
54907
  );
54325
54908
  } catch (err) {
54326
54909
  error(err instanceof Error ? err.message : String(err));
@@ -54581,10 +55164,10 @@ function assignProp(target, prop, value) {
54581
55164
  configurable: true
54582
55165
  });
54583
55166
  }
54584
- function getElementAtPath(obj, path52) {
54585
- if (!path52)
55167
+ function getElementAtPath(obj, path54) {
55168
+ if (!path54)
54586
55169
  return obj;
54587
- return path52.reduce((acc, key) => acc?.[key], obj);
55170
+ return path54.reduce((acc, key) => acc?.[key], obj);
54588
55171
  }
54589
55172
  function promiseAllObject(promisesObj) {
54590
55173
  const keys = Object.keys(promisesObj);
@@ -54904,11 +55487,11 @@ function aborted(x2, startIndex = 0) {
54904
55487
  }
54905
55488
  return false;
54906
55489
  }
54907
- function prefixIssues(path52, issues) {
55490
+ function prefixIssues(path54, issues) {
54908
55491
  return issues.map((iss) => {
54909
55492
  var _a3;
54910
55493
  (_a3 = iss).path ?? (_a3.path = []);
54911
- iss.path.unshift(path52);
55494
+ iss.path.unshift(path54);
54912
55495
  return iss;
54913
55496
  });
54914
55497
  }
@@ -60231,7 +60814,7 @@ var Protocol = class {
60231
60814
  return;
60232
60815
  }
60233
60816
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
60234
- await new Promise((resolve37) => setTimeout(resolve37, pollInterval));
60817
+ await new Promise((resolve38) => setTimeout(resolve38, pollInterval));
60235
60818
  options?.signal?.throwIfAborted();
60236
60819
  }
60237
60820
  } catch (error3) {
@@ -60248,7 +60831,7 @@ var Protocol = class {
60248
60831
  */
60249
60832
  request(request, resultSchema, options) {
60250
60833
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
60251
- return new Promise((resolve37, reject) => {
60834
+ return new Promise((resolve38, reject) => {
60252
60835
  const earlyReject = (error3) => {
60253
60836
  reject(error3);
60254
60837
  };
@@ -60326,7 +60909,7 @@ var Protocol = class {
60326
60909
  if (!parseResult.success) {
60327
60910
  reject(parseResult.error);
60328
60911
  } else {
60329
- resolve37(parseResult.data);
60912
+ resolve38(parseResult.data);
60330
60913
  }
60331
60914
  } catch (error3) {
60332
60915
  reject(error3);
@@ -60587,12 +61170,12 @@ var Protocol = class {
60587
61170
  }
60588
61171
  } catch {
60589
61172
  }
60590
- return new Promise((resolve37, reject) => {
61173
+ return new Promise((resolve38, reject) => {
60591
61174
  if (signal.aborted) {
60592
61175
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
60593
61176
  return;
60594
61177
  }
60595
- const timeoutId = setTimeout(resolve37, interval);
61178
+ const timeoutId = setTimeout(resolve38, interval);
60596
61179
  signal.addEventListener("abort", () => {
60597
61180
  clearTimeout(timeoutId);
60598
61181
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -61382,7 +61965,7 @@ var Server = class extends Protocol {
61382
61965
  };
61383
61966
 
61384
61967
  // src/mcp/server.ts
61385
- var path50 = __toESM(require("path"));
61968
+ var path52 = __toESM(require("path"));
61386
61969
 
61387
61970
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
61388
61971
  var import_node_process2 = __toESM(require("node:process"), 1);
@@ -61465,12 +62048,12 @@ var StdioServerTransport = class {
61465
62048
  this.onclose?.();
61466
62049
  }
61467
62050
  send(message) {
61468
- return new Promise((resolve37) => {
62051
+ return new Promise((resolve38) => {
61469
62052
  const json = serializeMessage(message);
61470
62053
  if (this._stdout.write(json)) {
61471
- resolve37();
62054
+ resolve38();
61472
62055
  } else {
61473
- this._stdout.once("drain", resolve37);
62056
+ this._stdout.once("drain", resolve38);
61474
62057
  }
61475
62058
  });
61476
62059
  }
@@ -61553,13 +62136,20 @@ var LaunchEnvironmentInputSchema = external_exports.object({
61553
62136
  force: external_exports.boolean().default(false).describe(
61554
62137
  "Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
61555
62138
  ),
61556
- resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
62139
+ resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree."),
62140
+ workUnitId: external_exports.string().min(1).max(128).optional(),
62141
+ source: external_exports.string().min(1).max(64).optional(),
62142
+ sourceUrl: external_exports.string().url().optional(),
62143
+ title: external_exports.string().min(1).max(256).optional(),
62144
+ parentWorkUnitId: external_exports.string().min(1).max(128).optional()
61557
62145
  });
61558
62146
  var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
61559
62147
  previewUrls: external_exports.record(external_exports.string()).optional(),
61560
62148
  workDir: external_exports.string().optional().describe("Where the session code lives \u2014 ALL file edits must go under this path"),
61561
62149
  worktreePath: external_exports.string().optional(),
61562
62150
  branch: external_exports.string().optional(),
62151
+ workUnitId: external_exports.string().optional(),
62152
+ attemptId: external_exports.string().uuid().optional(),
61563
62153
  blocked: external_exports.boolean().optional(),
61564
62154
  occupiedSlot: external_exports.object({
61565
62155
  agentId: external_exports.number().int(),
@@ -61692,6 +62282,17 @@ var HAR_MCP_TOOLS = [
61692
62282
  resume: {
61693
62283
  type: "boolean",
61694
62284
  description: "Resume a failed or partial launch (status failed/starting) without confirmReplace. Preserves worktree and env."
62285
+ },
62286
+ workUnitId: {
62287
+ type: "string",
62288
+ description: "Durable external work identifier to bind to this session."
62289
+ },
62290
+ source: { type: "string", description: "Optional provider/source name." },
62291
+ sourceUrl: { type: "string", description: "Optional source URL." },
62292
+ title: { type: "string", description: "Optional human-readable work title." },
62293
+ parentWorkUnitId: {
62294
+ type: "string",
62295
+ description: "Optional parent work unit identifier."
61695
62296
  }
61696
62297
  },
61697
62298
  ["agentId"]
@@ -61875,6 +62476,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
61875
62476
  confirmReplace: input.confirmReplace,
61876
62477
  force: input.force,
61877
62478
  resume: input.resume,
62479
+ workUnitId: input.workUnitId,
62480
+ source: input.source,
62481
+ sourceUrl: input.sourceUrl,
62482
+ title: input.title,
62483
+ parentWorkUnitId: input.parentWorkUnitId,
61878
62484
  capture: true
61879
62485
  });
61880
62486
  const parsed = LaunchEnvironmentOutputSchema.parse(result);
@@ -61894,6 +62500,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
61894
62500
  confirmReplace: false,
61895
62501
  force: false,
61896
62502
  resume: true,
62503
+ workUnitId: input.workUnitId,
62504
+ source: input.source,
62505
+ sourceUrl: input.sourceUrl,
62506
+ title: input.title,
62507
+ parentWorkUnitId: input.parentWorkUnitId,
61897
62508
  capture: true
61898
62509
  });
61899
62510
  const parsed = LaunchEnvironmentOutputSchema.parse(result);
@@ -62014,7 +62625,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
62014
62625
  const input = ControlUpInputSchema.parse({ ...args, repo });
62015
62626
  const result = await startControlAndSync({
62016
62627
  detach: input.detach,
62017
- cwd: path50.resolve(input.repo)
62628
+ cwd: path52.resolve(input.repo)
62018
62629
  });
62019
62630
  if (result.code !== 0) {
62020
62631
  return {
@@ -63094,13 +63705,13 @@ var PromisePolyfill = class extends Promise {
63094
63705
  // Available starting from Node 22
63095
63706
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
63096
63707
  static withResolver() {
63097
- let resolve37;
63708
+ let resolve38;
63098
63709
  let reject;
63099
63710
  const promise = new Promise((res, rej) => {
63100
- resolve37 = res;
63711
+ resolve38 = res;
63101
63712
  reject = rej;
63102
63713
  });
63103
- return { promise, resolve: resolve37, reject };
63714
+ return { promise, resolve: resolve38, reject };
63104
63715
  }
63105
63716
  };
63106
63717
 
@@ -63117,7 +63728,7 @@ function createPrompt(view) {
63117
63728
  output
63118
63729
  });
63119
63730
  const screen = new ScreenManager(rl);
63120
- const { promise, resolve: resolve37, reject } = PromisePolyfill.withResolver();
63731
+ const { promise, resolve: resolve38, reject } = PromisePolyfill.withResolver();
63121
63732
  const cancel = () => reject(new CancelPromptError());
63122
63733
  if (signal) {
63123
63734
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -63141,7 +63752,7 @@ function createPrompt(view) {
63141
63752
  cycle(() => {
63142
63753
  try {
63143
63754
  const nextView = view(config2, (value) => {
63144
- setImmediate(() => resolve37(value));
63755
+ setImmediate(() => resolve38(value));
63145
63756
  });
63146
63757
  const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
63147
63758
  screen.render(content, bottomContent);
@@ -64128,9 +64739,9 @@ var import_run_async = __toESM(require_run_async(), 1);
64128
64739
  var import_mute_stream2 = __toESM(require_lib3(), 1);
64129
64740
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
64130
64741
  var _2 = {
64131
- set: (obj, path52 = "", value) => {
64742
+ set: (obj, path54 = "", value) => {
64132
64743
  let pointer = obj;
64133
- path52.split(".").forEach((key, index, arr) => {
64744
+ path54.split(".").forEach((key, index, arr) => {
64134
64745
  if (key === "__proto__" || key === "constructor")
64135
64746
  return;
64136
64747
  if (index === arr.length - 1) {
@@ -64141,8 +64752,8 @@ var _2 = {
64141
64752
  pointer = pointer[key];
64142
64753
  });
64143
64754
  },
64144
- get: (obj, path52 = "", defaultValue) => {
64145
- const travel = (regexp) => String.prototype.split.call(path52, regexp).filter(Boolean).reduce(
64755
+ get: (obj, path54 = "", defaultValue) => {
64756
+ const travel = (regexp) => String.prototype.split.call(path54, regexp).filter(Boolean).reduce(
64146
64757
  // @ts-expect-error implicit any on res[key]
64147
64758
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
64148
64759
  obj
@@ -64256,7 +64867,7 @@ var PromptsRunner = class {
64256
64867
  throw new Error(`Prompt for type ${question.type} not found`);
64257
64868
  }
64258
64869
  let cleanupSignal;
64259
- const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve37, reject) => {
64870
+ const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve38, reject) => {
64260
64871
  const rl = import_node_readline.default.createInterface(setupReadlineOptions(this.opt));
64261
64872
  rl.resume();
64262
64873
  const onClose = () => {
@@ -64292,7 +64903,7 @@ var PromptsRunner = class {
64292
64903
  cleanupSignal = void 0;
64293
64904
  };
64294
64905
  }
64295
- activePrompt.run().then(resolve37, reject).finally(cleanup);
64906
+ activePrompt.run().then(resolve38, reject).finally(cleanup);
64296
64907
  }) : prompt2;
64297
64908
  const { signal: moduleSignal } = this.opt;
64298
64909
  if (moduleSignal?.aborted) {
@@ -64506,7 +65117,7 @@ var preferencesCommand = {
64506
65117
  };
64507
65118
 
64508
65119
  // src/cli/commands/telemetry.ts
64509
- var path51 = __toESM(require("path"));
65120
+ var path53 = __toESM(require("path"));
64510
65121
  init_control_config();
64511
65122
  init_otel_hooks();
64512
65123
  init_telemetry_config();
@@ -64591,7 +65202,7 @@ async function handleOff() {
64591
65202
  info("Mission Control will not auto-start. Existing usage rows are kept.");
64592
65203
  }
64593
65204
  async function handleWriteEnv(argv) {
64594
- const repoPath = path51.resolve(argv.repo);
65205
+ const repoPath = path53.resolve(argv.repo);
64595
65206
  const harnessRoot = resolveHarnessRoot(repoPath);
64596
65207
  const session = readSlotRegistry(harnessRoot, argv.agentId);
64597
65208
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -64603,7 +65214,7 @@ async function handleWriteEnv(argv) {
64603
65214
  suffix,
64604
65215
  createdAt: session?.createdAt
64605
65216
  });
64606
- const envFile = argv.envFile ?? path51.join(workDir, `.env.agent.${argv.agentId}`);
65217
+ const envFile = argv.envFile ?? path53.join(workDir, `.env.agent.${argv.agentId}`);
64607
65218
  const attrs = {
64608
65219
  sessionKey,
64609
65220
  agentId: argv.agentId,
@@ -64622,7 +65233,7 @@ async function handleWriteEnv(argv) {
64622
65233
  success(`Wrote session attribution to ${envFile}`);
64623
65234
  }
64624
65235
  function handlePrintEnv(argv) {
64625
- const repoPath = path51.resolve(argv.repo);
65236
+ const repoPath = path53.resolve(argv.repo);
64626
65237
  const workDir = argv.workDir ?? repoPath;
64627
65238
  const sessionKey = buildSessionKey({
64628
65239
  branch: argv.branch,