@osfactory/har 0.20.0 → 0.21.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 path53 = url.path;
769
+ if (path53.length === 0) {
770
770
  return;
771
771
  }
772
- if (url.scheme === "file" && path52.length === 1 && isNormalizedWindowsDriveLetter(path52[0])) {
772
+ if (url.scheme === "file" && path53.length === 1 && isNormalizedWindowsDriveLetter(path53[0])) {
773
773
  return;
774
774
  }
775
- path52.pop();
775
+ path53.pop();
776
776
  }
777
777
  function includesCredentials(url) {
778
778
  return url.username !== "" || url.password !== "";
@@ -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(path53, { 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: path53, 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(path53, filenameOrOptions, options = {}) {
6371
+ const stats = (0, import_fs5.statSync)(path53);
6372
+ return createFileFromPath(path53, 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(path53, filenameOrOptions, options) {
6375
+ const stats = await import_fs5.promises.stat(path53);
6376
+ return createFileFromPath(path53, 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({
@@ -6451,9 +6451,9 @@ var init_control_config = __esm({
6451
6451
  // src/core/telemetry-config.ts
6452
6452
  function getPreferencePath() {
6453
6453
  if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
6454
- return path35.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6454
+ return path36.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
6455
6455
  }
6456
- return path35.join(os9.homedir(), ".har", "telemetry.json");
6456
+ return path36.join(os9.homedir(), ".har", "telemetry.json");
6457
6457
  }
6458
6458
  function parseEnvOverride(raw) {
6459
6459
  if (raw === void 0 || raw === "") return void 0;
@@ -6474,10 +6474,10 @@ function normalizeSignals(enabled, raw) {
6474
6474
  function readTelemetryPreference() {
6475
6475
  const preferencePath = getPreferencePath();
6476
6476
  try {
6477
- if (!fs35.existsSync(preferencePath)) {
6477
+ if (!fs36.existsSync(preferencePath)) {
6478
6478
  return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
6479
6479
  }
6480
- const parsed = JSON.parse(fs35.readFileSync(preferencePath, "utf8"));
6480
+ const parsed = JSON.parse(fs36.readFileSync(preferencePath, "utf8"));
6481
6481
  const enabled = parsed.enabled !== false;
6482
6482
  return {
6483
6483
  enabled,
@@ -6500,8 +6500,8 @@ function writeTelemetryPreference(enabled, signals2) {
6500
6500
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6501
6501
  };
6502
6502
  const preferencePath = getPreferencePath();
6503
- fs35.mkdirSync(path35.dirname(preferencePath), { recursive: true });
6504
- fs35.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6503
+ fs36.mkdirSync(path36.dirname(preferencePath), { recursive: true });
6504
+ fs36.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
6505
6505
  return preference;
6506
6506
  }
6507
6507
  function isTelemetryEnabled() {
@@ -6516,13 +6516,13 @@ function getTelemetrySignals() {
6516
6516
  function getTelemetryPreferencePath() {
6517
6517
  return getPreferencePath();
6518
6518
  }
6519
- var fs35, os9, path35, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6519
+ var fs36, os9, path36, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
6520
6520
  var init_telemetry_config = __esm({
6521
6521
  "src/core/telemetry-config.ts"() {
6522
6522
  "use strict";
6523
- fs35 = __toESM(require("fs"));
6523
+ fs36 = __toESM(require("fs"));
6524
6524
  os9 = __toESM(require("os"));
6525
- path35 = __toESM(require("path"));
6525
+ path36 = __toESM(require("path"));
6526
6526
  DEFAULT_SIGNALS_ON = {
6527
6527
  metrics: true,
6528
6528
  logs: true,
@@ -6563,15 +6563,15 @@ __export(otel_hooks_exports, {
6563
6563
  });
6564
6564
  function getOtelHooksHome() {
6565
6565
  if (process.env.HAR_OTEL_HOOKS_HOME) {
6566
- return path41.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6566
+ return path42.resolve(process.env.HAR_OTEL_HOOKS_HOME);
6567
6567
  }
6568
- return path41.join(os12.homedir(), ".har", "otel-hooks");
6568
+ return path42.join(os12.homedir(), ".har", "otel-hooks");
6569
6569
  }
6570
6570
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
6571
- return path41.join(hooksHome, "otel_config.json");
6571
+ return path42.join(hooksHome, "otel_config.json");
6572
6572
  }
6573
6573
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
6574
- return path41.join(hooksHome, "run-otel-hook.sh");
6574
+ return path42.join(hooksHome, "run-otel-hook.sh");
6575
6575
  }
6576
6576
  function buildOtelHooksConfig(options) {
6577
6577
  const enabled = options?.enabled ?? isTelemetryEnabled();
@@ -6590,18 +6590,18 @@ function buildOtelHooksConfig(options) {
6590
6590
  };
6591
6591
  }
6592
6592
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
6593
- fs39.mkdirSync(hooksHome, { recursive: true });
6593
+ fs40.mkdirSync(hooksHome, { recursive: true });
6594
6594
  const configPath = getOtelHooksConfigPath(hooksHome);
6595
6595
  const payload = {
6596
6596
  _comment: "Managed by har telemetry \u2014 do not edit by hand; use: har telemetry on|off",
6597
6597
  ...config2
6598
6598
  };
6599
- fs39.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6599
+ fs40.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
6600
6600
  `);
6601
6601
  return configPath;
6602
6602
  }
6603
6603
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
6604
- fs39.mkdirSync(hooksHome, { recursive: true });
6604
+ fs40.mkdirSync(hooksHome, { recursive: true });
6605
6605
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
6606
6606
  const script = `#!/usr/bin/env bash
6607
6607
  # Managed by har telemetry \u2014 invokes opentelemetry-hooks with HAR config home.
@@ -6609,9 +6609,9 @@ set -euo pipefail
6609
6609
  export IDE_OTEL_HOOK_HOME="${hooksHome}"
6610
6610
  exec "${otelHookCommand}" "$@"
6611
6611
  `;
6612
- fs39.writeFileSync(wrapperPath, script, { mode: 493 });
6612
+ fs40.writeFileSync(wrapperPath, script, { mode: 493 });
6613
6613
  try {
6614
- fs39.chmodSync(wrapperPath, 493);
6614
+ fs40.chmodSync(wrapperPath, 493);
6615
6615
  } catch {
6616
6616
  }
6617
6617
  return wrapperPath;
@@ -6691,10 +6691,10 @@ function runSetupAgent(agent, otelHookCommand, hooksHome) {
6691
6691
  };
6692
6692
  }
6693
6693
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6694
- if (!fs39.existsSync(filePath)) return false;
6694
+ if (!fs40.existsSync(filePath)) return false;
6695
6695
  let raw;
6696
6696
  try {
6697
- raw = fs39.readFileSync(filePath, "utf8");
6697
+ raw = fs40.readFileSync(filePath, "utf8");
6698
6698
  } catch {
6699
6699
  return false;
6700
6700
  }
@@ -6733,16 +6733,16 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
6733
6733
  return changed;
6734
6734
  };
6735
6735
  if (!walk(parsed)) return false;
6736
- fs39.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6736
+ fs40.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
6737
6737
  `);
6738
6738
  return true;
6739
6739
  }
6740
6740
  function rewriteKnownHookRegistrations(wrapperPath) {
6741
6741
  const home = os12.homedir();
6742
6742
  const candidates = [
6743
- path41.join(home, ".cursor", "hooks.json"),
6744
- path41.join(home, ".claude", "settings.json"),
6745
- path41.join(home, ".codex", "hooks.json")
6743
+ path42.join(home, ".cursor", "hooks.json"),
6744
+ path42.join(home, ".claude", "settings.json"),
6745
+ path42.join(home, ".codex", "hooks.json")
6746
6746
  ];
6747
6747
  for (const filePath of candidates) {
6748
6748
  try {
@@ -6755,7 +6755,7 @@ function ensureOtelHooks(options) {
6755
6755
  const hooksHome = getOtelHooksHome();
6756
6756
  const errors = [];
6757
6757
  const agentsSetup = [];
6758
- fs39.mkdirSync(hooksHome, { recursive: true });
6758
+ fs40.mkdirSync(hooksHome, { recursive: true });
6759
6759
  let otelHookCommand = resolveOtelHookCommand();
6760
6760
  if (!otelHookCommand) {
6761
6761
  const installed = tryInstallPackage();
@@ -6824,14 +6824,14 @@ function ensureOtelHooks(options) {
6824
6824
  function disableOtelHooksExport() {
6825
6825
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
6826
6826
  }
6827
- var import_child_process9, fs39, os12, path41, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6827
+ var import_child_process9, fs40, os12, path42, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
6828
6828
  var init_otel_hooks = __esm({
6829
6829
  "src/core/otel-hooks.ts"() {
6830
6830
  "use strict";
6831
6831
  import_child_process9 = require("child_process");
6832
- fs39 = __toESM(require("fs"));
6832
+ fs40 = __toESM(require("fs"));
6833
6833
  os12 = __toESM(require("os"));
6834
- path41 = __toESM(require("path"));
6834
+ path42 = __toESM(require("path"));
6835
6835
  init_control_config();
6836
6836
  init_telemetry_config();
6837
6837
  OTEL_HOOKS_PACKAGE = "opentelemetry-hooks==0.14.0";
@@ -10035,8 +10035,8 @@ var require_utils2 = __commonJS({
10035
10035
  }
10036
10036
  return ind;
10037
10037
  }
10038
- function removeDotSegments(path52) {
10039
- let input = path52;
10038
+ function removeDotSegments(path53) {
10039
+ let input = path53;
10040
10040
  const output = [];
10041
10041
  let nextSlash = -1;
10042
10042
  let len = 0;
@@ -10288,8 +10288,8 @@ var require_schemes = __commonJS({
10288
10288
  wsComponent.secure = void 0;
10289
10289
  }
10290
10290
  if (wsComponent.resourceName) {
10291
- const [path52, query] = wsComponent.resourceName.split("?");
10292
- wsComponent.path = path52 && path52 !== "/" ? path52 : void 0;
10291
+ const [path53, query] = wsComponent.resourceName.split("?");
10292
+ wsComponent.path = path53 && path53 !== "/" ? path53 : void 0;
10293
10293
  wsComponent.query = query;
10294
10294
  wsComponent.resourceName = void 0;
10295
10295
  }
@@ -13682,12 +13682,12 @@ var require_dist = __commonJS({
13682
13682
  throw new Error(`Unknown format "${name}"`);
13683
13683
  return f2;
13684
13684
  };
13685
- function addFormats(ajv, list, fs44, exportName) {
13685
+ function addFormats(ajv, list, fs45, exportName) {
13686
13686
  var _a3;
13687
13687
  var _b2;
13688
13688
  (_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
13689
13689
  for (const f2 of list)
13690
- ajv.addFormat(f2, fs44[f2]);
13690
+ ajv.addFormat(f2, fs45[f2]);
13691
13691
  }
13692
13692
  module2.exports = exports2 = formatsPlugin;
13693
13693
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -14787,15 +14787,15 @@ var require_route = __commonJS({
14787
14787
  };
14788
14788
  }
14789
14789
  function wrapConversion(toModel, graph) {
14790
- const path52 = [graph[toModel].parent, toModel];
14790
+ const path53 = [graph[toModel].parent, toModel];
14791
14791
  let fn = conversions[graph[toModel].parent][toModel];
14792
14792
  let cur = graph[toModel].parent;
14793
14793
  while (graph[cur].parent) {
14794
- path52.unshift(graph[cur].parent);
14794
+ path53.unshift(graph[cur].parent);
14795
14795
  fn = link(conversions[graph[cur].parent][cur], fn);
14796
14796
  cur = graph[cur].parent;
14797
14797
  }
14798
- fn.conversion = path52;
14798
+ fn.conversion = path53;
14799
14799
  return fn;
14800
14800
  }
14801
14801
  module2.exports = function(fromModel) {
@@ -20725,7 +20725,7 @@ var require_iso2022 = __commonJS({
20725
20725
  // node_modules/chardet/index.js
20726
20726
  var require_chardet = __commonJS({
20727
20727
  "node_modules/chardet/index.js"(exports2, module2) {
20728
- var fs44 = require("fs");
20728
+ var fs45 = require("fs");
20729
20729
  var utf8 = require_utf8();
20730
20730
  var unicode = require_unicode();
20731
20731
  var mbcs = require_mbcs();
@@ -20799,28 +20799,28 @@ var require_chardet = __commonJS({
20799
20799
  var fd;
20800
20800
  var handler = function(err, buffer) {
20801
20801
  if (fd) {
20802
- fs44.closeSync(fd);
20802
+ fs45.closeSync(fd);
20803
20803
  }
20804
20804
  if (err) return cb(err, null);
20805
20805
  cb(null, self.detect(buffer, opts));
20806
20806
  };
20807
20807
  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) {
20808
+ fd = fs45.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
20809
+ fs45.read(fd, sample, 0, opts.sampleSize, null, function(err) {
20810
20810
  handler(err, sample);
20811
20811
  });
20812
20812
  return;
20813
20813
  }
20814
- fs44.readFile(filepath, handler);
20814
+ fs45.readFile(filepath, handler);
20815
20815
  };
20816
20816
  module2.exports.detectFileSync = function(filepath, opts) {
20817
20817
  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);
20818
+ var fd = fs45.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
20819
+ fs45.readSync(fd, sample2, 0, opts.sampleSize);
20820
+ fs45.closeSync(fd);
20821
20821
  return self.detect(sample2, opts);
20822
20822
  }
20823
- return self.detect(fs44.readFileSync(filepath), opts);
20823
+ return self.detect(fs45.readFileSync(filepath), opts);
20824
20824
  };
20825
20825
  module2.exports.detectAll = function(buffer, opts) {
20826
20826
  if (typeof opts !== "object") {
@@ -24285,16 +24285,16 @@ var require_os_tmpdir = __commonJS({
24285
24285
  var isWindows = process.platform === "win32";
24286
24286
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
24287
24287
  module2.exports = function() {
24288
- var path52;
24288
+ var path53;
24289
24289
  if (isWindows) {
24290
- path52 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24290
+ path53 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
24291
24291
  } else {
24292
- path52 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24292
+ path53 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
24293
24293
  }
24294
- if (trailingSlashRe.test(path52)) {
24295
- path52 = path52.slice(0, -1);
24294
+ if (trailingSlashRe.test(path53)) {
24295
+ path53 = path53.slice(0, -1);
24296
24296
  }
24297
- return path52;
24297
+ return path53;
24298
24298
  };
24299
24299
  }
24300
24300
  });
@@ -24302,9 +24302,9 @@ var require_os_tmpdir = __commonJS({
24302
24302
  // node_modules/tmp/lib/tmp.js
24303
24303
  var require_tmp = __commonJS({
24304
24304
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
24305
- var fs44 = require("fs");
24306
- var path52 = require("path");
24307
- var crypto4 = require("crypto");
24305
+ var fs45 = require("fs");
24306
+ var path53 = require("path");
24307
+ var crypto6 = require("crypto");
24308
24308
  var osTmpDir = require_os_tmpdir();
24309
24309
  var _c2 = process.binding("constants");
24310
24310
  var tmpDir = osTmpDir();
@@ -24322,9 +24322,9 @@ var require_tmp = __commonJS({
24322
24322
  function _randomChars(howMany) {
24323
24323
  var value = [], rnd = null;
24324
24324
  try {
24325
- rnd = crypto4.randomBytes(howMany);
24325
+ rnd = crypto6.randomBytes(howMany);
24326
24326
  } catch (e2) {
24327
- rnd = crypto4.pseudoRandomBytes(howMany);
24327
+ rnd = crypto6.pseudoRandomBytes(howMany);
24328
24328
  }
24329
24329
  for (var i2 = 0; i2 < howMany; i2++) {
24330
24330
  value.push(RANDOM_CHARS[rnd[i2] % RANDOM_CHARS.length]);
@@ -24345,7 +24345,7 @@ var require_tmp = __commonJS({
24345
24345
  }
24346
24346
  function _generateTmpName(opts) {
24347
24347
  if (opts.name) {
24348
- return path52.join(opts.dir || tmpDir, opts.name);
24348
+ return path53.join(opts.dir || tmpDir, opts.name);
24349
24349
  }
24350
24350
  if (opts.template) {
24351
24351
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -24356,7 +24356,7 @@ var require_tmp = __commonJS({
24356
24356
  _randomChars(12),
24357
24357
  opts.postfix || ""
24358
24358
  ].join("");
24359
- return path52.join(opts.dir || tmpDir, name);
24359
+ return path53.join(opts.dir || tmpDir, name);
24360
24360
  }
24361
24361
  function tmpName(options, callback) {
24362
24362
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -24366,7 +24366,7 @@ var require_tmp = __commonJS({
24366
24366
  return cb(new Error("Invalid template provided"));
24367
24367
  (function _getUniqueName() {
24368
24368
  const name = _generateTmpName(opts);
24369
- fs44.stat(name, function(err) {
24369
+ fs45.stat(name, function(err) {
24370
24370
  if (!err) {
24371
24371
  if (tries-- > 0) return _getUniqueName();
24372
24372
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -24384,7 +24384,7 @@ var require_tmp = __commonJS({
24384
24384
  do {
24385
24385
  const name = _generateTmpName(opts);
24386
24386
  try {
24387
- fs44.statSync(name);
24387
+ fs45.statSync(name);
24388
24388
  } catch (e2) {
24389
24389
  return name;
24390
24390
  }
@@ -24396,13 +24396,13 @@ var require_tmp = __commonJS({
24396
24396
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
24397
24397
  tmpName(opts, function _tmpNameCreated(err, name) {
24398
24398
  if (err) return cb(err);
24399
- fs44.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24399
+ fs45.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
24400
24400
  if (err2) return cb(err2);
24401
24401
  if (opts.discardDescriptor) {
24402
- return fs44.close(fd, function _discardCallback(err3) {
24402
+ return fs45.close(fd, function _discardCallback(err3) {
24403
24403
  if (err3) {
24404
24404
  try {
24405
- fs44.unlinkSync(name);
24405
+ fs45.unlinkSync(name);
24406
24406
  } catch (e2) {
24407
24407
  if (!isENOENT(e2)) {
24408
24408
  err3 = e2;
@@ -24425,9 +24425,9 @@ var require_tmp = __commonJS({
24425
24425
  opts.postfix = opts.postfix || ".tmp";
24426
24426
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
24427
24427
  const name = tmpNameSync(opts);
24428
- var fd = fs44.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24428
+ var fd = fs45.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
24429
24429
  if (opts.discardDescriptor) {
24430
- fs44.closeSync(fd);
24430
+ fs45.closeSync(fd);
24431
24431
  fd = void 0;
24432
24432
  }
24433
24433
  return {
@@ -24439,9 +24439,9 @@ var require_tmp = __commonJS({
24439
24439
  function _rmdirRecursiveSync(root) {
24440
24440
  const dirs = [root];
24441
24441
  do {
24442
- var dir2 = dirs.pop(), deferred = false, files = fs44.readdirSync(dir2);
24442
+ var dir2 = dirs.pop(), deferred = false, files = fs45.readdirSync(dir2);
24443
24443
  for (var i2 = 0, length = files.length; i2 < length; i2++) {
24444
- var file2 = path52.join(dir2, files[i2]), stat = fs44.lstatSync(file2);
24444
+ var file2 = path53.join(dir2, files[i2]), stat = fs45.lstatSync(file2);
24445
24445
  if (stat.isDirectory()) {
24446
24446
  if (!deferred) {
24447
24447
  deferred = true;
@@ -24449,11 +24449,11 @@ var require_tmp = __commonJS({
24449
24449
  }
24450
24450
  dirs.push(file2);
24451
24451
  } else {
24452
- fs44.unlinkSync(file2);
24452
+ fs45.unlinkSync(file2);
24453
24453
  }
24454
24454
  }
24455
24455
  if (!deferred) {
24456
- fs44.rmdirSync(dir2);
24456
+ fs45.rmdirSync(dir2);
24457
24457
  }
24458
24458
  } while (dirs.length !== 0);
24459
24459
  }
@@ -24461,7 +24461,7 @@ var require_tmp = __commonJS({
24461
24461
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
24462
24462
  tmpName(opts, function _tmpNameCreated(err, name) {
24463
24463
  if (err) return cb(err);
24464
- fs44.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24464
+ fs45.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
24465
24465
  if (err2) return cb(err2);
24466
24466
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
24467
24467
  });
@@ -24470,7 +24470,7 @@ var require_tmp = __commonJS({
24470
24470
  function dirSync(options) {
24471
24471
  var args = _parseArguments(options), opts = args[0];
24472
24472
  const name = tmpNameSync(opts);
24473
- fs44.mkdirSync(name, opts.mode || DIR_MODE);
24473
+ fs45.mkdirSync(name, opts.mode || DIR_MODE);
24474
24474
  return {
24475
24475
  name,
24476
24476
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -24480,7 +24480,7 @@ var require_tmp = __commonJS({
24480
24480
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
24481
24481
  try {
24482
24482
  if (0 <= fdPath[0]) {
24483
- fs44.closeSync(fdPath[0]);
24483
+ fs45.closeSync(fdPath[0]);
24484
24484
  }
24485
24485
  } catch (e2) {
24486
24486
  if (!isEBADF(e2) && !isENOENT(e2)) {
@@ -24488,7 +24488,7 @@ var require_tmp = __commonJS({
24488
24488
  }
24489
24489
  }
24490
24490
  try {
24491
- fs44.unlinkSync(fdPath[1]);
24491
+ fs45.unlinkSync(fdPath[1]);
24492
24492
  } catch (e2) {
24493
24493
  if (!isENOENT(e2)) {
24494
24494
  throw e2;
@@ -24501,7 +24501,7 @@ var require_tmp = __commonJS({
24501
24501
  return removeCallback;
24502
24502
  }
24503
24503
  function _prepareTmpDirRemoveCallback(name, opts) {
24504
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs44.rmdirSync.bind(fs44);
24504
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs45.rmdirSync.bind(fs45);
24505
24505
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
24506
24506
  if (!opts.keep) {
24507
24507
  _removeObjects.unshift(removeCallback);
@@ -35714,11 +35714,11 @@ var parser = new YargsParser({
35714
35714
  resolve: import_path2.resolve,
35715
35715
  // TODO: figure out a way to combine ESM and CJS coverage, such that
35716
35716
  // we can exercise all the lines below:
35717
- require: (path52) => {
35717
+ require: (path53) => {
35718
35718
  if (typeof require !== "undefined") {
35719
- return require(path52);
35720
- } else if (path52.match(/\.json$/)) {
35721
- return JSON.parse((0, import_fs2.readFileSync)(path52, "utf8"));
35719
+ return require(path53);
35720
+ } else if (path53.match(/\.json$/)) {
35721
+ return JSON.parse((0, import_fs2.readFileSync)(path53, "utf8"));
35722
35722
  } else {
35723
35723
  throw Error("only .json config files are supported in ESM");
35724
35724
  }
@@ -40399,8 +40399,8 @@ function getErrorMap() {
40399
40399
 
40400
40400
  // node_modules/zod/v3/helpers/parseUtil.js
40401
40401
  var makeIssue = (params) => {
40402
- const { data, path: path52, errorMaps, issueData } = params;
40403
- const fullPath = [...path52, ...issueData.path || []];
40402
+ const { data, path: path53, errorMaps, issueData } = params;
40403
+ const fullPath = [...path53, ...issueData.path || []];
40404
40404
  const fullIssue = {
40405
40405
  ...issueData,
40406
40406
  path: fullPath
@@ -40516,11 +40516,11 @@ var errorUtil;
40516
40516
 
40517
40517
  // node_modules/zod/v3/types.js
40518
40518
  var ParseInputLazyPath = class {
40519
- constructor(parent, value, path52, key) {
40519
+ constructor(parent, value, path53, key) {
40520
40520
  this._cachedPath = [];
40521
40521
  this.parent = parent;
40522
40522
  this.data = value;
40523
- this._path = path52;
40523
+ this._path = path53;
40524
40524
  this._key = key;
40525
40525
  }
40526
40526
  get path() {
@@ -44117,6 +44117,51 @@ var StageKindSchema = HarnessStageKindSchema;
44117
44117
  var VerificationResultSchema = HarnessVerificationResultSchema;
44118
44118
  var StageResultSchema = HarnessStageRunResultSchema;
44119
44119
  var RunRecordTriggerSchema = external_exports.enum(["cli", "mcp", "script"]);
44120
+ var WorkUnitIdSchema = external_exports.string().min(1).max(128).regex(
44121
+ /^[A-Za-z0-9][A-Za-z0-9._:/#@-]*$/,
44122
+ "work unit id must start with an alphanumeric character and contain only stable identifier characters"
44123
+ );
44124
+ var WorkAttemptIdSchema = external_exports.string().uuid();
44125
+ var WorkUnitMetadataSchema = external_exports.object({
44126
+ workUnitId: WorkUnitIdSchema,
44127
+ source: external_exports.string().min(1).max(64).optional(),
44128
+ sourceUrl: external_exports.string().url().optional(),
44129
+ title: external_exports.string().min(1).max(256).optional(),
44130
+ parentWorkUnitId: WorkUnitIdSchema.optional()
44131
+ });
44132
+ var WorkUnitOutcomeSchema = external_exports.object({
44133
+ decision: external_exports.enum(["completed", "abandoned"]),
44134
+ decidedAt: external_exports.string(),
44135
+ attemptId: WorkAttemptIdSchema.optional(),
44136
+ validationId: external_exports.string().uuid().optional(),
44137
+ treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/).optional(),
44138
+ reason: external_exports.string().max(2e3).optional()
44139
+ }).superRefine((outcome, ctx) => {
44140
+ if (outcome.decision === "completed" && (!outcome.attemptId || !outcome.validationId || !outcome.treeHash)) {
44141
+ ctx.addIssue({
44142
+ code: external_exports.ZodIssueCode.custom,
44143
+ message: "completed work must reference an attempt and exact-tree validation"
44144
+ });
44145
+ }
44146
+ });
44147
+ var WorkUnitRecordSchema = WorkUnitMetadataSchema.extend({
44148
+ version: external_exports.number().int().default(1),
44149
+ createdAt: external_exports.string(),
44150
+ updatedAt: external_exports.string(),
44151
+ outcome: WorkUnitOutcomeSchema.optional()
44152
+ }).passthrough();
44153
+ var WorkAttemptRecordSchema = external_exports.object({
44154
+ version: external_exports.number().int().default(1),
44155
+ attemptId: WorkAttemptIdSchema,
44156
+ workUnitId: WorkUnitIdSchema,
44157
+ agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
44158
+ sessionKey: external_exports.string().min(1).optional(),
44159
+ workDir: external_exports.string().optional(),
44160
+ worktreePath: external_exports.string().optional(),
44161
+ branch: external_exports.string().optional(),
44162
+ baseCommit: external_exports.string().optional(),
44163
+ createdAt: external_exports.string()
44164
+ }).passthrough();
44120
44165
  var RunRecordSchema = external_exports.object({
44121
44166
  runId: external_exports.string().uuid(),
44122
44167
  repoPath: external_exports.string(),
@@ -44132,7 +44177,9 @@ var RunRecordSchema = external_exports.object({
44132
44177
  relativePath: external_exports.string().optional(),
44133
44178
  command: external_exports.string().optional(),
44134
44179
  workDir: external_exports.string().optional(),
44135
- harnessRoot: external_exports.string().optional()
44180
+ harnessRoot: external_exports.string().optional(),
44181
+ workUnitId: WorkUnitIdSchema.optional(),
44182
+ attemptId: WorkAttemptIdSchema.optional()
44136
44183
  }).passthrough();
44137
44184
  var SlotRegistryEntrySchema = external_exports.object({
44138
44185
  version: external_exports.number().int().default(1),
@@ -44154,6 +44201,8 @@ var SlotRegistryEntrySchema = external_exports.object({
44154
44201
  createdAt: external_exports.string(),
44155
44202
  ports: external_exports.record(external_exports.number()).optional(),
44156
44203
  previewUrls: external_exports.record(external_exports.string()).optional(),
44204
+ workUnitId: WorkUnitIdSchema.optional(),
44205
+ attemptId: WorkAttemptIdSchema.optional(),
44157
44206
  status: external_exports.enum(["starting", "active", "failed", "completed"]).default("active"),
44158
44207
  lastError: external_exports.string().optional()
44159
44208
  }).passthrough();
@@ -44199,6 +44248,8 @@ var AgentSlotStatusSchema = external_exports.object({
44199
44248
  sessionCreatedAt: external_exports.string().optional(),
44200
44249
  /** Derived from first captured user prompt (OTEL hooks); not set at launch. */
44201
44250
  purpose: external_exports.string().optional(),
44251
+ workUnitId: WorkUnitIdSchema.optional(),
44252
+ attemptId: WorkAttemptIdSchema.optional(),
44202
44253
  sessionStatus: external_exports.enum(["starting", "active", "failed", "completed"]).optional(),
44203
44254
  lastError: external_exports.string().optional(),
44204
44255
  /** Set when a failed/starting session can be resumed without --replace. */
@@ -44259,6 +44310,10 @@ var SyncSlotsInputSchema = external_exports.object({
44259
44310
  slots: external_exports.array(AgentSlotStatusSchema),
44260
44311
  generatedAt: external_exports.string()
44261
44312
  });
44313
+ var SyncWorkUnitsInputSchema = external_exports.object({
44314
+ workUnits: external_exports.array(WorkUnitRecordSchema),
44315
+ attempts: external_exports.array(WorkAttemptRecordSchema)
44316
+ });
44262
44317
  var ChangedFileStatusSchema = external_exports.enum(["A", "M", "D", "R", "C", "T", "U"]);
44263
44318
  var ChangedFileSchema = external_exports.object({
44264
44319
  path: external_exports.string(),
@@ -44285,6 +44340,17 @@ var ValidationRecordSchema = external_exports.object({
44285
44340
  var SyncValidationsInputSchema = external_exports.object({
44286
44341
  validations: external_exports.array(ValidationRecordSchema)
44287
44342
  });
44343
+ var ValidationBindingRecordSchema = external_exports.object({
44344
+ bindingId: external_exports.string().uuid(),
44345
+ workUnitId: WorkUnitIdSchema,
44346
+ attemptId: WorkAttemptIdSchema,
44347
+ validationId: external_exports.string().uuid(),
44348
+ treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/),
44349
+ createdAt: external_exports.string()
44350
+ });
44351
+ var SyncValidationBindingsInputSchema = external_exports.object({
44352
+ bindings: external_exports.array(ValidationBindingRecordSchema)
44353
+ });
44288
44354
  var AgentToolSchema = external_exports.enum(["claude_code", "codex", "cursor"]);
44289
44355
  var UsageSourceSchema = external_exports.enum(["otel", "harvest"]);
44290
44356
  var AgentSessionUsageSchema = external_exports.object({
@@ -44294,6 +44360,8 @@ var AgentSessionUsageSchema = external_exports.object({
44294
44360
  workDir: external_exports.string().optional(),
44295
44361
  branch: external_exports.string().optional(),
44296
44362
  suffix: external_exports.string().optional(),
44363
+ workUnitId: WorkUnitIdSchema.optional(),
44364
+ attemptId: WorkAttemptIdSchema.optional(),
44297
44365
  tokensInput: external_exports.number().nonnegative().default(0),
44298
44366
  tokensOutput: external_exports.number().nonnegative().default(0),
44299
44367
  tokensCacheRead: external_exports.number().nonnegative().default(0),
@@ -44315,6 +44383,8 @@ var AgentSessionEventSchema = external_exports.object({
44315
44383
  eventName: external_exports.string().min(1),
44316
44384
  sequence: external_exports.number().int().nonnegative().default(0),
44317
44385
  timestamp: external_exports.string(),
44386
+ workUnitId: WorkUnitIdSchema.optional(),
44387
+ attemptId: WorkAttemptIdSchema.optional(),
44318
44388
  attributes: external_exports.record(external_exports.unknown()).optional(),
44319
44389
  promptText: external_exports.string().nullable().optional(),
44320
44390
  responseText: external_exports.string().nullable().optional(),
@@ -44677,7 +44747,7 @@ function handleRemove(argv) {
44677
44747
  }
44678
44748
 
44679
44749
  // src/cli/commands/env.ts
44680
- var path45 = __toESM(require("path"));
44750
+ var path46 = __toESM(require("path"));
44681
44751
 
44682
44752
  // src/core/harness.ts
44683
44753
  var fs20 = __toESM(require("fs"));
@@ -45456,13 +45526,13 @@ var MultipartBody = class {
45456
45526
  // node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
45457
45527
  var import_web = require("node:stream/web");
45458
45528
  var fileFromPathWarned = false;
45459
- async function fileFromPath3(path52, ...args) {
45529
+ async function fileFromPath3(path53, ...args) {
45460
45530
  const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
45461
45531
  if (!fileFromPathWarned) {
45462
- console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path52)}) instead`);
45532
+ console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path53)}) instead`);
45463
45533
  fileFromPathWarned = true;
45464
45534
  }
45465
- return await _fileFromPath(path52, ...args);
45535
+ return await _fileFromPath(path53, ...args);
45466
45536
  }
45467
45537
  var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
45468
45538
  var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
@@ -46059,29 +46129,29 @@ var APIClient = class {
46059
46129
  defaultIdempotencyKey() {
46060
46130
  return `stainless-node-retry-${uuid4()}`;
46061
46131
  }
46062
- get(path52, opts) {
46063
- return this.methodRequest("get", path52, opts);
46132
+ get(path53, opts) {
46133
+ return this.methodRequest("get", path53, opts);
46064
46134
  }
46065
- post(path52, opts) {
46066
- return this.methodRequest("post", path52, opts);
46135
+ post(path53, opts) {
46136
+ return this.methodRequest("post", path53, opts);
46067
46137
  }
46068
- patch(path52, opts) {
46069
- return this.methodRequest("patch", path52, opts);
46138
+ patch(path53, opts) {
46139
+ return this.methodRequest("patch", path53, opts);
46070
46140
  }
46071
- put(path52, opts) {
46072
- return this.methodRequest("put", path52, opts);
46141
+ put(path53, opts) {
46142
+ return this.methodRequest("put", path53, opts);
46073
46143
  }
46074
- delete(path52, opts) {
46075
- return this.methodRequest("delete", path52, opts);
46144
+ delete(path53, opts) {
46145
+ return this.methodRequest("delete", path53, opts);
46076
46146
  }
46077
- methodRequest(method, path52, opts) {
46147
+ methodRequest(method, path53, opts) {
46078
46148
  return this.request(Promise.resolve(opts).then(async (opts2) => {
46079
46149
  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 };
46150
+ return { method, path: path53, ...opts2, body };
46081
46151
  }));
46082
46152
  }
46083
- getAPIList(path52, Page, opts) {
46084
- return this.requestAPIList(Page, { method: "get", path: path52, ...opts });
46153
+ getAPIList(path53, Page, opts) {
46154
+ return this.requestAPIList(Page, { method: "get", path: path53, ...opts });
46085
46155
  }
46086
46156
  calculateContentLength(body) {
46087
46157
  if (typeof body === "string") {
@@ -46099,10 +46169,10 @@ var APIClient = class {
46099
46169
  return null;
46100
46170
  }
46101
46171
  buildRequest(options) {
46102
- const { method, path: path52, query, headers = {} } = options;
46172
+ const { method, path: path53, query, headers = {} } = options;
46103
46173
  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
46174
  const contentLength = this.calculateContentLength(body);
46105
- const url = this.buildURL(path52, query);
46175
+ const url = this.buildURL(path53, query);
46106
46176
  if ("timeout" in options)
46107
46177
  validatePositiveInteger("timeout", options.timeout);
46108
46178
  const timeout = options.timeout ?? this.timeout;
@@ -46211,8 +46281,8 @@ var APIClient = class {
46211
46281
  const request = this.makeRequest(options, null);
46212
46282
  return new PagePromise(this, request, Page);
46213
46283
  }
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));
46284
+ buildURL(path53, query) {
46285
+ const url = isAbsoluteURL(path53) ? new URL(path53) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path53.startsWith("/") ? path53.slice(1) : path53));
46216
46286
  const defaultQuery = this.defaultQuery();
46217
46287
  if (!isEmptyObj(defaultQuery)) {
46218
46288
  query = { ...defaultQuery, ...query };
@@ -49802,6 +49872,9 @@ function buildStageResult(input) {
49802
49872
  });
49803
49873
  }
49804
49874
 
49875
+ // src/core/run-service.ts
49876
+ var crypto5 = __toESM(require("crypto"));
49877
+
49805
49878
  // src/core/local-executor.ts
49806
49879
  var fs25 = __toESM(require("fs"));
49807
49880
  var path24 = __toESM(require("path"));
@@ -49854,6 +49927,8 @@ function buildLaunchFlagArgs(flags) {
49854
49927
  if (flags.confirmReplace) args.push("--replace");
49855
49928
  if (flags.force) args.push("--force");
49856
49929
  if (flags.resume) args.push("--resume");
49930
+ if (flags.workUnitId) args.push(`--work-id=${flags.workUnitId}`);
49931
+ if (flags.attemptId) args.push(`--attempt-id=${flags.attemptId}`);
49857
49932
  return args;
49858
49933
  }
49859
49934
  function resolveRepoPath(repoPath) {
@@ -50029,7 +50104,7 @@ var LocalScriptExecutor = class {
50029
50104
  var localScriptExecutor = new LocalScriptExecutor();
50030
50105
 
50031
50106
  // src/core/control-sync.ts
50032
- var path39 = __toESM(require("path"));
50107
+ var path40 = __toESM(require("path"));
50033
50108
  init_control_config();
50034
50109
 
50035
50110
  // src/core/control-registry.ts
@@ -50288,7 +50363,9 @@ function createRun(ctx, meta) {
50288
50363
  status: "unknown",
50289
50364
  startedAt,
50290
50365
  relativePath,
50291
- trigger: ctx.trigger ?? "cli"
50366
+ trigger: ctx.trigger ?? "cli",
50367
+ workUnitId: ctx.workUnitId,
50368
+ attemptId: ctx.attemptId
50292
50369
  });
50293
50370
  fs28.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
50294
50371
  return run2;
@@ -51069,6 +51146,8 @@ function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
51069
51146
  baseBranch: session?.baseBranch,
51070
51147
  baseCommit: session?.baseCommit,
51071
51148
  sessionCreatedAt: session?.createdAt,
51149
+ workUnitId: session?.workUnitId,
51150
+ attemptId: session?.attemptId,
51072
51151
  sessionStatus: session?.status,
51073
51152
  lastError: session?.lastError,
51074
51153
  resumeHint,
@@ -51285,6 +51364,173 @@ function listValidations(harnessRoot) {
51285
51364
  return records.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
51286
51365
  }
51287
51366
 
51367
+ // src/core/work-units.ts
51368
+ var crypto4 = __toESM(require("crypto"));
51369
+ var fs35 = __toESM(require("fs"));
51370
+ var path35 = __toESM(require("path"));
51371
+ var WORK_UNITS_DIR = "work-units";
51372
+ var WORK_ATTEMPTS_DIR = "work-attempts";
51373
+ var VALIDATION_BINDINGS_DIR = "validation-bindings";
51374
+ var EVIDENCE_DIRS = [WORK_UNITS_DIR, WORK_ATTEMPTS_DIR, VALIDATION_BINDINGS_DIR];
51375
+ function harEvidenceDir(harnessRoot, name) {
51376
+ return path35.join(harnessRoot, ".har", name);
51377
+ }
51378
+ function hashedRecordPath(harnessRoot, dir, id) {
51379
+ const digest = crypto4.createHash("sha256").update(id).digest("hex");
51380
+ return path35.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
51381
+ }
51382
+ function writeRecord2(file, value) {
51383
+ fs35.mkdirSync(path35.dirname(file), { recursive: true });
51384
+ const temp = `${file}.${process.pid}.tmp`;
51385
+ fs35.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
51386
+ `);
51387
+ fs35.renameSync(temp, file);
51388
+ }
51389
+ function ensureWorkEvidenceIgnored(harnessRoot) {
51390
+ const harDir = path35.join(harnessRoot, ".har");
51391
+ if (!fs35.existsSync(harDir)) return;
51392
+ const gitignorePath = path35.join(harDir, ".gitignore");
51393
+ const content = fs35.existsSync(gitignorePath) ? fs35.readFileSync(gitignorePath, "utf8") : "";
51394
+ const lines2 = new Set(content.split("\n").map((line) => line.trim()));
51395
+ const missing = EVIDENCE_DIRS.map((dir) => `${dir}/`).filter((dir) => !lines2.has(dir));
51396
+ if (missing.length === 0) return;
51397
+ const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
51398
+ fs35.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
51399
+ `);
51400
+ }
51401
+ function listRecords(harnessRoot, dir, parse4) {
51402
+ const recordDir = harEvidenceDir(harnessRoot, dir);
51403
+ if (!fs35.existsSync(recordDir)) return [];
51404
+ const records = [];
51405
+ for (const name of fs35.readdirSync(recordDir)) {
51406
+ if (!name.endsWith(".json")) continue;
51407
+ try {
51408
+ records.push(parse4(JSON.parse(fs35.readFileSync(path35.join(recordDir, name), "utf8"))));
51409
+ } catch {
51410
+ }
51411
+ }
51412
+ return records;
51413
+ }
51414
+ function findWorkUnit(harnessRoot, workUnitId) {
51415
+ const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
51416
+ const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
51417
+ if (!fs35.existsSync(file)) return void 0;
51418
+ try {
51419
+ return WorkUnitRecordSchema.parse(JSON.parse(fs35.readFileSync(file, "utf8")));
51420
+ } catch {
51421
+ return void 0;
51422
+ }
51423
+ }
51424
+ function upsertWorkUnit(harnessRoot, input) {
51425
+ const metadata = WorkUnitMetadataSchema.parse(input);
51426
+ ensureWorkEvidenceIgnored(harnessRoot);
51427
+ const existing = findWorkUnit(harnessRoot, metadata.workUnitId);
51428
+ if (existing) {
51429
+ if (existing.outcome) {
51430
+ throw new Error(
51431
+ `Work unit ${metadata.workUnitId} is already ${existing.outcome.decision}; reopening is not supported`
51432
+ );
51433
+ }
51434
+ for (const field of ["source", "sourceUrl", "title", "parentWorkUnitId"]) {
51435
+ if (metadata[field] !== void 0 && existing[field] !== void 0 && metadata[field] !== existing[field]) {
51436
+ throw new Error(
51437
+ `Work unit ${metadata.workUnitId} has immutable ${field}=${existing[field]}`
51438
+ );
51439
+ }
51440
+ }
51441
+ }
51442
+ const now = (/* @__PURE__ */ new Date()).toISOString();
51443
+ const record2 = WorkUnitRecordSchema.parse({
51444
+ ...existing,
51445
+ workUnitId: metadata.workUnitId,
51446
+ source: existing?.source ?? metadata.source,
51447
+ sourceUrl: existing?.sourceUrl ?? metadata.sourceUrl,
51448
+ title: existing?.title ?? metadata.title,
51449
+ parentWorkUnitId: existing?.parentWorkUnitId ?? metadata.parentWorkUnitId,
51450
+ version: 1,
51451
+ createdAt: existing?.createdAt ?? now,
51452
+ updatedAt: now,
51453
+ outcome: existing?.outcome
51454
+ });
51455
+ writeRecord2(
51456
+ hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId),
51457
+ record2
51458
+ );
51459
+ return record2;
51460
+ }
51461
+ function listWorkUnits(harnessRoot) {
51462
+ return listRecords(
51463
+ harnessRoot,
51464
+ WORK_UNITS_DIR,
51465
+ (value) => WorkUnitRecordSchema.parse(value)
51466
+ ).sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
51467
+ }
51468
+ function createWorkAttempt(harnessRoot, input) {
51469
+ const attempt = WorkAttemptRecordSchema.parse({
51470
+ ...input,
51471
+ version: 1,
51472
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
51473
+ });
51474
+ ensureWorkEvidenceIgnored(harnessRoot);
51475
+ writeRecord2(
51476
+ hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt.attemptId),
51477
+ attempt
51478
+ );
51479
+ return attempt;
51480
+ }
51481
+ function listWorkAttempts(harnessRoot) {
51482
+ return listRecords(
51483
+ harnessRoot,
51484
+ WORK_ATTEMPTS_DIR,
51485
+ (value) => WorkAttemptRecordSchema.parse(value)
51486
+ ).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
51487
+ }
51488
+ function bindValidationToAttempt(harnessRoot, input) {
51489
+ const stableKey = `${input.attemptId}:${input.validation.validationId}`;
51490
+ ensureWorkEvidenceIgnored(harnessRoot);
51491
+ const existingFile = hashedRecordPath(
51492
+ harnessRoot,
51493
+ VALIDATION_BINDINGS_DIR,
51494
+ stableKey
51495
+ );
51496
+ if (fs35.existsSync(existingFile)) {
51497
+ try {
51498
+ return ValidationBindingRecordSchema.parse(
51499
+ JSON.parse(fs35.readFileSync(existingFile, "utf8"))
51500
+ );
51501
+ } catch {
51502
+ }
51503
+ }
51504
+ const binding = ValidationBindingRecordSchema.parse({
51505
+ bindingId: crypto4.randomUUID(),
51506
+ workUnitId: input.workUnitId,
51507
+ attemptId: input.attemptId,
51508
+ validationId: input.validation.validationId,
51509
+ treeHash: input.validation.treeHash,
51510
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
51511
+ });
51512
+ writeRecord2(existingFile, binding);
51513
+ return binding;
51514
+ }
51515
+ function listValidationBindings(harnessRoot) {
51516
+ return listRecords(
51517
+ harnessRoot,
51518
+ VALIDATION_BINDINGS_DIR,
51519
+ (value) => ValidationBindingRecordSchema.parse(value)
51520
+ ).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
51521
+ }
51522
+ function decideWorkUnitOutcome(harnessRoot, workUnitId, outcome) {
51523
+ const existing = findWorkUnit(harnessRoot, workUnitId);
51524
+ if (!existing) throw new Error(`Unknown work unit: ${workUnitId}`);
51525
+ const record2 = WorkUnitRecordSchema.parse({
51526
+ ...existing,
51527
+ outcome,
51528
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
51529
+ });
51530
+ writeRecord2(hashedRecordPath(harnessRoot, WORK_UNITS_DIR, workUnitId), record2);
51531
+ return record2;
51532
+ }
51533
+
51288
51534
  // src/core/cloud-executor.ts
51289
51535
  var RemoteExecutor = class {
51290
51536
  constructor(apiUrl, apiKey) {
@@ -51311,14 +51557,14 @@ function createRemoteExecutor(apiUrl, apiKey) {
51311
51557
  init_telemetry_config();
51312
51558
 
51313
51559
  // src/core/usage-harvest/claude.ts
51314
- var fs37 = __toESM(require("fs"));
51560
+ var fs38 = __toESM(require("fs"));
51315
51561
  var os10 = __toESM(require("os"));
51316
- var path37 = __toESM(require("path"));
51562
+ var path38 = __toESM(require("path"));
51317
51563
  init_telemetry_config();
51318
51564
 
51319
51565
  // src/core/telemetry-env.ts
51320
- var fs36 = __toESM(require("fs"));
51321
- var path36 = __toESM(require("path"));
51566
+ var fs37 = __toESM(require("fs"));
51567
+ var path37 = __toESM(require("path"));
51322
51568
  init_control_config();
51323
51569
  function escapeAttrValue(value) {
51324
51570
  return value.replace(/[,=]/g, "_");
@@ -51332,6 +51578,10 @@ function buildOtelResourceAttributes(attrs) {
51332
51578
  ];
51333
51579
  if (attrs.branch) parts.push(`har.branch=${escapeAttrValue(attrs.branch)}`);
51334
51580
  if (attrs.suffix) parts.push(`har.suffix=${escapeAttrValue(attrs.suffix)}`);
51581
+ if (attrs.workUnitId) {
51582
+ parts.push(`har.work_unit_id=${escapeAttrValue(attrs.workUnitId)}`);
51583
+ }
51584
+ if (attrs.attemptId) parts.push(`har.attempt_id=${attrs.attemptId}`);
51335
51585
  return parts.join(",");
51336
51586
  }
51337
51587
  function buildSessionKey(input) {
@@ -51345,6 +51595,8 @@ function buildTelemetryEnvBlock(attrs) {
51345
51595
  "",
51346
51596
  "# HAR session attribution (generated)",
51347
51597
  `HAR_SESSION_KEY=${attrs.sessionKey}`,
51598
+ ...attrs.workUnitId ? [`HAR_WORK_UNIT_ID=${attrs.workUnitId}`] : [],
51599
+ ...attrs.attemptId ? [`HAR_ATTEMPT_ID=${attrs.attemptId}`] : [],
51348
51600
  `HAR_CONTROL_API_URL=${apiUrl}`,
51349
51601
  `OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}`,
51350
51602
  "# Agent telemetry: opentelemetry-hooks \u2192 Mission Control (har telemetry on|off)"
@@ -51358,8 +51610,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
51358
51610
  ${TELEMETRY_MARKER_END}
51359
51611
  `;
51360
51612
  let existing = "";
51361
- if (fs36.existsSync(envFilePath)) {
51362
- existing = fs36.readFileSync(envFilePath, "utf8");
51613
+ if (fs37.existsSync(envFilePath)) {
51614
+ existing = fs37.readFileSync(envFilePath, "utf8");
51363
51615
  const start = existing.indexOf(TELEMETRY_MARKER_START);
51364
51616
  if (start >= 0) {
51365
51617
  const end = existing.indexOf(TELEMETRY_MARKER_END, start);
@@ -51370,28 +51622,28 @@ ${TELEMETRY_MARKER_END}
51370
51622
  }
51371
51623
  }
51372
51624
  }
51373
- fs36.mkdirSync(path36.dirname(envFilePath), { recursive: true });
51625
+ fs37.mkdirSync(path37.dirname(envFilePath), { recursive: true });
51374
51626
  const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
51375
- fs36.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51627
+ fs37.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
51376
51628
  }
51377
51629
 
51378
51630
  // src/core/usage-harvest/claude.ts
51379
51631
  function pathsMatch(candidate, targets) {
51380
- const norm = path37.resolve(candidate);
51632
+ const norm = path38.resolve(candidate);
51381
51633
  return targets.some((t2) => {
51382
- const target = path37.resolve(t2);
51383
- return norm === target || norm.startsWith(target + path37.sep) || target.startsWith(norm + path37.sep);
51634
+ const target = path38.resolve(t2);
51635
+ return norm === target || norm.startsWith(target + path38.sep) || target.startsWith(norm + path38.sep);
51384
51636
  });
51385
51637
  }
51386
51638
  function claudeProjectsRoot() {
51387
- return process.env.HAR_CLAUDE_PROJECTS_DIR ? path37.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path37.join(os10.homedir(), ".claude", "projects");
51639
+ return process.env.HAR_CLAUDE_PROJECTS_DIR ? path38.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path38.join(os10.homedir(), ".claude", "projects");
51388
51640
  }
51389
51641
  function encodeClaudeProjectDir(cwd) {
51390
51642
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
51391
51643
  }
51392
51644
  function readJsonlRecords(filePath) {
51393
- if (!fs37.existsSync(filePath)) return [];
51394
- const lines2 = fs37.readFileSync(filePath, "utf8").split(/\r?\n/);
51645
+ if (!fs38.existsSync(filePath)) return [];
51646
+ const lines2 = fs38.readFileSync(filePath, "utf8").split(/\r?\n/);
51395
51647
  const out = [];
51396
51648
  for (const line of lines2) {
51397
51649
  const trimmed = line.trim();
@@ -51434,16 +51686,16 @@ function findMatchingClaudeTranscripts(slot) {
51434
51686
  const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
51435
51687
  if (targets.length === 0) return [];
51436
51688
  const root = claudeProjectsRoot();
51437
- if (!fs37.existsSync(root)) return [];
51689
+ if (!fs38.existsSync(root)) return [];
51438
51690
  const matches = [];
51439
- for (const entry of fs37.readdirSync(root, { withFileTypes: true })) {
51691
+ for (const entry of fs38.readdirSync(root, { withFileTypes: true })) {
51440
51692
  if (!entry.isDirectory()) continue;
51441
- const projectDir = path37.join(root, entry.name);
51693
+ const projectDir = path38.join(root, entry.name);
51442
51694
  const encodedHit = targets.some((t2) => entry.name.includes(encodeClaudeProjectDir(t2).slice(0, 40)));
51443
- for (const file of fs37.readdirSync(projectDir)) {
51695
+ for (const file of fs38.readdirSync(projectDir)) {
51444
51696
  if (!file.endsWith(".jsonl")) continue;
51445
- const filePath = path37.join(projectDir, file);
51446
- const stat = fs37.statSync(filePath);
51697
+ const filePath = path38.join(projectDir, file);
51698
+ const stat = fs38.statSync(filePath);
51447
51699
  const records = readJsonlRecords(filePath);
51448
51700
  let cwdHit = encodedHit;
51449
51701
  for (const record2 of records) {
@@ -51554,30 +51806,30 @@ function harvestClaudeEvents(slot) {
51554
51806
  }
51555
51807
 
51556
51808
  // src/core/usage-harvest/codex.ts
51557
- var fs38 = __toESM(require("fs"));
51809
+ var fs39 = __toESM(require("fs"));
51558
51810
  var os11 = __toESM(require("os"));
51559
- var path38 = __toESM(require("path"));
51811
+ var path39 = __toESM(require("path"));
51560
51812
  function pathsMatch2(candidate, targets) {
51561
- const norm = path38.resolve(candidate);
51813
+ const norm = path39.resolve(candidate);
51562
51814
  return targets.some((t2) => {
51563
- const target = path38.resolve(t2);
51564
- return norm === target || norm.startsWith(target + path38.sep) || target.startsWith(norm + path38.sep);
51815
+ const target = path39.resolve(t2);
51816
+ return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
51565
51817
  });
51566
51818
  }
51567
51819
  function codexSessionsRoot() {
51568
- return process.env.HAR_CODEX_SESSIONS_DIR ? path38.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path38.join(os11.homedir(), ".codex", "sessions");
51820
+ return process.env.HAR_CODEX_SESSIONS_DIR ? path39.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path39.join(os11.homedir(), ".codex", "sessions");
51569
51821
  }
51570
51822
  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);
51823
+ if (!fs39.existsSync(dir)) return out;
51824
+ for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
51825
+ const full = path39.join(dir, entry.name);
51574
51826
  if (entry.isDirectory()) walkJsonlFiles(full, out);
51575
51827
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
51576
51828
  }
51577
51829
  return out;
51578
51830
  }
51579
51831
  function readJsonl(filePath) {
51580
- const lines2 = fs38.readFileSync(filePath, "utf8").split(/\r?\n/);
51832
+ const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
51581
51833
  const out = [];
51582
51834
  for (const line of lines2) {
51583
51835
  const trimmed = line.trim();
@@ -51641,7 +51893,7 @@ function harvestCodexUsage(slot) {
51641
51893
  const extracted = extractCodexTokens(records);
51642
51894
  if (!extracted.cwd || !pathsMatch2(extracted.cwd, targets)) continue;
51643
51895
  if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
51644
- const mtime = fs38.statSync(file).mtimeMs;
51896
+ const mtime = fs39.statSync(file).mtimeMs;
51645
51897
  if (mtime >= bestMtime) {
51646
51898
  bestMtime = mtime;
51647
51899
  best = extracted;
@@ -51787,13 +52039,22 @@ async function syncRepoWithControl(options) {
51787
52039
  }
51788
52040
  const runs = listRuns(repoPath);
51789
52041
  const status = collectEnvironmentStatus(repoPath);
52042
+ const harnessRoot = resolveHarnessRoot(repoPath);
51790
52043
  const response = await fetch(`${process.env.HAR_CLOUD_API_URL}/api/sync`, {
51791
52044
  method: "POST",
51792
52045
  headers: {
51793
52046
  "Content-Type": "application/json",
51794
52047
  Authorization: `Bearer ${process.env.HAR_CLOUD_API_KEY}`
51795
52048
  },
51796
- body: JSON.stringify({ path: repoPath, runs, slots: status.slots })
52049
+ body: JSON.stringify({
52050
+ path: repoPath,
52051
+ runs,
52052
+ slots: status.slots,
52053
+ workUnits: listWorkUnits(harnessRoot),
52054
+ attempts: listWorkAttempts(harnessRoot),
52055
+ validations: listValidations(harnessRoot),
52056
+ validationBindings: listValidationBindings(harnessRoot)
52057
+ })
51797
52058
  });
51798
52059
  if (!response.ok) {
51799
52060
  throw new Error(`Cloud sync failed: ${response.status}`);
@@ -51806,7 +52067,7 @@ async function syncRepoWithControl(options) {
51806
52067
  const listResponse = await fetch(`${apiUrl}/api/repos`);
51807
52068
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
51808
52069
  const repos = await listResponse.json();
51809
- const existing = repos.find((r2) => path39.resolve(r2.path) === repoPath);
52070
+ const existing = repos.find((r2) => path40.resolve(r2.path) === repoPath);
51810
52071
  if (!existing) {
51811
52072
  return;
51812
52073
  }
@@ -51827,6 +52088,13 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51827
52088
  generatedAt: status.generatedAt
51828
52089
  });
51829
52090
  await postJson(`${apiUrl}/api/repos/${repoId}/slots`, slotsBody, dryRun);
52091
+ const workUnitsBody = SyncWorkUnitsInputSchema.parse({
52092
+ workUnits: listWorkUnits(resolveHarnessRoot(repoPath)),
52093
+ attempts: listWorkAttempts(resolveHarnessRoot(repoPath))
52094
+ });
52095
+ if (workUnitsBody.workUnits.length > 0 || workUnitsBody.attempts.length > 0) {
52096
+ await postJson(`${apiUrl}/api/repos/${repoId}/work-units`, workUnitsBody, dryRun);
52097
+ }
51830
52098
  if (isTelemetryEnabled() && process.env.NODE_ENV !== "test") {
51831
52099
  try {
51832
52100
  const usage2 = status.slots.flatMap(
@@ -51840,6 +52108,8 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51840
52108
  repoPath
51841
52109
  }).map((row) => ({
51842
52110
  ...row,
52111
+ workUnitId: slot.workUnitId,
52112
+ attemptId: slot.attemptId,
51843
52113
  sessionKey: row.sessionKey || buildSessionKey({
51844
52114
  branch: slot.branch,
51845
52115
  agentId: slot.agentId,
@@ -51861,7 +52131,11 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51861
52131
  suffix: slot.suffix,
51862
52132
  sessionCreatedAt: slot.sessionCreatedAt,
51863
52133
  repoPath
51864
- })
52134
+ }).map((event) => ({
52135
+ ...event,
52136
+ workUnitId: slot.workUnitId,
52137
+ attemptId: slot.attemptId
52138
+ }))
51865
52139
  );
51866
52140
  if (events.length > 0) {
51867
52141
  const eventsBody = SyncSessionEventsInputSchema.parse({ events });
@@ -51878,6 +52152,16 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
51878
52152
  const validationsBody = SyncValidationsInputSchema.parse({ validations });
51879
52153
  await postJson(`${apiUrl}/api/repos/${repoId}/validations`, validationsBody, dryRun);
51880
52154
  }
52155
+ const bindingsBody = SyncValidationBindingsInputSchema.parse({
52156
+ bindings: listValidationBindings(resolveHarnessRoot(repoPath))
52157
+ });
52158
+ if (bindingsBody.bindings.length > 0) {
52159
+ await postJson(
52160
+ `${apiUrl}/api/repos/${repoId}/validation-bindings`,
52161
+ bindingsBody,
52162
+ dryRun
52163
+ );
52164
+ }
51881
52165
  }
51882
52166
  var SYNC_TIMEOUT_MS = 15e3;
51883
52167
  function withTimeout(promise, ms, label) {
@@ -51935,7 +52219,7 @@ init_control_config();
51935
52219
 
51936
52220
  // src/core/control-lifecycle.ts
51937
52221
  var import_child_process8 = require("child_process");
51938
- var path40 = __toESM(require("path"));
52222
+ var path41 = __toESM(require("path"));
51939
52223
 
51940
52224
  // src/core/control-image.ts
51941
52225
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -51959,10 +52243,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
51959
52243
  var CONTROL_CONTAINER_PORT = 3847;
51960
52244
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
51961
52245
  function resolveControlDir() {
51962
- return path40.resolve(__dirname, "..", "control");
52246
+ return path41.resolve(__dirname, "..", "control");
51963
52247
  }
51964
52248
  function resolveControlBuildContext() {
51965
- return path40.resolve(resolveControlDir(), "..");
52249
+ return path41.resolve(resolveControlDir(), "..");
51966
52250
  }
51967
52251
  function buildDockerRunArgs(options) {
51968
52252
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -52018,7 +52302,7 @@ async function startMissionControl(options) {
52018
52302
  "-t",
52019
52303
  imageRef,
52020
52304
  "-f",
52021
- path40.join(resolveControlDir(), "Dockerfile"),
52305
+ path41.join(resolveControlDir(), "Dockerfile"),
52022
52306
  resolveControlBuildContext()
52023
52307
  ]);
52024
52308
  if (buildCode !== 0) {
@@ -52162,7 +52446,7 @@ async function ensureTelemetryInfrastructure(options) {
52162
52446
 
52163
52447
  // src/core/run-service.ts
52164
52448
  init_telemetry_config();
52165
- var path42 = __toESM(require("path"));
52449
+ var path43 = __toESM(require("path"));
52166
52450
  function extractShellOutput(result) {
52167
52451
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
52168
52452
  const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
@@ -52200,11 +52484,14 @@ var RunService = class {
52200
52484
  this.executor = executor;
52201
52485
  }
52202
52486
  async runStage(options) {
52487
+ const activeSession = options.agentId !== void 0 && options.kind !== "launch" ? readSlotRegistry(resolveHarnessRoot(options.repoPath), options.agentId) : void 0;
52203
52488
  const ctx = {
52204
52489
  repoPath: options.repoPath,
52205
52490
  capture: options.capture,
52206
52491
  agentId: options.agentId,
52207
- trigger: options.trigger
52492
+ trigger: options.trigger,
52493
+ workUnitId: options.workUnitId ?? activeSession?.workUnitId,
52494
+ attemptId: options.attemptId ?? activeSession?.attemptId
52208
52495
  };
52209
52496
  const stageLookup = options.stageId ? { id: options.stageId } : options.kind ? { kind: options.kind } : null;
52210
52497
  if (!stageLookup) {
@@ -52306,47 +52593,96 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52306
52593
  `;
52307
52594
  }
52308
52595
  }
52596
+ const harnessRoot = resolveHarnessRoot(options.repoPath);
52597
+ const resumableSession = options.resume ? readSlotRegistry(harnessRoot, options.agentId) : void 0;
52598
+ const workUnitId = options.workUnitId ?? resumableSession?.workUnitId;
52599
+ const attemptId = workUnitId ? resumableSession?.attemptId ?? crypto5.randomUUID() : void 0;
52600
+ if (workUnitId && attemptId) {
52601
+ const conflictingSession = listSlotRegistryEntries(harnessRoot).find(
52602
+ (entry) => entry.workUnitId === workUnitId && !(entry.agentId === options.agentId && (options.resume || options.confirmReplace))
52603
+ );
52604
+ if (conflictingSession) {
52605
+ return {
52606
+ code: 2,
52607
+ stdout: "",
52608
+ stderr: `Work unit ${workUnitId} is already bound to slot ${conflictingSession.agentId} (attempt ${conflictingSession.attemptId ?? "unknown"}).`,
52609
+ blocked: true
52610
+ };
52611
+ }
52612
+ upsertWorkUnit(harnessRoot, {
52613
+ workUnitId,
52614
+ source: options.source,
52615
+ sourceUrl: options.sourceUrl,
52616
+ title: options.title,
52617
+ parentWorkUnitId: options.parentWorkUnitId
52618
+ });
52619
+ createWorkAttempt(harnessRoot, {
52620
+ attemptId,
52621
+ workUnitId,
52622
+ agentId: options.agentId
52623
+ });
52624
+ }
52309
52625
  const result = await this.runStage({
52310
52626
  repoPath: options.repoPath,
52311
52627
  kind: "launch",
52312
52628
  agentId: options.agentId,
52629
+ workUnitId,
52630
+ attemptId,
52313
52631
  capture: options.capture ?? false,
52314
52632
  launchFlags: {
52315
52633
  worktree: options.worktree,
52316
52634
  claude: options.claude,
52317
52635
  confirmReplace: options.confirmReplace,
52318
52636
  force: options.force,
52319
- resume: options.resume
52637
+ resume: options.resume,
52638
+ workUnitId,
52639
+ attemptId
52320
52640
  },
52321
52641
  trigger: "cli"
52322
52642
  });
52323
52643
  const envResult = toEnvironmentRunResult(result);
52324
52644
  if (envResult.code === 0) {
52325
- const harnessRoot = resolveHarnessRoot(options.repoPath);
52326
52645
  const session = readSlotRegistry(harnessRoot, options.agentId);
52327
52646
  if (session) {
52328
52647
  envResult.workDir = session.workDir;
52329
52648
  envResult.worktreePath = session.worktreePath;
52330
52649
  envResult.branch = session.branch;
52331
52650
  envResult.previewUrls = envResult.previewUrls ?? session.previewUrls;
52651
+ envResult.workUnitId = session.workUnitId;
52652
+ envResult.attemptId = session.attemptId;
52332
52653
  const sessionKey = buildSessionKey({
52333
52654
  branch: session.branch,
52334
52655
  agentId: options.agentId,
52335
52656
  suffix: session.suffix,
52336
52657
  createdAt: session.createdAt
52337
52658
  });
52338
- const envFile = path42.join(session.workDir, `.env.agent.${options.agentId}`);
52659
+ const envFile = path43.join(session.workDir, `.env.agent.${options.agentId}`);
52339
52660
  try {
52340
52661
  appendTelemetryEnvToFile(envFile, {
52341
52662
  sessionKey,
52342
52663
  agentId: options.agentId,
52343
- repoPath: path42.resolve(options.repoPath),
52664
+ repoPath: path43.resolve(options.repoPath),
52344
52665
  workDir: session.workDir,
52345
52666
  branch: session.branch,
52346
- suffix: session.suffix
52667
+ suffix: session.suffix,
52668
+ workUnitId: session.workUnitId,
52669
+ attemptId: session.attemptId
52347
52670
  });
52348
52671
  } catch {
52349
52672
  }
52673
+ if (session.workUnitId && session.attemptId) {
52674
+ createWorkAttempt(harnessRoot, {
52675
+ attemptId: session.attemptId,
52676
+ workUnitId: session.workUnitId,
52677
+ agentId: options.agentId,
52678
+ sessionKey,
52679
+ workDir: session.workDir,
52680
+ worktreePath: session.worktreePath,
52681
+ branch: session.branch,
52682
+ baseCommit: session.baseCommit,
52683
+ createdAt: session.createdAt
52684
+ });
52685
+ }
52350
52686
  }
52351
52687
  if (telemetryBanner) {
52352
52688
  envResult.stderr = `${telemetryBanner}${envResult.stderr ?? ""}`;
@@ -52377,7 +52713,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52377
52713
  const harnessRoot = resolveHarnessRoot(options.repoPath);
52378
52714
  const checkoutDir = resolveAgentWorkDir(harnessRoot, options.agentId) ?? harnessRoot;
52379
52715
  const runId = typeof result.data === "object" && result.data !== null && !Array.isArray(result.data) ? result.data.runId : void 0;
52380
- recordValidation({
52716
+ const validation2 = recordValidation({
52381
52717
  checkoutDir,
52382
52718
  harnessRoot,
52383
52719
  status: verification.status,
@@ -52385,7 +52721,22 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52385
52721
  runId,
52386
52722
  agentId: options.agentId
52387
52723
  });
52724
+ const session = readSlotRegistry(harnessRoot, options.agentId);
52725
+ if (session?.workUnitId && session.attemptId) {
52726
+ bindValidationToAttempt(harnessRoot, {
52727
+ workUnitId: session.workUnitId,
52728
+ attemptId: session.attemptId,
52729
+ validation: validation2
52730
+ });
52731
+ }
52388
52732
  await syncRepoWithControlAsync(options.repoPath);
52733
+ return {
52734
+ code: shell.code,
52735
+ stdout: shell.stdout,
52736
+ stderr: shell.stderr,
52737
+ verification,
52738
+ validation: validation2
52739
+ };
52389
52740
  } catch {
52390
52741
  }
52391
52742
  }
@@ -52423,6 +52774,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52423
52774
  };
52424
52775
  }
52425
52776
  let verification;
52777
+ let validation2;
52426
52778
  if (!options.skipVerify) {
52427
52779
  const verify = await this.runVerification({
52428
52780
  repoPath: options.repoPath,
@@ -52432,6 +52784,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52432
52784
  trigger: options.trigger
52433
52785
  });
52434
52786
  verification = verify.verification;
52787
+ validation2 = verify.validation;
52435
52788
  if (verify.code !== 0 || verification?.status !== "pass") {
52436
52789
  return {
52437
52790
  ...verify,
@@ -52439,6 +52792,24 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
52439
52792
  };
52440
52793
  }
52441
52794
  }
52795
+ if (session.workUnitId && session.attemptId && !options.skipVerify && !validation2) {
52796
+ return {
52797
+ code: 1,
52798
+ stdout: "",
52799
+ stderr: "Full verification passed, but HAR could not record exact-tree validation proof. Session NOT completed.",
52800
+ verification
52801
+ };
52802
+ }
52803
+ if (session.workUnitId && session.attemptId && validation2) {
52804
+ decideWorkUnitOutcome(harnessRoot, session.workUnitId, {
52805
+ decision: "completed",
52806
+ decidedAt: (/* @__PURE__ */ new Date()).toISOString(),
52807
+ attemptId: session.attemptId,
52808
+ validationId: validation2.validationId,
52809
+ treeHash: validation2.treeHash
52810
+ });
52811
+ await syncRepoWithControlAsync(options.repoPath);
52812
+ }
52442
52813
  const teardown = await this.teardownEnvironment({
52443
52814
  repoPath: options.repoPath,
52444
52815
  agentId: options.agentId,
@@ -52522,9 +52893,9 @@ var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunSer
52522
52893
  var readline5 = __toESM(require("readline"));
52523
52894
 
52524
52895
  // src/core/hooks.ts
52525
- var fs40 = __toESM(require("fs"));
52896
+ var fs41 = __toESM(require("fs"));
52526
52897
  var os13 = __toESM(require("os"));
52527
- var path43 = __toESM(require("path"));
52898
+ var path44 = __toESM(require("path"));
52528
52899
  var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
52529
52900
  var MARKER_END = "# <<< har commit gate <<<";
52530
52901
  var PRE_COMMIT_BLOCK = [
@@ -52549,7 +52920,7 @@ function resolveCheckoutRoot(cwd) {
52549
52920
  function resolveHooksDir(checkoutDir) {
52550
52921
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
52551
52922
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
52552
- return path43.resolve(checkoutDir, hooksPath);
52923
+ return path44.resolve(checkoutDir, hooksPath);
52553
52924
  }
52554
52925
  function getConfiguredHooksPath(checkoutDir) {
52555
52926
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -52557,9 +52928,9 @@ function getConfiguredHooksPath(checkoutDir) {
52557
52928
  function defaultHarInvocation() {
52558
52929
  const entry = process.argv[1];
52559
52930
  if (entry && entry.endsWith(".js")) {
52560
- return `"${process.execPath}" "${path43.resolve(entry)}"`;
52931
+ return `"${process.execPath}" "${path44.resolve(entry)}"`;
52561
52932
  }
52562
- if (entry) return `"${path43.resolve(entry)}"`;
52933
+ if (entry) return `"${path44.resolve(entry)}"`;
52563
52934
  return "har";
52564
52935
  }
52565
52936
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -52580,40 +52951,40 @@ exit 0
52580
52951
  `;
52581
52952
  }
52582
52953
  function upsertMarkedBlock(filePath, block) {
52583
- if (!fs40.existsSync(filePath)) {
52584
- fs40.writeFileSync(filePath, `#!/bin/sh
52954
+ if (!fs41.existsSync(filePath)) {
52955
+ fs41.writeFileSync(filePath, `#!/bin/sh
52585
52956
  ${block}
52586
52957
  `, { mode: 493 });
52587
52958
  return "created";
52588
52959
  }
52589
- const content = fs40.readFileSync(filePath, "utf8");
52960
+ const content = fs41.readFileSync(filePath, "utf8");
52590
52961
  if (content.includes(MARKER_START)) {
52591
52962
  const pattern = new RegExp(
52592
52963
  `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
52593
52964
  );
52594
- fs40.writeFileSync(filePath, content.replace(pattern, block));
52595
- fs40.chmodSync(filePath, 493);
52965
+ fs41.writeFileSync(filePath, content.replace(pattern, block));
52966
+ fs41.chmodSync(filePath, 493);
52596
52967
  return "updated";
52597
52968
  }
52598
52969
  const suffix = content.endsWith("\n") ? "" : "\n";
52599
- fs40.writeFileSync(filePath, `${content}${suffix}
52970
+ fs41.writeFileSync(filePath, `${content}${suffix}
52600
52971
  ${block}
52601
52972
  `);
52602
- fs40.chmodSync(filePath, 493);
52973
+ fs41.chmodSync(filePath, 493);
52603
52974
  return "appended";
52604
52975
  }
52605
52976
  function removeMarkedBlock(filePath) {
52606
- if (!fs40.existsSync(filePath)) return false;
52607
- const content = fs40.readFileSync(filePath, "utf8");
52977
+ if (!fs41.existsSync(filePath)) return false;
52978
+ const content = fs41.readFileSync(filePath, "utf8");
52608
52979
  if (!content.includes(MARKER_START)) return false;
52609
52980
  const pattern = new RegExp(
52610
52981
  `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
52611
52982
  );
52612
52983
  const stripped = content.replace(pattern, "\n");
52613
52984
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
52614
- fs40.rmSync(filePath);
52985
+ fs41.rmSync(filePath);
52615
52986
  } else {
52616
- fs40.writeFileSync(filePath, stripped);
52987
+ fs41.writeFileSync(filePath, stripped);
52617
52988
  }
52618
52989
  return true;
52619
52990
  }
@@ -52635,20 +53006,20 @@ Or re-run with --force to write into that directory anyway.`
52635
53006
  );
52636
53007
  }
52637
53008
  const hooksDir = resolveHooksDir(checkout);
52638
- fs40.mkdirSync(hooksDir, { recursive: true });
53009
+ fs41.mkdirSync(hooksDir, { recursive: true });
52639
53010
  const invocation = options.harInvocation ?? defaultHarInvocation();
52640
- fs40.writeFileSync(
52641
- path43.join(hooksDir, "har-pre-commit"),
53011
+ fs41.writeFileSync(
53012
+ path44.join(hooksDir, "har-pre-commit"),
52642
53013
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
52643
53014
  { mode: 493 }
52644
53015
  );
52645
- fs40.writeFileSync(
52646
- path43.join(hooksDir, "har-post-commit"),
53016
+ fs41.writeFileSync(
53017
+ path44.join(hooksDir, "har-post-commit"),
52647
53018
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
52648
53019
  { mode: 493 }
52649
53020
  );
52650
- const preCommit = upsertMarkedBlock(path43.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
52651
- const postCommit = upsertMarkedBlock(path43.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
53021
+ const preCommit = upsertMarkedBlock(path44.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
53022
+ const postCommit = upsertMarkedBlock(path44.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
52652
53023
  ensureValidationsIgnored(checkout);
52653
53024
  return { hooksDir, preCommit, postCommit };
52654
53025
  }
@@ -52657,12 +53028,12 @@ function uninstallHooks(repoPath) {
52657
53028
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
52658
53029
  const hooksDir = resolveHooksDir(checkout);
52659
53030
  let removed = false;
52660
- removed = removeMarkedBlock(path43.join(hooksDir, "pre-commit")) || removed;
52661
- removed = removeMarkedBlock(path43.join(hooksDir, "post-commit")) || removed;
53031
+ removed = removeMarkedBlock(path44.join(hooksDir, "pre-commit")) || removed;
53032
+ removed = removeMarkedBlock(path44.join(hooksDir, "post-commit")) || removed;
52662
53033
  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);
53034
+ const full = path44.join(hooksDir, file);
53035
+ if (fs41.existsSync(full)) {
53036
+ fs41.rmSync(full);
52666
53037
  removed = true;
52667
53038
  }
52668
53039
  }
@@ -52681,10 +53052,10 @@ function isAgentWorktree(checkoutDir) {
52681
53052
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
52682
53053
  return true;
52683
53054
  }
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));
53055
+ const worktreesRoot = path44.join(os13.homedir(), "worktrees");
53056
+ const resolved = path44.resolve(checkoutDir);
53057
+ const name = path44.basename(resolved);
53058
+ return resolved.startsWith(`${worktreesRoot}${path44.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
52688
53059
  }
52689
53060
  function resolveEffectiveMode(checkoutDir, gate) {
52690
53061
  if (!gate.enabled) return "off";
@@ -52697,15 +53068,15 @@ function getHooksStatus(repoPath) {
52697
53068
  const hooksDir = resolveHooksDir(checkout);
52698
53069
  const gate = getCommitGateConfig(checkout);
52699
53070
  const hasBlock = (name) => {
52700
- const file = path43.join(hooksDir, name);
52701
- return fs40.existsSync(file) && fs40.readFileSync(file, "utf8").includes(MARKER_START);
53071
+ const file = path44.join(hooksDir, name);
53072
+ return fs41.existsSync(file) && fs41.readFileSync(file, "utf8").includes(MARKER_START);
52702
53073
  };
52703
53074
  return {
52704
53075
  checkout,
52705
53076
  hooksDir,
52706
53077
  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")),
53078
+ preCommitInstalled: hasBlock("pre-commit") && fs41.existsSync(path44.join(hooksDir, "har-pre-commit")),
53079
+ postCommitInstalled: hasBlock("post-commit") && fs41.existsSync(path44.join(hooksDir, "har-post-commit")),
52709
53080
  gate,
52710
53081
  effectiveMode: resolveEffectiveMode(checkout, gate)
52711
53082
  };
@@ -52716,7 +53087,7 @@ function checkCommitGate(cwd) {
52716
53087
  }
52717
53088
  const checkout = resolveCheckoutRoot(cwd);
52718
53089
  if (!checkout) return { exitCode: 0, messages: [] };
52719
- if (!fs40.existsSync(path43.join(checkout, ".har", "stages.json"))) {
53090
+ if (!fs41.existsSync(path44.join(checkout, ".har", "stages.json"))) {
52720
53091
  return { exitCode: 0, messages: [] };
52721
53092
  }
52722
53093
  const gate = getCommitGateConfig(checkout);
@@ -52836,20 +53207,20 @@ async function handleCommitGateOnboarding(options) {
52836
53207
  }
52837
53208
 
52838
53209
  // src/core/onboarding-preferences.ts
52839
- var fs41 = __toESM(require("fs"));
53210
+ var fs42 = __toESM(require("fs"));
52840
53211
  var os14 = __toESM(require("os"));
52841
- var path44 = __toESM(require("path"));
53212
+ var path45 = __toESM(require("path"));
52842
53213
  function getOnboardingPreferencesPath() {
52843
53214
  if (process.env.HAR_PREFERENCES_PATH) {
52844
- return path44.resolve(process.env.HAR_PREFERENCES_PATH);
53215
+ return path45.resolve(process.env.HAR_PREFERENCES_PATH);
52845
53216
  }
52846
- return path44.join(os14.homedir(), ".har", "preferences.json");
53217
+ return path45.join(os14.homedir(), ".har", "preferences.json");
52847
53218
  }
52848
53219
  function readOnboardingPreferences() {
52849
53220
  const preferencePath = getOnboardingPreferencesPath();
52850
53221
  try {
52851
- if (!fs41.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
52852
- return OnboardingPreferencesSchema.parse(JSON.parse(fs41.readFileSync(preferencePath, "utf8")));
53222
+ if (!fs42.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
53223
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs42.readFileSync(preferencePath, "utf8")));
52853
53224
  } catch {
52854
53225
  return OnboardingPreferencesSchema.parse({});
52855
53226
  }
@@ -52874,8 +53245,8 @@ function writeOnboardingPreferences(overrides) {
52874
53245
  };
52875
53246
  const parsed = OnboardingPreferencesSchema.parse(preference);
52876
53247
  const preferencePath = getOnboardingPreferencesPath();
52877
- fs41.mkdirSync(path44.dirname(preferencePath), { recursive: true });
52878
- fs41.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
53248
+ fs42.mkdirSync(path45.dirname(preferencePath), { recursive: true });
53249
+ fs42.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
52879
53250
  `);
52880
53251
  return parsed;
52881
53252
  }
@@ -53070,6 +53441,15 @@ var envCommand = {
53070
53441
  type: "boolean",
53071
53442
  default: false,
53072
53443
  describe: LAUNCH_RESUME_DESCRIBE
53444
+ }).option("work-id", {
53445
+ type: "string",
53446
+ describe: "Bind this session to a durable external work identifier"
53447
+ }).option("work-source", {
53448
+ type: "string",
53449
+ describe: "Optional provider/source name (for example github or linear)"
53450
+ }).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", {
53451
+ type: "string",
53452
+ describe: "Optional parent work unit identifier"
53073
53453
  }).epilog(LAUNCH_EPILOG),
53074
53454
  handleLaunch
53075
53455
  ).command(
@@ -53146,7 +53526,7 @@ var envCommand = {
53146
53526
  }
53147
53527
  };
53148
53528
  async function handleInit(argv) {
53149
- const repoPath = path45.resolve(argv.repo);
53529
+ const repoPath = path46.resolve(argv.repo);
53150
53530
  const onboarding = resolveOnboardingOptions(argv);
53151
53531
  header("har env init");
53152
53532
  info(`Repository: ${repoPath}`);
@@ -53210,7 +53590,7 @@ async function handleInit(argv) {
53210
53590
  }
53211
53591
  }
53212
53592
  async function handleMaintain(argv) {
53213
- const repoPath = path45.resolve(argv.repo);
53593
+ const repoPath = path46.resolve(argv.repo);
53214
53594
  const onboarding = resolveOnboardingOptions(argv);
53215
53595
  header("har env maintain");
53216
53596
  info(`Repository: ${repoPath}`);
@@ -53325,7 +53705,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
53325
53705
  if (autoYes) {
53326
53706
  const proposal = readAgentMdProposal(repoPath);
53327
53707
  if (proposal) {
53328
- writeFileSafe(path45.join(repoPath, "AGENT.md"), proposal.content);
53708
+ writeFileSafe(path46.join(repoPath, "AGENT.md"), proposal.content);
53329
53709
  clearAgentMdProposal(repoPath);
53330
53710
  info("Applied AGENT.md proposal (--yes)");
53331
53711
  }
@@ -53334,7 +53714,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
53334
53714
  await promptApplyAgentMdProposal(repoPath);
53335
53715
  }
53336
53716
  async function handleAddStage(argv) {
53337
- const repoPath = path45.resolve(argv.repo);
53717
+ const repoPath = path46.resolve(argv.repo);
53338
53718
  const available = listStageTemplateIds();
53339
53719
  if (argv.list) {
53340
53720
  for (const id of available) {
@@ -53411,7 +53791,7 @@ async function handleAddStage(argv) {
53411
53791
  }
53412
53792
  }
53413
53793
  async function handlePreflight(argv) {
53414
- const repo = path45.resolve(argv.repo);
53794
+ const repo = path46.resolve(argv.repo);
53415
53795
  const agentId = validateAgentId(argv.id, repo);
53416
53796
  const result = await preflightEnvironment({
53417
53797
  repoPath: repo,
@@ -53429,7 +53809,7 @@ async function handlePreflight(argv) {
53429
53809
  process.exit(result.code);
53430
53810
  }
53431
53811
  async function handleLaunch(argv) {
53432
- const repo = path45.resolve(argv.repo);
53812
+ const repo = path46.resolve(argv.repo);
53433
53813
  const agentId = validateAgentId(argv.id, repo);
53434
53814
  let confirmReplace = argv.replace;
53435
53815
  let force = argv.force;
@@ -53481,6 +53861,11 @@ async function handleLaunch(argv) {
53481
53861
  confirmReplace,
53482
53862
  force,
53483
53863
  resume: argv.resume,
53864
+ workUnitId: argv.workId,
53865
+ source: argv.workSource,
53866
+ sourceUrl: argv.workUrl,
53867
+ title: argv.workTitle,
53868
+ parentWorkUnitId: argv.parentWorkId,
53484
53869
  capture: false
53485
53870
  });
53486
53871
  if (result.blocked) {
@@ -53509,11 +53894,16 @@ async function handleRecover(argv) {
53509
53894
  claude: false,
53510
53895
  replace: false,
53511
53896
  force: false,
53512
- resume: true
53897
+ resume: true,
53898
+ workId: void 0,
53899
+ workSource: void 0,
53900
+ workUrl: void 0,
53901
+ workTitle: void 0,
53902
+ parentWorkId: void 0
53513
53903
  });
53514
53904
  }
53515
53905
  async function handleVerify(argv) {
53516
- const repo = path45.resolve(argv.repo);
53906
+ const repo = path46.resolve(argv.repo);
53517
53907
  const agentId = validateAgentId(argv.id, repo);
53518
53908
  const result = await runVerification({
53519
53909
  repoPath: repo,
@@ -53525,7 +53915,7 @@ async function handleVerify(argv) {
53525
53915
  process.exit(result.code);
53526
53916
  }
53527
53917
  async function handleTeardown(argv) {
53528
- const repo = path45.resolve(argv.repo);
53918
+ const repo = path46.resolve(argv.repo);
53529
53919
  const agentId = validateAgentId(argv.id, repo);
53530
53920
  const result = await teardownEnvironment({
53531
53921
  repoPath: repo,
@@ -53536,7 +53926,7 @@ async function handleTeardown(argv) {
53536
53926
  process.exit(result.code);
53537
53927
  }
53538
53928
  async function handleComplete(argv) {
53539
- const repo = path45.resolve(argv.repo);
53929
+ const repo = path46.resolve(argv.repo);
53540
53930
  const agentId = validateAgentId(argv.id, repo);
53541
53931
  const result = await completeEnvironment({
53542
53932
  repoPath: repo,
@@ -53557,7 +53947,7 @@ async function handleComplete(argv) {
53557
53947
  process.exit(result.code);
53558
53948
  }
53559
53949
  async function handleStatus(argv) {
53560
- const repoPath = path45.resolve(argv.repo);
53950
+ const repoPath = path46.resolve(argv.repo);
53561
53951
  if (argv.json) {
53562
53952
  const status = collectEnvironmentStatus(repoPath);
53563
53953
  const output = EnvironmentStatusSchema.parse(status);
@@ -53570,7 +53960,7 @@ async function handleStatus(argv) {
53570
53960
  });
53571
53961
  }
53572
53962
  async function handleRunsList(argv) {
53573
- const repoPath = path45.resolve(argv.repo);
53963
+ const repoPath = path46.resolve(argv.repo);
53574
53964
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
53575
53965
  if (argv.json) {
53576
53966
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -53587,7 +53977,7 @@ async function handleRunsList(argv) {
53587
53977
  }
53588
53978
  }
53589
53979
  async function handleRunsGet(argv) {
53590
- const run2 = getRun(path45.resolve(argv.repo), argv.runId);
53980
+ const run2 = getRun(path46.resolve(argv.repo), argv.runId);
53591
53981
  if (!run2) {
53592
53982
  error(`Run not found: ${argv.runId}`);
53593
53983
  process.exit(1);
@@ -53666,20 +54056,20 @@ function printNextSteps(auto2) {
53666
54056
  }
53667
54057
 
53668
54058
  // src/cli/commands/control.ts
53669
- var path47 = __toESM(require("path"));
54059
+ var path48 = __toESM(require("path"));
53670
54060
  init_control_config();
53671
54061
 
53672
54062
  // src/core/control-unregister.ts
53673
- var fs42 = __toESM(require("fs"));
53674
- var path46 = __toESM(require("path"));
54063
+ var fs43 = __toESM(require("fs"));
54064
+ var path47 = __toESM(require("path"));
53675
54065
  init_control_config();
53676
54066
  function listUnregisterWorktreeCandidates(repoPath) {
53677
54067
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
53678
54068
  const byPath = /* @__PURE__ */ new Map();
53679
54069
  const add = (partial2) => {
53680
- const resolved = path46.resolve(partial2.worktreePath);
54070
+ const resolved = path47.resolve(partial2.worktreePath);
53681
54071
  if (!resolved || resolved === harnessRoot) return;
53682
- const exists = partial2.exists ?? fs42.existsSync(resolved);
54072
+ const exists = partial2.exists ?? fs43.existsSync(resolved);
53683
54073
  const prev = byPath.get(resolved);
53684
54074
  if (prev) {
53685
54075
  byPath.set(resolved, {
@@ -53793,28 +54183,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
53793
54183
  trigger: "cli"
53794
54184
  });
53795
54185
  if (result.code !== 0) {
53796
- if (fs42.existsSync(candidate.worktreePath)) {
53797
- fs42.rmSync(candidate.worktreePath, { recursive: true, force: true });
54186
+ if (fs43.existsSync(candidate.worktreePath)) {
54187
+ fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
53798
54188
  }
53799
54189
  }
53800
54190
  outcomes.push({
53801
54191
  path: candidate.worktreePath,
53802
54192
  agentId: candidate.agentId,
53803
- deleted: !fs42.existsSync(candidate.worktreePath),
53804
- error: result.code !== 0 && fs42.existsSync(candidate.worktreePath) ? result.stderr : void 0
54193
+ deleted: !fs43.existsSync(candidate.worktreePath),
54194
+ error: result.code !== 0 && fs43.existsSync(candidate.worktreePath) ? result.stderr : void 0
53805
54195
  });
53806
54196
  } catch (err) {
53807
54197
  const message = err instanceof Error ? err.message : String(err);
53808
54198
  try {
53809
- if (fs42.existsSync(candidate.worktreePath)) {
53810
- fs42.rmSync(candidate.worktreePath, { recursive: true, force: true });
54199
+ if (fs43.existsSync(candidate.worktreePath)) {
54200
+ fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
53811
54201
  }
53812
54202
  } catch {
53813
54203
  }
53814
54204
  outcomes.push({
53815
54205
  path: candidate.worktreePath,
53816
54206
  agentId: candidate.agentId,
53817
- deleted: !fs42.existsSync(candidate.worktreePath),
54207
+ deleted: !fs43.existsSync(candidate.worktreePath),
53818
54208
  error: message
53819
54209
  });
53820
54210
  }
@@ -53996,7 +54386,7 @@ async function handleDown() {
53996
54386
  process.exit(code);
53997
54387
  }
53998
54388
  async function handleRegister(argv) {
53999
- const repoPath = path47.resolve(argv.repo);
54389
+ const repoPath = path48.resolve(argv.repo);
54000
54390
  header("har control register");
54001
54391
  info(`Repository: ${repoPath}`);
54002
54392
  try {
@@ -54020,7 +54410,7 @@ async function handleRegister(argv) {
54020
54410
  }
54021
54411
  }
54022
54412
  async function handleUnregister(argv) {
54023
- const repoPath = path47.resolve(argv.repo);
54413
+ const repoPath = path48.resolve(argv.repo);
54024
54414
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
54025
54415
  try {
54026
54416
  let deleteWorktrees = argv.deleteWorktrees;
@@ -54089,7 +54479,7 @@ async function handleUnregister(argv) {
54089
54479
  }
54090
54480
  }
54091
54481
  async function handleSync(argv) {
54092
- const repoPath = path47.resolve(argv.repo);
54482
+ const repoPath = path48.resolve(argv.repo);
54093
54483
  try {
54094
54484
  await syncRepoWithControl({
54095
54485
  repoPath,
@@ -54128,7 +54518,7 @@ async function handleWatch(argv) {
54128
54518
  };
54129
54519
  const tick = async () => {
54130
54520
  if (argv.repo) {
54131
- await syncOne(path47.resolve(argv.repo));
54521
+ await syncOne(path48.resolve(argv.repo));
54132
54522
  return;
54133
54523
  }
54134
54524
  try {
@@ -54159,11 +54549,11 @@ async function handleLogin(argv) {
54159
54549
  }
54160
54550
 
54161
54551
  // src/cli/commands/hooks.ts
54162
- var path49 = __toESM(require("path"));
54552
+ var path50 = __toESM(require("path"));
54163
54553
 
54164
54554
  // src/core/claude-hooks.ts
54165
- var fs43 = __toESM(require("fs"));
54166
- var path48 = __toESM(require("path"));
54555
+ var fs44 = __toESM(require("fs"));
54556
+ var path49 = __toESM(require("path"));
54167
54557
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
54168
54558
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
54169
54559
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -54174,8 +54564,8 @@ function isHarGuardEntry(entry) {
54174
54564
  );
54175
54565
  }
54176
54566
  function readSettings(settingsPath) {
54177
- if (!fs43.existsSync(settingsPath)) return {};
54178
- const raw = fs43.readFileSync(settingsPath, "utf8").trim();
54567
+ if (!fs44.existsSync(settingsPath)) return {};
54568
+ const raw = fs44.readFileSync(settingsPath, "utf8").trim();
54179
54569
  if (raw === "") return {};
54180
54570
  const parsed = JSON.parse(raw);
54181
54571
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -54184,19 +54574,19 @@ function readSettings(settingsPath) {
54184
54574
  return parsed;
54185
54575
  }
54186
54576
  function writeSettings(settingsPath, settings) {
54187
- fs43.mkdirSync(path48.dirname(settingsPath), { recursive: true });
54188
- fs43.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
54577
+ fs44.mkdirSync(path49.dirname(settingsPath), { recursive: true });
54578
+ fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
54189
54579
  }
54190
54580
  function installClaudeGuard(repoPath) {
54191
54581
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
54192
54582
  if (!templatePath) {
54193
54583
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
54194
54584
  }
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);
54585
+ const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54586
+ fs44.mkdirSync(path49.dirname(guardScript), { recursive: true });
54587
+ fs44.copyFileSync(templatePath, guardScript);
54588
+ fs44.chmodSync(guardScript, 493);
54589
+ const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54200
54590
  const settings = readSettings(settingsPath);
54201
54591
  const hooks = settings.hooks ?? {};
54202
54592
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -54210,15 +54600,15 @@ function installClaudeGuard(repoPath) {
54210
54600
  }
54211
54601
  function uninstallClaudeGuard(repoPath) {
54212
54602
  let removed = false;
54213
- const guardScript = path48.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54214
- if (fs43.existsSync(guardScript)) {
54215
- fs43.rmSync(guardScript);
54603
+ const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
54604
+ if (fs44.existsSync(guardScript)) {
54605
+ fs44.rmSync(guardScript);
54216
54606
  removed = true;
54217
- const parent = path48.dirname(guardScript);
54218
- if (fs43.existsSync(parent) && fs43.readdirSync(parent).length === 0) fs43.rmdirSync(parent);
54607
+ const parent = path49.dirname(guardScript);
54608
+ if (fs44.existsSync(parent) && fs44.readdirSync(parent).length === 0) fs44.rmdirSync(parent);
54219
54609
  }
54220
- const settingsPath = path48.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54221
- if (fs43.existsSync(settingsPath)) {
54610
+ const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54611
+ if (fs44.existsSync(settingsPath)) {
54222
54612
  const settings = readSettings(settingsPath);
54223
54613
  const preToolUse = settings.hooks?.PreToolUse;
54224
54614
  if (preToolUse) {
@@ -54243,8 +54633,8 @@ function uninstallClaudeGuard(repoPath) {
54243
54633
  return { removed };
54244
54634
  }
54245
54635
  function claudeGuardInstalled(repoPath) {
54246
- const settingsPath = path48.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54247
- if (!fs43.existsSync(settingsPath)) return false;
54636
+ const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
54637
+ if (!fs44.existsSync(settingsPath)) return false;
54248
54638
  try {
54249
54639
  const settings = readSettings(settingsPath);
54250
54640
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -54260,7 +54650,7 @@ function repoOption(y2) {
54260
54650
  function handleInstall2(argv) {
54261
54651
  try {
54262
54652
  if (argv.claude) {
54263
- const result2 = installClaudeGuard(path49.resolve(argv.repo));
54653
+ const result2 = installClaudeGuard(path50.resolve(argv.repo));
54264
54654
  success("Claude Code worktree guard installed.");
54265
54655
  info(`Guard script: ${result2.guardScript}`);
54266
54656
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -54268,7 +54658,7 @@ function handleInstall2(argv) {
54268
54658
  info("Commit both files so the guard travels with the repo.");
54269
54659
  return;
54270
54660
  }
54271
- const result = installHooks({ repoPath: path49.resolve(argv.repo), force: argv.force });
54661
+ const result = installHooks({ repoPath: path50.resolve(argv.repo), force: argv.force });
54272
54662
  success(`Commit gate installed in ${result.hooksDir}`);
54273
54663
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
54274
54664
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -54281,7 +54671,7 @@ function handleInstall2(argv) {
54281
54671
  function handleUninstall(argv) {
54282
54672
  try {
54283
54673
  if (argv.claude) {
54284
- const result2 = uninstallClaudeGuard(path49.resolve(argv.repo));
54674
+ const result2 = uninstallClaudeGuard(path50.resolve(argv.repo));
54285
54675
  if (result2.removed) {
54286
54676
  success("Claude Code worktree guard removed.");
54287
54677
  } else {
@@ -54289,7 +54679,7 @@ function handleUninstall(argv) {
54289
54679
  }
54290
54680
  return;
54291
54681
  }
54292
- const result = uninstallHooks(path49.resolve(argv.repo));
54682
+ const result = uninstallHooks(path50.resolve(argv.repo));
54293
54683
  if (result.removed) {
54294
54684
  success(`Commit gate removed from ${result.hooksDir}`);
54295
54685
  } else {
@@ -54302,7 +54692,7 @@ function handleUninstall(argv) {
54302
54692
  }
54303
54693
  function handleStatus2(argv) {
54304
54694
  try {
54305
- const status = getHooksStatus(path49.resolve(argv.repo));
54695
+ const status = getHooksStatus(path50.resolve(argv.repo));
54306
54696
  if (argv.json) {
54307
54697
  process.stdout.write(`${JSON.stringify(status, null, 2)}
54308
54698
  `);
@@ -54320,7 +54710,7 @@ function handleStatus2(argv) {
54320
54710
  );
54321
54711
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
54322
54712
  info(
54323
- `Claude guard: ${claudeGuardInstalled(path49.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
54713
+ `Claude guard: ${claudeGuardInstalled(path50.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
54324
54714
  );
54325
54715
  } catch (err) {
54326
54716
  error(err instanceof Error ? err.message : String(err));
@@ -54581,10 +54971,10 @@ function assignProp(target, prop, value) {
54581
54971
  configurable: true
54582
54972
  });
54583
54973
  }
54584
- function getElementAtPath(obj, path52) {
54585
- if (!path52)
54974
+ function getElementAtPath(obj, path53) {
54975
+ if (!path53)
54586
54976
  return obj;
54587
- return path52.reduce((acc, key) => acc?.[key], obj);
54977
+ return path53.reduce((acc, key) => acc?.[key], obj);
54588
54978
  }
54589
54979
  function promiseAllObject(promisesObj) {
54590
54980
  const keys = Object.keys(promisesObj);
@@ -54904,11 +55294,11 @@ function aborted(x2, startIndex = 0) {
54904
55294
  }
54905
55295
  return false;
54906
55296
  }
54907
- function prefixIssues(path52, issues) {
55297
+ function prefixIssues(path53, issues) {
54908
55298
  return issues.map((iss) => {
54909
55299
  var _a3;
54910
55300
  (_a3 = iss).path ?? (_a3.path = []);
54911
- iss.path.unshift(path52);
55301
+ iss.path.unshift(path53);
54912
55302
  return iss;
54913
55303
  });
54914
55304
  }
@@ -61382,7 +61772,7 @@ var Server = class extends Protocol {
61382
61772
  };
61383
61773
 
61384
61774
  // src/mcp/server.ts
61385
- var path50 = __toESM(require("path"));
61775
+ var path51 = __toESM(require("path"));
61386
61776
 
61387
61777
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
61388
61778
  var import_node_process2 = __toESM(require("node:process"), 1);
@@ -61553,13 +61943,20 @@ var LaunchEnvironmentInputSchema = external_exports.object({
61553
61943
  force: external_exports.boolean().default(false).describe(
61554
61944
  "Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
61555
61945
  ),
61556
- resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
61946
+ resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree."),
61947
+ workUnitId: external_exports.string().min(1).max(128).optional(),
61948
+ source: external_exports.string().min(1).max(64).optional(),
61949
+ sourceUrl: external_exports.string().url().optional(),
61950
+ title: external_exports.string().min(1).max(256).optional(),
61951
+ parentWorkUnitId: external_exports.string().min(1).max(128).optional()
61557
61952
  });
61558
61953
  var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
61559
61954
  previewUrls: external_exports.record(external_exports.string()).optional(),
61560
61955
  workDir: external_exports.string().optional().describe("Where the session code lives \u2014 ALL file edits must go under this path"),
61561
61956
  worktreePath: external_exports.string().optional(),
61562
61957
  branch: external_exports.string().optional(),
61958
+ workUnitId: external_exports.string().optional(),
61959
+ attemptId: external_exports.string().uuid().optional(),
61563
61960
  blocked: external_exports.boolean().optional(),
61564
61961
  occupiedSlot: external_exports.object({
61565
61962
  agentId: external_exports.number().int(),
@@ -61692,6 +62089,17 @@ var HAR_MCP_TOOLS = [
61692
62089
  resume: {
61693
62090
  type: "boolean",
61694
62091
  description: "Resume a failed or partial launch (status failed/starting) without confirmReplace. Preserves worktree and env."
62092
+ },
62093
+ workUnitId: {
62094
+ type: "string",
62095
+ description: "Durable external work identifier to bind to this session."
62096
+ },
62097
+ source: { type: "string", description: "Optional provider/source name." },
62098
+ sourceUrl: { type: "string", description: "Optional source URL." },
62099
+ title: { type: "string", description: "Optional human-readable work title." },
62100
+ parentWorkUnitId: {
62101
+ type: "string",
62102
+ description: "Optional parent work unit identifier."
61695
62103
  }
61696
62104
  },
61697
62105
  ["agentId"]
@@ -61875,6 +62283,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
61875
62283
  confirmReplace: input.confirmReplace,
61876
62284
  force: input.force,
61877
62285
  resume: input.resume,
62286
+ workUnitId: input.workUnitId,
62287
+ source: input.source,
62288
+ sourceUrl: input.sourceUrl,
62289
+ title: input.title,
62290
+ parentWorkUnitId: input.parentWorkUnitId,
61878
62291
  capture: true
61879
62292
  });
61880
62293
  const parsed = LaunchEnvironmentOutputSchema.parse(result);
@@ -61894,6 +62307,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
61894
62307
  confirmReplace: false,
61895
62308
  force: false,
61896
62309
  resume: true,
62310
+ workUnitId: input.workUnitId,
62311
+ source: input.source,
62312
+ sourceUrl: input.sourceUrl,
62313
+ title: input.title,
62314
+ parentWorkUnitId: input.parentWorkUnitId,
61897
62315
  capture: true
61898
62316
  });
61899
62317
  const parsed = LaunchEnvironmentOutputSchema.parse(result);
@@ -62014,7 +62432,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
62014
62432
  const input = ControlUpInputSchema.parse({ ...args, repo });
62015
62433
  const result = await startControlAndSync({
62016
62434
  detach: input.detach,
62017
- cwd: path50.resolve(input.repo)
62435
+ cwd: path51.resolve(input.repo)
62018
62436
  });
62019
62437
  if (result.code !== 0) {
62020
62438
  return {
@@ -64128,9 +64546,9 @@ var import_run_async = __toESM(require_run_async(), 1);
64128
64546
  var import_mute_stream2 = __toESM(require_lib3(), 1);
64129
64547
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
64130
64548
  var _2 = {
64131
- set: (obj, path52 = "", value) => {
64549
+ set: (obj, path53 = "", value) => {
64132
64550
  let pointer = obj;
64133
- path52.split(".").forEach((key, index, arr) => {
64551
+ path53.split(".").forEach((key, index, arr) => {
64134
64552
  if (key === "__proto__" || key === "constructor")
64135
64553
  return;
64136
64554
  if (index === arr.length - 1) {
@@ -64141,8 +64559,8 @@ var _2 = {
64141
64559
  pointer = pointer[key];
64142
64560
  });
64143
64561
  },
64144
- get: (obj, path52 = "", defaultValue) => {
64145
- const travel = (regexp) => String.prototype.split.call(path52, regexp).filter(Boolean).reduce(
64562
+ get: (obj, path53 = "", defaultValue) => {
64563
+ const travel = (regexp) => String.prototype.split.call(path53, regexp).filter(Boolean).reduce(
64146
64564
  // @ts-expect-error implicit any on res[key]
64147
64565
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
64148
64566
  obj
@@ -64506,7 +64924,7 @@ var preferencesCommand = {
64506
64924
  };
64507
64925
 
64508
64926
  // src/cli/commands/telemetry.ts
64509
- var path51 = __toESM(require("path"));
64927
+ var path52 = __toESM(require("path"));
64510
64928
  init_control_config();
64511
64929
  init_otel_hooks();
64512
64930
  init_telemetry_config();
@@ -64591,7 +65009,7 @@ async function handleOff() {
64591
65009
  info("Mission Control will not auto-start. Existing usage rows are kept.");
64592
65010
  }
64593
65011
  async function handleWriteEnv(argv) {
64594
- const repoPath = path51.resolve(argv.repo);
65012
+ const repoPath = path52.resolve(argv.repo);
64595
65013
  const harnessRoot = resolveHarnessRoot(repoPath);
64596
65014
  const session = readSlotRegistry(harnessRoot, argv.agentId);
64597
65015
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -64603,7 +65021,7 @@ async function handleWriteEnv(argv) {
64603
65021
  suffix,
64604
65022
  createdAt: session?.createdAt
64605
65023
  });
64606
- const envFile = argv.envFile ?? path51.join(workDir, `.env.agent.${argv.agentId}`);
65024
+ const envFile = argv.envFile ?? path52.join(workDir, `.env.agent.${argv.agentId}`);
64607
65025
  const attrs = {
64608
65026
  sessionKey,
64609
65027
  agentId: argv.agentId,
@@ -64622,7 +65040,7 @@ async function handleWriteEnv(argv) {
64622
65040
  success(`Wrote session attribution to ${envFile}`);
64623
65041
  }
64624
65042
  function handlePrintEnv(argv) {
64625
- const repoPath = path51.resolve(argv.repo);
65043
+ const repoPath = path52.resolve(argv.repo);
64626
65044
  const workDir = argv.workDir ?? repoPath;
64627
65045
  const sessionKey = buildSessionKey({
64628
65046
  branch: argv.branch,