@osfactory/har 0.46.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +881 -683
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -553,8 +553,8 @@ var init_parseUtil = __esm({
553
553
  init_errors();
554
554
  init_en();
555
555
  makeIssue = (params) => {
556
- const { data, path: path61, errorMaps, issueData } = params;
557
- const fullPath = [...path61, ...issueData.path || []];
556
+ const { data, path: path62, errorMaps, issueData } = params;
557
+ const fullPath = [...path62, ...issueData.path || []];
558
558
  const fullIssue = {
559
559
  ...issueData,
560
560
  path: fullPath
@@ -862,11 +862,11 @@ var init_types = __esm({
862
862
  init_parseUtil();
863
863
  init_util();
864
864
  ParseInputLazyPath = class {
865
- constructor(parent, value, path61, key) {
865
+ constructor(parent, value, path62, key) {
866
866
  this._cachedPath = [];
867
867
  this.parent = parent;
868
868
  this.data = value;
869
- this._path = path61;
869
+ this._path = path62;
870
870
  this._key = key;
871
871
  }
872
872
  get path() {
@@ -32522,32 +32522,32 @@ __export(otel_hooks_exports, {
32522
32522
  });
32523
32523
  function getOtelHooksHome() {
32524
32524
  if (process.env.HAR_OTEL_HOOKS_HOME) {
32525
- return path46.resolve(process.env.HAR_OTEL_HOOKS_HOME);
32525
+ return path47.resolve(process.env.HAR_OTEL_HOOKS_HOME);
32526
32526
  }
32527
- return path46.join(os15.homedir(), ".har", "otel-hooks");
32527
+ return path47.join(os15.homedir(), ".har", "otel-hooks");
32528
32528
  }
32529
32529
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
32530
- return path46.join(hooksHome, "otel_config.json");
32530
+ return path47.join(hooksHome, "otel_config.json");
32531
32531
  }
32532
32532
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
32533
- return path46.join(hooksHome, "run-otel-hook.sh");
32533
+ return path47.join(hooksHome, "run-otel-hook.sh");
32534
32534
  }
32535
32535
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
32536
- return path46.join(hooksHome, "state");
32536
+ return path47.join(hooksHome, "state");
32537
32537
  }
32538
32538
  function localOtelHookBin(hooksHome) {
32539
- return path46.join(hooksHome, "node_modules", ".bin", "otel-hook");
32539
+ return path47.join(hooksHome, "node_modules", ".bin", "otel-hook");
32540
32540
  }
32541
32541
  function installedPackageVersion(hooksHome) {
32542
32542
  try {
32543
- const pkgPath = path46.join(
32543
+ const pkgPath = path47.join(
32544
32544
  hooksHome,
32545
32545
  "node_modules",
32546
32546
  "@osfactory",
32547
32547
  "otel-hook",
32548
32548
  "package.json"
32549
32549
  );
32550
- const pkg = JSON.parse(fs40.readFileSync(pkgPath, "utf8"));
32550
+ const pkg = JSON.parse(fs41.readFileSync(pkgPath, "utf8"));
32551
32551
  return typeof pkg.version === "string" ? pkg.version : null;
32552
32552
  } catch {
32553
32553
  return null;
@@ -32598,15 +32598,15 @@ function buildOtelHooksConfig(options) {
32598
32598
  };
32599
32599
  }
32600
32600
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
32601
- fs40.mkdirSync(hooksHome, { recursive: true });
32601
+ fs41.mkdirSync(hooksHome, { recursive: true });
32602
32602
  const configPath = getOtelHooksConfigPath(hooksHome);
32603
- fs40.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
32603
+ fs41.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
32604
32604
  `);
32605
32605
  return configPath;
32606
32606
  }
32607
32607
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
32608
- fs40.mkdirSync(hooksHome, { recursive: true });
32609
- fs40.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
32608
+ fs41.mkdirSync(hooksHome, { recursive: true });
32609
+ fs41.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
32610
32610
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
32611
32611
  const configPath = getOtelHooksConfigPath(hooksHome);
32612
32612
  const stateDir = getOtelHooksStateDir(hooksHome);
@@ -32618,9 +32618,9 @@ exec "${otelHookCommand}" run \\
32618
32618
  --state-dir "${stateDir}" \\
32619
32619
  "$@"
32620
32620
  `;
32621
- fs40.writeFileSync(wrapperPath, script, { mode: 493 });
32621
+ fs41.writeFileSync(wrapperPath, script, { mode: 493 });
32622
32622
  try {
32623
- fs40.chmodSync(wrapperPath, 493);
32623
+ fs41.chmodSync(wrapperPath, 493);
32624
32624
  } catch {
32625
32625
  }
32626
32626
  return wrapperPath;
@@ -32633,11 +32633,11 @@ function commandExists2(command2) {
32633
32633
  }
32634
32634
  function resolveOtelHookCommand(hooksHome) {
32635
32635
  const local = localOtelHookBin(hooksHome);
32636
- if (fs40.existsSync(local)) return local;
32636
+ if (fs41.existsSync(local)) return local;
32637
32637
  return null;
32638
32638
  }
32639
32639
  function tryInstallPackage(hooksHome) {
32640
- fs40.mkdirSync(hooksHome, { recursive: true });
32640
+ fs41.mkdirSync(hooksHome, { recursive: true });
32641
32641
  if (!commandExists2("npm")) {
32642
32642
  return {
32643
32643
  ok: false,
@@ -32649,7 +32649,7 @@ function tryInstallPackage(hooksHome) {
32649
32649
  ["install", "--prefix", hooksHome, "--no-fund", "--no-audit", OTEL_HOOKS_PACKAGE],
32650
32650
  { encoding: "utf8", timeout: 18e4 }
32651
32651
  );
32652
- if (result.status === 0 && fs40.existsSync(localOtelHookBin(hooksHome))) {
32652
+ if (result.status === 0 && fs41.existsSync(localOtelHookBin(hooksHome))) {
32653
32653
  return { ok: true, detail: `npm install --prefix ${hooksHome} ${OTEL_HOOKS_PACKAGE}` };
32654
32654
  }
32655
32655
  return {
@@ -32675,14 +32675,14 @@ function uninstallLegacyPythonHooks(hooksHome) {
32675
32675
  }
32676
32676
  function removeLegacyPythonArtifacts(hooksHome) {
32677
32677
  const legacyPaths = [
32678
- path46.join(hooksHome, ".venv"),
32679
- path46.join(hooksHome, "otel_config.yaml"),
32680
- path46.join(hooksHome, "venv")
32678
+ path47.join(hooksHome, ".venv"),
32679
+ path47.join(hooksHome, "otel_config.yaml"),
32680
+ path47.join(hooksHome, "venv")
32681
32681
  ];
32682
32682
  for (const target of legacyPaths) {
32683
32683
  try {
32684
- if (fs40.existsSync(target)) {
32685
- fs40.rmSync(target, { recursive: true, force: true });
32684
+ if (fs41.existsSync(target)) {
32685
+ fs41.rmSync(target, { recursive: true, force: true });
32686
32686
  }
32687
32687
  } catch {
32688
32688
  }
@@ -32723,10 +32723,10 @@ function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
32723
32723
  };
32724
32724
  }
32725
32725
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
32726
- if (!fs40.existsSync(filePath)) return false;
32726
+ if (!fs41.existsSync(filePath)) return false;
32727
32727
  let raw;
32728
32728
  try {
32729
- raw = fs40.readFileSync(filePath, "utf8");
32729
+ raw = fs41.readFileSync(filePath, "utf8");
32730
32730
  } catch {
32731
32731
  return false;
32732
32732
  }
@@ -32773,15 +32773,15 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
32773
32773
  return changed;
32774
32774
  };
32775
32775
  if (!walk(parsed)) return false;
32776
- fs40.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
32776
+ fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
32777
32777
  `);
32778
32778
  return true;
32779
32779
  }
32780
32780
  function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
32781
- if (!fs40.existsSync(filePath)) return false;
32781
+ if (!fs41.existsSync(filePath)) return false;
32782
32782
  let raw;
32783
32783
  try {
32784
- raw = fs40.readFileSync(filePath, "utf8");
32784
+ raw = fs41.readFileSync(filePath, "utf8");
32785
32785
  } catch {
32786
32786
  return false;
32787
32787
  }
@@ -32816,21 +32816,21 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
32816
32816
  }
32817
32817
  }
32818
32818
  if (!changed) return false;
32819
- fs40.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
32819
+ fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
32820
32820
  `);
32821
32821
  return true;
32822
32822
  }
32823
32823
  function rewriteKnownHookRegistrations(wrapperPath) {
32824
32824
  const home = os15.homedir();
32825
32825
  const candidates = [
32826
- path46.join(home, ".cursor", "hooks.json"),
32827
- path46.join(home, ".claude", "settings.json"),
32828
- path46.join(home, ".codex", "hooks.json")
32826
+ path47.join(home, ".cursor", "hooks.json"),
32827
+ path47.join(home, ".claude", "settings.json"),
32828
+ path47.join(home, ".codex", "hooks.json")
32829
32829
  ];
32830
32830
  for (const filePath of candidates) {
32831
32831
  try {
32832
32832
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
32833
- if (filePath.endsWith(`${path46.sep}.cursor${path46.sep}hooks.json`)) {
32833
+ if (filePath.endsWith(`${path47.sep}.cursor${path47.sep}hooks.json`)) {
32834
32834
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
32835
32835
  }
32836
32836
  } catch {
@@ -32846,7 +32846,7 @@ function ensureOtelHooks(options) {
32846
32846
  const hooksHome = getOtelHooksHome();
32847
32847
  const errors = [];
32848
32848
  const providersSetup = [];
32849
- fs40.mkdirSync(hooksHome, { recursive: true });
32849
+ fs41.mkdirSync(hooksHome, { recursive: true });
32850
32850
  let otelHookCommand = resolveOtelHookCommand(hooksHome);
32851
32851
  const needsInstall = !otelHookCommand || installedPackageVersion(hooksHome) !== pinnedVersion();
32852
32852
  if (needsInstall) {
@@ -32940,14 +32940,14 @@ function ensureOtelHooks(options) {
32940
32940
  function disableOtelHooksExport() {
32941
32941
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
32942
32942
  }
32943
- var import_child_process10, fs40, os15, path46, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
32943
+ var import_child_process10, fs41, os15, path47, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
32944
32944
  var init_otel_hooks = __esm({
32945
32945
  "src/core/otel-hooks.ts"() {
32946
32946
  "use strict";
32947
32947
  import_child_process10 = require("child_process");
32948
- fs40 = __toESM(require("fs"));
32948
+ fs41 = __toESM(require("fs"));
32949
32949
  os15 = __toESM(require("os"));
32950
- path46 = __toESM(require("path"));
32950
+ path47 = __toESM(require("path"));
32951
32951
  init_control_config();
32952
32952
  init_telemetry_config();
32953
32953
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.1.2";
@@ -34063,15 +34063,15 @@ var require_route = __commonJS({
34063
34063
  };
34064
34064
  }
34065
34065
  function wrapConversion(toModel, graph) {
34066
- const path61 = [graph[toModel].parent, toModel];
34066
+ const path62 = [graph[toModel].parent, toModel];
34067
34067
  let fn = conversions[graph[toModel].parent][toModel];
34068
34068
  let cur = graph[toModel].parent;
34069
34069
  while (graph[cur].parent) {
34070
- path61.unshift(graph[cur].parent);
34070
+ path62.unshift(graph[cur].parent);
34071
34071
  fn = link(conversions[graph[cur].parent][cur], fn);
34072
34072
  cur = graph[cur].parent;
34073
34073
  }
34074
- fn.conversion = path61;
34074
+ fn.conversion = path62;
34075
34075
  return fn;
34076
34076
  }
34077
34077
  module2.exports = function(fromModel) {
@@ -40001,7 +40001,7 @@ var require_iso2022 = __commonJS({
40001
40001
  // node_modules/chardet/index.js
40002
40002
  var require_chardet = __commonJS({
40003
40003
  "node_modules/chardet/index.js"(exports2, module2) {
40004
- var fs47 = require("fs");
40004
+ var fs48 = require("fs");
40005
40005
  var utf8 = require_utf8();
40006
40006
  var unicode = require_unicode();
40007
40007
  var mbcs = require_mbcs();
@@ -40075,28 +40075,28 @@ var require_chardet = __commonJS({
40075
40075
  var fd;
40076
40076
  var handler = function(err, buffer) {
40077
40077
  if (fd) {
40078
- fs47.closeSync(fd);
40078
+ fs48.closeSync(fd);
40079
40079
  }
40080
40080
  if (err) return cb(err, null);
40081
40081
  cb(null, self.detect(buffer, opts));
40082
40082
  };
40083
40083
  if (opts && opts.sampleSize) {
40084
- fd = fs47.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
40085
- fs47.read(fd, sample, 0, opts.sampleSize, null, function(err) {
40084
+ fd = fs48.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
40085
+ fs48.read(fd, sample, 0, opts.sampleSize, null, function(err) {
40086
40086
  handler(err, sample);
40087
40087
  });
40088
40088
  return;
40089
40089
  }
40090
- fs47.readFile(filepath, handler);
40090
+ fs48.readFile(filepath, handler);
40091
40091
  };
40092
40092
  module2.exports.detectFileSync = function(filepath, opts) {
40093
40093
  if (opts && opts.sampleSize) {
40094
- var fd = fs47.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
40095
- fs47.readSync(fd, sample2, 0, opts.sampleSize);
40096
- fs47.closeSync(fd);
40094
+ var fd = fs48.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
40095
+ fs48.readSync(fd, sample2, 0, opts.sampleSize);
40096
+ fs48.closeSync(fd);
40097
40097
  return self.detect(sample2, opts);
40098
40098
  }
40099
- return self.detect(fs47.readFileSync(filepath), opts);
40099
+ return self.detect(fs48.readFileSync(filepath), opts);
40100
40100
  };
40101
40101
  module2.exports.detectAll = function(buffer, opts) {
40102
40102
  if (typeof opts !== "object") {
@@ -43561,16 +43561,16 @@ var require_os_tmpdir = __commonJS({
43561
43561
  var isWindows = process.platform === "win32";
43562
43562
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
43563
43563
  module2.exports = function() {
43564
- var path61;
43564
+ var path62;
43565
43565
  if (isWindows) {
43566
- path61 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
43566
+ path62 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
43567
43567
  } else {
43568
- path61 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
43568
+ path62 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
43569
43569
  }
43570
- if (trailingSlashRe.test(path61)) {
43571
- path61 = path61.slice(0, -1);
43570
+ if (trailingSlashRe.test(path62)) {
43571
+ path62 = path62.slice(0, -1);
43572
43572
  }
43573
- return path61;
43573
+ return path62;
43574
43574
  };
43575
43575
  }
43576
43576
  });
@@ -43578,8 +43578,8 @@ var require_os_tmpdir = __commonJS({
43578
43578
  // node_modules/tmp/lib/tmp.js
43579
43579
  var require_tmp = __commonJS({
43580
43580
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
43581
- var fs47 = require("fs");
43582
- var path61 = require("path");
43581
+ var fs48 = require("fs");
43582
+ var path62 = require("path");
43583
43583
  var crypto6 = require("crypto");
43584
43584
  var osTmpDir = require_os_tmpdir();
43585
43585
  var _c2 = process.binding("constants");
@@ -43621,7 +43621,7 @@ var require_tmp = __commonJS({
43621
43621
  }
43622
43622
  function _generateTmpName(opts) {
43623
43623
  if (opts.name) {
43624
- return path61.join(opts.dir || tmpDir, opts.name);
43624
+ return path62.join(opts.dir || tmpDir, opts.name);
43625
43625
  }
43626
43626
  if (opts.template) {
43627
43627
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -43632,7 +43632,7 @@ var require_tmp = __commonJS({
43632
43632
  _randomChars(12),
43633
43633
  opts.postfix || ""
43634
43634
  ].join("");
43635
- return path61.join(opts.dir || tmpDir, name);
43635
+ return path62.join(opts.dir || tmpDir, name);
43636
43636
  }
43637
43637
  function tmpName(options, callback) {
43638
43638
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -43642,7 +43642,7 @@ var require_tmp = __commonJS({
43642
43642
  return cb(new Error("Invalid template provided"));
43643
43643
  (function _getUniqueName() {
43644
43644
  const name = _generateTmpName(opts);
43645
- fs47.stat(name, function(err) {
43645
+ fs48.stat(name, function(err) {
43646
43646
  if (!err) {
43647
43647
  if (tries-- > 0) return _getUniqueName();
43648
43648
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -43660,7 +43660,7 @@ var require_tmp = __commonJS({
43660
43660
  do {
43661
43661
  const name = _generateTmpName(opts);
43662
43662
  try {
43663
- fs47.statSync(name);
43663
+ fs48.statSync(name);
43664
43664
  } catch (e) {
43665
43665
  return name;
43666
43666
  }
@@ -43672,13 +43672,13 @@ var require_tmp = __commonJS({
43672
43672
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
43673
43673
  tmpName(opts, function _tmpNameCreated(err, name) {
43674
43674
  if (err) return cb(err);
43675
- fs47.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
43675
+ fs48.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
43676
43676
  if (err2) return cb(err2);
43677
43677
  if (opts.discardDescriptor) {
43678
- return fs47.close(fd, function _discardCallback(err3) {
43678
+ return fs48.close(fd, function _discardCallback(err3) {
43679
43679
  if (err3) {
43680
43680
  try {
43681
- fs47.unlinkSync(name);
43681
+ fs48.unlinkSync(name);
43682
43682
  } catch (e) {
43683
43683
  if (!isENOENT(e)) {
43684
43684
  err3 = e;
@@ -43701,9 +43701,9 @@ var require_tmp = __commonJS({
43701
43701
  opts.postfix = opts.postfix || ".tmp";
43702
43702
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
43703
43703
  const name = tmpNameSync(opts);
43704
- var fd = fs47.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
43704
+ var fd = fs48.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
43705
43705
  if (opts.discardDescriptor) {
43706
- fs47.closeSync(fd);
43706
+ fs48.closeSync(fd);
43707
43707
  fd = void 0;
43708
43708
  }
43709
43709
  return {
@@ -43715,9 +43715,9 @@ var require_tmp = __commonJS({
43715
43715
  function _rmdirRecursiveSync(root) {
43716
43716
  const dirs = [root];
43717
43717
  do {
43718
- var dir2 = dirs.pop(), deferred = false, files = fs47.readdirSync(dir2);
43718
+ var dir2 = dirs.pop(), deferred = false, files = fs48.readdirSync(dir2);
43719
43719
  for (var i = 0, length = files.length; i < length; i++) {
43720
- var file2 = path61.join(dir2, files[i]), stat = fs47.lstatSync(file2);
43720
+ var file2 = path62.join(dir2, files[i]), stat = fs48.lstatSync(file2);
43721
43721
  if (stat.isDirectory()) {
43722
43722
  if (!deferred) {
43723
43723
  deferred = true;
@@ -43725,11 +43725,11 @@ var require_tmp = __commonJS({
43725
43725
  }
43726
43726
  dirs.push(file2);
43727
43727
  } else {
43728
- fs47.unlinkSync(file2);
43728
+ fs48.unlinkSync(file2);
43729
43729
  }
43730
43730
  }
43731
43731
  if (!deferred) {
43732
- fs47.rmdirSync(dir2);
43732
+ fs48.rmdirSync(dir2);
43733
43733
  }
43734
43734
  } while (dirs.length !== 0);
43735
43735
  }
@@ -43737,7 +43737,7 @@ var require_tmp = __commonJS({
43737
43737
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
43738
43738
  tmpName(opts, function _tmpNameCreated(err, name) {
43739
43739
  if (err) return cb(err);
43740
- fs47.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
43740
+ fs48.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
43741
43741
  if (err2) return cb(err2);
43742
43742
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
43743
43743
  });
@@ -43746,7 +43746,7 @@ var require_tmp = __commonJS({
43746
43746
  function dirSync(options) {
43747
43747
  var args = _parseArguments(options), opts = args[0];
43748
43748
  const name = tmpNameSync(opts);
43749
- fs47.mkdirSync(name, opts.mode || DIR_MODE);
43749
+ fs48.mkdirSync(name, opts.mode || DIR_MODE);
43750
43750
  return {
43751
43751
  name,
43752
43752
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -43756,7 +43756,7 @@ var require_tmp = __commonJS({
43756
43756
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
43757
43757
  try {
43758
43758
  if (0 <= fdPath[0]) {
43759
- fs47.closeSync(fdPath[0]);
43759
+ fs48.closeSync(fdPath[0]);
43760
43760
  }
43761
43761
  } catch (e) {
43762
43762
  if (!isEBADF(e) && !isENOENT(e)) {
@@ -43764,7 +43764,7 @@ var require_tmp = __commonJS({
43764
43764
  }
43765
43765
  }
43766
43766
  try {
43767
- fs47.unlinkSync(fdPath[1]);
43767
+ fs48.unlinkSync(fdPath[1]);
43768
43768
  } catch (e) {
43769
43769
  if (!isENOENT(e)) {
43770
43770
  throw e;
@@ -43777,7 +43777,7 @@ var require_tmp = __commonJS({
43777
43777
  return removeCallback;
43778
43778
  }
43779
43779
  function _prepareTmpDirRemoveCallback(name, opts) {
43780
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs47.rmdirSync.bind(fs47);
43780
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs48.rmdirSync.bind(fs48);
43781
43781
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
43782
43782
  if (!opts.keep) {
43783
43783
  _removeObjects.unshift(removeCallback);
@@ -56910,8 +56910,8 @@ var require_utils = __commonJS({
56910
56910
  }
56911
56911
  return ind;
56912
56912
  }
56913
- function removeDotSegments(path61) {
56914
- let input = path61;
56913
+ function removeDotSegments(path62) {
56914
+ let input = path62;
56915
56915
  const output = [];
56916
56916
  let nextSlash = -1;
56917
56917
  let len = 0;
@@ -57163,8 +57163,8 @@ var require_schemes = __commonJS({
57163
57163
  wsComponent.secure = void 0;
57164
57164
  }
57165
57165
  if (wsComponent.resourceName) {
57166
- const [path61, query] = wsComponent.resourceName.split("?");
57167
- wsComponent.path = path61 && path61 !== "/" ? path61 : void 0;
57166
+ const [path62, query] = wsComponent.resourceName.split("?");
57167
+ wsComponent.path = path62 && path62 !== "/" ? path62 : void 0;
57168
57168
  wsComponent.query = query;
57169
57169
  wsComponent.resourceName = void 0;
57170
57170
  }
@@ -60557,12 +60557,12 @@ var require_dist = __commonJS({
60557
60557
  throw new Error(`Unknown format "${name}"`);
60558
60558
  return f;
60559
60559
  };
60560
- function addFormats(ajv, list, fs47, exportName) {
60560
+ function addFormats(ajv, list, fs48, exportName) {
60561
60561
  var _a2;
60562
60562
  var _b2;
60563
60563
  (_a2 = (_b2 = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
60564
60564
  for (const f of list)
60565
- ajv.addFormat(f, fs47[f]);
60565
+ ajv.addFormat(f, fs48[f]);
60566
60566
  }
60567
60567
  module2.exports = exports2 = formatsPlugin;
60568
60568
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -61846,11 +61846,11 @@ var parser = new YargsParser({
61846
61846
  resolve: import_path2.resolve,
61847
61847
  // TODO: figure out a way to combine ESM and CJS coverage, such that
61848
61848
  // we can exercise all the lines below:
61849
- require: (path61) => {
61849
+ require: (path62) => {
61850
61850
  if (typeof require !== "undefined") {
61851
- return require(path61);
61852
- } else if (path61.match(/\.json$/)) {
61853
- return JSON.parse((0, import_fs2.readFileSync)(path61, "utf8"));
61851
+ return require(path62);
61852
+ } else if (path62.match(/\.json$/)) {
61853
+ return JSON.parse((0, import_fs2.readFileSync)(path62, "utf8"));
61854
61854
  } else {
61855
61855
  throw Error("only .json config files are supported in ESM");
61856
61856
  }
@@ -65759,7 +65759,7 @@ function handleRemove(argv) {
65759
65759
  }
65760
65760
 
65761
65761
  // src/cli/commands/env.ts
65762
- var path50 = __toESM(require("path"));
65762
+ var path51 = __toESM(require("path"));
65763
65763
 
65764
65764
  // src/cli/finish-command.ts
65765
65765
  init_sync_context();
@@ -65769,8 +65769,8 @@ async function finishCommand(code) {
65769
65769
  }
65770
65770
 
65771
65771
  // src/core/harness.ts
65772
- var fs36 = __toESM(require("fs"));
65773
- var path41 = __toESM(require("path"));
65772
+ var fs37 = __toESM(require("fs"));
65773
+ var path42 = __toESM(require("path"));
65774
65774
 
65775
65775
  // src/harness/generator.ts
65776
65776
  var fs28 = __toESM(require("fs"));
@@ -65894,9 +65894,485 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
65894
65894
  success("Harness adaptation complete.");
65895
65895
  }
65896
65896
 
65897
- // src/harness/validator.ts
65897
+ // src/harness/agent-md.ts
65898
+ var fs30 = __toESM(require("fs"));
65899
+ var path36 = __toESM(require("path"));
65900
+ init_file_ops();
65901
+ init_logging();
65902
+ init_manifest();
65903
+
65904
+ // src/harness/instruction-files.ts
65898
65905
  var fs29 = __toESM(require("fs"));
65906
+ var os13 = __toESM(require("os"));
65899
65907
  var path35 = __toESM(require("path"));
65908
+ var readline2 = __toESM(require("readline"));
65909
+ init_file_ops();
65910
+ init_logging();
65911
+ var AGENTS_MD = "AGENTS.md";
65912
+ var LEGACY_AGENT_MD = "AGENT.md";
65913
+ var CLAUDE_MD = "CLAUDE.md";
65914
+ var HAR_SECTION_START = "<!-- har:agent-environment:start -->";
65915
+ var HAR_SECTION_END = "<!-- har:agent-environment:end -->";
65916
+ var CLAUDE_HAR_SECTION_START = "<!-- har:claude-pointer:start -->";
65917
+ var CLAUDE_HAR_SECTION_END = "<!-- har:claude-pointer:end -->";
65918
+ var AgentsMdShrinkError = class extends Error {
65919
+ constructor(message) {
65920
+ super(message);
65921
+ this.name = "AgentsMdShrinkError";
65922
+ }
65923
+ };
65924
+ function escapeRegExp(value) {
65925
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
65926
+ }
65927
+ function countNonEmptyLines(text) {
65928
+ return text.split("\n").filter((line) => line.trim().length > 0).length;
65929
+ }
65930
+ function stripClaudePointerFromAgentsMd(content) {
65931
+ if (!content.includes(CLAUDE_HAR_SECTION_START)) return content;
65932
+ const pattern = new RegExp(
65933
+ `${escapeRegExp(CLAUDE_HAR_SECTION_START)}[\\s\\S]*?${escapeRegExp(CLAUDE_HAR_SECTION_END)}\\n?`,
65934
+ "g"
65935
+ );
65936
+ return content.replace(pattern, "").replace(/\n{3,}/g, "\n\n");
65937
+ }
65938
+ function extractOutsideHarSection(content) {
65939
+ const sanitized = stripClaudePointerFromAgentsMd(content);
65940
+ return removeCompleteMarkedBlocks(sanitized, HAR_SECTION_START, HAR_SECTION_END).trim();
65941
+ }
65942
+ function findLastCompleteMarkedBlock(content, startMarker, endMarker) {
65943
+ let last = null;
65944
+ let searchFrom = 0;
65945
+ while (searchFrom < content.length) {
65946
+ const start = content.indexOf(startMarker, searchFrom);
65947
+ if (start === -1) break;
65948
+ const end = content.indexOf(endMarker, start + startMarker.length);
65949
+ if (end === -1) break;
65950
+ const nestedStart = content.indexOf(startMarker, start + startMarker.length);
65951
+ if (nestedStart !== -1 && nestedStart < end) {
65952
+ searchFrom = start + startMarker.length;
65953
+ continue;
65954
+ }
65955
+ last = { start, end: end + endMarker.length };
65956
+ searchFrom = end + endMarker.length;
65957
+ }
65958
+ return last;
65959
+ }
65960
+ function removeCompleteMarkedBlocks(content, startMarker, endMarker) {
65961
+ let result = content;
65962
+ let block = findLastCompleteMarkedBlock(result, startMarker, endMarker);
65963
+ while (block) {
65964
+ result = result.slice(0, block.start) + result.slice(block.end);
65965
+ block = findLastCompleteMarkedBlock(result, startMarker, endMarker);
65966
+ }
65967
+ return result;
65968
+ }
65969
+ function checkOutsideContentPreserved(before, after, options) {
65970
+ const outsideBefore = extractOutsideHarSection(before);
65971
+ const outsideAfter = extractOutsideHarSection(after);
65972
+ const beforeLines = countNonEmptyLines(outsideBefore);
65973
+ const afterLines = countNonEmptyLines(outsideAfter);
65974
+ const minRatio = options.minOutsidePreservationRatio ?? 0.9;
65975
+ if (beforeLines >= 5 && afterLines < beforeLines * minRatio) {
65976
+ return "shrink";
65977
+ }
65978
+ return "ok";
65979
+ }
65980
+ function outsideContentShrinkMessage(beforeLines, afterLines) {
65981
+ return `Refusing to update ${AGENTS_MD}: refresh would drop project-specific content outside har:agent-environment markers (${beforeLines} \u2192 ${afterLines} non-empty lines). Keep custom sections outside those markers, or merge manually before --finalize.`;
65982
+ }
65983
+ function detectInstructionFiles(repoPath) {
65984
+ return {
65985
+ agentsMd: fs29.existsSync(path35.join(repoPath, AGENTS_MD)),
65986
+ agentMd: fs29.existsSync(path35.join(repoPath, LEGACY_AGENT_MD)),
65987
+ claudeMd: fs29.existsSync(path35.join(repoPath, CLAUDE_MD)),
65988
+ cursorDir: fs29.existsSync(path35.join(repoPath, ".cursor")),
65989
+ claudeDir: fs29.existsSync(path35.join(repoPath, ".claude")),
65990
+ codexHome: fs29.existsSync(path35.join(os13.homedir(), ".codex"))
65991
+ };
65992
+ }
65993
+ function formatDetectionReport(detection) {
65994
+ const lines2 = ["Detected:"];
65995
+ lines2.push(` - ${AGENTS_MD} (${detection.agentsMd ? "exists" : "missing"})`);
65996
+ if (detection.agentMd) {
65997
+ lines2.push(` - ${LEGACY_AGENT_MD} (legacy \u2014 will migrate into ${AGENTS_MD})`);
65998
+ }
65999
+ lines2.push(` - ${CLAUDE_MD} (${detection.claudeMd ? "exists" : "missing"})`);
66000
+ lines2.push(` - .cursor/ (${detection.cursorDir ? "exists" : "missing"})`);
66001
+ lines2.push(` - .claude/ (${detection.claudeDir ? "exists" : "missing"})`);
66002
+ lines2.push(` - ~/.codex (${detection.codexHome ? "exists" : "missing"})`);
66003
+ return lines2.join("\n");
66004
+ }
66005
+ function buildInstallPlan(detection, targets, options = {}) {
66006
+ const writeAgentsMd = options.writeAgentsMd !== false;
66007
+ const skillsEnabled = options.skillsEnabled !== false;
66008
+ const cursorExplicit = options.cursorRule;
66009
+ const wantsCursor = cursorExplicit === true || cursorExplicit !== false && (targets.includes("cursor") || detection.cursorDir);
66010
+ return {
66011
+ agentsMd: writeAgentsMd,
66012
+ migrateLegacyAgentMd: writeAgentsMd && detection.agentMd,
66013
+ claudeMd: skillsEnabled && targets.includes("claude"),
66014
+ cursorRule: wantsCursor,
66015
+ skills: skillsEnabled ? targets : []
66016
+ };
66017
+ }
66018
+ function formatInstallPlan(plan, detection) {
66019
+ const mark = (on) => on ? "[x]" : "[ ]";
66020
+ const lines2 = ["After you confirm, HAR will:"];
66021
+ const agentsAction = detection.agentsMd ? `Update ${AGENTS_MD} \u2014 refresh HAR / agent environment section` : `Create ${AGENTS_MD} \u2014 shared HAR workflow (Codex + cross-tool)`;
66022
+ lines2.push(` ${mark(plan.agentsMd)} ${agentsAction}`);
66023
+ if (plan.migrateLegacyAgentMd) {
66024
+ lines2.push(` ${mark(true)} Migrate ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD}, then remove legacy file`);
66025
+ }
66026
+ lines2.push(
66027
+ ` ${mark(plan.claudeMd)} Claude \u2014 ensure ${CLAUDE_MD} points at ${AGENTS_MD}; install .claude/skills if confirmed`
66028
+ );
66029
+ lines2.push(
66030
+ ` ${mark(plan.cursorRule)} Cursor \u2014 install/refresh .cursor/rules/har-workflow.mdc + commands if confirmed`
66031
+ );
66032
+ lines2.push(
66033
+ ` ${mark(plan.skills.includes("codex"))} Codex \u2014 global ~/.codex/prompts (skills); project contract is ${AGENTS_MD}`
66034
+ );
66035
+ return lines2.join("\n");
66036
+ }
66037
+ function loadHarAgentsSectionFromTemplate() {
66038
+ const templatePath = resolveTemplateFile("AGENTS.md.template");
66039
+ if (!templatePath) {
66040
+ throw new Error("AGENTS.md.template not found. Run npm run build.");
66041
+ }
66042
+ const content = fs29.readFileSync(templatePath, "utf8");
66043
+ const start = content.indexOf(HAR_SECTION_START);
66044
+ const end = content.indexOf(HAR_SECTION_END);
66045
+ if (start === -1 || end === -1 || end < start) {
66046
+ throw new Error("AGENTS.md.template is missing har:agent-environment markers.");
66047
+ }
66048
+ return content.slice(start, end + HAR_SECTION_END.length);
66049
+ }
66050
+ function loadAgentsMdTemplate() {
66051
+ const templatePath = resolveTemplateFile("AGENTS.md.template");
66052
+ if (!templatePath) {
66053
+ throw new Error("AGENTS.md.template not found. Run npm run build.");
66054
+ }
66055
+ return fs29.readFileSync(templatePath, "utf8");
66056
+ }
66057
+ function upsertMarkedBlock(content, block, startMarker, endMarker) {
66058
+ const existingBlock = findLastCompleteMarkedBlock(content, startMarker, endMarker);
66059
+ if (existingBlock) {
66060
+ const newContent = content.slice(0, existingBlock.start) + block + content.slice(existingBlock.end);
66061
+ return { content: newContent, action: "updated" };
66062
+ }
66063
+ const suffix = content.endsWith("\n") ? "" : "\n";
66064
+ return { content: `${content}${suffix}
66065
+ ${block}
66066
+ `, action: "appended" };
66067
+ }
66068
+ function mergeAgentsMdContent(existing, incoming) {
66069
+ const sanitizedExisting = stripClaudePointerFromAgentsMd(existing);
66070
+ const sanitizedIncoming = stripClaudePointerFromAgentsMd(incoming);
66071
+ let harSection = loadHarAgentsSectionFromTemplate();
66072
+ if (sanitizedIncoming.includes(HAR_SECTION_START)) {
66073
+ const start = sanitizedIncoming.indexOf(HAR_SECTION_START);
66074
+ const end = sanitizedIncoming.indexOf(HAR_SECTION_END, start + HAR_SECTION_START.length);
66075
+ if (end !== -1) {
66076
+ harSection = sanitizedIncoming.slice(start, end + HAR_SECTION_END.length);
66077
+ }
66078
+ }
66079
+ const { content } = upsertMarkedBlock(
66080
+ sanitizedExisting,
66081
+ harSection,
66082
+ HAR_SECTION_START,
66083
+ HAR_SECTION_END
66084
+ );
66085
+ return content;
66086
+ }
66087
+ function upsertAgentsMdHarSection(repoPath, options = {}) {
66088
+ const dest = path35.join(repoPath, AGENTS_MD);
66089
+ const section = loadHarAgentsSectionFromTemplate();
66090
+ if (!fs29.existsSync(dest)) {
66091
+ writeFileSafe(dest, loadAgentsMdTemplate());
66092
+ return "created";
66093
+ }
66094
+ const existing = fs29.readFileSync(dest, "utf8");
66095
+ const sanitized = stripClaudePointerFromAgentsMd(existing);
66096
+ const { content, action } = upsertMarkedBlock(
66097
+ sanitized,
66098
+ section,
66099
+ HAR_SECTION_START,
66100
+ HAR_SECTION_END
66101
+ );
66102
+ if (checkOutsideContentPreserved(existing, content, options) === "shrink") {
66103
+ const beforeLines = countNonEmptyLines(extractOutsideHarSection(existing));
66104
+ const afterLines = countNonEmptyLines(extractOutsideHarSection(content));
66105
+ const message = outsideContentShrinkMessage(beforeLines, afterLines);
66106
+ if (options.rejectSignificantShrink) {
66107
+ throw new AgentsMdShrinkError(message);
66108
+ }
66109
+ warn(message);
66110
+ return "skipped";
66111
+ }
66112
+ if (content === existing) {
66113
+ return "skipped";
66114
+ }
66115
+ writeFileSafe(dest, content);
66116
+ return action;
66117
+ }
66118
+ function migrateLegacyAgentMd(repoPath) {
66119
+ const legacyPath = path35.join(repoPath, LEGACY_AGENT_MD);
66120
+ const agentsPath = path35.join(repoPath, AGENTS_MD);
66121
+ if (!fs29.existsSync(legacyPath)) return false;
66122
+ const legacy = fs29.readFileSync(legacyPath, "utf8");
66123
+ if (!fs29.existsSync(agentsPath)) {
66124
+ writeFileSafe(agentsPath, legacy);
66125
+ upsertAgentsMdHarSection(repoPath);
66126
+ } else {
66127
+ const agents = fs29.readFileSync(agentsPath, "utf8");
66128
+ const legacyTrimmed = legacy.trim();
66129
+ if (legacyTrimmed.length > 0 && !agents.includes(legacyTrimmed)) {
66130
+ const suffix = agents.endsWith("\n") ? "" : "\n";
66131
+ writeFileSafe(agentsPath, `${agents}${suffix}
66132
+ ${legacyTrimmed}
66133
+ `);
66134
+ }
66135
+ upsertAgentsMdHarSection(repoPath);
66136
+ }
66137
+ fs29.unlinkSync(legacyPath);
66138
+ info(`Migrated ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD} (removed legacy file)`);
66139
+ return true;
66140
+ }
66141
+ function loadClaudeMdTemplate(projectName) {
66142
+ const templatePath = resolveTemplateFile("CLAUDE.md.template");
66143
+ if (!templatePath) {
66144
+ throw new Error("CLAUDE.md.template not found. Run npm run build.");
66145
+ }
66146
+ const displayName = projectName.replace(/_/g, " ");
66147
+ return fs29.readFileSync(templatePath, "utf8").replace(/__PROJECT_DISPLAY_NAME__/g, displayName);
66148
+ }
66149
+ function isThinClaudePointer(content) {
66150
+ const trimmed = content.trim();
66151
+ if (trimmed.length > 600) return false;
66152
+ return /AGENTS\.md|AGENT\.md/.test(trimmed) && (trimmed.includes(".har/README.md") || trimmed.includes("har-workflow"));
66153
+ }
66154
+ var CLAUDE_POINTER_BLOCK = `${CLAUDE_HAR_SECTION_START}
66155
+ ## HAR
66156
+
66157
+ This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
66158
+ [\`.har/README.md\`](./.har/README.md) before making changes.
66159
+ ${CLAUDE_HAR_SECTION_END}`;
66160
+ function ensureClaudeMdPointer(repoPath, options = {}) {
66161
+ const dest = path35.join(repoPath, CLAUDE_MD);
66162
+ const projectName = path35.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
66163
+ const thin = loadClaudeMdTemplate(projectName);
66164
+ if (!fs29.existsSync(dest)) {
66165
+ writeFileSafe(dest, thin);
66166
+ return "created";
66167
+ }
66168
+ const existing = fs29.readFileSync(dest, "utf8");
66169
+ if (isThinClaudePointer(existing) || options.force) {
66170
+ writeFileSafe(dest, thin);
66171
+ return "updated";
66172
+ }
66173
+ if (existing.includes(CLAUDE_HAR_SECTION_START) || /\[AGENTS\.md\]/.test(existing)) {
66174
+ if (existing.includes(CLAUDE_HAR_SECTION_START)) {
66175
+ const { content: content2, action: action2 } = upsertMarkedBlock(
66176
+ existing,
66177
+ CLAUDE_POINTER_BLOCK,
66178
+ CLAUDE_HAR_SECTION_START,
66179
+ CLAUDE_HAR_SECTION_END
66180
+ );
66181
+ writeFileSafe(dest, content2);
66182
+ return action2;
66183
+ }
66184
+ return "skipped";
66185
+ }
66186
+ const { content, action } = upsertMarkedBlock(
66187
+ existing,
66188
+ CLAUDE_POINTER_BLOCK,
66189
+ CLAUDE_HAR_SECTION_START,
66190
+ CLAUDE_HAR_SECTION_END
66191
+ );
66192
+ writeFileSafe(dest, content);
66193
+ return action;
66194
+ }
66195
+ async function askYesNo2(question, defaultYes = true) {
66196
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
66197
+ return new Promise((resolve47) => {
66198
+ process.stderr.write(`${question} `);
66199
+ rl.once("line", (answer) => {
66200
+ rl.close();
66201
+ const trimmed = answer.trim();
66202
+ if (trimmed === "") {
66203
+ resolve47(defaultYes);
66204
+ return;
66205
+ }
66206
+ resolve47(/^y(es)?$/i.test(trimmed));
66207
+ });
66208
+ });
66209
+ }
66210
+ async function handleInstructionFiles(options) {
66211
+ const { repoPath, mode } = options;
66212
+ const writeAgentsMd = options.writeAgentsMd !== false;
66213
+ const skillsEnabled = options.enabled !== false;
66214
+ const detection = detectInstructionFiles(repoPath);
66215
+ let targets;
66216
+ if (!skillsEnabled) {
66217
+ targets = [];
66218
+ } else if (typeof options.agents === "string") {
66219
+ targets = parseAgentTargets(options.agents);
66220
+ } else {
66221
+ targets = detectAgentTargets(repoPath);
66222
+ }
66223
+ if (skillsEnabled && targets.length === 0 && mode === "init" && typeof options.agents !== "string" && !options.autoYes) {
66224
+ targets = [...AGENT_SKILL_TARGETS];
66225
+ }
66226
+ let plan = buildInstallPlan(detection, targets, {
66227
+ writeAgentsMd,
66228
+ cursorRule: options.cursorRule,
66229
+ skillsEnabled
66230
+ });
66231
+ divider();
66232
+ process.stderr.write(`${formatDetectionReport(detection)}
66233
+
66234
+ `);
66235
+ process.stderr.write(`${formatInstallPlan(plan, detection)}
66236
+ `);
66237
+ divider();
66238
+ const shouldPrompt = !options.autoYes && skillsEnabled && typeof options.agents !== "string" && !(mode === "maintain" && targets.length > 0 && !detection.agentMd);
66239
+ if (shouldPrompt && targets.length > 0) {
66240
+ const accepted = await askYesNo2(
66241
+ `Install HAR agent instructions for: ${targets.join(", ")}? [Y/n]`
66242
+ );
66243
+ if (!accepted) {
66244
+ info("Skipped agent instruction adapters (AGENTS.md will still be updated)");
66245
+ targets = [];
66246
+ plan = buildInstallPlan(detection, targets, {
66247
+ writeAgentsMd,
66248
+ cursorRule: options.cursorRule === true ? true : false,
66249
+ skillsEnabled: false
66250
+ });
66251
+ }
66252
+ }
66253
+ let migratedLegacy = false;
66254
+ let agentsMdAction = null;
66255
+ let claudeMdAction = null;
66256
+ if (writeAgentsMd) {
66257
+ if (detection.agentMd) {
66258
+ migratedLegacy = migrateLegacyAgentMd(repoPath);
66259
+ }
66260
+ agentsMdAction = upsertAgentsMdHarSection(repoPath, {
66261
+ rejectSignificantShrink: options.finalize === true
66262
+ });
66263
+ if (agentsMdAction === "created") {
66264
+ success(`Wrote ${AGENTS_MD}`);
66265
+ } else if (agentsMdAction === "updated" || agentsMdAction === "appended") {
66266
+ info(
66267
+ `${agentsMdAction === "updated" ? "Refreshed" : "Appended"} HAR section in ${AGENTS_MD}`
66268
+ );
66269
+ } else if (agentsMdAction === "skipped" && options.finalize) {
66270
+ warn(
66271
+ `${AGENTS_MD} left unchanged \u2014 project-specific content outside har:agent-environment markers was preserved.`
66272
+ );
66273
+ }
66274
+ } else {
66275
+ agentsMdAction = "skipped";
66276
+ }
66277
+ if (plan.claudeMd) {
66278
+ claudeMdAction = ensureClaudeMdPointer(repoPath);
66279
+ if (claudeMdAction === "created") {
66280
+ success(`Wrote ${CLAUDE_MD} (pointer \u2192 ${AGENTS_MD})`);
66281
+ } else if (claudeMdAction === "updated" || claudeMdAction === "appended") {
66282
+ info(
66283
+ `${claudeMdAction === "updated" ? "Updated" : "Appended"} ${CLAUDE_MD} pointer \u2192 ${AGENTS_MD}`
66284
+ );
66285
+ }
66286
+ } else {
66287
+ claudeMdAction = "skipped";
66288
+ }
66289
+ return {
66290
+ detection,
66291
+ plan,
66292
+ targets,
66293
+ agentsMdAction,
66294
+ migratedLegacy,
66295
+ claudeMdAction
66296
+ };
66297
+ }
66298
+
66299
+ // src/harness/agent-md.ts
66300
+ var AGENTS_MD_PROPOSAL = "AGENTS.md.proposed";
66301
+ var AGENTS_MD_PROPOSAL_META = "AGENTS.md.proposed.meta.json";
66302
+ var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
66303
+ var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
66304
+ function readAgentMdProposal(repoPath) {
66305
+ const harnessDir = getHarnessDir(repoPath);
66306
+ const proposalPath = path36.join(harnessDir, AGENTS_MD_PROPOSAL);
66307
+ const metaPath = path36.join(harnessDir, AGENTS_MD_PROPOSAL_META);
66308
+ const legacyProposalPath = path36.join(harnessDir, AGENT_MD_PROPOSAL);
66309
+ const legacyMetaPath = path36.join(harnessDir, AGENT_MD_PROPOSAL_META);
66310
+ const resolvedProposal = fs30.existsSync(proposalPath) ? proposalPath : fs30.existsSync(legacyProposalPath) ? legacyProposalPath : null;
66311
+ if (!resolvedProposal) return null;
66312
+ const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
66313
+ const content = fs30.readFileSync(resolvedProposal, "utf8");
66314
+ let rationale = "";
66315
+ let createdAt = (/* @__PURE__ */ new Date()).toISOString();
66316
+ if (fs30.existsSync(resolvedMeta)) {
66317
+ try {
66318
+ const meta = JSON.parse(fs30.readFileSync(resolvedMeta, "utf8"));
66319
+ rationale = meta.rationale ?? "";
66320
+ createdAt = meta.createdAt ?? createdAt;
66321
+ } catch {
66322
+ rationale = "";
66323
+ }
66324
+ }
66325
+ return { content, rationale, createdAt };
66326
+ }
66327
+ function clearAgentMdProposal(repoPath) {
66328
+ const harnessDir = getHarnessDir(repoPath);
66329
+ for (const file of [
66330
+ AGENTS_MD_PROPOSAL,
66331
+ AGENTS_MD_PROPOSAL_META,
66332
+ AGENT_MD_PROPOSAL,
66333
+ AGENT_MD_PROPOSAL_META
66334
+ ]) {
66335
+ const p = path36.join(harnessDir, file);
66336
+ if (fs30.existsSync(p)) fs30.unlinkSync(p);
66337
+ }
66338
+ }
66339
+ function wouldProposalShrinkExisting(existing, proposal) {
66340
+ const outsideExisting = extractOutsideHarSection(existing);
66341
+ const outsideMerged = extractOutsideHarSection(mergeAgentsMdContent(existing, proposal));
66342
+ const existingLines = outsideExisting.split("\n").filter((l) => l.trim()).length;
66343
+ const mergedLines = outsideMerged.split("\n").filter((l) => l.trim()).length;
66344
+ return existingLines >= 5 && mergedLines < existingLines * 0.9;
66345
+ }
66346
+ function applyAgentMdProposalMerge(repoPath, options = {}) {
66347
+ const proposal = readAgentMdProposal(repoPath);
66348
+ if (!proposal) return false;
66349
+ const agentsMdPath = path36.join(repoPath, AGENTS_MD);
66350
+ if (fs30.existsSync(agentsMdPath)) {
66351
+ const existing = fs30.readFileSync(agentsMdPath, "utf8");
66352
+ if (wouldProposalShrinkExisting(existing, proposal.content)) {
66353
+ const message = `${AGENTS_MD} proposal would drop project-specific content outside har:agent-environment markers \u2014 merge custom sections from .har/${AGENTS_MD_PROPOSAL} manually, then delete the proposal.`;
66354
+ if (options.rejectSignificantShrink) {
66355
+ throw new AgentsMdShrinkError(message);
66356
+ }
66357
+ warn(message);
66358
+ return false;
66359
+ }
66360
+ writeFileSafe(agentsMdPath, mergeAgentsMdContent(existing, proposal.content));
66361
+ } else {
66362
+ writeFileSafe(agentsMdPath, proposal.content);
66363
+ }
66364
+ clearAgentMdProposal(repoPath);
66365
+ info(`Merged ${AGENTS_MD} proposal into repo root (preserved content outside managed markers)`);
66366
+ return true;
66367
+ }
66368
+ function finalizeAgentsMdInstructionFiles(repoPath) {
66369
+ applyAgentMdProposalMerge(repoPath, { rejectSignificantShrink: true });
66370
+ upsertAgentsMdHarSection(repoPath, { rejectSignificantShrink: true });
66371
+ }
66372
+
66373
+ // src/harness/validator.ts
66374
+ var fs31 = __toESM(require("fs"));
66375
+ var path37 = __toESM(require("path"));
65900
66376
  init_shell();
65901
66377
  init_manifest();
65902
66378
  init_stages();
@@ -65951,22 +66427,22 @@ var SHELL_SCRIPTS = [
65951
66427
  function validateHarness(repoPath) {
65952
66428
  const harnessDir = getHarnessDir(repoPath);
65953
66429
  const issues = [];
65954
- if (!fs29.existsSync(harnessDir)) {
66430
+ if (!fs31.existsSync(harnessDir)) {
65955
66431
  return {
65956
66432
  pass: false,
65957
66433
  issues: [{ file: ".har", message: "Harness directory not found", severity: "error" }]
65958
66434
  };
65959
66435
  }
65960
66436
  for (const file of getRequiredFiles(repoPath)) {
65961
- const filePath = path35.join(harnessDir, file);
65962
- if (!fs29.existsSync(filePath)) {
66437
+ const filePath = path37.join(harnessDir, file);
66438
+ if (!fs31.existsSync(filePath)) {
65963
66439
  issues.push({ file, message: "Required file missing", severity: "error" });
65964
66440
  }
65965
66441
  }
65966
66442
  for (const script of SHELL_SCRIPTS) {
65967
- const scriptPath = path35.join(harnessDir, script);
65968
- if (!fs29.existsSync(scriptPath)) continue;
65969
- const stat = fs29.statSync(scriptPath);
66443
+ const scriptPath = path37.join(harnessDir, script);
66444
+ if (!fs31.existsSync(scriptPath)) continue;
66445
+ const stat = fs31.statSync(scriptPath);
65970
66446
  if (!(stat.mode & 73)) {
65971
66447
  issues.push({ file: script, message: "Script is not executable", severity: "warning" });
65972
66448
  }
@@ -65981,9 +66457,9 @@ function validateHarness(repoPath) {
65981
66457
  }
65982
66458
  const manifest = readManifest(repoPath);
65983
66459
  const profile = manifest?.profile ?? "default";
65984
- const ecosystemPath = path35.join(harnessDir, "ecosystem.agent.template.cjs");
65985
- if (profile !== "cli" && fs29.existsSync(ecosystemPath)) {
65986
- const content = fs29.readFileSync(ecosystemPath, "utf8");
66460
+ const ecosystemPath = path37.join(harnessDir, "ecosystem.agent.template.cjs");
66461
+ if (profile !== "cli" && fs31.existsSync(ecosystemPath)) {
66462
+ const content = fs31.readFileSync(ecosystemPath, "utf8");
65987
66463
  if (!content.includes("module.exports")) {
65988
66464
  issues.push({
65989
66465
  file: "ecosystem.agent.template.cjs",
@@ -65992,9 +66468,9 @@ function validateHarness(repoPath) {
65992
66468
  });
65993
66469
  }
65994
66470
  }
65995
- const harnessEnvPath = path35.join(harnessDir, "harness.env");
65996
- if (fs29.existsSync(harnessEnvPath)) {
65997
- const content = fs29.readFileSync(harnessEnvPath, "utf8");
66471
+ const harnessEnvPath = path37.join(harnessDir, "harness.env");
66472
+ if (fs31.existsSync(harnessEnvPath)) {
66473
+ const content = fs31.readFileSync(harnessEnvPath, "utf8");
65998
66474
  if (content.includes("TODO: set migrate command")) {
65999
66475
  issues.push({ file: "harness.env", message: "Migrate command still has TODO", severity: "warning" });
66000
66476
  }
@@ -66002,17 +66478,17 @@ function validateHarness(repoPath) {
66002
66478
  issues.push({ file: "harness.env", message: "Seed command still has TODO", severity: "warning" });
66003
66479
  }
66004
66480
  }
66005
- const verifyPath = path35.join(harnessDir, "verify.sh");
66006
- if (fs29.existsSync(verifyPath)) {
66007
- const content = fs29.readFileSync(verifyPath, "utf8");
66481
+ const verifyPath = path37.join(harnessDir, "verify.sh");
66482
+ if (fs31.existsSync(verifyPath)) {
66483
+ const content = fs31.readFileSync(verifyPath, "utf8");
66008
66484
  if (content.includes("echo 'TODO:")) {
66009
66485
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
66010
66486
  }
66011
66487
  }
66012
- const stagesPath = path35.join(harnessDir, "stages.json");
66013
- if (fs29.existsSync(stagesPath)) {
66488
+ const stagesPath = path37.join(harnessDir, "stages.json");
66489
+ if (fs31.existsSync(stagesPath)) {
66014
66490
  try {
66015
- JSON.parse(fs29.readFileSync(stagesPath, "utf8"));
66491
+ JSON.parse(fs31.readFileSync(stagesPath, "utf8"));
66016
66492
  const registry2 = readStageRegistry(repoPath);
66017
66493
  if (registry2.stages.length === 0) {
66018
66494
  issues.push({ file: "stages.json", message: "No harness stages declared", severity: "warning" });
@@ -66027,9 +66503,9 @@ function validateHarness(repoPath) {
66027
66503
  } else {
66028
66504
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
66029
66505
  }
66030
- const readmePath = path35.join(harnessDir, "README.md");
66031
- if (fs29.existsSync(readmePath)) {
66032
- const content = fs29.readFileSync(readmePath, "utf8");
66506
+ const readmePath = path37.join(harnessDir, "README.md");
66507
+ if (fs31.existsSync(readmePath)) {
66508
+ const content = fs31.readFileSync(readmePath, "utf8");
66033
66509
  if (!content.includes(".har")) {
66034
66510
  issues.push({ file: "README.md", message: "README should document .har/ paths", severity: "warning" });
66035
66511
  }
@@ -66043,8 +66519,8 @@ function validateHarness(repoPath) {
66043
66519
  async function smokeTestHarness(repoPath) {
66044
66520
  const harnessDir = getHarnessDir(repoPath);
66045
66521
  const issues = [];
66046
- const setupScript = path35.join(harnessDir, "setup-infra.sh");
66047
- if (fs29.existsSync(setupScript)) {
66522
+ const setupScript = path37.join(harnessDir, "setup-infra.sh");
66523
+ if (fs31.existsSync(setupScript)) {
66048
66524
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
66049
66525
  if (result.code !== 0) {
66050
66526
  issues.push({
@@ -66059,8 +66535,8 @@ async function smokeTestHarness(repoPath) {
66059
66535
  }
66060
66536
 
66061
66537
  // src/harness/drift.ts
66062
- var fs30 = __toESM(require("fs"));
66063
- var path36 = __toESM(require("path"));
66538
+ var fs32 = __toESM(require("fs"));
66539
+ var path38 = __toESM(require("path"));
66064
66540
  init_env();
66065
66541
  init_manifest();
66066
66542
  init_stages();
@@ -66131,16 +66607,16 @@ function substituteProjectName(content, projectName) {
66131
66607
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
66132
66608
  }
66133
66609
  function listBoilerplateFiles(boilerplateDir) {
66134
- if (!fs30.existsSync(boilerplateDir)) return [];
66135
- return fs30.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
66610
+ if (!fs32.existsSync(boilerplateDir)) return [];
66611
+ return fs32.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
66136
66612
  }
66137
66613
  function compareHarnessToTemplate(repoPath) {
66138
- const resolved = path36.resolve(repoPath);
66614
+ const resolved = path38.resolve(repoPath);
66139
66615
  const manifest = readManifest(resolved);
66140
66616
  const profile = manifest?.profile ?? "default";
66141
66617
  const harnessDir = getHarnessDir(resolved);
66142
- const projectName = path36.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
66143
- const boilerplateDir = path36.join(resolveTemplatesDir(), PROFILE_DIRS2[profile]);
66618
+ const projectName = path38.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
66619
+ const boilerplateDir = path38.join(resolveTemplatesDir(), PROFILE_DIRS2[profile]);
66144
66620
  const templateFiles = listBoilerplateFiles(boilerplateDir);
66145
66621
  const missing = [];
66146
66622
  const checksumMismatch = [];
@@ -66148,17 +66624,17 @@ function compareHarnessToTemplate(repoPath) {
66148
66624
  const unchanged = [];
66149
66625
  for (const file of templateFiles) {
66150
66626
  const harnessFile = harnessFileForTemplate(file);
66151
- const templatePath = path36.join(boilerplateDir, file);
66152
- const harnessPath = path36.join(harnessDir, harnessFile);
66153
- let templateContent = fs30.readFileSync(templatePath, "utf8");
66627
+ const templatePath = path38.join(boilerplateDir, file);
66628
+ const harnessPath = path38.join(harnessDir, harnessFile);
66629
+ let templateContent = fs32.readFileSync(templatePath, "utf8");
66154
66630
  if (file === "harness.env") {
66155
66631
  templateContent = substituteProjectName(templateContent, projectName);
66156
66632
  }
66157
- if (!fs30.existsSync(harnessPath)) {
66633
+ if (!fs32.existsSync(harnessPath)) {
66158
66634
  missing.push(harnessFile);
66159
66635
  continue;
66160
66636
  }
66161
- const harnessChecksum = computeFileChecksum(fs30.readFileSync(harnessPath, "utf8"));
66637
+ const harnessChecksum = computeFileChecksum(fs32.readFileSync(harnessPath, "utf8"));
66162
66638
  const templateChecksum = computeFileChecksum(templateContent);
66163
66639
  if (harnessChecksum === templateChecksum) {
66164
66640
  unchanged.push(harnessFile);
@@ -66166,10 +66642,10 @@ function compareHarnessToTemplate(repoPath) {
66166
66642
  checksumMismatch.push(harnessFile);
66167
66643
  }
66168
66644
  }
66169
- if (fs30.existsSync(harnessDir)) {
66170
- for (const file of fs30.readdirSync(harnessDir)) {
66171
- const full = path36.join(harnessDir, file);
66172
- if (!fs30.statSync(full).isFile()) continue;
66645
+ if (fs32.existsSync(harnessDir)) {
66646
+ for (const file of fs32.readdirSync(harnessDir)) {
66647
+ const full = path38.join(harnessDir, file);
66648
+ if (!fs32.statSync(full).isFile()) continue;
66173
66649
  if (file === "manifest.json" || file.startsWith("ADAPT-PROMPT")) continue;
66174
66650
  if (profile === "cli" && CLI_EXPECTED_ABSENT.has(file)) {
66175
66651
  extra.push(file);
@@ -66200,29 +66676,29 @@ function compareHarnessToTemplate(repoPath) {
66200
66676
  }
66201
66677
 
66202
66678
  // src/harness/maintain-bundle.ts
66203
- var fs35 = __toESM(require("fs"));
66679
+ var fs36 = __toESM(require("fs"));
66204
66680
  var os14 = __toESM(require("os"));
66205
- var path40 = __toESM(require("path"));
66681
+ var path41 = __toESM(require("path"));
66206
66682
  init_file_ops();
66207
66683
  init_shell();
66208
66684
  init_manifest();
66209
66685
 
66210
66686
  // src/harness/plugin-drift.ts
66211
- var fs33 = __toESM(require("fs"));
66212
- var path38 = __toESM(require("path"));
66687
+ var fs35 = __toESM(require("fs"));
66688
+ var path40 = __toESM(require("path"));
66213
66689
  init_manifest();
66214
66690
 
66215
66691
  // src/harness/plugins.ts
66216
- var fs32 = __toESM(require("fs"));
66217
- var path37 = __toESM(require("path"));
66692
+ var fs34 = __toESM(require("fs"));
66693
+ var path39 = __toESM(require("path"));
66218
66694
  init_zod();
66219
66695
  init_logging();
66220
66696
 
66221
66697
  // src/harness/parser.ts
66222
- var fs31 = __toESM(require("fs"));
66698
+ var fs33 = __toESM(require("fs"));
66223
66699
  init_manifest();
66224
66700
  function harnessExists(repoPath) {
66225
- return fs31.existsSync(`${repoPath}/.har/setup-infra.sh`);
66701
+ return fs33.existsSync(`${repoPath}/.har/setup-infra.sh`);
66226
66702
  }
66227
66703
 
66228
66704
  // src/harness/plugins.ts
@@ -66247,16 +66723,16 @@ var PluginManifestSchema = external_exports.object({
66247
66723
  docsPath: external_exports.string().min(1)
66248
66724
  });
66249
66725
  function resolvePluginDir(pluginId) {
66250
- const dir = path37.join(resolveTemplatesDir(), "plugins", pluginId);
66251
- if (!fs32.existsSync(dir)) {
66726
+ const dir = path39.join(resolveTemplatesDir(), "plugins", pluginId);
66727
+ if (!fs34.existsSync(dir)) {
66252
66728
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
66253
66729
  }
66254
66730
  return dir;
66255
66731
  }
66256
66732
  function readPluginManifest(pluginId) {
66257
- const manifestPath = path37.join(resolvePluginDir(pluginId), "template.manifest.json");
66733
+ const manifestPath = path39.join(resolvePluginDir(pluginId), "template.manifest.json");
66258
66734
  const parsed = PluginManifestSchema.safeParse(
66259
- JSON.parse(fs32.readFileSync(manifestPath, "utf8"))
66735
+ JSON.parse(fs34.readFileSync(manifestPath, "utf8"))
66260
66736
  );
66261
66737
  if (!parsed.success) {
66262
66738
  throw new Error(`Invalid plugin manifest for ${pluginId}: ${parsed.error.message}`);
@@ -66267,40 +66743,40 @@ function readPluginManifest(pluginId) {
66267
66743
  return parsed.data;
66268
66744
  }
66269
66745
  function ensureParentDir(filePath) {
66270
- const parent = path37.dirname(filePath);
66271
- if (!fs32.existsSync(parent)) {
66272
- fs32.mkdirSync(parent, { recursive: true });
66746
+ const parent = path39.dirname(filePath);
66747
+ if (!fs34.existsSync(parent)) {
66748
+ fs34.mkdirSync(parent, { recursive: true });
66273
66749
  }
66274
66750
  }
66275
66751
  function copyPluginFile(pluginDir, file, repoPath, force) {
66276
- const srcPath = path37.join(pluginDir, file.src);
66277
- const destPath = path37.join(repoPath, file.dest);
66278
- if (!fs32.existsSync(srcPath)) {
66752
+ const srcPath = path39.join(pluginDir, file.src);
66753
+ const destPath = path39.join(repoPath, file.dest);
66754
+ if (!fs34.existsSync(srcPath)) {
66279
66755
  throw new Error(`Plugin file missing: ${file.src}`);
66280
66756
  }
66281
- if (fs32.existsSync(destPath) && !force) {
66757
+ if (fs34.existsSync(destPath) && !force) {
66282
66758
  throw new Error(
66283
66759
  `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
66284
66760
  );
66285
66761
  }
66286
66762
  ensureParentDir(destPath);
66287
- fs32.copyFileSync(srcPath, destPath);
66763
+ fs34.copyFileSync(srcPath, destPath);
66288
66764
  if (file.executable) {
66289
- fs32.chmodSync(destPath, 493);
66765
+ fs34.chmodSync(destPath, 493);
66290
66766
  }
66291
66767
  return { written: true, path: file.dest };
66292
66768
  }
66293
66769
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
66294
- const packagePath = path37.join(repoPath, "package.json");
66295
- if (!fs32.existsSync(packagePath)) {
66770
+ const packagePath = path39.join(repoPath, "package.json");
66771
+ if (!fs34.existsSync(packagePath)) {
66296
66772
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
66297
66773
  }
66298
- const fragmentPath = path37.join(pluginDir, fragmentRelPath);
66299
- if (!fs32.existsSync(fragmentPath)) {
66774
+ const fragmentPath = path39.join(pluginDir, fragmentRelPath);
66775
+ if (!fs34.existsSync(fragmentPath)) {
66300
66776
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
66301
66777
  }
66302
- const pkg = JSON.parse(fs32.readFileSync(packagePath, "utf8"));
66303
- const fragment = JSON.parse(fs32.readFileSync(fragmentPath, "utf8"));
66778
+ const pkg = JSON.parse(fs34.readFileSync(packagePath, "utf8"));
66779
+ const fragment = JSON.parse(fs34.readFileSync(fragmentPath, "utf8"));
66304
66780
  for (const section of ["scripts", "devDependencies"]) {
66305
66781
  const existing = pkg[section] ?? {};
66306
66782
  const incoming = fragment[section] ?? {};
@@ -66313,7 +66789,7 @@ function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
66313
66789
  }
66314
66790
  pkg[section] = existing;
66315
66791
  }
66316
- fs32.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
66792
+ fs34.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
66317
66793
  }
66318
66794
  function patchStageRegistry(repoPath, manifest, force) {
66319
66795
  const registry2 = readStageRegistry(repoPath);
@@ -66353,8 +66829,8 @@ function assertHarnessPresent(repoPath) {
66353
66829
  }
66354
66830
  function assertStageNotPresent(repoPath, stageId, force) {
66355
66831
  if (force) return;
66356
- const scriptPath = path37.join(repoPath, ".har", "stages", `${stageId}.sh`);
66357
- if (fs32.existsSync(scriptPath)) {
66832
+ const scriptPath = path39.join(repoPath, ".har", "stages", `${stageId}.sh`);
66833
+ if (fs34.existsSync(scriptPath)) {
66358
66834
  throw new Error(
66359
66835
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
66360
66836
  );
@@ -66367,7 +66843,7 @@ function assertStageNotPresent(repoPath, stageId, force) {
66367
66843
  }
66368
66844
  }
66369
66845
  function applyPlugin(repoPath, pluginId, options = {}) {
66370
- const resolved = path37.resolve(repoPath);
66846
+ const resolved = path39.resolve(repoPath);
66371
66847
  const force = options.force ?? false;
66372
66848
  const warnings = [];
66373
66849
  const filesWritten = [];
@@ -66386,7 +66862,7 @@ function applyPlugin(repoPath, pluginId, options = {}) {
66386
66862
  if (file.skipFlag === "skipCi" && options.skipCi) {
66387
66863
  continue;
66388
66864
  }
66389
- if (fs32.existsSync(path37.join(resolved, file.dest)) && !force) {
66865
+ if (fs34.existsSync(path39.join(resolved, file.dest)) && !force) {
66390
66866
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
66391
66867
  continue;
66392
66868
  }
@@ -66421,18 +66897,18 @@ function applyPlugin(repoPath, pluginId, options = {}) {
66421
66897
  };
66422
66898
  }
66423
66899
  function listPluginIds() {
66424
- const root = path37.join(resolveTemplatesDir(), "plugins");
66425
- if (!fs32.existsSync(root)) return [...PLUGIN_IDS];
66426
- return fs32.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
66900
+ const root = path39.join(resolveTemplatesDir(), "plugins");
66901
+ if (!fs34.existsSync(root)) return [...PLUGIN_IDS];
66902
+ return fs34.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
66427
66903
  }
66428
66904
 
66429
66905
  // src/harness/plugin-drift.ts
66430
66906
  init_stages();
66431
66907
  var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
66432
66908
  function detectInstalledPlugins(repoPath) {
66433
- const resolved = path38.resolve(repoPath);
66434
- const registryPath = path38.join(resolved, ".har", "stages.json");
66435
- if (!fs33.existsSync(registryPath)) return [];
66909
+ const resolved = path40.resolve(repoPath);
66910
+ const registryPath = path40.join(resolved, ".har", "stages.json");
66911
+ if (!fs35.existsSync(registryPath)) return [];
66436
66912
  const registry2 = readStageRegistry(resolved);
66437
66913
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
66438
66914
  const installed = [];
@@ -66445,17 +66921,17 @@ function detectInstalledPlugins(repoPath) {
66445
66921
  return installed;
66446
66922
  }
66447
66923
  function pluginTemplatePath(pluginId, srcRel) {
66448
- return path38.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
66924
+ return path40.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
66449
66925
  }
66450
66926
  function readBundledPluginFile(pluginId, srcRel) {
66451
- return fs33.readFileSync(pluginTemplatePath(pluginId, srcRel), "utf8");
66927
+ return fs35.readFileSync(pluginTemplatePath(pluginId, srcRel), "utf8");
66452
66928
  }
66453
66929
  function listPluginDestPaths(pluginId, repoPath) {
66454
66930
  const manifest = readPluginManifest(pluginId);
66455
66931
  const paths = manifest.files.map((file) => file.dest);
66456
66932
  if (manifest.optionalFiles) {
66457
66933
  for (const file of manifest.optionalFiles) {
66458
- if (fs33.existsSync(path38.join(repoPath, file.dest))) {
66934
+ if (fs35.existsSync(path40.join(repoPath, file.dest))) {
66459
66935
  paths.push(file.dest);
66460
66936
  }
66461
66937
  }
@@ -66514,9 +66990,9 @@ function readTemplatePluginFile(pluginId, dest) {
66514
66990
  return null;
66515
66991
  }
66516
66992
  function readInstalledPluginFile(repoPath, pluginId, dest) {
66517
- const installedPath = path38.join(path38.resolve(repoPath), dest);
66518
- if (!fs33.existsSync(installedPath)) return null;
66519
- const content = fs33.readFileSync(installedPath, "utf8");
66993
+ const installedPath = path40.join(path40.resolve(repoPath), dest);
66994
+ if (!fs35.existsSync(installedPath)) return null;
66995
+ const content = fs35.readFileSync(installedPath, "utf8");
66520
66996
  const manifest = readPluginManifest(pluginId);
66521
66997
  const fragmentRel = manifest.merge?.[dest];
66522
66998
  if (fragmentRel) {
@@ -66535,7 +67011,7 @@ function pluginActionHint(pluginId, dest, kind) {
66535
67011
  }
66536
67012
  function comparePluginToTemplate(repoPath, pluginId) {
66537
67013
  const manifest = readPluginManifest(pluginId);
66538
- const resolved = path38.resolve(repoPath);
67014
+ const resolved = path40.resolve(repoPath);
66539
67015
  const destPaths = listPluginDestPaths(pluginId, resolved);
66540
67016
  const missing = [];
66541
67017
  const checksumMismatch = [];
@@ -66550,8 +67026,8 @@ function comparePluginToTemplate(repoPath, pluginId) {
66550
67026
  }
66551
67027
  if (dest === "package.json") {
66552
67028
  const fragmentRel = manifest.merge?.[dest];
66553
- const installedPath = path38.join(resolved, dest);
66554
- const installedRaw = fs33.readFileSync(installedPath, "utf8");
67029
+ const installedPath = path40.join(resolved, dest);
67030
+ const installedRaw = fs35.readFileSync(installedPath, "utf8");
66555
67031
  if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
66556
67032
  unchanged.push(dest);
66557
67033
  } else if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
@@ -66609,293 +67085,6 @@ function buildPluginDriftActions(repoPath, pluginDrift) {
66609
67085
  );
66610
67086
  }
66611
67087
 
66612
- // src/harness/instruction-files.ts
66613
- var fs34 = __toESM(require("fs"));
66614
- var os13 = __toESM(require("os"));
66615
- var path39 = __toESM(require("path"));
66616
- var readline2 = __toESM(require("readline"));
66617
- init_file_ops();
66618
- init_logging();
66619
- var AGENTS_MD = "AGENTS.md";
66620
- var LEGACY_AGENT_MD = "AGENT.md";
66621
- var CLAUDE_MD = "CLAUDE.md";
66622
- var HAR_SECTION_START = "<!-- har:agent-environment:start -->";
66623
- var HAR_SECTION_END = "<!-- har:agent-environment:end -->";
66624
- var CLAUDE_HAR_SECTION_START = "<!-- har:claude-pointer:start -->";
66625
- var CLAUDE_HAR_SECTION_END = "<!-- har:claude-pointer:end -->";
66626
- function escapeRegExp(value) {
66627
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
66628
- }
66629
- function detectInstructionFiles(repoPath) {
66630
- return {
66631
- agentsMd: fs34.existsSync(path39.join(repoPath, AGENTS_MD)),
66632
- agentMd: fs34.existsSync(path39.join(repoPath, LEGACY_AGENT_MD)),
66633
- claudeMd: fs34.existsSync(path39.join(repoPath, CLAUDE_MD)),
66634
- cursorDir: fs34.existsSync(path39.join(repoPath, ".cursor")),
66635
- claudeDir: fs34.existsSync(path39.join(repoPath, ".claude")),
66636
- codexHome: fs34.existsSync(path39.join(os13.homedir(), ".codex"))
66637
- };
66638
- }
66639
- function formatDetectionReport(detection) {
66640
- const lines2 = ["Detected:"];
66641
- lines2.push(` - ${AGENTS_MD} (${detection.agentsMd ? "exists" : "missing"})`);
66642
- if (detection.agentMd) {
66643
- lines2.push(` - ${LEGACY_AGENT_MD} (legacy \u2014 will migrate into ${AGENTS_MD})`);
66644
- }
66645
- lines2.push(` - ${CLAUDE_MD} (${detection.claudeMd ? "exists" : "missing"})`);
66646
- lines2.push(` - .cursor/ (${detection.cursorDir ? "exists" : "missing"})`);
66647
- lines2.push(` - .claude/ (${detection.claudeDir ? "exists" : "missing"})`);
66648
- lines2.push(` - ~/.codex (${detection.codexHome ? "exists" : "missing"})`);
66649
- return lines2.join("\n");
66650
- }
66651
- function buildInstallPlan(detection, targets, options = {}) {
66652
- const writeAgentsMd = options.writeAgentsMd !== false;
66653
- const skillsEnabled = options.skillsEnabled !== false;
66654
- const cursorExplicit = options.cursorRule;
66655
- const wantsCursor = cursorExplicit === true || cursorExplicit !== false && (targets.includes("cursor") || detection.cursorDir);
66656
- return {
66657
- agentsMd: writeAgentsMd,
66658
- migrateLegacyAgentMd: writeAgentsMd && detection.agentMd,
66659
- claudeMd: skillsEnabled && targets.includes("claude"),
66660
- cursorRule: wantsCursor,
66661
- skills: skillsEnabled ? targets : []
66662
- };
66663
- }
66664
- function formatInstallPlan(plan, detection) {
66665
- const mark = (on) => on ? "[x]" : "[ ]";
66666
- const lines2 = ["After you confirm, HAR will:"];
66667
- const agentsAction = detection.agentsMd ? `Update ${AGENTS_MD} \u2014 refresh HAR / agent environment section` : `Create ${AGENTS_MD} \u2014 shared HAR workflow (Codex + cross-tool)`;
66668
- lines2.push(` ${mark(plan.agentsMd)} ${agentsAction}`);
66669
- if (plan.migrateLegacyAgentMd) {
66670
- lines2.push(` ${mark(true)} Migrate ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD}, then remove legacy file`);
66671
- }
66672
- lines2.push(
66673
- ` ${mark(plan.claudeMd)} Claude \u2014 ensure ${CLAUDE_MD} points at ${AGENTS_MD}; install .claude/skills if confirmed`
66674
- );
66675
- lines2.push(
66676
- ` ${mark(plan.cursorRule)} Cursor \u2014 install/refresh .cursor/rules/har-workflow.mdc + commands if confirmed`
66677
- );
66678
- lines2.push(
66679
- ` ${mark(plan.skills.includes("codex"))} Codex \u2014 global ~/.codex/prompts (skills); project contract is ${AGENTS_MD}`
66680
- );
66681
- return lines2.join("\n");
66682
- }
66683
- function loadHarAgentsSectionFromTemplate() {
66684
- const templatePath = resolveTemplateFile("AGENTS.md.template");
66685
- if (!templatePath) {
66686
- throw new Error("AGENTS.md.template not found. Run npm run build.");
66687
- }
66688
- const content = fs34.readFileSync(templatePath, "utf8");
66689
- const start = content.indexOf(HAR_SECTION_START);
66690
- const end = content.indexOf(HAR_SECTION_END);
66691
- if (start === -1 || end === -1 || end < start) {
66692
- throw new Error("AGENTS.md.template is missing har:agent-environment markers.");
66693
- }
66694
- return content.slice(start, end + HAR_SECTION_END.length);
66695
- }
66696
- function loadAgentsMdTemplate() {
66697
- const templatePath = resolveTemplateFile("AGENTS.md.template");
66698
- if (!templatePath) {
66699
- throw new Error("AGENTS.md.template not found. Run npm run build.");
66700
- }
66701
- return fs34.readFileSync(templatePath, "utf8");
66702
- }
66703
- function upsertMarkedBlock(content, block, startMarker, endMarker) {
66704
- if (content.includes(startMarker)) {
66705
- const pattern = new RegExp(
66706
- `${escapeRegExp(startMarker)}[\\s\\S]*?${escapeRegExp(endMarker)}`
66707
- );
66708
- return { content: content.replace(pattern, block), action: "updated" };
66709
- }
66710
- const suffix = content.endsWith("\n") ? "" : "\n";
66711
- return { content: `${content}${suffix}
66712
- ${block}
66713
- `, action: "appended" };
66714
- }
66715
- function upsertAgentsMdHarSection(repoPath) {
66716
- const dest = path39.join(repoPath, AGENTS_MD);
66717
- const section = loadHarAgentsSectionFromTemplate();
66718
- if (!fs34.existsSync(dest)) {
66719
- writeFileSafe(dest, loadAgentsMdTemplate());
66720
- return "created";
66721
- }
66722
- const existing = fs34.readFileSync(dest, "utf8");
66723
- const { content, action } = upsertMarkedBlock(
66724
- existing,
66725
- section,
66726
- HAR_SECTION_START,
66727
- HAR_SECTION_END
66728
- );
66729
- writeFileSafe(dest, content);
66730
- return action;
66731
- }
66732
- function migrateLegacyAgentMd(repoPath) {
66733
- const legacyPath = path39.join(repoPath, LEGACY_AGENT_MD);
66734
- const agentsPath = path39.join(repoPath, AGENTS_MD);
66735
- if (!fs34.existsSync(legacyPath)) return false;
66736
- const legacy = fs34.readFileSync(legacyPath, "utf8");
66737
- if (!fs34.existsSync(agentsPath)) {
66738
- writeFileSafe(agentsPath, legacy);
66739
- upsertAgentsMdHarSection(repoPath);
66740
- } else {
66741
- upsertAgentsMdHarSection(repoPath);
66742
- }
66743
- fs34.unlinkSync(legacyPath);
66744
- info(`Migrated ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD} (removed legacy file)`);
66745
- return true;
66746
- }
66747
- function loadClaudeMdTemplate(projectName) {
66748
- const templatePath = resolveTemplateFile("CLAUDE.md.template");
66749
- if (!templatePath) {
66750
- throw new Error("CLAUDE.md.template not found. Run npm run build.");
66751
- }
66752
- const displayName = projectName.replace(/_/g, " ");
66753
- return fs34.readFileSync(templatePath, "utf8").replace(/__PROJECT_DISPLAY_NAME__/g, displayName);
66754
- }
66755
- function isThinClaudePointer(content) {
66756
- const trimmed = content.trim();
66757
- if (trimmed.length > 600) return false;
66758
- return /AGENTS\.md|AGENT\.md/.test(trimmed) && (trimmed.includes(".har/README.md") || trimmed.includes("har-workflow"));
66759
- }
66760
- var CLAUDE_POINTER_BLOCK = `${CLAUDE_HAR_SECTION_START}
66761
- ## HAR
66762
-
66763
- This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
66764
- [\`.har/README.md\`](./.har/README.md) before making changes.
66765
- ${CLAUDE_HAR_SECTION_END}`;
66766
- function ensureClaudeMdPointer(repoPath, options = {}) {
66767
- const dest = path39.join(repoPath, CLAUDE_MD);
66768
- const projectName = path39.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
66769
- const thin = loadClaudeMdTemplate(projectName);
66770
- if (!fs34.existsSync(dest)) {
66771
- writeFileSafe(dest, thin);
66772
- return "created";
66773
- }
66774
- const existing = fs34.readFileSync(dest, "utf8");
66775
- if (isThinClaudePointer(existing) || options.force) {
66776
- writeFileSafe(dest, thin);
66777
- return "updated";
66778
- }
66779
- if (existing.includes(CLAUDE_HAR_SECTION_START) || /\[AGENTS\.md\]/.test(existing)) {
66780
- if (existing.includes(CLAUDE_HAR_SECTION_START)) {
66781
- const { content: content2, action: action2 } = upsertMarkedBlock(
66782
- existing,
66783
- CLAUDE_POINTER_BLOCK,
66784
- CLAUDE_HAR_SECTION_START,
66785
- CLAUDE_HAR_SECTION_END
66786
- );
66787
- writeFileSafe(dest, content2);
66788
- return action2;
66789
- }
66790
- return "skipped";
66791
- }
66792
- const { content, action } = upsertMarkedBlock(
66793
- existing,
66794
- CLAUDE_POINTER_BLOCK,
66795
- CLAUDE_HAR_SECTION_START,
66796
- CLAUDE_HAR_SECTION_END
66797
- );
66798
- writeFileSafe(dest, content);
66799
- return action;
66800
- }
66801
- async function askYesNo2(question, defaultYes = true) {
66802
- const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
66803
- return new Promise((resolve47) => {
66804
- process.stderr.write(`${question} `);
66805
- rl.once("line", (answer) => {
66806
- rl.close();
66807
- const trimmed = answer.trim();
66808
- if (trimmed === "") {
66809
- resolve47(defaultYes);
66810
- return;
66811
- }
66812
- resolve47(/^y(es)?$/i.test(trimmed));
66813
- });
66814
- });
66815
- }
66816
- async function handleInstructionFiles(options) {
66817
- const { repoPath, mode } = options;
66818
- const writeAgentsMd = options.writeAgentsMd !== false;
66819
- const skillsEnabled = options.enabled !== false;
66820
- const detection = detectInstructionFiles(repoPath);
66821
- let targets;
66822
- if (!skillsEnabled) {
66823
- targets = [];
66824
- } else if (typeof options.agents === "string") {
66825
- targets = parseAgentTargets(options.agents);
66826
- } else {
66827
- targets = detectAgentTargets(repoPath);
66828
- }
66829
- if (skillsEnabled && targets.length === 0 && mode === "init" && typeof options.agents !== "string" && !options.autoYes) {
66830
- targets = [...AGENT_SKILL_TARGETS];
66831
- }
66832
- let plan = buildInstallPlan(detection, targets, {
66833
- writeAgentsMd,
66834
- cursorRule: options.cursorRule,
66835
- skillsEnabled
66836
- });
66837
- divider();
66838
- process.stderr.write(`${formatDetectionReport(detection)}
66839
-
66840
- `);
66841
- process.stderr.write(`${formatInstallPlan(plan, detection)}
66842
- `);
66843
- divider();
66844
- const shouldPrompt = !options.autoYes && skillsEnabled && typeof options.agents !== "string" && !(mode === "maintain" && targets.length > 0 && !detection.agentMd);
66845
- if (shouldPrompt && targets.length > 0) {
66846
- const accepted = await askYesNo2(
66847
- `Install HAR agent instructions for: ${targets.join(", ")}? [Y/n]`
66848
- );
66849
- if (!accepted) {
66850
- info("Skipped agent instruction adapters (AGENTS.md will still be updated)");
66851
- targets = [];
66852
- plan = buildInstallPlan(detection, targets, {
66853
- writeAgentsMd,
66854
- cursorRule: options.cursorRule === true ? true : false,
66855
- skillsEnabled: false
66856
- });
66857
- }
66858
- }
66859
- let migratedLegacy = false;
66860
- let agentsMdAction = null;
66861
- let claudeMdAction = null;
66862
- if (writeAgentsMd) {
66863
- if (detection.agentMd) {
66864
- migratedLegacy = migrateLegacyAgentMd(repoPath);
66865
- }
66866
- agentsMdAction = upsertAgentsMdHarSection(repoPath);
66867
- if (agentsMdAction === "created") {
66868
- success(`Wrote ${AGENTS_MD}`);
66869
- } else if (agentsMdAction === "updated" || agentsMdAction === "appended") {
66870
- info(
66871
- `${agentsMdAction === "updated" ? "Refreshed" : "Appended"} HAR section in ${AGENTS_MD}`
66872
- );
66873
- }
66874
- } else {
66875
- agentsMdAction = "skipped";
66876
- }
66877
- if (plan.claudeMd) {
66878
- claudeMdAction = ensureClaudeMdPointer(repoPath);
66879
- if (claudeMdAction === "created") {
66880
- success(`Wrote ${CLAUDE_MD} (pointer \u2192 ${AGENTS_MD})`);
66881
- } else if (claudeMdAction === "updated" || claudeMdAction === "appended") {
66882
- info(
66883
- `${claudeMdAction === "updated" ? "Updated" : "Appended"} ${CLAUDE_MD} pointer \u2192 ${AGENTS_MD}`
66884
- );
66885
- }
66886
- } else {
66887
- claudeMdAction = "skipped";
66888
- }
66889
- return {
66890
- detection,
66891
- plan,
66892
- targets,
66893
- agentsMdAction,
66894
- migratedLegacy,
66895
- claudeMdAction
66896
- };
66897
- }
66898
-
66899
67088
  // src/harness/maintain-bundle.ts
66900
67089
  var MAINTAIN_DIR = "maintain";
66901
67090
  var PROFILE_DIRS3 = {
@@ -66907,14 +67096,14 @@ function substituteProjectName2(content, projectName) {
66907
67096
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
66908
67097
  }
66909
67098
  function projectNameFromRepo(repoPath) {
66910
- return path40.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
67099
+ return path41.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
66911
67100
  }
66912
67101
  function boilerplateDirForProfile(profile) {
66913
- return path40.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
67102
+ return path41.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
66914
67103
  }
66915
67104
  function readBundledTemplateContent(repoPath, profile, file) {
66916
- const templatePath = path40.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
66917
- let content = fs35.readFileSync(templatePath, "utf8");
67105
+ const templatePath = path41.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
67106
+ let content = fs36.readFileSync(templatePath, "utf8");
66918
67107
  if (file === "harness.env") {
66919
67108
  content = substituteProjectName2(content, projectNameFromRepo(repoPath));
66920
67109
  }
@@ -66945,12 +67134,12 @@ function actionHint(file, kind) {
66945
67134
  return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
66946
67135
  }
66947
67136
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
66948
- const tmpDir = fs35.mkdtempSync(path40.join(os14.tmpdir(), "har-maintain-diff-"));
67137
+ const tmpDir = fs36.mkdtempSync(path41.join(os14.tmpdir(), "har-maintain-diff-"));
66949
67138
  try {
66950
- const installedPath = path40.join(tmpDir, "installed");
66951
- const templatePath = path40.join(tmpDir, "template");
66952
- fs35.writeFileSync(installedPath, installedContent);
66953
- fs35.writeFileSync(templatePath, templateContent);
67139
+ const installedPath = path41.join(tmpDir, "installed");
67140
+ const templatePath = path41.join(tmpDir, "template");
67141
+ fs36.writeFileSync(installedPath, installedContent);
67142
+ fs36.writeFileSync(templatePath, templateContent);
66954
67143
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
66955
67144
  const body = result.stdout.trim();
66956
67145
  if (!body) return "";
@@ -66959,7 +67148,7 @@ function createUnifiedDiff(installedContent, templateContent, installedLabel, te
66959
67148
  ${body.split("\n").slice(2).join("\n")}
66960
67149
  `;
66961
67150
  } finally {
66962
- fs35.rmSync(tmpDir, { recursive: true, force: true });
67151
+ fs36.rmSync(tmpDir, { recursive: true, force: true });
66963
67152
  }
66964
67153
  }
66965
67154
  function buildActions(repoPath, profile, drift) {
@@ -66974,7 +67163,7 @@ function buildActions(repoPath, profile, drift) {
66974
67163
  });
66975
67164
  }
66976
67165
  for (const file of drift.checksumMismatch) {
66977
- const installedPath = path40.join(harnessDir, file);
67166
+ const installedPath = path41.join(harnessDir, file);
66978
67167
  const installedRel = `maintain/installed/${file}`;
66979
67168
  const templateRel = `maintain/templates/${file}`;
66980
67169
  const diffRel = `maintain/diffs/${file}.diff`;
@@ -66982,7 +67171,7 @@ function buildActions(repoPath, profile, drift) {
66982
67171
  file,
66983
67172
  kind: "drift",
66984
67173
  template: templateRel,
66985
- installed: fs35.existsSync(installedPath) ? installedRel : void 0,
67174
+ installed: fs36.existsSync(installedPath) ? installedRel : void 0,
66986
67175
  diff: diffRel,
66987
67176
  hint: actionHint(file, "drift")
66988
67177
  });
@@ -67101,6 +67290,10 @@ function buildReadme(report) {
67101
67290
  lines2.push("", "## Agent instruction files (generator 0.5.0)", "");
67102
67291
  lines2.push(
67103
67292
  "Repo-root agent docs are **outside** `.har/` checksum drift. Apply while adapting:",
67293
+ "",
67294
+ "**Merge contract:** `har env maintain --finalize` refreshes only the content between",
67295
+ "`<!-- har:agent-environment:start/end -->` in `AGENTS.md`. Custom `## Project` sections and",
67296
+ "other guidance **outside** those markers must survive finalize \u2014 relocate them if needed.",
67104
67297
  ""
67105
67298
  );
67106
67299
  for (const note of report.instructionFiles) {
@@ -67130,28 +67323,28 @@ function buildReadme(report) {
67130
67323
  }
67131
67324
  function writeBundleArtifacts(repoPath, profile, drift, report) {
67132
67325
  const harnessDir = getHarnessDir(repoPath);
67133
- const bundleDir = path40.join(harnessDir, MAINTAIN_DIR);
67134
- if (fs35.existsSync(bundleDir)) {
67135
- fs35.rmSync(bundleDir, { recursive: true, force: true });
67326
+ const bundleDir = path41.join(harnessDir, MAINTAIN_DIR);
67327
+ if (fs36.existsSync(bundleDir)) {
67328
+ fs36.rmSync(bundleDir, { recursive: true, force: true });
67136
67329
  }
67137
67330
  const dirs = [
67138
67331
  bundleDir,
67139
- path40.join(bundleDir, "templates"),
67140
- path40.join(bundleDir, "installed"),
67141
- path40.join(bundleDir, "diffs"),
67142
- path40.join(bundleDir, "stale")
67332
+ path41.join(bundleDir, "templates"),
67333
+ path41.join(bundleDir, "installed"),
67334
+ path41.join(bundleDir, "diffs"),
67335
+ path41.join(bundleDir, "stale")
67143
67336
  ];
67144
67337
  for (const dir of dirs) {
67145
- fs35.mkdirSync(dir, { recursive: true });
67338
+ fs36.mkdirSync(dir, { recursive: true });
67146
67339
  }
67147
67340
  const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
67148
67341
  for (const file of affectedFiles) {
67149
67342
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
67150
- writeFileSafe(path40.join(bundleDir, "templates", file), templateContent);
67151
- const harnessPath = path40.join(harnessDir, file);
67152
- if (fs35.existsSync(harnessPath)) {
67153
- const installedContent = fs35.readFileSync(harnessPath, "utf8");
67154
- writeFileSafe(path40.join(bundleDir, "installed", file), installedContent);
67343
+ writeFileSafe(path41.join(bundleDir, "templates", file), templateContent);
67344
+ const harnessPath = path41.join(harnessDir, file);
67345
+ if (fs36.existsSync(harnessPath)) {
67346
+ const installedContent = fs36.readFileSync(harnessPath, "utf8");
67347
+ writeFileSafe(path41.join(bundleDir, "installed", file), installedContent);
67155
67348
  const diff = createUnifiedDiff(
67156
67349
  installedContent,
67157
67350
  templateContent,
@@ -67159,14 +67352,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
67159
67352
  `templates/${file}`
67160
67353
  );
67161
67354
  if (diff) {
67162
- writeFileSafe(path40.join(bundleDir, "diffs", `${file}.diff`), diff);
67355
+ writeFileSafe(path41.join(bundleDir, "diffs", `${file}.diff`), diff);
67163
67356
  }
67164
67357
  }
67165
67358
  }
67166
- writeFileSafe(path40.join(bundleDir, "README.md"), buildReadme(report));
67167
- writeFileSafe(path40.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
67359
+ writeFileSafe(path41.join(bundleDir, "README.md"), buildReadme(report));
67360
+ writeFileSafe(path41.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
67168
67361
  writeFileSafe(
67169
- path40.join(bundleDir, "validation.json"),
67362
+ path41.join(bundleDir, "validation.json"),
67170
67363
  JSON.stringify(report.validation, null, 2) + "\n"
67171
67364
  );
67172
67365
  if (report.stale.length > 0) {
@@ -67178,34 +67371,34 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
67178
67371
  ...report.stale.map((s) => `- **${s.file}** \u2014 ${s.hint}`),
67179
67372
  ""
67180
67373
  ];
67181
- writeFileSafe(path40.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
67374
+ writeFileSafe(path41.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
67182
67375
  }
67183
67376
  return bundleDir;
67184
67377
  }
67185
67378
  function ensureParentDir2(filePath) {
67186
- const parent = path40.dirname(filePath);
67187
- if (!fs35.existsSync(parent)) {
67188
- fs35.mkdirSync(parent, { recursive: true });
67379
+ const parent = path41.dirname(filePath);
67380
+ if (!fs36.existsSync(parent)) {
67381
+ fs36.mkdirSync(parent, { recursive: true });
67189
67382
  }
67190
67383
  }
67191
67384
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
67192
67385
  if (report.pluginActions.length === 0) return;
67193
67386
  for (const action of report.pluginActions) {
67194
- const pluginRoot = path40.join(bundleDir, "plugins", action.pluginId);
67195
- const templatesDir = path40.join(pluginRoot, "templates");
67196
- const installedDir = path40.join(pluginRoot, "installed");
67197
- const diffsDir = path40.join(pluginRoot, "diffs");
67387
+ const pluginRoot = path41.join(bundleDir, "plugins", action.pluginId);
67388
+ const templatesDir = path41.join(pluginRoot, "templates");
67389
+ const installedDir = path41.join(pluginRoot, "installed");
67390
+ const diffsDir = path41.join(pluginRoot, "diffs");
67198
67391
  for (const dir of [templatesDir, installedDir, diffsDir]) {
67199
- fs35.mkdirSync(dir, { recursive: true });
67392
+ fs36.mkdirSync(dir, { recursive: true });
67200
67393
  }
67201
67394
  const templateContent = readTemplatePluginFile(action.pluginId, action.file);
67202
67395
  if (templateContent === null) continue;
67203
- const templatePath = path40.join(templatesDir, action.file);
67396
+ const templatePath = path41.join(templatesDir, action.file);
67204
67397
  ensureParentDir2(templatePath);
67205
67398
  writeFileSafe(templatePath, templateContent);
67206
67399
  const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
67207
67400
  if (installedContent !== null) {
67208
- const installedPath = path40.join(installedDir, action.file);
67401
+ const installedPath = path41.join(installedDir, action.file);
67209
67402
  ensureParentDir2(installedPath);
67210
67403
  writeFileSafe(installedPath, installedContent);
67211
67404
  const diff = createUnifiedDiff(
@@ -67215,7 +67408,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
67215
67408
  `templates/${action.file}`
67216
67409
  );
67217
67410
  if (diff) {
67218
- const diffPath = path40.join(diffsDir, `${action.file}.diff`);
67411
+ const diffPath = path41.join(diffsDir, `${action.file}.diff`);
67219
67412
  ensureParentDir2(diffPath);
67220
67413
  writeFileSafe(diffPath, diff);
67221
67414
  }
@@ -67251,9 +67444,9 @@ function buildMaintainBundle(repoPath, validation2, drift) {
67251
67444
  return { bundleDir, report };
67252
67445
  }
67253
67446
  function removeMaintainBundle(repoPath) {
67254
- const bundleDir = path40.join(getHarnessDir(repoPath), MAINTAIN_DIR);
67255
- if (fs35.existsSync(bundleDir)) {
67256
- fs35.rmSync(bundleDir, { recursive: true, force: true });
67447
+ const bundleDir = path41.join(getHarnessDir(repoPath), MAINTAIN_DIR);
67448
+ if (fs36.existsSync(bundleDir)) {
67449
+ fs36.rmSync(bundleDir, { recursive: true, force: true });
67257
67450
  }
67258
67451
  }
67259
67452
  function formatMaintainBundlePromptSection(report) {
@@ -67342,11 +67535,11 @@ init_manifest();
67342
67535
  init_stages();
67343
67536
  function listHarnessScripts(repoPath) {
67344
67537
  const harnessDir = getHarnessDir(repoPath);
67345
- if (!fs36.existsSync(harnessDir)) return [];
67346
- return fs36.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
67538
+ if (!fs37.existsSync(harnessDir)) return [];
67539
+ return fs37.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
67347
67540
  }
67348
67541
  function describeProject(repoPath) {
67349
- const resolved = path41.resolve(repoPath);
67542
+ const resolved = path42.resolve(repoPath);
67350
67543
  const manifest = readManifest(resolved);
67351
67544
  const present = harnessExists(resolved);
67352
67545
  return {
@@ -67366,8 +67559,8 @@ function describeProject(repoPath) {
67366
67559
  };
67367
67560
  }
67368
67561
  async function initHarness(options) {
67369
- const repoPath = path41.resolve(options.repoPath);
67370
- if (!fs36.existsSync(repoPath)) {
67562
+ const repoPath = path42.resolve(options.repoPath);
67563
+ if (!fs37.existsSync(repoPath)) {
67371
67564
  throw new Error(`Path not found: ${repoPath}`);
67372
67565
  }
67373
67566
  const scaffold = scaffoldHarnessBoilerplate(repoPath, {
@@ -67387,9 +67580,9 @@ async function initHarness(options) {
67387
67580
  };
67388
67581
  }
67389
67582
  async function maintainHarness(options) {
67390
- const repoPath = path41.resolve(options.repoPath);
67583
+ const repoPath = path42.resolve(options.repoPath);
67391
67584
  const harnessDir = getHarnessDir(repoPath);
67392
- if (!fs36.existsSync(harnessDir)) {
67585
+ if (!fs37.existsSync(harnessDir)) {
67393
67586
  throw new Error('No .har/ found. Run "har env init" first.');
67394
67587
  }
67395
67588
  const drift = compareHarnessToTemplate(repoPath);
@@ -67399,6 +67592,7 @@ async function maintainHarness(options) {
67399
67592
  throw new Error("Cannot finalize: harness validation has errors. Fix them first.");
67400
67593
  }
67401
67594
  syncAgentSlotsToHarnessEnv(repoPath);
67595
+ finalizeAgentsMdInstructionFiles(repoPath);
67402
67596
  const existing = readManifest(repoPath);
67403
67597
  finalizeHarness(
67404
67598
  repoPath,
@@ -67423,13 +67617,13 @@ function addPlugin(repoPath, pluginId, options = {}) {
67423
67617
  }
67424
67618
 
67425
67619
  // src/harness/custom-stage.ts
67426
- var fs37 = __toESM(require("fs"));
67427
- var path42 = __toESM(require("path"));
67620
+ var fs38 = __toESM(require("fs"));
67621
+ var path43 = __toESM(require("path"));
67428
67622
  init_schema2();
67429
67623
  init_stages();
67430
67624
  var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
67431
67625
  function addCustomStage(repoPath, options) {
67432
- const resolved = path42.resolve(repoPath);
67626
+ const resolved = path43.resolve(repoPath);
67433
67627
  if (!harnessExists(resolved)) {
67434
67628
  throw new Error('No .har/ harness found. Run "har env init" first.');
67435
67629
  }
@@ -67466,20 +67660,20 @@ function addCustomStage(repoPath, options) {
67466
67660
  if (options.command) {
67467
67661
  stage.command = options.command;
67468
67662
  } else {
67469
- const scriptRel = path42.join("stages", `${id}.sh`);
67470
- const scriptAbs = path42.join(resolved, ".har", scriptRel);
67471
- if (fs37.existsSync(scriptAbs) && !options.force) {
67663
+ const scriptRel = path43.join("stages", `${id}.sh`);
67664
+ const scriptAbs = path43.join(resolved, ".har", scriptRel);
67665
+ if (fs38.existsSync(scriptAbs) && !options.force) {
67472
67666
  throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
67473
67667
  }
67474
- const skeletonPath = path42.join(
67668
+ const skeletonPath = path43.join(
67475
67669
  resolveTemplatesDir(),
67476
67670
  "plugins",
67477
67671
  "custom-stage-skeleton.sh"
67478
67672
  );
67479
- const skeleton = fs37.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind).replace(/__STAGE_DESCRIPTION__/g, stage.description);
67480
- fs37.mkdirSync(path42.dirname(scriptAbs), { recursive: true });
67481
- fs37.writeFileSync(scriptAbs, skeleton);
67482
- fs37.chmodSync(scriptAbs, 493);
67673
+ const skeleton = fs38.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind).replace(/__STAGE_DESCRIPTION__/g, stage.description);
67674
+ fs38.mkdirSync(path43.dirname(scriptAbs), { recursive: true });
67675
+ fs38.writeFileSync(scriptAbs, skeleton);
67676
+ fs38.chmodSync(scriptAbs, 493);
67483
67677
  filesWritten.push(`.har/${scriptRel}`);
67484
67678
  stage.script = scriptRel;
67485
67679
  stage.artifacts = [
@@ -67527,8 +67721,8 @@ function addCustomStage(repoPath, options) {
67527
67721
  }
67528
67722
 
67529
67723
  // src/harness/adaptation-prompt.ts
67530
- var fs38 = __toESM(require("fs"));
67531
- var path43 = __toESM(require("path"));
67724
+ var fs39 = __toESM(require("fs"));
67725
+ var path44 = __toESM(require("path"));
67532
67726
  var readline3 = __toESM(require("readline"));
67533
67727
 
67534
67728
  // src/utils/clipboard.ts
@@ -67618,7 +67812,7 @@ function loadTemplate(name) {
67618
67812
  if (!filePath) {
67619
67813
  throw new Error(`Adaptation prompt template not found: ${name}. Run npm run build.`);
67620
67814
  }
67621
- return fs38.readFileSync(filePath, "utf8");
67815
+ return fs39.readFileSync(filePath, "utf8");
67622
67816
  }
67623
67817
  function applyProfilePlaceholders(content, profile) {
67624
67818
  return content.replace(/\{\{PROFILE\}\}/g, profile).replace(/\{\{PROFILE_HINT\}\}/g, PROFILE_HINTS[profile]);
@@ -67640,7 +67834,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
67640
67834
  }
67641
67835
  function writeAdaptationPrompt(repoPath, content) {
67642
67836
  const harnessDir = getHarnessDir(repoPath);
67643
- const filePath = path43.join(harnessDir, ADAPTATION_PROMPT_FILE);
67837
+ const filePath = path44.join(harnessDir, ADAPTATION_PROMPT_FILE);
67644
67838
  writeFileSafe(filePath, content);
67645
67839
  return filePath;
67646
67840
  }
@@ -67695,27 +67889,27 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
67695
67889
  }
67696
67890
 
67697
67891
  // src/harness/cursor-rule.ts
67698
- var fs39 = __toESM(require("fs"));
67699
- var path44 = __toESM(require("path"));
67892
+ var fs40 = __toESM(require("fs"));
67893
+ var path45 = __toESM(require("path"));
67700
67894
  var readline4 = __toESM(require("readline"));
67701
67895
  init_file_ops();
67702
67896
  init_logging();
67703
67897
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
67704
67898
  function getCursorRulePath(repoPath) {
67705
- return path44.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
67899
+ return path45.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
67706
67900
  }
67707
67901
  function isCursorWorkspace(repoPath) {
67708
- return fs39.existsSync(path44.join(repoPath, ".cursor"));
67902
+ return fs40.existsSync(path45.join(repoPath, ".cursor"));
67709
67903
  }
67710
67904
  function cursorRuleExists(repoPath) {
67711
- return fs39.existsSync(getCursorRulePath(repoPath));
67905
+ return fs40.existsSync(getCursorRulePath(repoPath));
67712
67906
  }
67713
67907
  function scaffoldCursorRule(repoPath) {
67714
67908
  const templatePath = resolveTemplateFile("cursor-rule.mdc.template");
67715
67909
  if (!templatePath) {
67716
67910
  throw new Error("Cursor rule template not found (cursor-rule.mdc.template). Run npm run build.");
67717
67911
  }
67718
- const content = fs39.readFileSync(templatePath, "utf8");
67912
+ const content = fs40.readFileSync(templatePath, "utf8");
67719
67913
  writeFileSafe(getCursorRulePath(repoPath), content);
67720
67914
  }
67721
67915
  async function handleCursorRule(options) {
@@ -67805,7 +67999,7 @@ init_control_config();
67805
67999
 
67806
68000
  // src/core/control-lifecycle.ts
67807
68001
  var import_child_process9 = require("child_process");
67808
- var path45 = __toESM(require("path"));
68002
+ var path46 = __toESM(require("path"));
67809
68003
 
67810
68004
  // src/core/control-image.ts
67811
68005
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -67831,10 +68025,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
67831
68025
  var CONTROL_CONTAINER_PORT = 3847;
67832
68026
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
67833
68027
  function resolveControlDir() {
67834
- return path45.resolve(__dirname, "..", "control");
68028
+ return path46.resolve(__dirname, "..", "control");
67835
68029
  }
67836
68030
  function resolveControlBuildContext() {
67837
- return path45.resolve(resolveControlDir(), "..");
68031
+ return path46.resolve(resolveControlDir(), "..");
67838
68032
  }
67839
68033
  function buildDockerRunArgs(options) {
67840
68034
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -67890,7 +68084,7 @@ async function startMissionControl(options) {
67890
68084
  "-t",
67891
68085
  imageRef,
67892
68086
  "-f",
67893
- path45.join(resolveControlDir(), "Dockerfile"),
68087
+ path46.join(resolveControlDir(), "Dockerfile"),
67894
68088
  resolveControlBuildContext()
67895
68089
  ]);
67896
68090
  if (buildCode !== 0) {
@@ -68037,7 +68231,7 @@ async function ensureTelemetryInfrastructure(options) {
68037
68231
  // src/core/run-service.ts
68038
68232
  init_telemetry_config();
68039
68233
  init_telemetry_env();
68040
- var path47 = __toESM(require("path"));
68234
+ var path48 = __toESM(require("path"));
68041
68235
  init_local_executor();
68042
68236
  function extractShellOutput(result) {
68043
68237
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
@@ -68240,12 +68434,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
68240
68434
  suffix: session.suffix,
68241
68435
  createdAt: session.createdAt
68242
68436
  });
68243
- const envFile = path47.join(session.workDir, `.env.agent.${options.agentId}`);
68437
+ const envFile = path48.join(session.workDir, `.env.agent.${options.agentId}`);
68244
68438
  try {
68245
68439
  appendTelemetryEnvToFile(envFile, {
68246
68440
  sessionKey,
68247
68441
  agentId: options.agentId,
68248
- repoPath: path47.resolve(options.repoPath),
68442
+ repoPath: path48.resolve(options.repoPath),
68249
68443
  workDir: session.workDir,
68250
68444
  branch: session.branch,
68251
68445
  suffix: session.suffix,
@@ -68483,9 +68677,9 @@ init_slot_status();
68483
68677
  var readline5 = __toESM(require("readline"));
68484
68678
 
68485
68679
  // src/core/hooks.ts
68486
- var fs41 = __toESM(require("fs"));
68680
+ var fs42 = __toESM(require("fs"));
68487
68681
  var os16 = __toESM(require("os"));
68488
- var path48 = __toESM(require("path"));
68682
+ var path49 = __toESM(require("path"));
68489
68683
  init_shell();
68490
68684
  init_schema2();
68491
68685
  init_stages();
@@ -68516,7 +68710,7 @@ function resolveCheckoutRoot(cwd) {
68516
68710
  function resolveHooksDir(checkoutDir) {
68517
68711
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
68518
68712
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
68519
- return path48.resolve(checkoutDir, hooksPath);
68713
+ return path49.resolve(checkoutDir, hooksPath);
68520
68714
  }
68521
68715
  function getConfiguredHooksPath(checkoutDir) {
68522
68716
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -68524,9 +68718,9 @@ function getConfiguredHooksPath(checkoutDir) {
68524
68718
  function defaultHarInvocation() {
68525
68719
  const entry = process.argv[1];
68526
68720
  if (entry && entry.endsWith(".js")) {
68527
- return `"${process.execPath}" "${path48.resolve(entry)}"`;
68721
+ return `"${process.execPath}" "${path49.resolve(entry)}"`;
68528
68722
  }
68529
- if (entry) return `"${path48.resolve(entry)}"`;
68723
+ if (entry) return `"${path49.resolve(entry)}"`;
68530
68724
  return "har";
68531
68725
  }
68532
68726
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -68547,40 +68741,40 @@ exit 0
68547
68741
  `;
68548
68742
  }
68549
68743
  function upsertMarkedBlock2(filePath, block) {
68550
- if (!fs41.existsSync(filePath)) {
68551
- fs41.writeFileSync(filePath, `#!/bin/sh
68744
+ if (!fs42.existsSync(filePath)) {
68745
+ fs42.writeFileSync(filePath, `#!/bin/sh
68552
68746
  ${block}
68553
68747
  `, { mode: 493 });
68554
68748
  return "created";
68555
68749
  }
68556
- const content = fs41.readFileSync(filePath, "utf8");
68750
+ const content = fs42.readFileSync(filePath, "utf8");
68557
68751
  if (content.includes(MARKER_START)) {
68558
68752
  const pattern = new RegExp(
68559
68753
  `${escapeRegExp2(MARKER_START)}[\\s\\S]*?${escapeRegExp2(MARKER_END)}`
68560
68754
  );
68561
- fs41.writeFileSync(filePath, content.replace(pattern, block));
68562
- fs41.chmodSync(filePath, 493);
68755
+ fs42.writeFileSync(filePath, content.replace(pattern, block));
68756
+ fs42.chmodSync(filePath, 493);
68563
68757
  return "updated";
68564
68758
  }
68565
68759
  const suffix = content.endsWith("\n") ? "" : "\n";
68566
- fs41.writeFileSync(filePath, `${content}${suffix}
68760
+ fs42.writeFileSync(filePath, `${content}${suffix}
68567
68761
  ${block}
68568
68762
  `);
68569
- fs41.chmodSync(filePath, 493);
68763
+ fs42.chmodSync(filePath, 493);
68570
68764
  return "appended";
68571
68765
  }
68572
68766
  function removeMarkedBlock(filePath) {
68573
- if (!fs41.existsSync(filePath)) return false;
68574
- const content = fs41.readFileSync(filePath, "utf8");
68767
+ if (!fs42.existsSync(filePath)) return false;
68768
+ const content = fs42.readFileSync(filePath, "utf8");
68575
68769
  if (!content.includes(MARKER_START)) return false;
68576
68770
  const pattern = new RegExp(
68577
68771
  `\\n?${escapeRegExp2(MARKER_START)}[\\s\\S]*?${escapeRegExp2(MARKER_END)}\\n?`
68578
68772
  );
68579
68773
  const stripped = content.replace(pattern, "\n");
68580
68774
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
68581
- fs41.rmSync(filePath);
68775
+ fs42.rmSync(filePath);
68582
68776
  } else {
68583
- fs41.writeFileSync(filePath, stripped);
68777
+ fs42.writeFileSync(filePath, stripped);
68584
68778
  }
68585
68779
  return true;
68586
68780
  }
@@ -68602,20 +68796,20 @@ Or re-run with --force to write into that directory anyway.`
68602
68796
  );
68603
68797
  }
68604
68798
  const hooksDir = resolveHooksDir(checkout);
68605
- fs41.mkdirSync(hooksDir, { recursive: true });
68799
+ fs42.mkdirSync(hooksDir, { recursive: true });
68606
68800
  const invocation = options.harInvocation ?? defaultHarInvocation();
68607
- fs41.writeFileSync(
68608
- path48.join(hooksDir, "har-pre-commit"),
68801
+ fs42.writeFileSync(
68802
+ path49.join(hooksDir, "har-pre-commit"),
68609
68803
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
68610
68804
  { mode: 493 }
68611
68805
  );
68612
- fs41.writeFileSync(
68613
- path48.join(hooksDir, "har-post-commit"),
68806
+ fs42.writeFileSync(
68807
+ path49.join(hooksDir, "har-post-commit"),
68614
68808
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
68615
68809
  { mode: 493 }
68616
68810
  );
68617
- const preCommit = upsertMarkedBlock2(path48.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
68618
- const postCommit = upsertMarkedBlock2(path48.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
68811
+ const preCommit = upsertMarkedBlock2(path49.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
68812
+ const postCommit = upsertMarkedBlock2(path49.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
68619
68813
  ensureValidationsIgnored(checkout);
68620
68814
  return { hooksDir, preCommit, postCommit };
68621
68815
  }
@@ -68624,12 +68818,12 @@ function uninstallHooks(repoPath) {
68624
68818
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
68625
68819
  const hooksDir = resolveHooksDir(checkout);
68626
68820
  let removed = false;
68627
- removed = removeMarkedBlock(path48.join(hooksDir, "pre-commit")) || removed;
68628
- removed = removeMarkedBlock(path48.join(hooksDir, "post-commit")) || removed;
68821
+ removed = removeMarkedBlock(path49.join(hooksDir, "pre-commit")) || removed;
68822
+ removed = removeMarkedBlock(path49.join(hooksDir, "post-commit")) || removed;
68629
68823
  for (const file of ["har-pre-commit", "har-post-commit"]) {
68630
- const full = path48.join(hooksDir, file);
68631
- if (fs41.existsSync(full)) {
68632
- fs41.rmSync(full);
68824
+ const full = path49.join(hooksDir, file);
68825
+ if (fs42.existsSync(full)) {
68826
+ fs42.rmSync(full);
68633
68827
  removed = true;
68634
68828
  }
68635
68829
  }
@@ -68648,10 +68842,10 @@ function isAgentWorktree(checkoutDir) {
68648
68842
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
68649
68843
  return true;
68650
68844
  }
68651
- const worktreesRoot = path48.join(os16.homedir(), "worktrees");
68652
- const resolved = path48.resolve(checkoutDir);
68653
- const name = path48.basename(resolved);
68654
- return resolved.startsWith(`${worktreesRoot}${path48.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
68845
+ const worktreesRoot = path49.join(os16.homedir(), "worktrees");
68846
+ const resolved = path49.resolve(checkoutDir);
68847
+ const name = path49.basename(resolved);
68848
+ return resolved.startsWith(`${worktreesRoot}${path49.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
68655
68849
  }
68656
68850
  function resolveEffectiveMode(checkoutDir, gate) {
68657
68851
  if (!gate.enabled) return "off";
@@ -68664,15 +68858,15 @@ function getHooksStatus(repoPath) {
68664
68858
  const hooksDir = resolveHooksDir(checkout);
68665
68859
  const gate = getCommitGateConfig(checkout);
68666
68860
  const hasBlock = (name) => {
68667
- const file = path48.join(hooksDir, name);
68668
- return fs41.existsSync(file) && fs41.readFileSync(file, "utf8").includes(MARKER_START);
68861
+ const file = path49.join(hooksDir, name);
68862
+ return fs42.existsSync(file) && fs42.readFileSync(file, "utf8").includes(MARKER_START);
68669
68863
  };
68670
68864
  return {
68671
68865
  checkout,
68672
68866
  hooksDir,
68673
68867
  configuredHooksPath: getConfiguredHooksPath(checkout),
68674
- preCommitInstalled: hasBlock("pre-commit") && fs41.existsSync(path48.join(hooksDir, "har-pre-commit")),
68675
- postCommitInstalled: hasBlock("post-commit") && fs41.existsSync(path48.join(hooksDir, "har-post-commit")),
68868
+ preCommitInstalled: hasBlock("pre-commit") && fs42.existsSync(path49.join(hooksDir, "har-pre-commit")),
68869
+ postCommitInstalled: hasBlock("post-commit") && fs42.existsSync(path49.join(hooksDir, "har-post-commit")),
68676
68870
  gate,
68677
68871
  effectiveMode: resolveEffectiveMode(checkout, gate)
68678
68872
  };
@@ -68683,7 +68877,7 @@ function checkCommitGate(cwd) {
68683
68877
  }
68684
68878
  const checkout = resolveCheckoutRoot(cwd);
68685
68879
  if (!checkout) return { exitCode: 0, messages: [] };
68686
- if (!fs41.existsSync(path48.join(checkout, ".har", "stages.json"))) {
68880
+ if (!fs42.existsSync(path49.join(checkout, ".har", "stages.json"))) {
68687
68881
  return { exitCode: 0, messages: [] };
68688
68882
  }
68689
68883
  const gate = getCommitGateConfig(checkout);
@@ -68805,21 +68999,21 @@ async function handleCommitGateOnboarding(options) {
68805
68999
  }
68806
69000
 
68807
69001
  // src/core/onboarding-preferences.ts
68808
- var fs42 = __toESM(require("fs"));
69002
+ var fs43 = __toESM(require("fs"));
68809
69003
  var os17 = __toESM(require("os"));
68810
- var path49 = __toESM(require("path"));
69004
+ var path50 = __toESM(require("path"));
68811
69005
  init_schema2();
68812
69006
  function getOnboardingPreferencesPath() {
68813
69007
  if (process.env.HAR_PREFERENCES_PATH) {
68814
- return path49.resolve(process.env.HAR_PREFERENCES_PATH);
69008
+ return path50.resolve(process.env.HAR_PREFERENCES_PATH);
68815
69009
  }
68816
- return path49.join(os17.homedir(), ".har", "preferences.json");
69010
+ return path50.join(os17.homedir(), ".har", "preferences.json");
68817
69011
  }
68818
69012
  function readOnboardingPreferences() {
68819
69013
  const preferencePath = getOnboardingPreferencesPath();
68820
69014
  try {
68821
- if (!fs42.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
68822
- return OnboardingPreferencesSchema.parse(JSON.parse(fs42.readFileSync(preferencePath, "utf8")));
69015
+ if (!fs43.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
69016
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs43.readFileSync(preferencePath, "utf8")));
68823
69017
  } catch {
68824
69018
  return OnboardingPreferencesSchema.parse({});
68825
69019
  }
@@ -68844,8 +69038,8 @@ function writeOnboardingPreferences(overrides) {
68844
69038
  };
68845
69039
  const parsed = OnboardingPreferencesSchema.parse(preference);
68846
69040
  const preferencePath = getOnboardingPreferencesPath();
68847
- fs42.mkdirSync(path49.dirname(preferencePath), { recursive: true });
68848
- fs42.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
69041
+ fs43.mkdirSync(path50.dirname(preferencePath), { recursive: true });
69042
+ fs43.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
68849
69043
  `);
68850
69044
  return parsed;
68851
69045
  }
@@ -69136,7 +69330,7 @@ var envCommand = {
69136
69330
  }
69137
69331
  };
69138
69332
  async function handleInit(argv) {
69139
- const repoPath = path50.resolve(argv.repo);
69333
+ const repoPath = path51.resolve(argv.repo);
69140
69334
  const onboarding = resolveOnboardingOptions(argv);
69141
69335
  header("har env init");
69142
69336
  info(`Repository: ${repoPath}`);
@@ -69182,7 +69376,7 @@ async function handleInit(argv) {
69182
69376
  }
69183
69377
  }
69184
69378
  async function handleMaintain(argv) {
69185
- const repoPath = path50.resolve(argv.repo);
69379
+ const repoPath = path51.resolve(argv.repo);
69186
69380
  const onboarding = resolveOnboardingOptions(argv);
69187
69381
  header("har env maintain");
69188
69382
  info(`Repository: ${repoPath}`);
@@ -69237,6 +69431,8 @@ async function handleMaintain(argv) {
69237
69431
  mode: "maintain",
69238
69432
  autoYes: argv.yes,
69239
69433
  cursorRule: onboarding.cursorRule,
69434
+ writeAgentsMd: !argv.finalize,
69435
+ finalize: argv.finalize,
69240
69436
  ...onboarding.agentSkills
69241
69437
  });
69242
69438
  } catch (err) {
@@ -69288,7 +69484,9 @@ async function applyAgentIntegrations(options) {
69288
69484
  enabled: options.enabled,
69289
69485
  cursorRule: options.cursorRule,
69290
69486
  autoYes: options.autoYes,
69291
- mode: options.mode
69487
+ mode: options.mode,
69488
+ writeAgentsMd: options.writeAgentsMd,
69489
+ finalize: options.finalize
69292
69490
  });
69293
69491
  const cursorRuleFlag = options.cursorRule === false ? false : options.cursorRule === true || instruction.plan.cursorRule ? true : false;
69294
69492
  await handleCursorRule({
@@ -69309,7 +69507,7 @@ async function applyAgentIntegrations(options) {
69309
69507
  }
69310
69508
  }
69311
69509
  async function handleAddPlugin(argv) {
69312
- const repoPath = path50.resolve(argv.repo);
69510
+ const repoPath = path51.resolve(argv.repo);
69313
69511
  const available = listPluginIds();
69314
69512
  if (argv.list) {
69315
69513
  for (const id of available) {
@@ -69347,7 +69545,7 @@ async function handleAddPlugin(argv) {
69347
69545
  }
69348
69546
  }
69349
69547
  async function handleAddStage(argv) {
69350
- const repoPath = path50.resolve(argv.repo);
69548
+ const repoPath = path51.resolve(argv.repo);
69351
69549
  const available = listPluginIds();
69352
69550
  if (argv.list) {
69353
69551
  warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
@@ -69413,7 +69611,7 @@ async function handleAddStage(argv) {
69413
69611
  });
69414
69612
  }
69415
69613
  async function handlePreflight(argv) {
69416
- const repo = path50.resolve(argv.repo);
69614
+ const repo = path51.resolve(argv.repo);
69417
69615
  const agentId = validateAgentId(argv.id, repo);
69418
69616
  const result = await preflightEnvironment({
69419
69617
  repoPath: repo,
@@ -69429,7 +69627,7 @@ async function handlePreflight(argv) {
69429
69627
  return finishCommand(result.code);
69430
69628
  }
69431
69629
  async function handleLaunch(argv) {
69432
- const repo = path50.resolve(argv.repo);
69630
+ const repo = path51.resolve(argv.repo);
69433
69631
  const agentId = validateAgentId(argv.id, repo);
69434
69632
  if (!argv.resume) {
69435
69633
  const guard = checkLaunchGuard2(repo, agentId, {});
@@ -69484,7 +69682,7 @@ async function handleRecover(argv) {
69484
69682
  });
69485
69683
  }
69486
69684
  async function handleVerify(argv) {
69487
- const repo = path50.resolve(argv.repo);
69685
+ const repo = path51.resolve(argv.repo);
69488
69686
  const agentId = validateAgentId(argv.id, repo);
69489
69687
  const result = await runVerification({
69490
69688
  repoPath: repo,
@@ -69496,7 +69694,7 @@ async function handleVerify(argv) {
69496
69694
  return finishCommand(result.code);
69497
69695
  }
69498
69696
  async function handleTeardown(argv) {
69499
- const repo = path50.resolve(argv.repo);
69697
+ const repo = path51.resolve(argv.repo);
69500
69698
  const agentId = validateAgentId(argv.id, repo);
69501
69699
  const result = await teardownEnvironment({
69502
69700
  repoPath: repo,
@@ -69507,7 +69705,7 @@ async function handleTeardown(argv) {
69507
69705
  return finishCommand(result.code);
69508
69706
  }
69509
69707
  async function handleComplete(argv) {
69510
- const repo = path50.resolve(argv.repo);
69708
+ const repo = path51.resolve(argv.repo);
69511
69709
  const agentId = validateAgentId(argv.id, repo);
69512
69710
  const result = await completeEnvironment({
69513
69711
  repoPath: repo,
@@ -69528,7 +69726,7 @@ async function handleComplete(argv) {
69528
69726
  return finishCommand(result.code);
69529
69727
  }
69530
69728
  async function handleStatus(argv) {
69531
- const repoPath = path50.resolve(argv.repo);
69729
+ const repoPath = path51.resolve(argv.repo);
69532
69730
  if (argv.json) {
69533
69731
  const status = collectEnvironmentStatus(repoPath);
69534
69732
  const output = EnvironmentStatusSchema.parse(status);
@@ -69541,7 +69739,7 @@ async function handleStatus(argv) {
69541
69739
  });
69542
69740
  }
69543
69741
  async function handleRunsList(argv) {
69544
- const repoPath = path50.resolve(argv.repo);
69742
+ const repoPath = path51.resolve(argv.repo);
69545
69743
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
69546
69744
  if (argv.json) {
69547
69745
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -69558,7 +69756,7 @@ async function handleRunsList(argv) {
69558
69756
  }
69559
69757
  }
69560
69758
  async function handleRunsGet(argv) {
69561
- const run2 = getRun(path50.resolve(argv.repo), argv.runId);
69759
+ const run2 = getRun(path51.resolve(argv.repo), argv.runId);
69562
69760
  if (!run2) {
69563
69761
  error(`Run not found: ${argv.runId}`);
69564
69762
  return finishCommand(1);
@@ -69640,7 +69838,7 @@ function printNextSteps() {
69640
69838
  }
69641
69839
 
69642
69840
  // src/cli/commands/control.ts
69643
- var path54 = __toESM(require("path"));
69841
+ var path55 = __toESM(require("path"));
69644
69842
 
69645
69843
  // node_modules/@inquirer/core/dist/esm/lib/key.mjs
69646
69844
  var isUpKey = (key) => (
@@ -71694,9 +71892,9 @@ var import_run_async = __toESM(require_run_async(), 1);
71694
71892
  var import_mute_stream2 = __toESM(require_lib(), 1);
71695
71893
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
71696
71894
  var _ = {
71697
- set: (obj, path61 = "", value) => {
71895
+ set: (obj, path62 = "", value) => {
71698
71896
  let pointer = obj;
71699
- path61.split(".").forEach((key, index, arr) => {
71897
+ path62.split(".").forEach((key, index, arr) => {
71700
71898
  if (key === "__proto__" || key === "constructor")
71701
71899
  return;
71702
71900
  if (index === arr.length - 1) {
@@ -71707,8 +71905,8 @@ var _ = {
71707
71905
  pointer = pointer[key];
71708
71906
  });
71709
71907
  },
71710
- get: (obj, path61 = "", defaultValue) => {
71711
- const travel = (regexp) => String.prototype.split.call(path61, regexp).filter(Boolean).reduce(
71908
+ get: (obj, path62 = "", defaultValue) => {
71909
+ const travel = (regexp) => String.prototype.split.call(path62, regexp).filter(Boolean).reduce(
71712
71910
  // @ts-expect-error implicit any on res[key]
71713
71911
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
71714
71912
  obj
@@ -71962,21 +72160,21 @@ init_control_port();
71962
72160
  init_control_sync();
71963
72161
 
71964
72162
  // src/core/control-sync-selection.ts
71965
- var fs43 = __toESM(require("fs"));
72163
+ var fs44 = __toESM(require("fs"));
71966
72164
  var os18 = __toESM(require("os"));
71967
- var path51 = __toESM(require("path"));
72165
+ var path52 = __toESM(require("path"));
71968
72166
  init_control_repo_path();
71969
72167
  function getSelectionPath() {
71970
72168
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
71971
- return path51.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
72169
+ return path52.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
71972
72170
  }
71973
- return path51.join(os18.homedir(), ".har", "sync-selection.json");
72171
+ return path52.join(os18.homedir(), ".har", "sync-selection.json");
71974
72172
  }
71975
72173
  function readSyncSelection() {
71976
72174
  const selectionPath = getSelectionPath();
71977
72175
  try {
71978
- if (!fs43.existsSync(selectionPath)) return null;
71979
- const parsed = JSON.parse(fs43.readFileSync(selectionPath, "utf8"));
72176
+ if (!fs44.existsSync(selectionPath)) return null;
72177
+ const parsed = JSON.parse(fs44.readFileSync(selectionPath, "utf8"));
71980
72178
  if (!Array.isArray(parsed.repos)) return null;
71981
72179
  return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
71982
72180
  } catch {
@@ -71986,8 +72184,8 @@ function readSyncSelection() {
71986
72184
  function writeSyncSelection(repos) {
71987
72185
  const selectionPath = getSelectionPath();
71988
72186
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
71989
- fs43.mkdirSync(path51.dirname(selectionPath), { recursive: true });
71990
- fs43.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
72187
+ fs44.mkdirSync(path52.dirname(selectionPath), { recursive: true });
72188
+ fs44.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
71991
72189
  }
71992
72190
  function resolveSyncSelection(input) {
71993
72191
  const { discovered, stored, forceSelect, isTTY } = input;
@@ -72094,8 +72292,8 @@ If your browser did not open, paste that URL.
72094
72292
  }
72095
72293
 
72096
72294
  // src/core/control-unregister.ts
72097
- var fs44 = __toESM(require("fs"));
72098
- var path52 = __toESM(require("path"));
72295
+ var fs45 = __toESM(require("fs"));
72296
+ var path53 = __toESM(require("path"));
72099
72297
  init_control_repo_path();
72100
72298
  init_control_registry();
72101
72299
  init_control_config();
@@ -72105,9 +72303,9 @@ function listUnregisterWorktreeCandidates(repoPath) {
72105
72303
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
72106
72304
  const byPath = /* @__PURE__ */ new Map();
72107
72305
  const add = (partial2) => {
72108
- const resolved = path52.resolve(partial2.worktreePath);
72306
+ const resolved = path53.resolve(partial2.worktreePath);
72109
72307
  if (!resolved || resolved === harnessRoot) return;
72110
- const exists = partial2.exists ?? fs44.existsSync(resolved);
72308
+ const exists = partial2.exists ?? fs45.existsSync(resolved);
72111
72309
  const prev = byPath.get(resolved);
72112
72310
  if (prev) {
72113
72311
  byPath.set(resolved, {
@@ -72221,28 +72419,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
72221
72419
  trigger: "cli"
72222
72420
  });
72223
72421
  if (result.code !== 0) {
72224
- if (fs44.existsSync(candidate.worktreePath)) {
72225
- fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
72422
+ if (fs45.existsSync(candidate.worktreePath)) {
72423
+ fs45.rmSync(candidate.worktreePath, { recursive: true, force: true });
72226
72424
  }
72227
72425
  }
72228
72426
  outcomes.push({
72229
72427
  path: candidate.worktreePath,
72230
72428
  agentId: candidate.agentId,
72231
- deleted: !fs44.existsSync(candidate.worktreePath),
72232
- error: result.code !== 0 && fs44.existsSync(candidate.worktreePath) ? result.stderr : void 0
72429
+ deleted: !fs45.existsSync(candidate.worktreePath),
72430
+ error: result.code !== 0 && fs45.existsSync(candidate.worktreePath) ? result.stderr : void 0
72233
72431
  });
72234
72432
  } catch (err) {
72235
72433
  const message = err instanceof Error ? err.message : String(err);
72236
72434
  try {
72237
- if (fs44.existsSync(candidate.worktreePath)) {
72238
- fs44.rmSync(candidate.worktreePath, { recursive: true, force: true });
72435
+ if (fs45.existsSync(candidate.worktreePath)) {
72436
+ fs45.rmSync(candidate.worktreePath, { recursive: true, force: true });
72239
72437
  }
72240
72438
  } catch {
72241
72439
  }
72242
72440
  outcomes.push({
72243
72441
  path: candidate.worktreePath,
72244
72442
  agentId: candidate.agentId,
72245
- deleted: !fs44.existsSync(candidate.worktreePath),
72443
+ deleted: !fs45.existsSync(candidate.worktreePath),
72246
72444
  error: message
72247
72445
  });
72248
72446
  }
@@ -72305,16 +72503,16 @@ init_control_config();
72305
72503
  init_control_registry();
72306
72504
 
72307
72505
  // src/core/harness-scrub.ts
72308
- var fs45 = __toESM(require("fs"));
72309
- var path53 = __toESM(require("path"));
72506
+ var fs46 = __toESM(require("fs"));
72507
+ var path54 = __toESM(require("path"));
72310
72508
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
72311
72509
  function scrubLocalHarnessDirs(repoPath) {
72312
72510
  const results = [];
72313
- const resolved = path53.resolve(repoPath);
72314
- if (!fs45.existsSync(resolved)) {
72511
+ const resolved = path54.resolve(repoPath);
72512
+ if (!fs46.existsSync(resolved)) {
72315
72513
  for (const directory of HARNESS_SCRUB_DIRS) {
72316
72514
  results.push({
72317
- path: path53.join(resolved, ".har", directory),
72515
+ path: path54.join(resolved, ".har", directory),
72318
72516
  directory,
72319
72517
  deleted: false,
72320
72518
  error: "repository path does not exist"
@@ -72323,24 +72521,24 @@ function scrubLocalHarnessDirs(repoPath) {
72323
72521
  return results;
72324
72522
  }
72325
72523
  for (const directory of HARNESS_SCRUB_DIRS) {
72326
- const target = path53.join(resolved, ".har", directory);
72327
- if (!fs45.existsSync(target)) {
72524
+ const target = path54.join(resolved, ".har", directory);
72525
+ if (!fs46.existsSync(target)) {
72328
72526
  results.push({ path: target, directory, deleted: true });
72329
72527
  continue;
72330
72528
  }
72331
72529
  try {
72332
- fs45.rmSync(target, { recursive: true, force: true });
72530
+ fs46.rmSync(target, { recursive: true, force: true });
72333
72531
  results.push({
72334
72532
  path: target,
72335
72533
  directory,
72336
- deleted: !fs45.existsSync(target),
72337
- error: fs45.existsSync(target) ? "failed to remove directory" : void 0
72534
+ deleted: !fs46.existsSync(target),
72535
+ error: fs46.existsSync(target) ? "failed to remove directory" : void 0
72338
72536
  });
72339
72537
  } catch (err) {
72340
72538
  results.push({
72341
72539
  path: target,
72342
72540
  directory,
72343
- deleted: !fs45.existsSync(target),
72541
+ deleted: !fs46.existsSync(target),
72344
72542
  error: err instanceof Error ? err.message : String(err)
72345
72543
  });
72346
72544
  }
@@ -72351,7 +72549,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
72351
72549
  const results = [];
72352
72550
  const seen = /* @__PURE__ */ new Set();
72353
72551
  for (const repoPath of repoPaths) {
72354
- const key = path53.resolve(repoPath);
72552
+ const key = path54.resolve(repoPath);
72355
72553
  if (seen.has(key)) continue;
72356
72554
  seen.add(key);
72357
72555
  results.push(...scrubLocalHarnessDirs(key));
@@ -72607,7 +72805,7 @@ async function handleDown() {
72607
72805
  return finishCommand(code);
72608
72806
  }
72609
72807
  async function handleRegister(argv) {
72610
- const repoPath = path54.resolve(argv.repo);
72808
+ const repoPath = path55.resolve(argv.repo);
72611
72809
  header("har control register");
72612
72810
  info(`Repository: ${repoPath}`);
72613
72811
  try {
@@ -72699,7 +72897,7 @@ async function handleReset(argv) {
72699
72897
  }
72700
72898
  }
72701
72899
  async function handleUnregister(argv) {
72702
- const repoPath = path54.resolve(argv.repo);
72900
+ const repoPath = path55.resolve(argv.repo);
72703
72901
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
72704
72902
  try {
72705
72903
  let deleteWorktrees = argv.deleteWorktrees;
@@ -72878,11 +73076,11 @@ async function handleLogin(argv) {
72878
73076
  }
72879
73077
 
72880
73078
  // src/cli/commands/hooks.ts
72881
- var path56 = __toESM(require("path"));
73079
+ var path57 = __toESM(require("path"));
72882
73080
 
72883
73081
  // src/core/claude-hooks.ts
72884
- var fs46 = __toESM(require("fs"));
72885
- var path55 = __toESM(require("path"));
73082
+ var fs47 = __toESM(require("fs"));
73083
+ var path56 = __toESM(require("path"));
72886
73084
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
72887
73085
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
72888
73086
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -72893,8 +73091,8 @@ function isHarGuardEntry(entry) {
72893
73091
  );
72894
73092
  }
72895
73093
  function readSettings(settingsPath) {
72896
- if (!fs46.existsSync(settingsPath)) return {};
72897
- const raw = fs46.readFileSync(settingsPath, "utf8").trim();
73094
+ if (!fs47.existsSync(settingsPath)) return {};
73095
+ const raw = fs47.readFileSync(settingsPath, "utf8").trim();
72898
73096
  if (raw === "") return {};
72899
73097
  const parsed = JSON.parse(raw);
72900
73098
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -72903,19 +73101,19 @@ function readSettings(settingsPath) {
72903
73101
  return parsed;
72904
73102
  }
72905
73103
  function writeSettings(settingsPath, settings) {
72906
- fs46.mkdirSync(path55.dirname(settingsPath), { recursive: true });
72907
- fs46.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
73104
+ fs47.mkdirSync(path56.dirname(settingsPath), { recursive: true });
73105
+ fs47.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
72908
73106
  }
72909
73107
  function installClaudeGuard(repoPath) {
72910
73108
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
72911
73109
  if (!templatePath) {
72912
73110
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
72913
73111
  }
72914
- const guardScript = path55.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
72915
- fs46.mkdirSync(path55.dirname(guardScript), { recursive: true });
72916
- fs46.copyFileSync(templatePath, guardScript);
72917
- fs46.chmodSync(guardScript, 493);
72918
- const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
73112
+ const guardScript = path56.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
73113
+ fs47.mkdirSync(path56.dirname(guardScript), { recursive: true });
73114
+ fs47.copyFileSync(templatePath, guardScript);
73115
+ fs47.chmodSync(guardScript, 493);
73116
+ const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
72919
73117
  const settings = readSettings(settingsPath);
72920
73118
  const hooks = settings.hooks ?? {};
72921
73119
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -72929,15 +73127,15 @@ function installClaudeGuard(repoPath) {
72929
73127
  }
72930
73128
  function uninstallClaudeGuard(repoPath) {
72931
73129
  let removed = false;
72932
- const guardScript = path55.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
72933
- if (fs46.existsSync(guardScript)) {
72934
- fs46.rmSync(guardScript);
73130
+ const guardScript = path56.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
73131
+ if (fs47.existsSync(guardScript)) {
73132
+ fs47.rmSync(guardScript);
72935
73133
  removed = true;
72936
- const parent = path55.dirname(guardScript);
72937
- if (fs46.existsSync(parent) && fs46.readdirSync(parent).length === 0) fs46.rmdirSync(parent);
73134
+ const parent = path56.dirname(guardScript);
73135
+ if (fs47.existsSync(parent) && fs47.readdirSync(parent).length === 0) fs47.rmdirSync(parent);
72938
73136
  }
72939
- const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
72940
- if (fs46.existsSync(settingsPath)) {
73137
+ const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
73138
+ if (fs47.existsSync(settingsPath)) {
72941
73139
  const settings = readSettings(settingsPath);
72942
73140
  const preToolUse = settings.hooks?.PreToolUse;
72943
73141
  if (preToolUse) {
@@ -72962,8 +73160,8 @@ function uninstallClaudeGuard(repoPath) {
72962
73160
  return { removed };
72963
73161
  }
72964
73162
  function claudeGuardInstalled(repoPath) {
72965
- const settingsPath = path55.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
72966
- if (!fs46.existsSync(settingsPath)) return false;
73163
+ const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
73164
+ if (!fs47.existsSync(settingsPath)) return false;
72967
73165
  try {
72968
73166
  const settings = readSettings(settingsPath);
72969
73167
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -72980,7 +73178,7 @@ function repoOption(y) {
72980
73178
  function handleInstall2(argv) {
72981
73179
  try {
72982
73180
  if (argv.claude) {
72983
- const result2 = installClaudeGuard(path56.resolve(argv.repo));
73181
+ const result2 = installClaudeGuard(path57.resolve(argv.repo));
72984
73182
  success("Claude Code worktree guard installed.");
72985
73183
  info(`Guard script: ${result2.guardScript}`);
72986
73184
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -72988,7 +73186,7 @@ function handleInstall2(argv) {
72988
73186
  info("Commit both files so the guard travels with the repo.");
72989
73187
  return;
72990
73188
  }
72991
- const result = installHooks({ repoPath: path56.resolve(argv.repo), force: argv.force });
73189
+ const result = installHooks({ repoPath: path57.resolve(argv.repo), force: argv.force });
72992
73190
  success(`Commit gate installed in ${result.hooksDir}`);
72993
73191
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
72994
73192
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -73001,7 +73199,7 @@ function handleInstall2(argv) {
73001
73199
  function handleUninstall(argv) {
73002
73200
  try {
73003
73201
  if (argv.claude) {
73004
- const result2 = uninstallClaudeGuard(path56.resolve(argv.repo));
73202
+ const result2 = uninstallClaudeGuard(path57.resolve(argv.repo));
73005
73203
  if (result2.removed) {
73006
73204
  success("Claude Code worktree guard removed.");
73007
73205
  } else {
@@ -73009,7 +73207,7 @@ function handleUninstall(argv) {
73009
73207
  }
73010
73208
  return;
73011
73209
  }
73012
- const result = uninstallHooks(path56.resolve(argv.repo));
73210
+ const result = uninstallHooks(path57.resolve(argv.repo));
73013
73211
  if (result.removed) {
73014
73212
  success(`Commit gate removed from ${result.hooksDir}`);
73015
73213
  } else {
@@ -73022,7 +73220,7 @@ function handleUninstall(argv) {
73022
73220
  }
73023
73221
  function handleStatus2(argv) {
73024
73222
  try {
73025
- const status = getHooksStatus(path56.resolve(argv.repo));
73223
+ const status = getHooksStatus(path57.resolve(argv.repo));
73026
73224
  if (argv.json) {
73027
73225
  process.stdout.write(`${JSON.stringify(status, null, 2)}
73028
73226
  `);
@@ -73040,7 +73238,7 @@ function handleStatus2(argv) {
73040
73238
  );
73041
73239
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
73042
73240
  info(
73043
- `Claude guard: ${claudeGuardInstalled(path56.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
73241
+ `Claude guard: ${claudeGuardInstalled(path57.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
73044
73242
  );
73045
73243
  } catch (err) {
73046
73244
  error(err instanceof Error ? err.message : String(err));
@@ -73301,10 +73499,10 @@ function assignProp(target, prop, value) {
73301
73499
  configurable: true
73302
73500
  });
73303
73501
  }
73304
- function getElementAtPath(obj, path61) {
73305
- if (!path61)
73502
+ function getElementAtPath(obj, path62) {
73503
+ if (!path62)
73306
73504
  return obj;
73307
- return path61.reduce((acc, key) => acc?.[key], obj);
73505
+ return path62.reduce((acc, key) => acc?.[key], obj);
73308
73506
  }
73309
73507
  function promiseAllObject(promisesObj) {
73310
73508
  const keys = Object.keys(promisesObj);
@@ -73624,11 +73822,11 @@ function aborted(x, startIndex = 0) {
73624
73822
  }
73625
73823
  return false;
73626
73824
  }
73627
- function prefixIssues(path61, issues) {
73825
+ function prefixIssues(path62, issues) {
73628
73826
  return issues.map((iss) => {
73629
73827
  var _a2;
73630
73828
  (_a2 = iss).path ?? (_a2.path = []);
73631
- iss.path.unshift(path61);
73829
+ iss.path.unshift(path62);
73632
73830
  return iss;
73633
73831
  });
73634
73832
  }
@@ -80102,7 +80300,7 @@ var Server = class extends Protocol {
80102
80300
  };
80103
80301
 
80104
80302
  // src/mcp/server.ts
80105
- var path57 = __toESM(require("path"));
80303
+ var path58 = __toESM(require("path"));
80106
80304
 
80107
80305
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
80108
80306
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -80745,7 +80943,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
80745
80943
  const input = ControlUpInputSchema.parse({ ...args, repo });
80746
80944
  const result = await startControlAndSync({
80747
80945
  detach: input.detach,
80748
- cwd: path57.resolve(input.repo)
80946
+ cwd: path58.resolve(input.repo)
80749
80947
  });
80750
80948
  if (result.code !== 0) {
80751
80949
  return {
@@ -80809,11 +81007,11 @@ var mcpCommand = {
80809
81007
  };
80810
81008
 
80811
81009
  // src/cli/commands/onboard.ts
80812
- var path59 = __toESM(require("path"));
81010
+ var path60 = __toESM(require("path"));
80813
81011
  init_stages();
80814
81012
 
80815
81013
  // src/core/onboarding.ts
80816
- var path58 = __toESM(require("path"));
81014
+ var path59 = __toESM(require("path"));
80817
81015
  init_control_config();
80818
81016
  init_control_sync();
80819
81017
  init_otel_hooks();
@@ -80948,7 +81146,7 @@ async function defaultEnsureControl(options) {
80948
81146
  return { started: true, apiUrl: result.apiUrl };
80949
81147
  }
80950
81148
  async function runOnboarding(options, deps = {}) {
80951
- const repoPath = path58.resolve(options.repoPath);
81149
+ const repoPath = path59.resolve(options.repoPath);
80952
81150
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
80953
81151
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
80954
81152
  const init = deps.initHarness ?? initHarness;
@@ -81136,7 +81334,7 @@ async function promptChoices(args) {
81136
81334
  };
81137
81335
  }
81138
81336
  const pluginChoices = listPluginChoices();
81139
- const repoPath = path59.resolve(args.repo);
81337
+ const repoPath = path60.resolve(args.repo);
81140
81338
  const alreadyPresent = harnessExists(repoPath);
81141
81339
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
81142
81340
  const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
@@ -81253,7 +81451,7 @@ function printSummary(result) {
81253
81451
  console.error("");
81254
81452
  }
81255
81453
  async function handleOnboard(argv) {
81256
- const repoPath = path59.resolve(argv.repo);
81454
+ const repoPath = path60.resolve(argv.repo);
81257
81455
  header("har onboard");
81258
81456
  info(`Repository: ${repoPath}`);
81259
81457
  try {
@@ -81484,7 +81682,7 @@ var preferencesCommand = {
81484
81682
  };
81485
81683
 
81486
81684
  // src/cli/commands/telemetry.ts
81487
- var path60 = __toESM(require("path"));
81685
+ var path61 = __toESM(require("path"));
81488
81686
  init_control_config();
81489
81687
  init_control_sync();
81490
81688
  init_manifest();
@@ -81577,7 +81775,7 @@ async function handleOff() {
81577
81775
  info("Mission Control will not auto-start. Existing usage rows are kept.");
81578
81776
  }
81579
81777
  async function handleWriteEnv(argv) {
81580
- const repoPath = path60.resolve(argv.repo);
81778
+ const repoPath = path61.resolve(argv.repo);
81581
81779
  const harnessRoot = resolveHarnessRoot(repoPath);
81582
81780
  const session = readSlotRegistry(harnessRoot, argv.agentId);
81583
81781
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -81589,7 +81787,7 @@ async function handleWriteEnv(argv) {
81589
81787
  suffix,
81590
81788
  createdAt: session?.createdAt
81591
81789
  });
81592
- const envFile = argv.envFile ?? path60.join(workDir, `.env.agent.${argv.agentId}`);
81790
+ const envFile = argv.envFile ?? path61.join(workDir, `.env.agent.${argv.agentId}`);
81593
81791
  const attrs = {
81594
81792
  sessionKey,
81595
81793
  agentId: argv.agentId,
@@ -81605,7 +81803,7 @@ async function handleWriteEnv(argv) {
81605
81803
  success(`Wrote session attribution to ${envFile}`);
81606
81804
  }
81607
81805
  function handlePrintEnv(argv) {
81608
- const repoPath = path60.resolve(argv.repo);
81806
+ const repoPath = path61.resolve(argv.repo);
81609
81807
  const workDir = argv.workDir ?? repoPath;
81610
81808
  const sessionKey = buildSessionKey({
81611
81809
  branch: argv.branch,