@osfactory/har 1.14.1 → 1.14.3

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 +663 -584
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35872,6 +35872,20 @@ function resolveMainWorkingTree(cwd) {
35872
35872
  }
35873
35873
  return path7.resolve(toplevel);
35874
35874
  }
35875
+ function listLinkedWorktrees(cwd) {
35876
+ const porcelain = tryGit(cwd, "worktree list --porcelain");
35877
+ if (!porcelain) return [];
35878
+ const main = resolveMainWorkingTree(cwd);
35879
+ const mainResolved = main ? path7.resolve(main) : void 0;
35880
+ const paths = [];
35881
+ for (const line of porcelain.split("\n")) {
35882
+ if (!line.startsWith("worktree ")) continue;
35883
+ const worktree = path7.resolve(line.slice("worktree ".length));
35884
+ if (mainResolved && worktree === mainResolved) continue;
35885
+ paths.push(worktree);
35886
+ }
35887
+ return paths;
35888
+ }
35875
35889
  function canonicalizeControlRepoPath(repoPath) {
35876
35890
  const resolved = path7.resolve(repoPath);
35877
35891
  const toplevel = tryGit(resolved, "rev-parse --show-toplevel");
@@ -37467,13 +37481,55 @@ var init_work_units = __esm({
37467
37481
  // src/core/sync-sources.ts
37468
37482
  function resolveSyncSourcePaths(canonicalPath, workspacePath) {
37469
37483
  const canonical = path18.resolve(canonicalPath);
37470
- if (!workspacePath) return [canonical];
37471
- const workspace = path18.resolve(workspacePath);
37472
- if (workspace === canonical) return [canonical];
37473
- const canonicalRoot = resolveHarnessRoot(canonical);
37474
- const workspaceRoot = resolveHarnessRoot(workspace);
37475
- if (path18.resolve(canonicalRoot) === path18.resolve(workspaceRoot)) return [canonical];
37476
- return [canonical, workspace];
37484
+ const paths = [canonical];
37485
+ const seenRoots = /* @__PURE__ */ new Set([path18.resolve(resolveHarnessRoot(canonical))]);
37486
+ const add = (candidate) => {
37487
+ const resolved = path18.resolve(candidate);
37488
+ const root = path18.resolve(resolveHarnessRoot(resolved));
37489
+ if (seenRoots.has(root)) return;
37490
+ seenRoots.add(root);
37491
+ paths.push(resolved);
37492
+ };
37493
+ if (workspacePath) add(workspacePath);
37494
+ for (const worktree of listLinkedWorktrees(canonical)) {
37495
+ if (hasHarnessEvidence(worktree)) add(worktree);
37496
+ }
37497
+ return paths;
37498
+ }
37499
+ function hasHarnessEvidence(repoPath) {
37500
+ const root = resolveHarnessRoot(repoPath);
37501
+ const harDir = path18.join(root, DEFAULT_HAR_DIR);
37502
+ if (!fs18.existsSync(harDir)) return false;
37503
+ for (const sub of EVIDENCE_SUBDIRS) {
37504
+ const dir = path18.join(harDir, sub);
37505
+ if (!fs18.existsSync(dir)) continue;
37506
+ try {
37507
+ if (fs18.readdirSync(dir).length > 0) return true;
37508
+ } catch {
37509
+ continue;
37510
+ }
37511
+ }
37512
+ return false;
37513
+ }
37514
+ function mergeSlotStatuses(groups) {
37515
+ const byId = /* @__PURE__ */ new Map();
37516
+ for (const group of groups) {
37517
+ for (const slot of group) {
37518
+ const existing = byId.get(slot.agentId);
37519
+ byId.set(slot.agentId, existing ? preferSlotStatus(existing, slot) : slot);
37520
+ }
37521
+ }
37522
+ return [...byId.values()].sort((a, b2) => a.agentId - b2.agentId);
37523
+ }
37524
+ function preferSlotStatus(a, b2) {
37525
+ if (a.active !== b2.active) return a.active ? a : b2;
37526
+ const aCreated = a.sessionCreatedAt ?? "";
37527
+ const bCreated = b2.sessionCreatedAt ?? "";
37528
+ if (aCreated !== bCreated) return aCreated >= bCreated ? a : b2;
37529
+ const aRun = a.lastRunAt ?? "";
37530
+ const bRun = b2.lastRunAt ?? "";
37531
+ if (aRun !== bRun) return aRun >= bRun ? a : b2;
37532
+ return a;
37477
37533
  }
37478
37534
  function mergeById(groups, id) {
37479
37535
  const seen = /* @__PURE__ */ new Map();
@@ -37537,16 +37593,19 @@ function collectCommitBindingsForSync(sourcePaths) {
37537
37593
  (record2) => record2.bindingId
37538
37594
  );
37539
37595
  }
37540
- var path18;
37596
+ var fs18, path18, EVIDENCE_SUBDIRS;
37541
37597
  var init_sync_sources = __esm({
37542
37598
  "src/core/sync-sources.ts"() {
37543
37599
  "use strict";
37600
+ fs18 = __toESM(require("fs"));
37544
37601
  path18 = __toESM(require("path"));
37545
37602
  init_manifest();
37546
37603
  init_commit_bindings();
37604
+ init_control_repo_path();
37547
37605
  init_runs();
37548
37606
  init_validations();
37549
37607
  init_work_units();
37608
+ EVIDENCE_SUBDIRS = ["slots", "runs", "work-units", "validations"];
37550
37609
  }
37551
37610
  });
37552
37611
 
@@ -37689,18 +37748,18 @@ function spawnResult(cmd, args, opts, shell) {
37689
37748
  proc.on("close", (code) => resolve70({ code: code ?? 1, stdout, stderr }));
37690
37749
  });
37691
37750
  }
37692
- var import_child_process4, fs18, path19, realSystemOps, defaultExec, stderrLog, realSleep;
37751
+ var import_child_process4, fs19, path19, realSystemOps, defaultExec, stderrLog, realSleep;
37693
37752
  var init_exec = __esm({
37694
37753
  "src/runtime/exec.ts"() {
37695
37754
  "use strict";
37696
37755
  import_child_process4 = require("child_process");
37697
- fs18 = __toESM(require("fs"));
37756
+ fs19 = __toESM(require("fs"));
37698
37757
  path19 = __toESM(require("path"));
37699
37758
  realSystemOps = {
37700
37759
  which(cmd) {
37701
37760
  if (cmd.includes("/")) {
37702
37761
  try {
37703
- fs18.accessSync(cmd, fs18.constants.X_OK);
37762
+ fs19.accessSync(cmd, fs19.constants.X_OK);
37704
37763
  return cmd;
37705
37764
  } catch {
37706
37765
  return null;
@@ -37710,8 +37769,8 @@ var init_exec = __esm({
37710
37769
  if (!dir) continue;
37711
37770
  const candidate = path19.join(dir, cmd);
37712
37771
  try {
37713
- fs18.accessSync(candidate, fs18.constants.X_OK);
37714
- if (fs18.statSync(candidate).isFile()) return candidate;
37772
+ fs19.accessSync(candidate, fs19.constants.X_OK);
37773
+ if (fs19.statSync(candidate).isFile()) return candidate;
37715
37774
  } catch {
37716
37775
  }
37717
37776
  }
@@ -37758,15 +37817,15 @@ function declaredNodePackageManager(dir, env3 = {}, _ops = realSystemOps) {
37758
37817
  const explicit = env3.HARNESS_NODE_PACKAGE_MANAGER;
37759
37818
  if (explicit) return explicit;
37760
37819
  const pkgPath = path20.join(dir, "package.json");
37761
- if (fs19.existsSync(pkgPath)) {
37762
- const raw = fs19.readFileSync(pkgPath, "utf8");
37820
+ if (fs20.existsSync(pkgPath)) {
37821
+ const raw = fs20.readFileSync(pkgPath, "utf8");
37763
37822
  const match = raw.match(/"packageManager"\s*:\s*"([a-z]*)@/);
37764
37823
  if (match && match[1]) return match[1];
37765
37824
  }
37766
- if (fs19.existsSync(path20.join(dir, "bun.lock")) || fs19.existsSync(path20.join(dir, "bun.lockb"))) return "bun";
37767
- if (fs19.existsSync(path20.join(dir, "pnpm-lock.yaml"))) return "pnpm";
37768
- if (fs19.existsSync(path20.join(dir, "yarn.lock"))) return "yarn";
37769
- if (fs19.existsSync(path20.join(dir, "package-lock.json"))) return "npm";
37825
+ if (fs20.existsSync(path20.join(dir, "bun.lock")) || fs20.existsSync(path20.join(dir, "bun.lockb"))) return "bun";
37826
+ if (fs20.existsSync(path20.join(dir, "pnpm-lock.yaml"))) return "pnpm";
37827
+ if (fs20.existsSync(path20.join(dir, "yarn.lock"))) return "yarn";
37828
+ if (fs20.existsSync(path20.join(dir, "package-lock.json"))) return "npm";
37770
37829
  return "";
37771
37830
  }
37772
37831
  function nodePackageManager(dir, env3 = {}, ops = realSystemOps) {
@@ -37794,11 +37853,11 @@ function nodeLockfile(manager) {
37794
37853
  async function nodeInstall(dir, manager, declared = "", ops = realSystemOps) {
37795
37854
  const substituting = declared !== "" && declared !== manager;
37796
37855
  const lockfile = substituting ? nodeLockfile(manager) : "";
37797
- const hadLockfile = lockfile !== "" && fs19.existsSync(path20.join(dir, lockfile));
37856
+ const hadLockfile = lockfile !== "" && fs20.existsSync(path20.join(dir, lockfile));
37798
37857
  const result = await ops.run(manager, ["install", "--silent"], { cwd: dir, stream: true });
37799
37858
  if (substituting && !hadLockfile && lockfile !== "") {
37800
- fs19.rmSync(path20.join(dir, lockfile), { force: true });
37801
- if (manager === "bun") fs19.rmSync(path20.join(dir, "bun.lockb"), { force: true });
37859
+ fs20.rmSync(path20.join(dir, lockfile), { force: true });
37860
+ if (manager === "bun") fs20.rmSync(path20.join(dir, "bun.lockb"), { force: true });
37802
37861
  }
37803
37862
  return result.code;
37804
37863
  }
@@ -37818,11 +37877,11 @@ function pkgExec(manager, env3 = {}, ops = realSystemOps) {
37818
37877
  if (ops.which("pnpm")) return "pnpm dlx";
37819
37878
  return "npx --yes";
37820
37879
  }
37821
- var fs19, path20, NODE_PACKAGE_MANAGERS;
37880
+ var fs20, path20, NODE_PACKAGE_MANAGERS;
37822
37881
  var init_node_pm = __esm({
37823
37882
  "src/runtime/node-pm.ts"() {
37824
37883
  "use strict";
37825
- fs19 = __toESM(require("fs"));
37884
+ fs20 = __toESM(require("fs"));
37826
37885
  path20 = __toESM(require("path"));
37827
37886
  init_exec();
37828
37887
  NODE_PACKAGE_MANAGERS = ["npm", "bun", "pnpm", "yarn"];
@@ -37836,15 +37895,15 @@ function quoteEnvValue(value) {
37836
37895
  return `'${value.replace(/'/g, `'\\''`)}'`;
37837
37896
  }
37838
37897
  function toolchainReady(workDir) {
37839
- if (fs20.existsSync(path21.join(workDir, "package.json")) && fs20.existsSync(path21.join(workDir, "node_modules"))) {
37898
+ if (fs21.existsSync(path21.join(workDir, "package.json")) && fs21.existsSync(path21.join(workDir, "node_modules"))) {
37840
37899
  return true;
37841
37900
  }
37842
- return fs20.existsSync(path21.join(workDir, ".har", "venv"));
37901
+ return fs21.existsSync(path21.join(workDir, ".har", "venv"));
37843
37902
  }
37844
37903
  function detectEcosystem(dir, env3 = {}) {
37845
37904
  const configured = env3.HARNESS_ECOSYSTEM ?? "auto";
37846
37905
  if (configured && configured !== "auto") return configured;
37847
- const has = (name) => fs20.existsSync(path21.join(dir, name));
37906
+ const has = (name) => fs21.existsSync(path21.join(dir, name));
37848
37907
  if (has("package.json")) return "node";
37849
37908
  if (has("pyproject.toml") || has("setup.py") || has("setup.cfg") || has("requirements.txt") || has("Pipfile")) {
37850
37909
  return "python";
@@ -37877,22 +37936,22 @@ function pythonRequiresMinimum(spec) {
37877
37936
  }
37878
37937
  function pythonReadDotVersion(dir) {
37879
37938
  const file = path21.join(dir, ".python-version");
37880
- if (!fs20.existsSync(file)) return null;
37881
- const first = fs20.readFileSync(file, "utf8").split("\n")[0].replace(/\s/g, "");
37939
+ if (!fs21.existsSync(file)) return null;
37940
+ const first = fs21.readFileSync(file, "utf8").split("\n")[0].replace(/\s/g, "");
37882
37941
  return first || null;
37883
37942
  }
37884
37943
  function pythonReadRequiresSpec(dir) {
37885
37944
  const pyproject = path21.join(dir, "pyproject.toml");
37886
- if (fs20.existsSync(pyproject)) {
37887
- for (const line of fs20.readFileSync(pyproject, "utf8").split("\n")) {
37945
+ if (fs21.existsSync(pyproject)) {
37946
+ for (const line of fs21.readFileSync(pyproject, "utf8").split("\n")) {
37888
37947
  const m = line.match(/^\s*requires-python\s*=\s*"([^"]*)"/);
37889
37948
  if (m) return m[1];
37890
37949
  }
37891
37950
  }
37892
37951
  const setupCfg = path21.join(dir, "setup.cfg");
37893
- if (fs20.existsSync(setupCfg)) {
37952
+ if (fs21.existsSync(setupCfg)) {
37894
37953
  let inOptions = false;
37895
- for (const line of fs20.readFileSync(setupCfg, "utf8").split("\n")) {
37954
+ for (const line of fs21.readFileSync(setupCfg, "utf8").split("\n")) {
37896
37955
  if (/^\[options\]/.test(line)) {
37897
37956
  inOptions = true;
37898
37957
  continue;
@@ -37916,10 +37975,10 @@ function pythonProjectMinimum(dir) {
37916
37975
  return reqMin ?? dotVer;
37917
37976
  }
37918
37977
  function pythonIsUvProject(dir) {
37919
- if (fs20.existsSync(path21.join(dir, "uv.lock"))) return true;
37978
+ if (fs21.existsSync(path21.join(dir, "uv.lock"))) return true;
37920
37979
  const pyproject = path21.join(dir, "pyproject.toml");
37921
- if (!fs20.existsSync(pyproject)) return false;
37922
- return /^\[tool\.uv\]/m.test(fs20.readFileSync(pyproject, "utf8"));
37980
+ if (!fs21.existsSync(pyproject)) return false;
37981
+ return /^\[tool\.uv\]/m.test(fs21.readFileSync(pyproject, "utf8"));
37923
37982
  }
37924
37983
  function iosFindProjectFile(dir, suffix) {
37925
37984
  const matches = [];
@@ -37927,7 +37986,7 @@ function iosFindProjectFile(dir, suffix) {
37927
37986
  const abs = rel ? path21.join(dir, rel) : dir;
37928
37987
  let entries;
37929
37988
  try {
37930
- entries = fs20.readdirSync(abs, { withFileTypes: true });
37989
+ entries = fs21.readdirSync(abs, { withFileTypes: true });
37931
37990
  } catch {
37932
37991
  return;
37933
37992
  }
@@ -37950,15 +38009,15 @@ function iosHasProject(dir, env3) {
37950
38009
  const workspace = env3.HARNESS_XCODE_WORKSPACE;
37951
38010
  const project = env3.HARNESS_XCODE_PROJECT;
37952
38011
  if (workspace || project) {
37953
- if (workspace && fs20.existsSync(path21.join(dir, workspace))) return true;
37954
- if (project && fs20.existsSync(path21.join(dir, project))) return true;
38012
+ if (workspace && fs21.existsSync(path21.join(dir, workspace))) return true;
38013
+ if (project && fs21.existsSync(path21.join(dir, project))) return true;
37955
38014
  return false;
37956
38015
  }
37957
38016
  if (iosFindProjectFile(dir, ".xcworkspace")) return true;
37958
38017
  return iosFindProjectFile(dir, ".xcodeproj") !== null;
37959
38018
  }
37960
38019
  function iosProjectGenerator(dir) {
37961
- const has = (name) => fs20.existsSync(path21.join(dir, name));
38020
+ const has = (name) => fs21.existsSync(path21.join(dir, name));
37962
38021
  if (has("Project.swift") || has("Workspace.swift")) return "tuist";
37963
38022
  if (has("project.yml") || has("project.yaml")) return "xcodegen";
37964
38023
  if (has("Podfile")) return "pod";
@@ -37967,11 +38026,11 @@ function iosProjectGenerator(dir) {
37967
38026
  async function provisionToolchain(options) {
37968
38027
  return new Provisioner(options).provision();
37969
38028
  }
37970
- var fs20, path21, ProvisionError, Provisioner;
38029
+ var fs21, path21, ProvisionError, Provisioner;
37971
38030
  var init_provision = __esm({
37972
38031
  "src/runtime/provision.ts"() {
37973
38032
  "use strict";
37974
- fs20 = __toESM(require("fs"));
38033
+ fs21 = __toESM(require("fs"));
37975
38034
  path21 = __toESM(require("path"));
37976
38035
  init_exec();
37977
38036
  init_node_pm();
@@ -38003,11 +38062,11 @@ var init_provision = __esm({
38003
38062
  this.logFn(message);
38004
38063
  }
38005
38064
  appendEnv(key, value) {
38006
- fs20.appendFileSync(this.envFile, `${key}=${quoteEnvValue(value)}
38065
+ fs21.appendFileSync(this.envFile, `${key}=${quoteEnvValue(value)}
38007
38066
  `);
38008
38067
  }
38009
38068
  appendPathPrefix(prefix) {
38010
- if (!prefix || !fs20.existsSync(prefix)) return;
38069
+ if (!prefix || !fs21.existsSync(prefix)) return;
38011
38070
  this.appendEnv("PATH", `${prefix}:${process.env.PATH ?? ""}`);
38012
38071
  }
38013
38072
  /** Extra process env for subprocesses (venv activation is PATH + VIRTUAL_ENV). */
@@ -38075,7 +38134,7 @@ var init_provision = __esm({
38075
38134
  const found = await this.pythonUvFind(dir, minimum);
38076
38135
  if (executable(found)) return found;
38077
38136
  }
38078
- if (fs20.existsSync(path21.join(dir, ".python-version"))) {
38137
+ if (fs21.existsSync(path21.join(dir, ".python-version"))) {
38079
38138
  const found = await this.pythonUvFind(dir, pythonReadDotVersion(dir));
38080
38139
  if (executable(found)) return found;
38081
38140
  if (this.ops.which("pyenv")) {
@@ -38142,23 +38201,23 @@ var init_provision = __esm({
38142
38201
  }
38143
38202
  await this.pythonWarnIfBelowMinimum(interpreter, projectMin);
38144
38203
  const venvPython = path21.join(venvDir, "bin", "python");
38145
- if (fs20.existsSync(venvDir) && fs20.existsSync(venvPython) && projectMin) {
38204
+ if (fs21.existsSync(venvDir) && fs21.existsSync(venvPython) && projectMin) {
38146
38205
  const venvVer = await this.pythonVersionFromBin(venvPython);
38147
38206
  if (venvVer && !pythonVersionGe(venvVer, projectMin)) {
38148
38207
  this.log(`Existing venv Python ${venvVer} is older than required ${projectMin} \u2014 recreating...`);
38149
- fs20.rmSync(venvDir, { recursive: true, force: true });
38208
+ fs21.rmSync(venvDir, { recursive: true, force: true });
38150
38209
  }
38151
38210
  }
38152
- if (!fs20.existsSync(venvDir)) {
38211
+ if (!fs21.existsSync(venvDir)) {
38153
38212
  if (!await this.pythonCreateVenv(dir, venvDir, interpreter)) {
38154
- fs20.rmSync(venvDir, { recursive: true, force: true });
38213
+ fs21.rmSync(venvDir, { recursive: true, force: true });
38155
38214
  this.log("venv creation failed (on Debian/Ubuntu install python3-venv) \u2014 using resolved interpreter");
38156
38215
  this.appendEnv("HARNESS_ECOSYSTEM", "python");
38157
38216
  this.appendEnv("PYTHON_BIN", interpreter);
38158
38217
  return;
38159
38218
  }
38160
38219
  }
38161
- if (!fs20.existsSync(venvPython)) {
38220
+ if (!fs21.existsSync(venvPython)) {
38162
38221
  this.log(`Python venv at ${venvRel} is missing or broken \u2014 using resolved interpreter`);
38163
38222
  this.appendEnv("HARNESS_ECOSYSTEM", "python");
38164
38223
  this.appendEnv("PYTHON_BIN", interpreter);
@@ -38178,19 +38237,19 @@ var init_provision = __esm({
38178
38237
  quietStderr: quiet,
38179
38238
  stream: !quiet
38180
38239
  });
38181
- if (fs20.existsSync(path21.join(dir, "pyproject.toml"))) {
38240
+ if (fs21.existsSync(path21.join(dir, "pyproject.toml"))) {
38182
38241
  const dev = await pip(["install", "-q", "-e", ".[dev]"], true);
38183
38242
  if (dev.code !== 0) {
38184
38243
  const plain = await pip(["install", "-q", "-e", "."], false);
38185
38244
  if (plain.code !== 0) throw new ProvisionError("pip install -e . failed");
38186
38245
  }
38187
- } else if (fs20.existsSync(path21.join(dir, "requirements.txt"))) {
38246
+ } else if (fs21.existsSync(path21.join(dir, "requirements.txt"))) {
38188
38247
  const result = await pip(["install", "-q", "-r", "requirements.txt"], false);
38189
38248
  if (result.code !== 0) throw new ProvisionError("pip install -r requirements.txt failed");
38190
- } else if (fs20.existsSync(path21.join(dir, "setup.py")) || fs20.existsSync(path21.join(dir, "setup.cfg"))) {
38249
+ } else if (fs21.existsSync(path21.join(dir, "setup.py")) || fs21.existsSync(path21.join(dir, "setup.cfg"))) {
38191
38250
  const result = await pip(["install", "-q", "-e", "."], false);
38192
38251
  if (result.code !== 0) throw new ProvisionError("pip install -e . failed");
38193
- } else if (fs20.existsSync(path21.join(dir, "Pipfile")) && this.ops.which("pipenv")) {
38252
+ } else if (fs21.existsSync(path21.join(dir, "Pipfile")) && this.ops.which("pipenv")) {
38194
38253
  const result = await this.ops.run("pipenv", ["install", "--dev"], {
38195
38254
  cwd: dir,
38196
38255
  stream: true,
@@ -38250,7 +38309,7 @@ var init_provision = __esm({
38250
38309
  const mvn = this.ops.which("mvn");
38251
38310
  if (mvn) {
38252
38311
  this.appendEnv("MVN_BIN", mvn);
38253
- } else if (fs20.existsSync(path21.join(dir, "gradlew"))) {
38312
+ } else if (fs21.existsSync(path21.join(dir, "gradlew"))) {
38254
38313
  this.appendEnv("GRADLE_BIN", path21.join(dir, "gradlew"));
38255
38314
  } else {
38256
38315
  const gradle = this.ops.which("gradle");
@@ -38303,8 +38362,8 @@ var init_provision = __esm({
38303
38362
  }
38304
38363
  }
38305
38364
  async iosPodInstall(dir) {
38306
- if (!fs20.existsSync(path21.join(dir, "Podfile"))) return;
38307
- if (fs20.existsSync(path21.join(dir, "Pods"))) return;
38365
+ if (!fs21.existsSync(path21.join(dir, "Podfile"))) return;
38366
+ if (fs21.existsSync(path21.join(dir, "Pods"))) return;
38308
38367
  if (!this.ops.which("pod")) {
38309
38368
  this.log("ERROR: this repo uses CocoaPods (Podfile, no Pods/) and pod is not on PATH.");
38310
38369
  this.log(" Install CocoaPods, or set HARNESS_INSTALL_CMD in harness.env to provision the project another way.");
@@ -38330,8 +38389,8 @@ var init_provision = __esm({
38330
38389
  // ── monorepo root ──
38331
38390
  async provisionMonorepoRoot() {
38332
38391
  if (!this.relPrefix || !this.worktreeDir) return;
38333
- if (!fs20.existsSync(path21.join(this.worktreeDir, "package.json"))) return;
38334
- if (fs20.existsSync(path21.join(this.worktreeDir, "node_modules"))) return;
38392
+ if (!fs21.existsSync(path21.join(this.worktreeDir, "package.json"))) return;
38393
+ if (fs21.existsSync(path21.join(this.worktreeDir, "node_modules"))) return;
38335
38394
  const manager = nodePackageManager(this.worktreeDir, this.env, this.ops);
38336
38395
  this.log(`Installing monorepo root dependencies in ${this.worktreeDir} with ${manager}...`);
38337
38396
  const code = await nodeInstall(
@@ -38454,8 +38513,8 @@ function seedGitExclude(repoRoot, git2 = defaultGit) {
38454
38513
  if (!commonDir) return;
38455
38514
  const resolved = path22.isAbsolute(commonDir) ? commonDir : path22.resolve(repoRoot, commonDir);
38456
38515
  const excludeFile = path22.join(resolved, "info", "exclude");
38457
- if (!fs21.existsSync(path22.dirname(excludeFile))) return;
38458
- const existing = fs21.existsSync(excludeFile) ? fs21.readFileSync(excludeFile, "utf8") : "";
38516
+ if (!fs22.existsSync(path22.dirname(excludeFile))) return;
38517
+ const existing = fs22.existsSync(excludeFile) ? fs22.readFileSync(excludeFile, "utf8") : "";
38459
38518
  const lines = new Set(existing.split("\n"));
38460
38519
  let appended = "";
38461
38520
  for (const pattern of GIT_EXCLUDE_PATTERNS) {
@@ -38464,7 +38523,7 @@ function seedGitExclude(repoRoot, git2 = defaultGit) {
38464
38523
  }
38465
38524
  if (!appended) return;
38466
38525
  const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
38467
- fs21.appendFileSync(excludeFile, prefix + appended);
38526
+ fs22.appendFileSync(excludeFile, prefix + appended);
38468
38527
  }
38469
38528
  function resolveResumeSession(repoPath, agentId) {
38470
38529
  const session = readSlotRegistry(repoPath, agentId);
@@ -38477,7 +38536,7 @@ function resolveResumeSession(repoPath, agentId) {
38477
38536
  };
38478
38537
  }
38479
38538
  const workDir = session?.workDir ?? "";
38480
- if (!workDir || !fs21.existsSync(workDir) || !fs21.statSync(workDir).isDirectory()) {
38539
+ if (!workDir || !fs22.existsSync(workDir) || !fs22.statSync(workDir).isDirectory()) {
38481
38540
  return {
38482
38541
  ok: false,
38483
38542
  code: "missing-work-dir",
@@ -38485,7 +38544,7 @@ function resolveResumeSession(repoPath, agentId) {
38485
38544
  };
38486
38545
  }
38487
38546
  const envFile = path22.join(workDir, `.env.agent.${agentId}`);
38488
- if (!fs21.existsSync(envFile)) {
38547
+ if (!fs22.existsSync(envFile)) {
38489
38548
  return {
38490
38549
  ok: false,
38491
38550
  code: "missing-env-file",
@@ -38517,7 +38576,7 @@ function removeSessionWorktree(options) {
38517
38576
  }
38518
38577
  const owned = options.mode === void 0 || options.mode === "worktree";
38519
38578
  if (!owned) {
38520
- if (worktreePath && fs21.existsSync(worktreePath) && options.mode === "external") {
38579
+ if (worktreePath && fs22.existsSync(worktreePath) && options.mode === "external") {
38521
38580
  result.preservedWorktree = worktreePath;
38522
38581
  }
38523
38582
  tryGit3(git2, ["worktree", "prune"], options.repoRoot);
@@ -38531,17 +38590,17 @@ function removeSessionWorktree(options) {
38531
38590
  }
38532
38591
  return result;
38533
38592
  }
38534
- if (worktreePath && fs21.existsSync(worktreePath)) {
38593
+ if (worktreePath && fs22.existsSync(worktreePath)) {
38535
38594
  for (const name of [
38536
38595
  `.env.agent.${options.agentId}`,
38537
38596
  `ecosystem.agent.${options.agentId}.config.cjs`
38538
38597
  ]) {
38539
- fs21.rmSync(path22.join(worktreePath, name), { force: true });
38598
+ fs22.rmSync(path22.join(worktreePath, name), { force: true });
38540
38599
  }
38541
38600
  try {
38542
38601
  git2(["worktree", "remove", worktreePath, "--force"], options.repoRoot);
38543
38602
  } catch {
38544
- fs21.rmSync(worktreePath, { recursive: true, force: true });
38603
+ fs22.rmSync(worktreePath, { recursive: true, force: true });
38545
38604
  }
38546
38605
  result.removedWorktree = worktreePath;
38547
38606
  }
@@ -38556,12 +38615,12 @@ function removeSessionWorktree(options) {
38556
38615
  }
38557
38616
  return result;
38558
38617
  }
38559
- var import_child_process5, fs21, os8, path22, crypto6, defaultGit, GIT_EXCLUDE_PATTERNS;
38618
+ var import_child_process5, fs22, os8, path22, crypto6, defaultGit, GIT_EXCLUDE_PATTERNS;
38560
38619
  var init_worktree = __esm({
38561
38620
  "src/runtime/worktree.ts"() {
38562
38621
  "use strict";
38563
38622
  import_child_process5 = require("child_process");
38564
- fs21 = __toESM(require("fs"));
38623
+ fs22 = __toESM(require("fs"));
38565
38624
  os8 = __toESM(require("os"));
38566
38625
  path22 = __toESM(require("path"));
38567
38626
  crypto6 = __toESM(require("crypto"));
@@ -38621,8 +38680,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
38621
38680
  ${TELEMETRY_MARKER_END}
38622
38681
  `;
38623
38682
  let existing = "";
38624
- if (fs22.existsSync(envFilePath)) {
38625
- existing = fs22.readFileSync(envFilePath, "utf8");
38683
+ if (fs23.existsSync(envFilePath)) {
38684
+ existing = fs23.readFileSync(envFilePath, "utf8");
38626
38685
  const start = existing.indexOf(TELEMETRY_MARKER_START);
38627
38686
  if (start >= 0) {
38628
38687
  const end = existing.indexOf(TELEMETRY_MARKER_END, start);
@@ -38633,15 +38692,15 @@ ${TELEMETRY_MARKER_END}
38633
38692
  }
38634
38693
  }
38635
38694
  }
38636
- fs22.mkdirSync(path23.dirname(envFilePath), { recursive: true });
38695
+ fs23.mkdirSync(path23.dirname(envFilePath), { recursive: true });
38637
38696
  const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
38638
- fs22.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
38697
+ fs23.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
38639
38698
  }
38640
- var fs22, path23, TELEMETRY_MARKER_START, TELEMETRY_MARKER_END;
38699
+ var fs23, path23, TELEMETRY_MARKER_START, TELEMETRY_MARKER_END;
38641
38700
  var init_telemetry_env = __esm({
38642
38701
  "src/core/telemetry-env.ts"() {
38643
38702
  "use strict";
38644
- fs22 = __toESM(require("fs"));
38703
+ fs23 = __toESM(require("fs"));
38645
38704
  path23 = __toESM(require("path"));
38646
38705
  init_control_config();
38647
38706
  init_shell();
@@ -38665,8 +38724,8 @@ function substituteEnvTemplate(template, values) {
38665
38724
  }
38666
38725
  function generateAgentEnvFile(options) {
38667
38726
  const templatePath = options.templatePath ?? path24.join(options.harnessDir, "env.template");
38668
- if (!fs23.existsSync(templatePath)) return false;
38669
- const template = fs23.readFileSync(templatePath, "utf8");
38727
+ if (!fs24.existsSync(templatePath)) return false;
38728
+ const template = fs24.readFileSync(templatePath, "utf8");
38670
38729
  const v2 = options.values;
38671
38730
  const rendered = substituteEnvTemplate(template, {
38672
38731
  AGENT_ID: v2.agentId,
@@ -38678,8 +38737,8 @@ function generateAgentEnvFile(options) {
38678
38737
  BROWSER_PORT: v2.browserPort,
38679
38738
  REPO_ROOT: v2.repoRoot
38680
38739
  });
38681
- fs23.mkdirSync(path24.dirname(options.envFile), { recursive: true });
38682
- fs23.writeFileSync(options.envFile, rendered);
38740
+ fs24.mkdirSync(path24.dirname(options.envFile), { recursive: true });
38741
+ fs24.writeFileSync(options.envFile, rendered);
38683
38742
  return true;
38684
38743
  }
38685
38744
  function appendSessionTelemetry(options) {
@@ -38707,11 +38766,11 @@ function appendSessionTelemetry(options) {
38707
38766
  appendTelemetryEnvToFile(envFile, attrs);
38708
38767
  return envFile;
38709
38768
  }
38710
- var fs23, path24, AGENT_ENV_TEMPLATE_VARS;
38769
+ var fs24, path24, AGENT_ENV_TEMPLATE_VARS;
38711
38770
  var init_agent_env = __esm({
38712
38771
  "src/runtime/agent-env.ts"() {
38713
38772
  "use strict";
38714
- fs23 = __toESM(require("fs"));
38773
+ fs24 = __toESM(require("fs"));
38715
38774
  path24 = __toESM(require("path"));
38716
38775
  init_telemetry_env();
38717
38776
  init_slot_registry();
@@ -38736,20 +38795,20 @@ function resolveTemplatesDir() {
38736
38795
  path25.join(__dirname, "..", "harness", "templates")
38737
38796
  ];
38738
38797
  for (const dir of candidates) {
38739
- if (fs24.existsSync(path25.join(dir, "har-boilerplate"))) return dir;
38798
+ if (fs25.existsSync(path25.join(dir, "har-boilerplate"))) return dir;
38740
38799
  }
38741
38800
  throw new Error("Templates directory not found. Run npm run build.");
38742
38801
  }
38743
38802
  function resolveTemplateFile(name) {
38744
38803
  const dir = resolveTemplatesDir();
38745
38804
  const filePath = path25.join(dir, name);
38746
- return fs24.existsSync(filePath) ? filePath : null;
38805
+ return fs25.existsSync(filePath) ? filePath : null;
38747
38806
  }
38748
- var fs24, path25;
38807
+ var fs25, path25;
38749
38808
  var init_paths = __esm({
38750
38809
  "src/utils/paths.ts"() {
38751
38810
  "use strict";
38752
- fs24 = __toESM(require("fs"));
38811
+ fs25 = __toESM(require("fs"));
38753
38812
  path25 = __toESM(require("path"));
38754
38813
  }
38755
38814
  });
@@ -38761,10 +38820,10 @@ function templatesDirFor(options) {
38761
38820
  function readProfileManifest(profile, options) {
38762
38821
  const templates = templatesDirFor(options);
38763
38822
  const manifestPath = path26.join(templates, "profiles", profile, "profile.manifest.json");
38764
- if (!fs25.existsSync(manifestPath)) {
38823
+ if (!fs26.existsSync(manifestPath)) {
38765
38824
  throw new Error(`Profile manifest not found: ${manifestPath}. Run npm run build.`);
38766
38825
  }
38767
- const parsed = ProfileManifestSchema.safeParse(JSON.parse(fs25.readFileSync(manifestPath, "utf8")));
38826
+ const parsed = ProfileManifestSchema.safeParse(JSON.parse(fs26.readFileSync(manifestPath, "utf8")));
38768
38827
  if (!parsed.success) {
38769
38828
  throw new Error(`Invalid profile manifest for ${profile}: ${parsed.error.message}`);
38770
38829
  }
@@ -38782,7 +38841,7 @@ function readProfileCapabilities(profile, options) {
38782
38841
  }
38783
38842
  function resolveProfileBundleDir(bundle, options) {
38784
38843
  const dir = path26.join(templatesDirFor(options), bundle.path);
38785
- if (!fs25.existsSync(dir)) {
38844
+ if (!fs26.existsSync(dir)) {
38786
38845
  throw new Error(`Profile bundle not found: ${bundle.id} (${bundle.path}). Run npm run build.`);
38787
38846
  }
38788
38847
  return dir;
@@ -38801,21 +38860,21 @@ function renderProfileDoc(profile, docName, options) {
38801
38860
  const parts = sections.map((name) => {
38802
38861
  const profilePath = path26.join(templates, "profiles", profile, "docs", dir, `${name}.md`);
38803
38862
  const sharedPath = path26.join(templates, "shared-docs", dir, `${name}.md`);
38804
- const sectionPath = fs25.existsSync(profilePath) ? profilePath : sharedPath;
38805
- if (!fs25.existsSync(sectionPath)) {
38863
+ const sectionPath = fs26.existsSync(profilePath) ? profilePath : sharedPath;
38864
+ if (!fs26.existsSync(sectionPath)) {
38806
38865
  throw new Error(`Doc section not found for ${profile}/${docName}: ${name} (${sectionPath})`);
38807
38866
  }
38808
- return fs25.readFileSync(sectionPath, "utf8");
38867
+ return fs26.readFileSync(sectionPath, "utf8");
38809
38868
  });
38810
38869
  return parts.join("\n");
38811
38870
  }
38812
38871
  function readComposedTemplateContent(entry) {
38813
38872
  if (entry.content !== void 0) return entry.content;
38814
- return fs25.readFileSync(entry.sourcePath, "utf8");
38873
+ return fs26.readFileSync(entry.sourcePath, "utf8");
38815
38874
  }
38816
38875
  function walkTemplateFiles(dir, prefix = "") {
38817
38876
  const out = [];
38818
- for (const entry of fs25.readdirSync(dir, { withFileTypes: true })) {
38877
+ for (const entry of fs26.readdirSync(dir, { withFileTypes: true })) {
38819
38878
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
38820
38879
  if (entry.isDirectory()) {
38821
38880
  out.push(...walkTemplateFiles(path26.join(dir, entry.name), rel));
@@ -38844,11 +38903,11 @@ function composeProfileTemplateMap(profile, options) {
38844
38903
  }
38845
38904
  return map;
38846
38905
  }
38847
- var fs25, path26, ProfileBundleRefSchema, ProfileCapabilitiesSchema, ProfileManifestSchema;
38906
+ var fs26, path26, ProfileBundleRefSchema, ProfileCapabilitiesSchema, ProfileManifestSchema;
38848
38907
  var init_profiles = __esm({
38849
38908
  "src/harness/profiles.ts"() {
38850
38909
  "use strict";
38851
- fs25 = __toESM(require("fs"));
38910
+ fs26 = __toESM(require("fs"));
38852
38911
  path26 = __toESM(require("path"));
38853
38912
  init_zod();
38854
38913
  init_paths();
@@ -38905,13 +38964,13 @@ function harnessUsesPm2(repoPath) {
38905
38964
  const capabilities = harnessCapabilities(repoPath);
38906
38965
  if (capabilities) return capabilities.processManager === "pm2";
38907
38966
  const harnessRoot = resolveHarnessRoot(repoPath);
38908
- return fs26.existsSync(path27.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
38967
+ return fs27.existsSync(path27.join(harnessRoot, ".har", "ecosystem.agent.template.cjs"));
38909
38968
  }
38910
- var fs26, path27;
38969
+ var fs27, path27;
38911
38970
  var init_capabilities = __esm({
38912
38971
  "src/harness/capabilities.ts"() {
38913
38972
  "use strict";
38914
- fs26 = __toESM(require("fs"));
38973
+ fs27 = __toESM(require("fs"));
38915
38974
  path27 = __toESM(require("path"));
38916
38975
  init_manifest();
38917
38976
  init_env();
@@ -38922,7 +38981,7 @@ var init_capabilities = __esm({
38922
38981
  // src/core/slot-ports.ts
38923
38982
  function loadInfraState(harnessRoot, repoRoot) {
38924
38983
  let statePath = path28.join(harnessRoot, ".har", "state", "infra.env");
38925
- if (!fs27.existsSync(statePath) && repoRoot) {
38984
+ if (!fs28.existsSync(statePath) && repoRoot) {
38926
38985
  try {
38927
38986
  const commonDir = (0, import_child_process6.execSync)("git rev-parse --git-common-dir", {
38928
38987
  cwd: repoRoot,
@@ -38940,8 +38999,8 @@ function loadInfraState(harnessRoot, repoRoot) {
38940
38999
  } catch {
38941
39000
  }
38942
39001
  }
38943
- if (!fs27.existsSync(statePath)) return {};
38944
- return parseHarnessEnvSource(fs27.readFileSync(statePath, "utf8")).values;
39002
+ if (!fs28.existsSync(statePath)) return {};
39003
+ return parseHarnessEnvSource(fs28.readFileSync(statePath, "utf8")).values;
38945
39004
  }
38946
39005
  function portStep(env3) {
38947
39006
  return Number(env3.HARNESS_PORT_STEP ?? 10);
@@ -38952,7 +39011,7 @@ function defaultAppPort(base, agentId, step) {
38952
39011
  function slotPortLaneEnd(defaultPort, step) {
38953
39012
  return defaultPort + step - 1;
38954
39013
  }
38955
- function isPortInUse(port, host = "127.0.0.1") {
39014
+ function probeTcpPort(port, host) {
38956
39015
  try {
38957
39016
  (0, import_child_process6.execSync)(`bash -c 'exec 3<>/dev/tcp/${host}/${port}'`, { stdio: "ignore" });
38958
39017
  return true;
@@ -38960,6 +39019,10 @@ function isPortInUse(port, host = "127.0.0.1") {
38960
39019
  return false;
38961
39020
  }
38962
39021
  }
39022
+ function isPortInUse(port, host) {
39023
+ if (host !== void 0) return probeTcpPort(port, host);
39024
+ return probeTcpPort(port, "127.0.0.1") || probeTcpPort(port, "::1");
39025
+ }
38963
39026
  function pickFreePort(start, end) {
38964
39027
  for (let port = start; port <= end; port++) {
38965
39028
  if (!isPortInUse(port)) return port;
@@ -39008,12 +39071,12 @@ function allocateAppPorts(repoPath, agentId) {
39008
39071
  allocated: frontend !== feDefault || api !== apiDefault || debug !== debugDefault
39009
39072
  };
39010
39073
  }
39011
- var import_child_process6, fs27, path28;
39074
+ var import_child_process6, fs28, path28;
39012
39075
  var init_slot_ports = __esm({
39013
39076
  "src/core/slot-ports.ts"() {
39014
39077
  "use strict";
39015
39078
  import_child_process6 = require("child_process");
39016
- fs27 = __toESM(require("fs"));
39079
+ fs28 = __toESM(require("fs"));
39017
39080
  path28 = __toESM(require("path"));
39018
39081
  init_env();
39019
39082
  init_manifest();
@@ -39082,9 +39145,9 @@ function infraStatePath(harnessDir) {
39082
39145
  }
39083
39146
  function readInfraState(harnessDir) {
39084
39147
  const statePath = infraStatePath(harnessDir);
39085
- if (!fs28.existsSync(statePath)) return {};
39148
+ if (!fs29.existsSync(statePath)) return {};
39086
39149
  const ports = {};
39087
- for (const line of fs28.readFileSync(statePath, "utf8").split("\n")) {
39150
+ for (const line of fs29.readFileSync(statePath, "utf8").split("\n")) {
39088
39151
  const match = line.match(/^export\s+([A-Z_]+)=(\d+)\s*$/);
39089
39152
  if (match) ports[match[1]] = Number(match[2]);
39090
39153
  }
@@ -39092,8 +39155,8 @@ function readInfraState(harnessDir) {
39092
39155
  }
39093
39156
  function writeInfraState(harnessDir, ports) {
39094
39157
  const statePath = infraStatePath(harnessDir);
39095
- fs28.mkdirSync(path29.dirname(statePath), { recursive: true });
39096
- fs28.writeFileSync(
39158
+ fs29.mkdirSync(path29.dirname(statePath), { recursive: true });
39159
+ fs29.writeFileSync(
39097
39160
  statePath,
39098
39161
  `# Persisted by setup-infra.sh \u2014 host ports for shared docker compose services.
39099
39162
  export AGENT_DB_PORT=${ports.AGENT_DB_PORT}
@@ -39254,7 +39317,7 @@ async function setupInfra(options) {
39254
39317
  }
39255
39318
  }
39256
39319
  const sharedEcosystem = path29.join(harnessDir, "ecosystem.shared.config.cjs");
39257
- if (fs28.existsSync(sharedEcosystem)) {
39320
+ if (fs29.existsSync(sharedEcosystem)) {
39258
39321
  log("Starting shared app services from ecosystem.shared.config.cjs...");
39259
39322
  const [pkgCmd, ...pkgArgs] = pkgExecPrefix;
39260
39323
  exec(pkgCmd, [...pkgArgs, "pm2", "startOrReload", sharedEcosystem], { cwd: repoRoot });
@@ -39317,11 +39380,11 @@ async function removeMinioBucket(agentId, options) {
39317
39380
  const port = options.minioPort ?? 19e3;
39318
39381
  await request("DELETE", `http://localhost:${port}/agent-${agentId}?force=true`, "minioadmin:minioadmin");
39319
39382
  }
39320
- var fs28, path29, INFRA_LANES, defaultHttpRequest;
39383
+ var fs29, path29, INFRA_LANES, defaultHttpRequest;
39321
39384
  var init_infra = __esm({
39322
39385
  "src/runtime/infra.ts"() {
39323
39386
  "use strict";
39324
- fs28 = __toESM(require("fs"));
39387
+ fs29 = __toESM(require("fs"));
39325
39388
  path29 = __toESM(require("path"));
39326
39389
  init_slot_ports();
39327
39390
  init_exec();
@@ -39366,7 +39429,7 @@ function renderTemplate(template, vars) {
39366
39429
  );
39367
39430
  }
39368
39431
  function generateEcosystemConfig(options) {
39369
- const template = fs29.readFileSync(options.templatePath, "utf8");
39432
+ const template = fs30.readFileSync(options.templatePath, "utf8");
39370
39433
  const rendered = renderTemplate(template, {
39371
39434
  AGENT_ID: String(options.agentId),
39372
39435
  HARNESS_PROJECT_NAME: options.projectName,
@@ -39374,7 +39437,7 @@ function generateEcosystemConfig(options) {
39374
39437
  DEBUG_PORT: String(options.debugPort)
39375
39438
  });
39376
39439
  const configPath = path30.join(options.workDir, `ecosystem.agent.${options.agentId}.config.cjs`);
39377
- fs29.writeFileSync(configPath, rendered);
39440
+ fs30.writeFileSync(configPath, rendered);
39378
39441
  return configPath;
39379
39442
  }
39380
39443
  function pm2(args, options, cwd) {
@@ -39420,11 +39483,11 @@ async function waitForHealthCheck(options) {
39420
39483
  log(`Check logs: ./.har/agent-cli.sh ${agentId} logs`);
39421
39484
  return false;
39422
39485
  }
39423
- var fs29, path30, defaultHttpStatus;
39486
+ var fs30, path30, defaultHttpStatus;
39424
39487
  var init_process = __esm({
39425
39488
  "src/runtime/process.ts"() {
39426
39489
  "use strict";
39427
- fs29 = __toESM(require("fs"));
39490
+ fs30 = __toESM(require("fs"));
39428
39491
  path30 = __toESM(require("path"));
39429
39492
  init_exec();
39430
39493
  defaultHttpStatus = async (url) => {
@@ -39452,7 +39515,7 @@ function simSlug(value) {
39452
39515
  function repoDigest(repoRoot) {
39453
39516
  let resolved = repoRoot;
39454
39517
  try {
39455
- resolved = fs30.realpathSync(repoRoot);
39518
+ resolved = fs31.realpathSync(repoRoot);
39456
39519
  } catch {
39457
39520
  }
39458
39521
  return crypto7.createHash("sha1").update(resolved).digest("hex").slice(0, 6);
@@ -39473,7 +39536,7 @@ function claimFile(harnessDir, agentId) {
39473
39536
  }
39474
39537
  function writeClaim(harnessDir, agentId, udid, name, createdByHar, now = () => /* @__PURE__ */ new Date()) {
39475
39538
  const file = claimFile(harnessDir, agentId);
39476
- fs30.mkdirSync(path31.dirname(file), { recursive: true });
39539
+ fs31.mkdirSync(path31.dirname(file), { recursive: true });
39477
39540
  const claim = {
39478
39541
  agentId,
39479
39542
  udid,
@@ -39481,21 +39544,21 @@ function writeClaim(harnessDir, agentId, udid, name, createdByHar, now = () => /
39481
39544
  createdByHar,
39482
39545
  claimedAt: now().toISOString()
39483
39546
  };
39484
- fs30.writeFileSync(file, JSON.stringify(claim, null, 2) + "\n");
39547
+ fs31.writeFileSync(file, JSON.stringify(claim, null, 2) + "\n");
39485
39548
  }
39486
39549
  function readClaim(harnessDir, agentId) {
39487
39550
  const file = claimFile(harnessDir, agentId);
39488
- if (!fs30.existsSync(file)) return void 0;
39551
+ if (!fs31.existsSync(file)) return void 0;
39489
39552
  try {
39490
- return JSON.parse(fs30.readFileSync(file, "utf8"));
39553
+ return JSON.parse(fs31.readFileSync(file, "utf8"));
39491
39554
  } catch {
39492
39555
  return void 0;
39493
39556
  }
39494
39557
  }
39495
39558
  function claimOwnerOf(harnessDir, udid, selfAgentId, slotIsLive) {
39496
39559
  const dir = claimsDir(harnessDir);
39497
- if (!fs30.existsSync(dir)) return void 0;
39498
- for (const entry of fs30.readdirSync(dir)) {
39560
+ if (!fs31.existsSync(dir)) return void 0;
39561
+ for (const entry of fs31.readdirSync(dir)) {
39499
39562
  const match = entry.match(/^agent-(\d+)\.json$/);
39500
39563
  if (!match) continue;
39501
39564
  const id = Number(match[1]);
@@ -39697,7 +39760,7 @@ function releaseSimulator(ctx, stdout = (message) => process.stdout.write(`${mes
39697
39760
  const log = ctx.log ?? simLog;
39698
39761
  const claim = readClaim(ctx.harnessDir, ctx.agentId);
39699
39762
  if (claim) {
39700
- fs30.rmSync(claimFile(ctx.harnessDir, ctx.agentId), { force: true });
39763
+ fs31.rmSync(claimFile(ctx.harnessDir, ctx.agentId), { force: true });
39701
39764
  if (claim.createdByHar === true && claim.udid) {
39702
39765
  simctl.tryCall(["shutdown", claim.udid]);
39703
39766
  if (simctl.tryCall(["delete", claim.udid])) {
@@ -39710,12 +39773,12 @@ function releaseSimulator(ctx, stdout = (message) => process.stdout.write(`${mes
39710
39773
  }
39711
39774
  deleteDevicesWithPrefix(simctl, deviceLabelPrefix(ctx.env, ctx.repoRoot, ctx.agentId), log);
39712
39775
  }
39713
- var crypto7, fs30, path31, simLog, Simctl;
39776
+ var crypto7, fs31, path31, simLog, Simctl;
39714
39777
  var init_xcode_sim = __esm({
39715
39778
  "src/runtime/xcode-sim.ts"() {
39716
39779
  "use strict";
39717
39780
  crypto7 = __toESM(require("crypto"));
39718
- fs30 = __toESM(require("fs"));
39781
+ fs31 = __toESM(require("fs"));
39719
39782
  path31 = __toESM(require("path"));
39720
39783
  init_exec();
39721
39784
  simLog = (message) => process.stderr.write(`==> simulator: ${message}
@@ -39853,7 +39916,7 @@ function inspectControlUpReadiness(repoPath) {
39853
39916
  const control = controlContainerOnPort(containers, port);
39854
39917
  const warnings = [];
39855
39918
  const controlHarnessDir = path32.join(resolved, "control", ".har");
39856
- const harnessSlot1Active = fs31.existsSync(controlHarnessDir) && readSlotRegistry(path32.join(resolved, "control"), 1)?.status === "active";
39919
+ const harnessSlot1Active = fs32.existsSync(controlHarnessDir) && readSlotRegistry(path32.join(resolved, "control"), 1)?.status === "active";
39857
39920
  if (control) {
39858
39921
  return {
39859
39922
  warnings,
@@ -39882,12 +39945,12 @@ function inspectControlUpReadiness(repoPath) {
39882
39945
  harnessSlot1Active
39883
39946
  };
39884
39947
  }
39885
- var import_child_process7, fs31, path32;
39948
+ var import_child_process7, fs32, path32;
39886
39949
  var init_control_port = __esm({
39887
39950
  "src/core/control-port.ts"() {
39888
39951
  "use strict";
39889
39952
  import_child_process7 = require("child_process");
39890
- fs31 = __toESM(require("fs"));
39953
+ fs32 = __toESM(require("fs"));
39891
39954
  path32 = __toESM(require("path"));
39892
39955
  init_control_config();
39893
39956
  init_slot_registry();
@@ -39922,20 +39985,20 @@ function sameGitCheckout2(a, b2) {
39922
39985
  }
39923
39986
  function discoverWorktree(harnessRoot, agentId, projectName) {
39924
39987
  const session = readSlotRegistry(harnessRoot, agentId);
39925
- if (session?.worktreePath && fs32.existsSync(session.worktreePath)) {
39988
+ if (session?.worktreePath && fs33.existsSync(session.worktreePath)) {
39926
39989
  return session.worktreePath;
39927
39990
  }
39928
39991
  const legacy = path33.join(os9.homedir(), "worktrees", `${projectName}-agent-${agentId}`);
39929
- if (fs32.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
39992
+ if (fs33.existsSync(legacy) && sameGitCheckout2(harnessRoot, legacy)) return legacy;
39930
39993
  const worktreesRoot = path33.join(os9.homedir(), "worktrees");
39931
- if (!fs32.existsSync(worktreesRoot)) return void 0;
39994
+ if (!fs33.existsSync(worktreesRoot)) return void 0;
39932
39995
  const suffix = `-har-agent-${agentId}-`;
39933
39996
  const relPrefix = runGit(harnessRoot, "rev-parse --show-prefix") ?? "";
39934
- for (const name of fs32.readdirSync(worktreesRoot)) {
39997
+ for (const name of fs33.readdirSync(worktreesRoot)) {
39935
39998
  if (!name.includes(suffix)) continue;
39936
39999
  const candidate = path33.join(worktreesRoot, name);
39937
40000
  if (!sameGitCheckout2(harnessRoot, candidate)) continue;
39938
- if (!fs32.existsSync(path33.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
40001
+ if (!fs33.existsSync(path33.join(candidate, relPrefix, `.env.agent.${agentId}`))) continue;
39939
40002
  return candidate;
39940
40003
  }
39941
40004
  return void 0;
@@ -39947,9 +40010,9 @@ function collectOccupiedSlot(repoPath, agentId) {
39947
40010
  const session = readSlotRegistry(harnessRoot, agentId);
39948
40011
  const worktreePath = discoverWorktree(harnessRoot, agentId, projectName);
39949
40012
  const workDir = session?.workDir;
39950
- const envInWorkDir = workDir ? fs32.existsSync(path33.join(workDir, `.env.agent.${agentId}`)) : false;
39951
- const envInRoot = fs32.existsSync(path33.join(harnessRoot, `.env.agent.${agentId}`));
39952
- const envInWorktree = worktreePath ? fs32.existsSync(path33.join(worktreePath, `.env.agent.${agentId}`)) : false;
40013
+ const envInWorkDir = workDir ? fs33.existsSync(path33.join(workDir, `.env.agent.${agentId}`)) : false;
40014
+ const envInRoot = fs33.existsSync(path33.join(harnessRoot, `.env.agent.${agentId}`));
40015
+ const envInWorktree = worktreePath ? fs33.existsSync(path33.join(worktreePath, `.env.agent.${agentId}`)) : false;
39953
40016
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
39954
40017
  if (!active) return void 0;
39955
40018
  const dirty = worktreePath ? worktreeDirty(worktreePath) : void 0;
@@ -40040,11 +40103,11 @@ function checkLaunchGuard(repoPath, agentId, options = {}) {
40040
40103
  reason: formatOccupiedSlot(slot, repoPath)
40041
40104
  };
40042
40105
  }
40043
- var fs32, os9, path33, import_child_process8;
40106
+ var fs33, os9, path33, import_child_process8;
40044
40107
  var init_slot_launch_guard_occupied = __esm({
40045
40108
  "src/core/slot-launch-guard-occupied.ts"() {
40046
40109
  "use strict";
40047
- fs32 = __toESM(require("fs"));
40110
+ fs33 = __toESM(require("fs"));
40048
40111
  os9 = __toESM(require("os"));
40049
40112
  path33 = __toESM(require("path"));
40050
40113
  import_child_process8 = require("child_process");
@@ -40096,40 +40159,40 @@ exit 0
40096
40159
  `;
40097
40160
  }
40098
40161
  function upsertMarkedBlock(filePath, block) {
40099
- if (!fs33.existsSync(filePath)) {
40100
- fs33.writeFileSync(filePath, `#!/bin/sh
40162
+ if (!fs34.existsSync(filePath)) {
40163
+ fs34.writeFileSync(filePath, `#!/bin/sh
40101
40164
  ${block}
40102
40165
  `, { mode: 493 });
40103
40166
  return "created";
40104
40167
  }
40105
- const content = fs33.readFileSync(filePath, "utf8");
40168
+ const content = fs34.readFileSync(filePath, "utf8");
40106
40169
  if (content.includes(MARKER_START)) {
40107
40170
  const pattern = new RegExp(
40108
40171
  `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
40109
40172
  );
40110
- fs33.writeFileSync(filePath, content.replace(pattern, block));
40111
- fs33.chmodSync(filePath, 493);
40173
+ fs34.writeFileSync(filePath, content.replace(pattern, block));
40174
+ fs34.chmodSync(filePath, 493);
40112
40175
  return "updated";
40113
40176
  }
40114
40177
  const suffix = content.endsWith("\n") ? "" : "\n";
40115
- fs33.writeFileSync(filePath, `${content}${suffix}
40178
+ fs34.writeFileSync(filePath, `${content}${suffix}
40116
40179
  ${block}
40117
40180
  `);
40118
- fs33.chmodSync(filePath, 493);
40181
+ fs34.chmodSync(filePath, 493);
40119
40182
  return "appended";
40120
40183
  }
40121
40184
  function removeMarkedBlock(filePath) {
40122
- if (!fs33.existsSync(filePath)) return false;
40123
- const content = fs33.readFileSync(filePath, "utf8");
40185
+ if (!fs34.existsSync(filePath)) return false;
40186
+ const content = fs34.readFileSync(filePath, "utf8");
40124
40187
  if (!content.includes(MARKER_START)) return false;
40125
40188
  const pattern = new RegExp(
40126
40189
  `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
40127
40190
  );
40128
40191
  const stripped = content.replace(pattern, "\n");
40129
40192
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
40130
- fs33.rmSync(filePath);
40193
+ fs34.rmSync(filePath);
40131
40194
  } else {
40132
- fs33.writeFileSync(filePath, stripped);
40195
+ fs34.writeFileSync(filePath, stripped);
40133
40196
  }
40134
40197
  return true;
40135
40198
  }
@@ -40151,14 +40214,14 @@ Or re-run with --force to write into that directory anyway.`
40151
40214
  );
40152
40215
  }
40153
40216
  const hooksDir = resolveHooksDir(checkout);
40154
- fs33.mkdirSync(hooksDir, { recursive: true });
40217
+ fs34.mkdirSync(hooksDir, { recursive: true });
40155
40218
  const invocation = options.harInvocation ?? defaultHarInvocation();
40156
- fs33.writeFileSync(
40219
+ fs34.writeFileSync(
40157
40220
  path34.join(hooksDir, "har-pre-commit"),
40158
40221
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
40159
40222
  { mode: 493 }
40160
40223
  );
40161
- fs33.writeFileSync(
40224
+ fs34.writeFileSync(
40162
40225
  path34.join(hooksDir, "har-post-commit"),
40163
40226
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
40164
40227
  { mode: 493 }
@@ -40177,8 +40240,8 @@ function uninstallHooks(repoPath) {
40177
40240
  removed = removeMarkedBlock(path34.join(hooksDir, "post-commit")) || removed;
40178
40241
  for (const file of ["har-pre-commit", "har-post-commit"]) {
40179
40242
  const full = path34.join(hooksDir, file);
40180
- if (fs33.existsSync(full)) {
40181
- fs33.rmSync(full);
40243
+ if (fs34.existsSync(full)) {
40244
+ fs34.rmSync(full);
40182
40245
  removed = true;
40183
40246
  }
40184
40247
  }
@@ -40214,14 +40277,14 @@ function getHooksStatus(repoPath) {
40214
40277
  const gate = getCommitGateConfig(checkout);
40215
40278
  const hasBlock = (name) => {
40216
40279
  const file = path34.join(hooksDir, name);
40217
- return fs33.existsSync(file) && fs33.readFileSync(file, "utf8").includes(MARKER_START);
40280
+ return fs34.existsSync(file) && fs34.readFileSync(file, "utf8").includes(MARKER_START);
40218
40281
  };
40219
40282
  return {
40220
40283
  checkout,
40221
40284
  hooksDir,
40222
40285
  configuredHooksPath: getConfiguredHooksPath(checkout),
40223
- preCommitInstalled: hasBlock("pre-commit") && fs33.existsSync(path34.join(hooksDir, "har-pre-commit")),
40224
- postCommitInstalled: hasBlock("post-commit") && fs33.existsSync(path34.join(hooksDir, "har-post-commit")),
40286
+ preCommitInstalled: hasBlock("pre-commit") && fs34.existsSync(path34.join(hooksDir, "har-pre-commit")),
40287
+ postCommitInstalled: hasBlock("post-commit") && fs34.existsSync(path34.join(hooksDir, "har-post-commit")),
40225
40288
  gate,
40226
40289
  effectiveMode: resolveEffectiveMode(checkout, gate)
40227
40290
  };
@@ -40232,7 +40295,7 @@ function checkCommitGate(cwd) {
40232
40295
  }
40233
40296
  const checkout = resolveCheckoutRoot(cwd);
40234
40297
  if (!checkout) return { exitCode: 0, messages: [] };
40235
- if (!fs33.existsSync(path34.join(checkout, ".har", "stages.json"))) {
40298
+ if (!fs34.existsSync(path34.join(checkout, ".har", "stages.json"))) {
40236
40299
  return { exitCode: 0, messages: [] };
40237
40300
  }
40238
40301
  const gate = getCommitGateConfig(checkout);
@@ -40308,11 +40371,11 @@ async function recordCommitAssociation(cwd) {
40308
40371
  return { attached: false };
40309
40372
  }
40310
40373
  }
40311
- var fs33, os10, path34, MARKER_START, MARKER_END, PRE_COMMIT_BLOCK, POST_COMMIT_BLOCK;
40374
+ var fs34, os10, path34, MARKER_START, MARKER_END, PRE_COMMIT_BLOCK, POST_COMMIT_BLOCK;
40312
40375
  var init_hooks = __esm({
40313
40376
  "src/core/hooks.ts"() {
40314
40377
  "use strict";
40315
- fs33 = __toESM(require("fs"));
40378
+ fs34 = __toESM(require("fs"));
40316
40379
  os10 = __toESM(require("os"));
40317
40380
  path34 = __toESM(require("path"));
40318
40381
  init_shell();
@@ -40813,9 +40876,9 @@ var init_slot_database = __esm({
40813
40876
  // src/runtime/hooks.ts
40814
40877
  function readHookHarnessEnv(harnessDir) {
40815
40878
  const envPath = path37.join(harnessDir, "harness.env");
40816
- if (!fs34.existsSync(envPath)) return {};
40879
+ if (!fs35.existsSync(envPath)) return {};
40817
40880
  try {
40818
- return parseHarnessEnvSource(fs34.readFileSync(envPath, "utf8")).values;
40881
+ return parseHarnessEnvSource(fs35.readFileSync(envPath, "utf8")).values;
40819
40882
  } catch {
40820
40883
  return {};
40821
40884
  }
@@ -40844,7 +40907,7 @@ function hookDisplayPath(hook) {
40844
40907
  }
40845
40908
  function runLifecycleHook(hook, context) {
40846
40909
  const file = lifecycleHookPath(context.harnessDir, hook);
40847
- if (!fs34.existsSync(file)) return { ran: false, code: 0 };
40910
+ if (!fs35.existsSync(file)) return { ran: false, code: 0 };
40848
40911
  context.log?.(`Running ${hookDisplayPath(hook)}...`);
40849
40912
  const env3 = hookEnv(hook, context);
40850
40913
  const cwd = context.workDir ?? path37.dirname(context.harnessDir);
@@ -40862,11 +40925,11 @@ function runLifecycleHook(hook, context) {
40862
40925
  function postHookFailureMode(env3) {
40863
40926
  return env3.HARNESS_HOOK_POST_FAILURE === "fail" ? "fail" : "warn";
40864
40927
  }
40865
- var fs34, path37, import_child_process12, LIFECYCLE_HOOKS, HOOK_CONTRACT_VERSION, HOOKS_DIR;
40928
+ var fs35, path37, import_child_process12, LIFECYCLE_HOOKS, HOOK_CONTRACT_VERSION, HOOKS_DIR;
40866
40929
  var init_hooks2 = __esm({
40867
40930
  "src/runtime/hooks.ts"() {
40868
40931
  "use strict";
40869
- fs34 = __toESM(require("fs"));
40932
+ fs35 = __toESM(require("fs"));
40870
40933
  path37 = __toESM(require("path"));
40871
40934
  import_child_process12 = require("child_process");
40872
40935
  init_schema2();
@@ -41009,7 +41072,7 @@ function detectProcessManager(repoPath) {
41009
41072
  const harnessRoot = resolveHarnessRoot(repoPath);
41010
41073
  const manifest = readManifest(harnessRoot);
41011
41074
  if (manifest?.profile === "ios") return "simulator";
41012
- if (fs35.existsSync(path38.join(getHarnessDir(harnessRoot), "simulator.sh"))) return "simulator";
41075
+ if (fs36.existsSync(path38.join(getHarnessDir(harnessRoot), "simulator.sh"))) return "simulator";
41013
41076
  return "none";
41014
41077
  }
41015
41078
  function heredocEnvFile(envFile, agentId, workDir, worktreeDir) {
@@ -41021,8 +41084,8 @@ function heredocEnvFile(envFile, agentId, workDir, worktreeDir) {
41021
41084
  "NODE_ENV=test",
41022
41085
  ""
41023
41086
  ].join("\n");
41024
- fs35.mkdirSync(path38.dirname(envFile), { recursive: true });
41025
- fs35.writeFileSync(envFile, content);
41087
+ fs36.mkdirSync(path38.dirname(envFile), { recursive: true });
41088
+ fs36.writeFileSync(envFile, content);
41026
41089
  }
41027
41090
  async function launchSession(options) {
41028
41091
  const repoRoot = resolveHarnessRoot(options.repoPath);
@@ -41283,7 +41346,7 @@ async function launchSession(options) {
41283
41346
  throw new Error("simulator acquisition failed");
41284
41347
  }
41285
41348
  ({ udid: simUdid, name: simName } = sim);
41286
- fs35.appendFileSync(
41349
+ fs36.appendFileSync(
41287
41350
  session.envFile,
41288
41351
  [
41289
41352
  `HARNESS_SIMULATOR_UDID=${quoteEnvValue(simUdid)}`,
@@ -41391,20 +41454,20 @@ function seedExtraExcludePattern(repoRoot, pattern, exec) {
41391
41454
  if (commonDir.code !== 0) return;
41392
41455
  const resolved = path38.isAbsolute(commonDir.stdout.trim()) ? commonDir.stdout.trim() : path38.resolve(repoRoot, commonDir.stdout.trim());
41393
41456
  const excludeFile = path38.join(resolved, "info", "exclude");
41394
- if (!fs35.existsSync(path38.dirname(excludeFile))) return;
41395
- const existing = fs35.existsSync(excludeFile) ? fs35.readFileSync(excludeFile, "utf8") : "";
41457
+ if (!fs36.existsSync(path38.dirname(excludeFile))) return;
41458
+ const existing = fs36.existsSync(excludeFile) ? fs36.readFileSync(excludeFile, "utf8") : "";
41396
41459
  if (existing.split("\n").includes(pattern)) return;
41397
- fs35.appendFileSync(excludeFile, `${pattern}
41460
+ fs36.appendFileSync(excludeFile, `${pattern}
41398
41461
  `);
41399
41462
  }
41400
41463
  function repoRooted(requested, resolved) {
41401
41464
  return path38.resolve(requested) === resolved ? requested : resolved;
41402
41465
  }
41403
- var fs35, path38, stderrLine;
41466
+ var fs36, path38, stderrLine;
41404
41467
  var init_launch = __esm({
41405
41468
  "src/runtime/launch.ts"() {
41406
41469
  "use strict";
41407
- fs35 = __toESM(require("fs"));
41470
+ fs36 = __toESM(require("fs"));
41408
41471
  path38 = __toESM(require("path"));
41409
41472
  init_env();
41410
41473
  init_manifest();
@@ -41484,7 +41547,7 @@ async function teardownSession(options) {
41484
41547
  ];
41485
41548
  for (const dir of [repoRoot, workDir]) {
41486
41549
  if (!dir) continue;
41487
- for (const file of generated(dir)) fs36.rmSync(file, { force: true });
41550
+ for (const file of generated(dir)) fs37.rmSync(file, { force: true });
41488
41551
  }
41489
41552
  const removed = removeSessionWorktree({
41490
41553
  repoRoot,
@@ -41528,11 +41591,11 @@ async function teardownSession(options) {
41528
41591
  out(`\u2713 Agent ${agentId} torn down`);
41529
41592
  return { code: 0 };
41530
41593
  }
41531
- var fs36, path39, os11;
41594
+ var fs37, path39, os11;
41532
41595
  var init_teardown = __esm({
41533
41596
  "src/runtime/teardown.ts"() {
41534
41597
  "use strict";
41535
- fs36 = __toESM(require("fs"));
41598
+ fs37 = __toESM(require("fs"));
41536
41599
  path39 = __toESM(require("path"));
41537
41600
  os11 = __toESM(require("os"));
41538
41601
  init_env();
@@ -41554,7 +41617,7 @@ var init_teardown = __esm({
41554
41617
  // src/runtime/verify.ts
41555
41618
  function resolveVerifyRunner(harnessDir) {
41556
41619
  const installed = path40.join(harnessDir, "lib", "verify-runner.mjs");
41557
- if (fs37.existsSync(installed)) return installed;
41620
+ if (fs38.existsSync(installed)) return installed;
41558
41621
  return path40.join(
41559
41622
  resolveTemplatesDir(),
41560
41623
  "runtime-bundles",
@@ -41615,11 +41678,11 @@ exec node ${JSON.stringify(resolveVerifyRunner(harnessDir))} --agent ${agentId}$
41615
41678
  env: baseEnv
41616
41679
  };
41617
41680
  }
41618
- var fs37, path40, XC_TARGET_FLAGS_FUNCTION, XC_BLOCK, API_PORT_BLOCK, VerifyPlanError;
41681
+ var fs38, path40, XC_TARGET_FLAGS_FUNCTION, XC_BLOCK, API_PORT_BLOCK, VerifyPlanError;
41619
41682
  var init_verify = __esm({
41620
41683
  "src/runtime/verify.ts"() {
41621
41684
  "use strict";
41622
- fs37 = __toESM(require("fs"));
41685
+ fs38 = __toESM(require("fs"));
41623
41686
  path40 = __toESM(require("path"));
41624
41687
  init_paths();
41625
41688
  init_manifest();
@@ -41949,13 +42012,13 @@ function resolveStageScriptPath(repoPath, stage) {
41949
42012
  return path41.join(harnessDir, scriptName);
41950
42013
  }
41951
42014
  const stageScript = path41.join(harnessDir, "stages", `${stage.id}.sh`);
41952
- if (fs38.existsSync(stageScript)) {
42015
+ if (fs39.existsSync(stageScript)) {
41953
42016
  return stageScript;
41954
42017
  }
41955
42018
  const fallback = stage.kind === "inspect" ? "agent-cli.sh" : RUNTIME_SCRIPT_FOR_KIND[stage.kind];
41956
42019
  if (fallback) {
41957
42020
  const fallbackPath = path41.join(harnessDir, fallback);
41958
- if (fs38.existsSync(fallbackPath)) return fallbackPath;
42021
+ if (fs39.existsSync(fallbackPath)) return fallbackPath;
41959
42022
  }
41960
42023
  throw new Error(
41961
42024
  `Stage "${stage.id}" has no runnable script. Add script to stages.json, create .har/stages/${stage.id}.sh, or run verification via har_run_verification.`
@@ -42036,8 +42099,8 @@ function inspectOp(stage) {
42036
42099
  }
42037
42100
  function harnessScriptIsLegacy(repoPath, scriptName) {
42038
42101
  const file = path41.join(getHarnessDir(resolveHarnessRoot(repoPath)), scriptName);
42039
- if (!fs38.existsSync(file)) return false;
42040
- return !fs38.readFileSync(file, "utf8").includes("exec har env");
42102
+ if (!fs39.existsSync(file)) return false;
42103
+ return !fs39.readFileSync(file, "utf8").includes("exec har env");
42041
42104
  }
42042
42105
  function warnLegacyRuntimeScript(repoPath, scriptName) {
42043
42106
  const key = `${path41.resolve(repoPath)}:${scriptName}`;
@@ -42149,11 +42212,11 @@ async function runPackageRuntimeStage(repoPath, stage, options, capture) {
42149
42212
  }
42150
42213
  return void 0;
42151
42214
  }
42152
- var fs38, path41, RUNTIME_SCRIPT_FOR_KIND, warnedLegacyScripts, LocalScriptExecutor, localScriptExecutor;
42215
+ var fs39, path41, RUNTIME_SCRIPT_FOR_KIND, warnedLegacyScripts, LocalScriptExecutor, localScriptExecutor;
42153
42216
  var init_local_executor = __esm({
42154
42217
  "src/core/local-executor.ts"() {
42155
42218
  "use strict";
42156
- fs38 = __toESM(require("fs"));
42219
+ fs39 = __toESM(require("fs"));
42157
42220
  path41 = __toESM(require("path"));
42158
42221
  init_manifest();
42159
42222
  init_env();
@@ -42211,10 +42274,10 @@ var init_local_executor = __esm({
42211
42274
  const harnessDir = getHarnessDir(repoPath);
42212
42275
  const artifactsDirName = getArtifactsDir(repoPath);
42213
42276
  const artifactsDir = path41.join(harnessDir, artifactsDirName);
42214
- if (!fs38.existsSync(artifactsDir)) return [];
42277
+ if (!fs39.existsSync(artifactsDir)) return [];
42215
42278
  const entries = [];
42216
42279
  const walk = (dir, prefix) => {
42217
- for (const entry of fs38.readdirSync(dir, { withFileTypes: true })) {
42280
+ for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
42218
42281
  const full = path41.join(dir, entry.name);
42219
42282
  const relative6 = path41.join(prefix, entry.name);
42220
42283
  if (entry.isDirectory()) {
@@ -42222,7 +42285,7 @@ var init_local_executor = __esm({
42222
42285
  continue;
42223
42286
  }
42224
42287
  if (filter2?.stageId && !relative6.includes(filter2.stageId)) continue;
42225
- const stat = fs38.statSync(full);
42288
+ const stat = fs39.statSync(full);
42226
42289
  entries.push({
42227
42290
  path: full,
42228
42291
  relativePath: relative6,
@@ -42281,11 +42344,11 @@ function gitPrefix2(cwd) {
42281
42344
  }
42282
42345
  function discoverSessionWorktreePath(harnessRoot, agentId) {
42283
42346
  const worktreesRoot = path42.join(os12.homedir(), "worktrees");
42284
- if (!fs39.existsSync(worktreesRoot)) return void 0;
42347
+ if (!fs40.existsSync(worktreesRoot)) return void 0;
42285
42348
  const suffix = `-har-agent-${agentId}-`;
42286
42349
  const relPrefix = gitPrefix2(harnessRoot);
42287
- const matches = fs39.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path42.join(worktreesRoot, entry.name)).filter(
42288
- (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs39.existsSync(path42.join(candidate, relPrefix, `.env.agent.${agentId}`))
42350
+ const matches = fs40.readdirSync(worktreesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.includes(suffix)).map((entry) => path42.join(worktreesRoot, entry.name)).filter(
42351
+ (candidate) => sameGitCheckout3(harnessRoot, candidate) && fs40.existsSync(path42.join(candidate, relPrefix, `.env.agent.${agentId}`))
42289
42352
  );
42290
42353
  return matches.sort()[0];
42291
42354
  }
@@ -42293,7 +42356,7 @@ function resolveAgentEnvFile(harnessRoot, agentId) {
42293
42356
  const session = readSlotRegistry(harnessRoot, agentId);
42294
42357
  if (session?.workDir) {
42295
42358
  const inWorkDir = path42.join(session.workDir, `.env.agent.${agentId}`);
42296
- if (fs39.existsSync(inWorkDir)) return inWorkDir;
42359
+ if (fs40.existsSync(inWorkDir)) return inWorkDir;
42297
42360
  }
42298
42361
  const env3 = readHarnessEnv(harnessRoot);
42299
42362
  const projectName = env3.HARNESS_PROJECT_NAME ?? path42.basename(harnessRoot);
@@ -42302,16 +42365,16 @@ function resolveAgentEnvFile(harnessRoot, agentId) {
42302
42365
  path42.join(harnessRoot, `.env.agent.${agentId}`),
42303
42366
  path42.join(os12.homedir(), "worktrees", `${projectName}-agent-${agentId}`, relPrefix, `.env.agent.${agentId}`)
42304
42367
  ]) {
42305
- if (fs39.existsSync(candidate)) return candidate;
42368
+ if (fs40.existsSync(candidate)) return candidate;
42306
42369
  }
42307
42370
  const worktreesRoot = path42.join(os12.homedir(), "worktrees");
42308
- if (!fs39.existsSync(worktreesRoot)) return void 0;
42371
+ if (!fs40.existsSync(worktreesRoot)) return void 0;
42309
42372
  const suffix = `-har-agent-${agentId}-`;
42310
- for (const name of fs39.readdirSync(worktreesRoot).sort()) {
42373
+ for (const name of fs40.readdirSync(worktreesRoot).sort()) {
42311
42374
  if (!name.includes(suffix)) continue;
42312
42375
  const candidateDir = path42.join(worktreesRoot, name);
42313
42376
  const candidate = path42.join(candidateDir, relPrefix, `.env.agent.${agentId}`);
42314
- if (!fs39.existsSync(candidate)) continue;
42377
+ if (!fs40.existsSync(candidate)) continue;
42315
42378
  if (!sameGitCheckout3(harnessRoot, candidateDir)) continue;
42316
42379
  return candidate;
42317
42380
  }
@@ -42319,7 +42382,7 @@ function resolveAgentEnvFile(harnessRoot, agentId) {
42319
42382
  }
42320
42383
  function parseEnvFilePorts(envFile) {
42321
42384
  const values = {};
42322
- for (const line of fs39.readFileSync(envFile, "utf8").split("\n")) {
42385
+ for (const line of fs40.readFileSync(envFile, "utf8").split("\n")) {
42323
42386
  const match = line.match(/^(?:export\s+)?([A-Z_][A-Z0-9_]*)=(.*)$/);
42324
42387
  if (!match) continue;
42325
42388
  values[match[1]] = match[2].replace(/^["']|["']$/g, "");
@@ -42347,8 +42410,8 @@ function loadAgentPorts(harnessRoot, agentId) {
42347
42410
  const allocated = allocateAppPorts(harnessRoot, agentId);
42348
42411
  const infraEnv = path42.join(getHarnessDir(harnessRoot), "state", "infra.env");
42349
42412
  const infraState = {};
42350
- if (fs39.existsSync(infraEnv)) {
42351
- for (const line of fs39.readFileSync(infraEnv, "utf8").split("\n")) {
42413
+ if (fs40.existsSync(infraEnv)) {
42414
+ for (const line of fs40.readFileSync(infraEnv, "utf8").split("\n")) {
42352
42415
  const match = line.match(/^(?:export\s+)?([A-Z_][A-Z0-9_]*)=(.*)$/);
42353
42416
  if (match) infraState[match[1]] = match[2].replace(/^["']|["']$/g, "");
42354
42417
  }
@@ -42437,11 +42500,11 @@ function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs, untrackedPaths)
42437
42500
  "worktrees",
42438
42501
  `${projectName}-agent-${agentId}`
42439
42502
  );
42440
- const worktreePath = session?.worktreePath && fs39.existsSync(session.worktreePath) ? session.worktreePath : fs39.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
42503
+ const worktreePath = session?.worktreePath && fs40.existsSync(session.worktreePath) ? session.worktreePath : fs40.existsSync(legacyWorktreePath) ? legacyWorktreePath : discoverSessionWorktreePath(harnessRoot, agentId);
42441
42504
  const workDir = resolveAgentWorkDir(harnessRoot, agentId);
42442
- const envInWorkDir = workDir ? fs39.existsSync(path42.join(workDir, `.env.agent.${agentId}`)) : false;
42443
- const envInRoot = fs39.existsSync(path42.join(harnessRoot, `.env.agent.${agentId}`));
42444
- const envInWorktree = worktreePath ? fs39.existsSync(path42.join(worktreePath, `.env.agent.${agentId}`)) : false;
42505
+ const envInWorkDir = workDir ? fs40.existsSync(path42.join(workDir, `.env.agent.${agentId}`)) : false;
42506
+ const envInRoot = fs40.existsSync(path42.join(harnessRoot, `.env.agent.${agentId}`));
42507
+ const envInWorktree = worktreePath ? fs40.existsSync(path42.join(worktreePath, `.env.agent.${agentId}`)) : false;
42445
42508
  const active = session !== void 0 && session.status !== "completed" || envInWorkDir || envInRoot || envInWorktree;
42446
42509
  const latest = latestRunForAgent(runs, agentId);
42447
42510
  const verifyRun = runs.find((r) => r.agentId === agentId && r.stageId === "verify");
@@ -42549,11 +42612,11 @@ function collectEnvironmentStatus(repoPath) {
42549
42612
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
42550
42613
  };
42551
42614
  }
42552
- var fs39, os12, path42, import_child_process14, BYPASS_WARNING_MS;
42615
+ var fs40, os12, path42, import_child_process14, BYPASS_WARNING_MS;
42553
42616
  var init_slot_status = __esm({
42554
42617
  "src/core/slot-status.ts"() {
42555
42618
  "use strict";
42556
- fs39 = __toESM(require("fs"));
42619
+ fs40 = __toESM(require("fs"));
42557
42620
  os12 = __toESM(require("os"));
42558
42621
  path42 = __toESM(require("path"));
42559
42622
  import_child_process14 = require("child_process");
@@ -43196,8 +43259,8 @@ function encodeClaudeProjectDir(cwd) {
43196
43259
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
43197
43260
  }
43198
43261
  function readJsonlRecords(filePath) {
43199
- if (!fs40.existsSync(filePath)) return [];
43200
- const lines = fs40.readFileSync(filePath, "utf8").split(/\r?\n/);
43262
+ if (!fs41.existsSync(filePath)) return [];
43263
+ const lines = fs41.readFileSync(filePath, "utf8").split(/\r?\n/);
43201
43264
  const out = [];
43202
43265
  for (const line of lines) {
43203
43266
  const trimmed = line.trim();
@@ -43289,18 +43352,18 @@ function findMatchingClaudeTranscripts(slot) {
43289
43352
  const fallbackTargets = slot.includeRepoPathFallback && slot.repoPath && !primaryTargets.includes(slot.repoPath) ? [slot.repoPath] : [];
43290
43353
  if (primaryTargets.length === 0 && fallbackTargets.length === 0) return [];
43291
43354
  const root = claudeProjectsRoot();
43292
- if (!fs40.existsSync(root)) return [];
43355
+ if (!fs41.existsSync(root)) return [];
43293
43356
  const primary = [];
43294
43357
  const fallback = [];
43295
- for (const entry of fs40.readdirSync(root, { withFileTypes: true })) {
43358
+ for (const entry of fs41.readdirSync(root, { withFileTypes: true })) {
43296
43359
  if (!entry.isDirectory()) continue;
43297
43360
  const projectDir = path44.join(root, entry.name);
43298
43361
  const primaryEncoded = primaryTargets.some((t) => entry.name === encodeClaudeProjectDir(t));
43299
43362
  const fallbackEncoded = fallbackTargets.some((t) => entry.name === encodeClaudeProjectDir(t));
43300
- for (const file of fs40.readdirSync(projectDir)) {
43363
+ for (const file of fs41.readdirSync(projectDir)) {
43301
43364
  if (!file.endsWith(".jsonl")) continue;
43302
43365
  const filePath = path44.join(projectDir, file);
43303
- const stat = fs40.statSync(filePath);
43366
+ const stat = fs41.statSync(filePath);
43304
43367
  const records = readJsonlRecords(filePath);
43305
43368
  let primaryHit = primaryEncoded;
43306
43369
  let fallbackHit = fallbackEncoded;
@@ -43443,11 +43506,11 @@ function harvestClaudeEvents(slot) {
43443
43506
  ).flatMap((entry) => entry.match.records);
43444
43507
  return capHarvestedEvents(extractPromptEvents(records, sessionKey, slot));
43445
43508
  }
43446
- var fs40, os14, path44, MAX_HARVESTED_SESSION_EVENTS;
43509
+ var fs41, os14, path44, MAX_HARVESTED_SESSION_EVENTS;
43447
43510
  var init_claude = __esm({
43448
43511
  "src/core/usage-harvest/claude.ts"() {
43449
43512
  "use strict";
43450
- fs40 = __toESM(require("fs"));
43513
+ fs41 = __toESM(require("fs"));
43451
43514
  os14 = __toESM(require("os"));
43452
43515
  path44 = __toESM(require("path"));
43453
43516
  init_schema2();
@@ -43464,8 +43527,8 @@ function codexSessionsRoot() {
43464
43527
  return process.env.HAR_CODEX_SESSIONS_DIR ? path45.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path45.join(os15.homedir(), ".codex", "sessions");
43465
43528
  }
43466
43529
  function walkJsonlFiles(dir, out = []) {
43467
- if (!fs41.existsSync(dir)) return out;
43468
- for (const entry of fs41.readdirSync(dir, { withFileTypes: true })) {
43530
+ if (!fs42.existsSync(dir)) return out;
43531
+ for (const entry of fs42.readdirSync(dir, { withFileTypes: true })) {
43469
43532
  const full = path45.join(dir, entry.name);
43470
43533
  if (entry.isDirectory()) walkJsonlFiles(full, out);
43471
43534
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
@@ -43473,7 +43536,7 @@ function walkJsonlFiles(dir, out = []) {
43473
43536
  return out;
43474
43537
  }
43475
43538
  function readJsonl(filePath) {
43476
- const lines = fs41.readFileSync(filePath, "utf8").split(/\r?\n/);
43539
+ const lines = fs42.readFileSync(filePath, "utf8").split(/\r?\n/);
43477
43540
  const out = [];
43478
43541
  for (const line of lines) {
43479
43542
  const trimmed = line.trim();
@@ -43540,7 +43603,7 @@ function harvestCodexUsage(slot) {
43540
43603
  const extracted = extractCodexTokens(records);
43541
43604
  if (!extracted.cwd) continue;
43542
43605
  if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
43543
- const mtime = fs41.statSync(file).mtimeMs;
43606
+ const mtime = fs42.statSync(file).mtimeMs;
43544
43607
  if (workspaceMatchesTarget(extracted.cwd, primaryTargets)) {
43545
43608
  if (mtime >= bestPrimaryMtime) {
43546
43609
  bestPrimaryMtime = mtime;
@@ -43576,11 +43639,11 @@ function harvestCodexUsage(slot) {
43576
43639
  lastSeenAt: best.seen?.lastAt ?? now
43577
43640
  };
43578
43641
  }
43579
- var fs41, os15, path45;
43642
+ var fs42, os15, path45;
43580
43643
  var init_codex = __esm({
43581
43644
  "src/core/usage-harvest/codex.ts"() {
43582
43645
  "use strict";
43583
- fs41 = __toESM(require("fs"));
43646
+ fs42 = __toESM(require("fs"));
43584
43647
  os15 = __toESM(require("os"));
43585
43648
  path45 = __toESM(require("path"));
43586
43649
  init_schema2();
@@ -43639,8 +43702,8 @@ function getStatePath() {
43639
43702
  function readState() {
43640
43703
  const statePath = getStatePath();
43641
43704
  try {
43642
- if (!fs42.existsSync(statePath)) return { states: [] };
43643
- const parsed = JSON.parse(fs42.readFileSync(statePath, "utf8"));
43705
+ if (!fs43.existsSync(statePath)) return { states: [] };
43706
+ const parsed = JSON.parse(fs43.readFileSync(statePath, "utf8"));
43644
43707
  return Array.isArray(parsed.states) ? parsed : { states: [] };
43645
43708
  } catch {
43646
43709
  return { states: [] };
@@ -43648,8 +43711,8 @@ function readState() {
43648
43711
  }
43649
43712
  function writeState(state) {
43650
43713
  const statePath = getStatePath();
43651
- fs42.mkdirSync(path46.dirname(statePath), { recursive: true });
43652
- fs42.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
43714
+ fs43.mkdirSync(path46.dirname(statePath), { recursive: true });
43715
+ fs43.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
43653
43716
  }
43654
43717
  function readPortalWatermark(repoPath, portalUrl) {
43655
43718
  const canonical = canonicalizeControlRepoPath(repoPath);
@@ -43714,11 +43777,11 @@ function selectSince(rows, since, getTimestamp) {
43714
43777
  }
43715
43778
  return { selected, maxSyncedAt };
43716
43779
  }
43717
- var fs42, os16, path46;
43780
+ var fs43, os16, path46;
43718
43781
  var init_portal_watermark = __esm({
43719
43782
  "src/core/portal-watermark.ts"() {
43720
43783
  "use strict";
43721
- fs42 = __toESM(require("fs"));
43784
+ fs43 = __toESM(require("fs"));
43722
43785
  os16 = __toESM(require("os"));
43723
43786
  path46 = __toESM(require("path"));
43724
43787
  init_control_repo_path();
@@ -44427,10 +44490,26 @@ async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, por
44427
44490
  };
44428
44491
  }
44429
44492
  }
44493
+ function collectEnvironmentStatusForSync(canonicalPath, sourcePaths) {
44494
+ const collected = /* @__PURE__ */ new Map();
44495
+ const groups = [];
44496
+ for (const source of sourcePaths) {
44497
+ const key = path48.resolve(source);
44498
+ let status = collected.get(key);
44499
+ if (!status) {
44500
+ status = collectEnvironmentStatus(source);
44501
+ collected.set(key, status);
44502
+ }
44503
+ groups.push(status.slots);
44504
+ }
44505
+ const canonicalKey = path48.resolve(canonicalPath);
44506
+ const canonical = collected.get(canonicalKey) ?? collectEnvironmentStatus(canonicalPath);
44507
+ return { ...canonical, slots: mergeSlotStatuses(groups) };
44508
+ }
44430
44509
  async function buildPortalPayload(repoPath, sourcePaths, controlApiUrl, since, full = false, portal) {
44431
44510
  const rawRunsBySource = collectRunsBySource(sourcePaths);
44432
44511
  const runs = mergeRunsBySource(rawRunsBySource);
44433
- const status = collectEnvironmentStatus(repoPath);
44512
+ const status = collectEnvironmentStatusForSync(repoPath, sourcePaths);
44434
44513
  const manifest = readManifest(repoPath);
44435
44514
  const stagesRegistry = readStageRegistry(repoPath);
44436
44515
  const validations = collectValidationsForSync(sourcePaths);
@@ -44787,7 +44866,7 @@ async function syncRepoWithControl(options) {
44787
44866
  }
44788
44867
  const sourcePaths = resolveSyncSourcePaths(repoPath, workspacePath);
44789
44868
  const runs = collectRunsForSync(sourcePaths);
44790
- const status = collectEnvironmentStatus(repoPath);
44869
+ const status = collectEnvironmentStatusForSync(repoPath, sourcePaths);
44791
44870
  const cloudWork = collectWorkUnitsForSync(sourcePaths);
44792
44871
  const harnessRoot = resolveHarnessRoot(repoPath);
44793
44872
  const response = await fetch(`${process.env.HAR_CLOUD_API_URL}/api/sync`, {
@@ -44862,7 +44941,7 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, workspacePath, dry
44862
44941
  },
44863
44942
  sourcePaths
44864
44943
  );
44865
- const status = collectEnvironmentStatus(repoPath);
44944
+ const status = collectEnvironmentStatusForSync(repoPath, sourcePaths);
44866
44945
  const slotsBody = SyncSlotsInputSchema.parse({
44867
44946
  slots: status.slots,
44868
44947
  generatedAt: status.generatedAt
@@ -52696,10 +52775,10 @@ var require_lib2 = __commonJS({
52696
52775
  exports2.analyse = analyse;
52697
52776
  var detectFile = (filepath, opts = {}) => new Promise((resolve70, reject) => {
52698
52777
  let fd;
52699
- const fs81 = (0, node_1.default)();
52778
+ const fs82 = (0, node_1.default)();
52700
52779
  const handler = (err, buffer) => {
52701
52780
  if (fd) {
52702
- fs81.closeSync(fd);
52781
+ fs82.closeSync(fd);
52703
52782
  }
52704
52783
  if (err) {
52705
52784
  reject(err);
@@ -52711,9 +52790,9 @@ var require_lib2 = __commonJS({
52711
52790
  };
52712
52791
  const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
52713
52792
  if (sampleSize > 0) {
52714
- fd = fs81.openSync(filepath, "r");
52793
+ fd = fs82.openSync(filepath, "r");
52715
52794
  let sample = Buffer.allocUnsafe(sampleSize);
52716
- fs81.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
52795
+ fs82.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
52717
52796
  if (err) {
52718
52797
  handler(err, null);
52719
52798
  } else {
@@ -52725,22 +52804,22 @@ var require_lib2 = __commonJS({
52725
52804
  });
52726
52805
  return;
52727
52806
  }
52728
- fs81.readFile(filepath, handler);
52807
+ fs82.readFile(filepath, handler);
52729
52808
  });
52730
52809
  exports2.detectFile = detectFile;
52731
52810
  var detectFileSync = (filepath, opts = {}) => {
52732
- const fs81 = (0, node_1.default)();
52811
+ const fs82 = (0, node_1.default)();
52733
52812
  if (opts && opts.sampleSize) {
52734
- const fd = fs81.openSync(filepath, "r");
52813
+ const fd = fs82.openSync(filepath, "r");
52735
52814
  let sample = Buffer.allocUnsafe(opts.sampleSize);
52736
- const bytesRead = fs81.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
52815
+ const bytesRead = fs82.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
52737
52816
  if (bytesRead < opts.sampleSize) {
52738
52817
  sample = sample.subarray(0, bytesRead);
52739
52818
  }
52740
- fs81.closeSync(fd);
52819
+ fs82.closeSync(fd);
52741
52820
  return (0, exports2.detect)(sample);
52742
52821
  }
52743
- return (0, exports2.detect)(fs81.readFileSync(filepath));
52822
+ return (0, exports2.detect)(fs82.readFileSync(filepath));
52744
52823
  };
52745
52824
  exports2.detectFileSync = detectFileSync;
52746
52825
  exports2.default = {
@@ -66095,7 +66174,7 @@ function installedPackageVersion(hooksHome) {
66095
66174
  "otel-hook",
66096
66175
  "package.json"
66097
66176
  );
66098
- const pkg = JSON.parse(fs69.readFileSync(pkgPath, "utf8"));
66177
+ const pkg = JSON.parse(fs70.readFileSync(pkgPath, "utf8"));
66099
66178
  return typeof pkg.version === "string" ? pkg.version : null;
66100
66179
  } catch {
66101
66180
  return null;
@@ -66146,15 +66225,15 @@ function buildOtelHooksConfig(options) {
66146
66225
  };
66147
66226
  }
66148
66227
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
66149
- fs69.mkdirSync(hooksHome, { recursive: true });
66228
+ fs70.mkdirSync(hooksHome, { recursive: true });
66150
66229
  const configPath = getOtelHooksConfigPath(hooksHome);
66151
- fs69.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
66230
+ fs70.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
66152
66231
  `);
66153
66232
  return configPath;
66154
66233
  }
66155
66234
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
66156
- fs69.mkdirSync(hooksHome, { recursive: true });
66157
- fs69.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
66235
+ fs70.mkdirSync(hooksHome, { recursive: true });
66236
+ fs70.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
66158
66237
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
66159
66238
  const configPath = getOtelHooksConfigPath(hooksHome);
66160
66239
  const stateDir = getOtelHooksStateDir(hooksHome);
@@ -66177,9 +66256,9 @@ set -uo pipefail
66177
66256
  "$@" || true
66178
66257
  exit 0
66179
66258
  `;
66180
- fs69.writeFileSync(wrapperPath, script, { mode: 493 });
66259
+ fs70.writeFileSync(wrapperPath, script, { mode: 493 });
66181
66260
  try {
66182
- fs69.chmodSync(wrapperPath, 493);
66261
+ fs70.chmodSync(wrapperPath, 493);
66183
66262
  } catch {
66184
66263
  }
66185
66264
  return wrapperPath;
@@ -66192,7 +66271,7 @@ function commandExists3(command2) {
66192
66271
  }
66193
66272
  function resolveOtelHookCommand(hooksHome) {
66194
66273
  const local = localOtelHookBin(hooksHome);
66195
- if (fs69.existsSync(local)) return local;
66274
+ if (fs70.existsSync(local)) return local;
66196
66275
  return null;
66197
66276
  }
66198
66277
  function resolveHooksInstaller(hooksHome) {
@@ -66207,7 +66286,7 @@ function resolveHooksInstaller(hooksHome) {
66207
66286
  return candidates.find((candidate) => commandExists3(candidate.command)) ?? null;
66208
66287
  }
66209
66288
  function tryInstallPackage(hooksHome) {
66210
- fs69.mkdirSync(hooksHome, { recursive: true });
66289
+ fs70.mkdirSync(hooksHome, { recursive: true });
66211
66290
  const installer = resolveHooksInstaller(hooksHome);
66212
66291
  if (!installer) {
66213
66292
  return {
@@ -66220,7 +66299,7 @@ function tryInstallPackage(hooksHome) {
66220
66299
  encoding: "utf8",
66221
66300
  timeout: 18e4
66222
66301
  });
66223
- if (result.status === 0 && fs69.existsSync(localOtelHookBin(hooksHome))) {
66302
+ if (result.status === 0 && fs70.existsSync(localOtelHookBin(hooksHome))) {
66224
66303
  return { ok: true, detail: described };
66225
66304
  }
66226
66305
  return {
@@ -66252,8 +66331,8 @@ function removeLegacyPythonArtifacts(hooksHome) {
66252
66331
  ];
66253
66332
  for (const target of legacyPaths) {
66254
66333
  try {
66255
- if (fs69.existsSync(target)) {
66256
- fs69.rmSync(target, { recursive: true, force: true });
66334
+ if (fs70.existsSync(target)) {
66335
+ fs70.rmSync(target, { recursive: true, force: true });
66257
66336
  }
66258
66337
  } catch {
66259
66338
  }
@@ -66301,10 +66380,10 @@ function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
66301
66380
  };
66302
66381
  }
66303
66382
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
66304
- if (!fs69.existsSync(filePath)) return false;
66383
+ if (!fs70.existsSync(filePath)) return false;
66305
66384
  let raw;
66306
66385
  try {
66307
- raw = fs69.readFileSync(filePath, "utf8");
66386
+ raw = fs70.readFileSync(filePath, "utf8");
66308
66387
  } catch {
66309
66388
  return false;
66310
66389
  }
@@ -66351,15 +66430,15 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
66351
66430
  return changed;
66352
66431
  };
66353
66432
  if (!walk(parsed)) return false;
66354
- fs69.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
66433
+ fs70.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
66355
66434
  `);
66356
66435
  return true;
66357
66436
  }
66358
66437
  function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
66359
- if (!fs69.existsSync(filePath)) return false;
66438
+ if (!fs70.existsSync(filePath)) return false;
66360
66439
  let raw;
66361
66440
  try {
66362
- raw = fs69.readFileSync(filePath, "utf8");
66441
+ raw = fs70.readFileSync(filePath, "utf8");
66363
66442
  } catch {
66364
66443
  return false;
66365
66444
  }
@@ -66394,7 +66473,7 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
66394
66473
  }
66395
66474
  }
66396
66475
  if (!changed) return false;
66397
- fs69.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
66476
+ fs70.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
66398
66477
  `);
66399
66478
  return true;
66400
66479
  }
@@ -66424,7 +66503,7 @@ function ensureOtelHooks(options) {
66424
66503
  const hooksHome = getOtelHooksHome();
66425
66504
  const errors = [];
66426
66505
  const providersSetup = [];
66427
- fs69.mkdirSync(hooksHome, { recursive: true });
66506
+ fs70.mkdirSync(hooksHome, { recursive: true });
66428
66507
  let otelHookCommand = resolveOtelHookCommand(hooksHome);
66429
66508
  const needsInstall = !otelHookCommand || installedPackageVersion(hooksHome) !== pinnedVersion();
66430
66509
  if (needsInstall) {
@@ -66518,12 +66597,12 @@ function ensureOtelHooks(options) {
66518
66597
  function disableOtelHooksExport() {
66519
66598
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
66520
66599
  }
66521
- var import_child_process19, fs69, os22, path79, OTEL_HOOKS_PACKAGE, HOOK_TIMEOUT_SECONDS, HOOK_EXPORT_TIMEOUT_MS, HOOK_FLUSH_TIMEOUT_MS, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
66600
+ var import_child_process19, fs70, os22, path79, OTEL_HOOKS_PACKAGE, HOOK_TIMEOUT_SECONDS, HOOK_EXPORT_TIMEOUT_MS, HOOK_FLUSH_TIMEOUT_MS, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
66522
66601
  var init_otel_hooks = __esm({
66523
66602
  "src/core/otel-hooks.ts"() {
66524
66603
  "use strict";
66525
66604
  import_child_process19 = require("child_process");
66526
- fs69 = __toESM(require("fs"));
66605
+ fs70 = __toESM(require("fs"));
66527
66606
  os22 = __toESM(require("os"));
66528
66607
  path79 = __toESM(require("path"));
66529
66608
  init_control_config();
@@ -73395,12 +73474,12 @@ var require_dist = __commonJS({
73395
73474
  throw new Error(`Unknown format "${name}"`);
73396
73475
  return f2;
73397
73476
  };
73398
- function addFormats(ajv, list, fs81, exportName) {
73477
+ function addFormats(ajv, list, fs82, exportName) {
73399
73478
  var _a2;
73400
73479
  var _b2;
73401
73480
  (_a2 = (_b2 = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
73402
73481
  for (const f2 of list)
73403
- ajv.addFormat(f2, fs81[f2]);
73482
+ ajv.addFormat(f2, fs82[f2]);
73404
73483
  }
73405
73484
  module2.exports = exports2 = formatsPlugin;
73406
73485
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -78267,7 +78346,7 @@ init_sync_context();
78267
78346
  var path51 = __toESM(require("path"));
78268
78347
 
78269
78348
  // src/harness/agent-skills.ts
78270
- var fs43 = __toESM(require("fs"));
78349
+ var fs44 = __toESM(require("fs"));
78271
78350
  var os17 = __toESM(require("os"));
78272
78351
  var path50 = __toESM(require("path"));
78273
78352
  var readline = __toESM(require("readline"));
@@ -78279,17 +78358,17 @@ var AGENT_SKILL_TARGETS = ["claude", "cursor", "codex"];
78279
78358
  var MANAGED_HEADER = "<!-- managed by har \u2014 regenerated by `har agents install` / `har env maintain`; edit at your own risk -->";
78280
78359
  function agentSkillsTemplateDir() {
78281
78360
  const dir = path50.join(resolveTemplatesDir(), "agent-skills");
78282
- if (!fs43.existsSync(dir)) {
78361
+ if (!fs44.existsSync(dir)) {
78283
78362
  throw new Error("Agent skills templates not found (templates/agent-skills). Run npm run build.");
78284
78363
  }
78285
78364
  return dir;
78286
78365
  }
78287
78366
  function readSkillsManifest() {
78288
78367
  const manifestPath = path50.join(agentSkillsTemplateDir(), "skills.manifest.json");
78289
- return JSON.parse(fs43.readFileSync(manifestPath, "utf8"));
78368
+ return JSON.parse(fs44.readFileSync(manifestPath, "utf8"));
78290
78369
  }
78291
78370
  function readSkillBody(entry) {
78292
- return fs43.readFileSync(path50.join(agentSkillsTemplateDir(), entry.body), "utf8");
78371
+ return fs44.readFileSync(path50.join(agentSkillsTemplateDir(), entry.body), "utf8");
78293
78372
  }
78294
78373
  function renderYamlValue(value) {
78295
78374
  if (typeof value === "string") return JSON.stringify(value);
@@ -78353,7 +78432,7 @@ function resolveScaffoldPath(repoPath, file) {
78353
78432
  return path50.join(repoPath, file.relPath);
78354
78433
  }
78355
78434
  function isHarManaged(filePath) {
78356
- return fs43.readFileSync(filePath, "utf8").includes(MANAGED_HEADER);
78435
+ return fs44.readFileSync(filePath, "utf8").includes(MANAGED_HEADER);
78357
78436
  }
78358
78437
  function scaffoldAgentSkills(repoPath, agents, options = {}) {
78359
78438
  const written = [];
@@ -78361,7 +78440,7 @@ function scaffoldAgentSkills(repoPath, agents, options = {}) {
78361
78440
  const records = [];
78362
78441
  for (const file of renderSkillFiles(agents)) {
78363
78442
  const destPath = resolveScaffoldPath(repoPath, file);
78364
- if (fs43.existsSync(destPath) && !options.force && !isHarManaged(destPath)) {
78443
+ if (fs44.existsSync(destPath) && !options.force && !isHarManaged(destPath)) {
78365
78444
  warn(`Skipped ${file.relPath} \u2014 exists with user modifications (use --force to overwrite)`);
78366
78445
  skipped.push(file.relPath);
78367
78446
  continue;
@@ -78395,16 +78474,16 @@ function removeAgentSkills(repoPath, agents) {
78395
78474
  const removed = [];
78396
78475
  for (const file of renderSkillFiles(agents)) {
78397
78476
  const destPath = resolveScaffoldPath(repoPath, file);
78398
- if (!fs43.existsSync(destPath)) continue;
78477
+ if (!fs44.existsSync(destPath)) continue;
78399
78478
  if (!isHarManaged(destPath)) {
78400
78479
  warn(`Kept ${file.relPath} \u2014 has user modifications`);
78401
78480
  continue;
78402
78481
  }
78403
- fs43.rmSync(destPath);
78482
+ fs44.rmSync(destPath);
78404
78483
  removed.push(file.relPath);
78405
78484
  const parent = path50.dirname(destPath);
78406
- if (fs43.existsSync(parent) && fs43.readdirSync(parent).length === 0) {
78407
- fs43.rmdirSync(parent);
78485
+ if (fs44.existsSync(parent) && fs44.readdirSync(parent).length === 0) {
78486
+ fs44.rmdirSync(parent);
78408
78487
  }
78409
78488
  }
78410
78489
  const manifest = readManifest(repoPath);
@@ -78423,9 +78502,9 @@ function detectAgentTargets(repoPath) {
78423
78502
  const manifest = readManifest(repoPath);
78424
78503
  const scaffolded = new Set((manifest?.scaffoldedAgentFiles ?? []).map((entry) => entry.agent));
78425
78504
  const detected = new Set(scaffolded);
78426
- if (fs43.existsSync(path50.join(repoPath, ".claude"))) detected.add("claude");
78427
- if (fs43.existsSync(path50.join(repoPath, ".cursor"))) detected.add("cursor");
78428
- if (fs43.existsSync(path50.join(os17.homedir(), ".codex"))) detected.add("codex");
78505
+ if (fs44.existsSync(path50.join(repoPath, ".claude"))) detected.add("claude");
78506
+ if (fs44.existsSync(path50.join(repoPath, ".cursor"))) detected.add("cursor");
78507
+ if (fs44.existsSync(path50.join(os17.homedir(), ".codex"))) detected.add("codex");
78429
78508
  return AGENT_SKILL_TARGETS.filter((agent) => detected.has(agent));
78430
78509
  }
78431
78510
  function parseAgentTargets(raw) {
@@ -78558,7 +78637,7 @@ function handleRemove(argv) {
78558
78637
  }
78559
78638
 
78560
78639
  // src/cli/commands/env.ts
78561
- var fs72 = __toESM(require("fs"));
78640
+ var fs73 = __toESM(require("fs"));
78562
78641
  var path83 = __toESM(require("path"));
78563
78642
 
78564
78643
  // src/cli/finish-command.ts
@@ -78569,17 +78648,17 @@ async function finishCommand(code) {
78569
78648
  }
78570
78649
 
78571
78650
  // src/core/harness.ts
78572
- var fs66 = __toESM(require("fs"));
78651
+ var fs67 = __toESM(require("fs"));
78573
78652
  var path75 = __toESM(require("path"));
78574
78653
 
78575
78654
  // src/harness/generator.ts
78576
- var fs49 = __toESM(require("fs"));
78655
+ var fs50 = __toESM(require("fs"));
78577
78656
  var path57 = __toESM(require("path"));
78578
78657
  init_file_ops();
78579
78658
  init_logging();
78580
78659
 
78581
78660
  // src/core/gitignore.ts
78582
- var fs44 = __toESM(require("fs"));
78661
+ var fs45 = __toESM(require("fs"));
78583
78662
  var path52 = __toESM(require("path"));
78584
78663
  var HARNESS_ROOT_GITIGNORE_PATTERNS = [
78585
78664
  ".env.agent.*",
@@ -78587,7 +78666,7 @@ var HARNESS_ROOT_GITIGNORE_PATTERNS = [
78587
78666
  ];
78588
78667
  function ensureRootGitignorePatterns(checkoutDir) {
78589
78668
  const gitignorePath = path52.join(checkoutDir, ".gitignore");
78590
- const content = fs44.existsSync(gitignorePath) ? fs44.readFileSync(gitignorePath, "utf8") : "";
78669
+ const content = fs45.existsSync(gitignorePath) ? fs45.readFileSync(gitignorePath, "utf8") : "";
78591
78670
  const lines = content.split("\n").map((line) => line.trim());
78592
78671
  const missing = HARNESS_ROOT_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
78593
78672
  if (missing.length === 0) return;
@@ -78596,11 +78675,11 @@ function ensureRootGitignorePatterns(checkoutDir) {
78596
78675
  const block = lines.some((line) => line.includes("HAR agent slot artifacts")) || header2.length === 0 ? `${missing.join("\n")}
78597
78676
  ` : `${header2}${missing.join("\n")}
78598
78677
  `;
78599
- fs44.writeFileSync(gitignorePath, `${content}${suffix}${block}`);
78678
+ fs45.writeFileSync(gitignorePath, `${content}${suffix}${block}`);
78600
78679
  }
78601
78680
 
78602
78681
  // src/harness/gitignore-template.ts
78603
- var fs45 = __toESM(require("fs"));
78682
+ var fs46 = __toESM(require("fs"));
78604
78683
  var path53 = __toESM(require("path"));
78605
78684
  var HARNESS_GITIGNORE_TEMPLATE = "gitignore.template";
78606
78685
  var HARNESS_GITIGNORE_FILE = ".gitignore";
@@ -78612,22 +78691,22 @@ function templateFileForHarness(harnessFile) {
78612
78691
  }
78613
78692
  function resolveGitignoreTemplateSource(boilerplateDir) {
78614
78693
  const primary = path53.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
78615
- if (fs45.existsSync(primary)) return primary;
78694
+ if (fs46.existsSync(primary)) return primary;
78616
78695
  const legacy = path53.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
78617
- if (fs45.existsSync(legacy)) return legacy;
78696
+ if (fs46.existsSync(legacy)) return legacy;
78618
78697
  return null;
78619
78698
  }
78620
78699
  function writeHarnessGitignore(harnessDir, boilerplateDir) {
78621
78700
  const src = resolveGitignoreTemplateSource(boilerplateDir);
78622
78701
  if (!src) return;
78623
- fs45.writeFileSync(path53.join(harnessDir, HARNESS_GITIGNORE_FILE), fs45.readFileSync(src, "utf8"));
78702
+ fs46.writeFileSync(path53.join(harnessDir, HARNESS_GITIGNORE_FILE), fs46.readFileSync(src, "utf8"));
78624
78703
  }
78625
78704
  function isExpectedHarnessOnlyFile(harnessFile, templateFiles) {
78626
78705
  return harnessFile === HARNESS_GITIGNORE_FILE && templateFiles.includes(HARNESS_GITIGNORE_TEMPLATE);
78627
78706
  }
78628
78707
 
78629
78708
  // src/harness/drift.ts
78630
- var fs46 = __toESM(require("fs"));
78709
+ var fs47 = __toESM(require("fs"));
78631
78710
  var path54 = __toESM(require("path"));
78632
78711
  init_env();
78633
78712
  init_manifest();
@@ -78757,7 +78836,7 @@ function compareHarnessToTemplate(repoPath) {
78757
78836
  for (const file of templateFiles) {
78758
78837
  const harnessFile = harnessFileForTemplate(file);
78759
78838
  const harnessPath = path54.join(harnessDir, harnessFile);
78760
- if (userOwnedFiles.has(harnessFile) && fs46.existsSync(harnessPath)) {
78839
+ if (userOwnedFiles.has(harnessFile) && fs47.existsSync(harnessPath)) {
78761
78840
  ownedByUser.push(harnessFile);
78762
78841
  continue;
78763
78842
  }
@@ -78765,11 +78844,11 @@ function compareHarnessToTemplate(repoPath) {
78765
78844
  readComposedTemplateContent(composed.get(file)),
78766
78845
  projectName
78767
78846
  );
78768
- if (!fs46.existsSync(harnessPath)) {
78847
+ if (!fs47.existsSync(harnessPath)) {
78769
78848
  missing.push(harnessFile);
78770
78849
  continue;
78771
78850
  }
78772
- const installedChecksum = computeFileChecksum(fs46.readFileSync(harnessPath, "utf8"));
78851
+ const installedChecksum = computeFileChecksum(fs47.readFileSync(harnessPath, "utf8"));
78773
78852
  const templateChecksum = computeFileChecksum(templateContent);
78774
78853
  const recordedFile = fileBaseline?.[harnessFile];
78775
78854
  const recordedTemplate = templateBaseline?.[harnessFile];
@@ -78782,10 +78861,10 @@ function compareHarnessToTemplate(repoPath) {
78782
78861
  else if (status === "upstream-updated") upstreamUpdated.push(harnessFile);
78783
78862
  else conflict.push(harnessFile);
78784
78863
  }
78785
- if (fs46.existsSync(harnessDir)) {
78786
- for (const file of fs46.readdirSync(harnessDir)) {
78864
+ if (fs47.existsSync(harnessDir)) {
78865
+ for (const file of fs47.readdirSync(harnessDir)) {
78787
78866
  const full = path54.join(harnessDir, file);
78788
- if (!fs46.statSync(full).isFile()) continue;
78867
+ if (!fs47.statSync(full).isFile()) continue;
78789
78868
  if (file === "manifest.json" || file === "plugins.json" || file.startsWith("ADAPT-PROMPT") || file.startsWith("MIGRATE-PROMPT")) {
78790
78869
  continue;
78791
78870
  }
@@ -78819,7 +78898,7 @@ function compareHarnessToTemplate(repoPath) {
78819
78898
  init_manifest();
78820
78899
 
78821
78900
  // src/harness/plugin-ledger.ts
78822
- var fs47 = __toESM(require("fs"));
78901
+ var fs48 = __toESM(require("fs"));
78823
78902
  var path55 = __toESM(require("path"));
78824
78903
  init_zod();
78825
78904
  init_file_ops();
@@ -78847,9 +78926,9 @@ function getPluginLedgerPath(repoPath) {
78847
78926
  }
78848
78927
  function readPluginLedger(repoPath) {
78849
78928
  const ledgerPath = getPluginLedgerPath(repoPath);
78850
- if (!fs47.existsSync(ledgerPath)) return null;
78929
+ if (!fs48.existsSync(ledgerPath)) return null;
78851
78930
  try {
78852
- const raw = JSON.parse(fs47.readFileSync(ledgerPath, "utf8"));
78931
+ const raw = JSON.parse(fs48.readFileSync(ledgerPath, "utf8"));
78853
78932
  const parsed = PluginLedgerSchema.safeParse(raw);
78854
78933
  return parsed.success ? parsed.data : null;
78855
78934
  } catch {
@@ -78859,8 +78938,8 @@ function readPluginLedger(repoPath) {
78859
78938
  function writePluginLedger(repoPath, ledger) {
78860
78939
  const ledgerPath = getPluginLedgerPath(repoPath);
78861
78940
  const harnessDir = path55.dirname(ledgerPath);
78862
- if (!fs47.existsSync(harnessDir)) {
78863
- fs47.mkdirSync(harnessDir, { recursive: true });
78941
+ if (!fs48.existsSync(harnessDir)) {
78942
+ fs48.mkdirSync(harnessDir, { recursive: true });
78864
78943
  }
78865
78944
  writeFileSafe(ledgerPath, `${JSON.stringify(ledger, null, 2)}
78866
78945
  `);
@@ -78900,7 +78979,7 @@ init_schema2();
78900
78979
  init_stages();
78901
78980
 
78902
78981
  // src/harness/lifecycle-shims.ts
78903
- var fs48 = __toESM(require("fs"));
78982
+ var fs49 = __toESM(require("fs"));
78904
78983
  var path56 = __toESM(require("path"));
78905
78984
  init_manifest();
78906
78985
  init_stages();
@@ -78933,10 +79012,10 @@ function retireLifecycleShims(repoPath) {
78933
79012
  const pruned = [];
78934
79013
  for (const shim3 of LIFECYCLE_SHIM_FILES) {
78935
79014
  const file = path56.join(harnessDir, shim3);
78936
- if (!fs48.existsSync(file) || !fs48.statSync(file).isFile()) continue;
78937
- const content = fs48.readFileSync(file, "utf8");
79015
+ if (!fs49.existsSync(file) || !fs49.statSync(file).isFile()) continue;
79016
+ const content = fs49.readFileSync(file, "utf8");
78938
79017
  if (!isManagedShimContent(content)) continue;
78939
- fs48.rmSync(file);
79018
+ fs49.rmSync(file);
78940
79019
  pruned.push(shim3);
78941
79020
  }
78942
79021
  const stagesRewritten = stripLifecycleShimCommands(repoPath);
@@ -78972,21 +79051,21 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
78972
79051
  const profile = options.profile ?? "default";
78973
79052
  const profileManifest = readProfileManifest(profile);
78974
79053
  const bundleIds = profileManifest.bundles.map((b2) => b2.id);
78975
- if (fs49.existsSync(harnessDir) && !options.force) {
79054
+ if (fs50.existsSync(harnessDir) && !options.force) {
78976
79055
  throw new Error(
78977
79056
  '.har/ already exists. Use --force to overwrite or run "har env maintain" to update in place.'
78978
79057
  );
78979
79058
  }
78980
- if (options.force && fs49.existsSync(harnessDir)) {
78981
- fs49.rmSync(harnessDir, { recursive: true, force: true });
79059
+ if (options.force && fs50.existsSync(harnessDir)) {
79060
+ fs50.rmSync(harnessDir, { recursive: true, force: true });
78982
79061
  }
78983
- fs49.mkdirSync(harnessDir, { recursive: true });
79062
+ fs50.mkdirSync(harnessDir, { recursive: true });
78984
79063
  for (const bundle of profileManifest.bundles) {
78985
79064
  const bundleDir = resolveProfileBundleDir(bundle);
78986
79065
  copyDirRecursive(bundleDir, harnessDir);
78987
79066
  }
78988
79067
  for (const docName of Object.keys(profileManifest.docs)) {
78989
- fs49.writeFileSync(path57.join(harnessDir, docName), renderProfileDoc(profile, docName));
79068
+ fs50.writeFileSync(path57.join(harnessDir, docName), renderProfileDoc(profile, docName));
78990
79069
  }
78991
79070
  const gitignoreSource = composeProfileTemplateMap(profile).get(HARNESS_GITIGNORE_TEMPLATE);
78992
79071
  if (gitignoreSource) {
@@ -78995,10 +79074,10 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
78995
79074
  syncAgentSlotsToHarnessEnv(repoPath);
78996
79075
  retireLifecycleShims(repoPath);
78997
79076
  const harnessEnvPath = path57.join(harnessDir, "harness.env");
78998
- if (fs49.existsSync(harnessEnvPath)) {
78999
- let content = fs49.readFileSync(harnessEnvPath, "utf8");
79077
+ if (fs50.existsSync(harnessEnvPath)) {
79078
+ let content = fs50.readFileSync(harnessEnvPath, "utf8");
79000
79079
  content = substituteTemplateTokens(content, projectName);
79001
- fs49.writeFileSync(harnessEnvPath, content);
79080
+ fs50.writeFileSync(harnessEnvPath, content);
79002
79081
  const validation2 = validateHarnessEnvSource(content);
79003
79082
  if (!validation2.ok) {
79004
79083
  const details = validation2.issues.filter((i) => i.severity === "error").map((i) => i.line !== void 0 ? `line ${i.line}: ${i.message}` : i.message).join("\n ");
@@ -79036,14 +79115,14 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
79036
79115
  }
79037
79116
 
79038
79117
  // src/harness/agent-md.ts
79039
- var fs51 = __toESM(require("fs"));
79118
+ var fs52 = __toESM(require("fs"));
79040
79119
  var path60 = __toESM(require("path"));
79041
79120
  init_file_ops();
79042
79121
  init_logging();
79043
79122
  init_manifest();
79044
79123
 
79045
79124
  // src/harness/instruction-files.ts
79046
- var fs50 = __toESM(require("fs"));
79125
+ var fs51 = __toESM(require("fs"));
79047
79126
  var os19 = __toESM(require("os"));
79048
79127
  var path59 = __toESM(require("path"));
79049
79128
 
@@ -81795,12 +81874,12 @@ function outsideContentShrinkMessage(beforeLines, afterLines) {
81795
81874
  }
81796
81875
  function detectInstructionFiles(repoPath) {
81797
81876
  return {
81798
- agentsMd: fs50.existsSync(path59.join(repoPath, AGENTS_MD)),
81799
- agentMd: fs50.existsSync(path59.join(repoPath, LEGACY_AGENT_MD)),
81800
- claudeMd: fs50.existsSync(path59.join(repoPath, CLAUDE_MD)),
81801
- cursorDir: fs50.existsSync(path59.join(repoPath, ".cursor")),
81802
- claudeDir: fs50.existsSync(path59.join(repoPath, ".claude")),
81803
- codexHome: fs50.existsSync(path59.join(os19.homedir(), ".codex"))
81877
+ agentsMd: fs51.existsSync(path59.join(repoPath, AGENTS_MD)),
81878
+ agentMd: fs51.existsSync(path59.join(repoPath, LEGACY_AGENT_MD)),
81879
+ claudeMd: fs51.existsSync(path59.join(repoPath, CLAUDE_MD)),
81880
+ cursorDir: fs51.existsSync(path59.join(repoPath, ".cursor")),
81881
+ claudeDir: fs51.existsSync(path59.join(repoPath, ".claude")),
81882
+ codexHome: fs51.existsSync(path59.join(os19.homedir(), ".codex"))
81804
81883
  };
81805
81884
  }
81806
81885
  function formatDetectionReport(detection) {
@@ -81865,7 +81944,7 @@ function loadHarAgentsSectionFromTemplate(options = {}) {
81865
81944
  if (!templatePath) {
81866
81945
  throw new Error("AGENTS.md.template not found. Run npm run build.");
81867
81946
  }
81868
- const content = fs50.readFileSync(templatePath, "utf8");
81947
+ const content = fs51.readFileSync(templatePath, "utf8");
81869
81948
  const start = content.indexOf(HAR_SECTION_START);
81870
81949
  const end = content.indexOf(HAR_SECTION_END);
81871
81950
  if (start === -1 || end === -1 || end < start) {
@@ -81883,7 +81962,7 @@ function loadAgentsMdTemplate() {
81883
81962
  if (!templatePath) {
81884
81963
  throw new Error("AGENTS.md.template not found. Run npm run build.");
81885
81964
  }
81886
- return fs50.readFileSync(templatePath, "utf8");
81965
+ return fs51.readFileSync(templatePath, "utf8");
81887
81966
  }
81888
81967
  function upsertMarkedBlock2(content, block, startMarker, endMarker) {
81889
81968
  const existingBlock = findLastCompleteMarkedBlock(content, startMarker, endMarker);
@@ -81919,11 +81998,11 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
81919
81998
  const dest = path59.join(repoPath, AGENTS_MD);
81920
81999
  const ejected = readManifest(repoPath)?.ejected === true;
81921
82000
  const section = loadHarAgentsSectionFromTemplate({ ejected });
81922
- if (!fs50.existsSync(dest)) {
82001
+ if (!fs51.existsSync(dest)) {
81923
82002
  writeFileSafe(dest, loadAgentsMdTemplate());
81924
82003
  return "created";
81925
82004
  }
81926
- const existing = fs50.readFileSync(dest, "utf8");
82005
+ const existing = fs51.readFileSync(dest, "utf8");
81927
82006
  const sanitized = stripClaudePointerFromAgentsMd(existing);
81928
82007
  const { content, action } = upsertMarkedBlock2(
81929
82008
  sanitized,
@@ -81950,13 +82029,13 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
81950
82029
  function migrateLegacyAgentMd(repoPath) {
81951
82030
  const legacyPath = path59.join(repoPath, LEGACY_AGENT_MD);
81952
82031
  const agentsPath = path59.join(repoPath, AGENTS_MD);
81953
- if (!fs50.existsSync(legacyPath)) return false;
81954
- const legacy = fs50.readFileSync(legacyPath, "utf8");
81955
- if (!fs50.existsSync(agentsPath)) {
82032
+ if (!fs51.existsSync(legacyPath)) return false;
82033
+ const legacy = fs51.readFileSync(legacyPath, "utf8");
82034
+ if (!fs51.existsSync(agentsPath)) {
81956
82035
  writeFileSafe(agentsPath, legacy);
81957
82036
  upsertAgentsMdHarSection(repoPath);
81958
82037
  } else {
81959
- const agents = fs50.readFileSync(agentsPath, "utf8");
82038
+ const agents = fs51.readFileSync(agentsPath, "utf8");
81960
82039
  const legacyTrimmed = legacy.trim();
81961
82040
  if (legacyTrimmed.length > 0 && !agents.includes(legacyTrimmed)) {
81962
82041
  const suffix = agents.endsWith("\n") ? "" : "\n";
@@ -81966,7 +82045,7 @@ ${legacyTrimmed}
81966
82045
  }
81967
82046
  upsertAgentsMdHarSection(repoPath);
81968
82047
  }
81969
- fs50.unlinkSync(legacyPath);
82048
+ fs51.unlinkSync(legacyPath);
81970
82049
  info(`Migrated ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD} (removed legacy file)`);
81971
82050
  return true;
81972
82051
  }
@@ -81976,7 +82055,7 @@ function loadClaudeMdTemplate() {
81976
82055
  if (!templatePath) {
81977
82056
  throw new Error("CLAUDE.md.template not found. Run npm run build.");
81978
82057
  }
81979
- return fs50.readFileSync(templatePath, "utf8");
82058
+ return fs51.readFileSync(templatePath, "utf8");
81980
82059
  }
81981
82060
  function isHarOwnedClaudeMd(content) {
81982
82061
  const trimmed = content.trim();
@@ -81990,11 +82069,11 @@ function hasAgentsImport(content) {
81990
82069
  function ensureClaudeMdPointer(repoPath, options = {}) {
81991
82070
  const dest = path59.join(repoPath, CLAUDE_MD);
81992
82071
  const thin = loadClaudeMdTemplate();
81993
- if (!fs50.existsSync(dest)) {
82072
+ if (!fs51.existsSync(dest)) {
81994
82073
  writeFileSafe(dest, thin);
81995
82074
  return "created";
81996
82075
  }
81997
- const existing = fs50.readFileSync(dest, "utf8");
82076
+ const existing = fs51.readFileSync(dest, "utf8");
81998
82077
  if (isHarOwnedClaudeMd(existing) || options.force) {
81999
82078
  if (existing.trim() === CLAUDE_MD_IMPORT) return "skipped";
82000
82079
  writeFileSafe(dest, thin);
@@ -82132,15 +82211,15 @@ function readAgentMdProposal(repoPath) {
82132
82211
  const metaPath = path60.join(harnessDir, AGENTS_MD_PROPOSAL_META);
82133
82212
  const legacyProposalPath = path60.join(harnessDir, AGENT_MD_PROPOSAL);
82134
82213
  const legacyMetaPath = path60.join(harnessDir, AGENT_MD_PROPOSAL_META);
82135
- const resolvedProposal = fs51.existsSync(proposalPath) ? proposalPath : fs51.existsSync(legacyProposalPath) ? legacyProposalPath : null;
82214
+ const resolvedProposal = fs52.existsSync(proposalPath) ? proposalPath : fs52.existsSync(legacyProposalPath) ? legacyProposalPath : null;
82136
82215
  if (!resolvedProposal) return null;
82137
82216
  const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
82138
- const content = fs51.readFileSync(resolvedProposal, "utf8");
82217
+ const content = fs52.readFileSync(resolvedProposal, "utf8");
82139
82218
  let rationale = "";
82140
82219
  let createdAt = (/* @__PURE__ */ new Date()).toISOString();
82141
- if (fs51.existsSync(resolvedMeta)) {
82220
+ if (fs52.existsSync(resolvedMeta)) {
82142
82221
  try {
82143
- const meta = JSON.parse(fs51.readFileSync(resolvedMeta, "utf8"));
82222
+ const meta = JSON.parse(fs52.readFileSync(resolvedMeta, "utf8"));
82144
82223
  rationale = meta.rationale ?? "";
82145
82224
  createdAt = meta.createdAt ?? createdAt;
82146
82225
  } catch {
@@ -82158,7 +82237,7 @@ function clearAgentMdProposal(repoPath) {
82158
82237
  AGENT_MD_PROPOSAL_META
82159
82238
  ]) {
82160
82239
  const p = path60.join(harnessDir, file);
82161
- if (fs51.existsSync(p)) fs51.unlinkSync(p);
82240
+ if (fs52.existsSync(p)) fs52.unlinkSync(p);
82162
82241
  }
82163
82242
  }
82164
82243
  function wouldProposalShrinkExisting(existing, proposal) {
@@ -82172,8 +82251,8 @@ function applyAgentMdProposalMerge(repoPath, options = {}) {
82172
82251
  const proposal = readAgentMdProposal(repoPath);
82173
82252
  if (!proposal) return false;
82174
82253
  const agentsMdPath = path60.join(repoPath, AGENTS_MD);
82175
- if (fs51.existsSync(agentsMdPath)) {
82176
- const existing = fs51.readFileSync(agentsMdPath, "utf8");
82254
+ if (fs52.existsSync(agentsMdPath)) {
82255
+ const existing = fs52.readFileSync(agentsMdPath, "utf8");
82177
82256
  if (wouldProposalShrinkExisting(existing, proposal.content)) {
82178
82257
  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.`;
82179
82258
  if (options.rejectSignificantShrink) {
@@ -82196,7 +82275,7 @@ function finalizeAgentsMdInstructionFiles(repoPath) {
82196
82275
  }
82197
82276
 
82198
82277
  // src/harness/validator.ts
82199
- var fs53 = __toESM(require("fs"));
82278
+ var fs54 = __toESM(require("fs"));
82200
82279
  var path62 = __toESM(require("path"));
82201
82280
  init_shell();
82202
82281
  init_env();
@@ -82204,7 +82283,7 @@ init_manifest();
82204
82283
  init_stages();
82205
82284
 
82206
82285
  // src/harness/verification.ts
82207
- var fs52 = __toESM(require("fs"));
82286
+ var fs53 = __toESM(require("fs"));
82208
82287
  var path61 = __toESM(require("path"));
82209
82288
  init_env();
82210
82289
  init_provision();
@@ -82233,7 +82312,7 @@ function nodeSmokeCommand(repoPath) {
82233
82312
  const pkgPath = path61.join(repoPath, "package.json");
82234
82313
  let scripts = {};
82235
82314
  try {
82236
- scripts = JSON.parse(fs52.readFileSync(pkgPath, "utf8")).scripts ?? {};
82315
+ scripts = JSON.parse(fs53.readFileSync(pkgPath, "utf8")).scripts ?? {};
82237
82316
  } catch {
82238
82317
  scripts = {};
82239
82318
  }
@@ -82264,7 +82343,7 @@ function nodeSmokeCommand(repoPath) {
82264
82343
  function nodeScriptOrSkip(repoPath, script) {
82265
82344
  const pkgPath = path61.join(repoPath, "package.json");
82266
82345
  try {
82267
- const scripts = JSON.parse(fs52.readFileSync(pkgPath, "utf8")).scripts ?? {};
82346
+ const scripts = JSON.parse(fs53.readFileSync(pkgPath, "utf8")).scripts ?? {};
82268
82347
  if (scripts[script]) {
82269
82348
  return script === "test" ? "${NPM_BIN:-npm} test" : `\${NPM_BIN:-npm} run ${script}`;
82270
82349
  }
@@ -82389,7 +82468,7 @@ function ensureEcosystemVerificationStages(repoPath) {
82389
82468
  const skipped = /* @__PURE__ */ new Set();
82390
82469
  for (const stage of defaults.stages) {
82391
82470
  if (stages.some((s) => s.id === stage.id)) continue;
82392
- if (stage.script && !fs52.existsSync(path61.join(harnessDir, stage.script))) {
82471
+ if (stage.script && !fs53.existsSync(path61.join(harnessDir, stage.script))) {
82393
82472
  skipped.add(stage.id);
82394
82473
  continue;
82395
82474
  }
@@ -82447,7 +82526,7 @@ var SHELL_SCRIPTS = [
82447
82526
  function validateHarness(repoPath) {
82448
82527
  const harnessDir = getHarnessDir(repoPath);
82449
82528
  const issues = [];
82450
- if (!fs53.existsSync(harnessDir)) {
82529
+ if (!fs54.existsSync(harnessDir)) {
82451
82530
  return {
82452
82531
  pass: false,
82453
82532
  issues: [{ file: ".har", message: "Harness directory not found", severity: "error" }]
@@ -82455,14 +82534,14 @@ function validateHarness(repoPath) {
82455
82534
  }
82456
82535
  for (const file of getRequiredFiles(repoPath)) {
82457
82536
  const filePath = path62.join(harnessDir, file);
82458
- if (!fs53.existsSync(filePath)) {
82537
+ if (!fs54.existsSync(filePath)) {
82459
82538
  issues.push({ file, message: "Required file missing", severity: "error" });
82460
82539
  }
82461
82540
  }
82462
82541
  for (const script of SHELL_SCRIPTS) {
82463
82542
  const scriptPath = path62.join(harnessDir, script);
82464
- if (!fs53.existsSync(scriptPath)) continue;
82465
- const stat = fs53.statSync(scriptPath);
82543
+ if (!fs54.existsSync(scriptPath)) continue;
82544
+ const stat = fs54.statSync(scriptPath);
82466
82545
  if (!(stat.mode & 73)) {
82467
82546
  issues.push({ file: script, message: "Script is not executable", severity: "warning" });
82468
82547
  }
@@ -82478,8 +82557,8 @@ function validateHarness(repoPath) {
82478
82557
  const manifest = readManifest(repoPath);
82479
82558
  const profile = manifest?.profile ?? "default";
82480
82559
  const ecosystemPath = path62.join(harnessDir, "ecosystem.agent.template.cjs");
82481
- if (profile !== "cli" && fs53.existsSync(ecosystemPath)) {
82482
- const content = fs53.readFileSync(ecosystemPath, "utf8");
82560
+ if (profile !== "cli" && fs54.existsSync(ecosystemPath)) {
82561
+ const content = fs54.readFileSync(ecosystemPath, "utf8");
82483
82562
  if (!content.includes("module.exports")) {
82484
82563
  issues.push({
82485
82564
  file: "ecosystem.agent.template.cjs",
@@ -82489,8 +82568,8 @@ function validateHarness(repoPath) {
82489
82568
  }
82490
82569
  }
82491
82570
  const harnessEnvPath = path62.join(harnessDir, "harness.env");
82492
- if (fs53.existsSync(harnessEnvPath)) {
82493
- const content = fs53.readFileSync(harnessEnvPath, "utf8");
82571
+ if (fs54.existsSync(harnessEnvPath)) {
82572
+ const content = fs54.readFileSync(harnessEnvPath, "utf8");
82494
82573
  if (content.includes("TODO: set migrate command")) {
82495
82574
  issues.push({ file: "harness.env", message: "Migrate command still has TODO", severity: "warning" });
82496
82575
  }
@@ -82507,16 +82586,16 @@ function validateHarness(repoPath) {
82507
82586
  }
82508
82587
  }
82509
82588
  const verifyPath = path62.join(harnessDir, "verify.sh");
82510
- if (fs53.existsSync(verifyPath)) {
82511
- const content = fs53.readFileSync(verifyPath, "utf8");
82589
+ if (fs54.existsSync(verifyPath)) {
82590
+ const content = fs54.readFileSync(verifyPath, "utf8");
82512
82591
  if (content.includes("echo 'TODO:")) {
82513
82592
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
82514
82593
  }
82515
82594
  }
82516
82595
  const stagesPath = path62.join(harnessDir, "stages.json");
82517
- if (fs53.existsSync(stagesPath)) {
82596
+ if (fs54.existsSync(stagesPath)) {
82518
82597
  try {
82519
- JSON.parse(fs53.readFileSync(stagesPath, "utf8"));
82598
+ JSON.parse(fs54.readFileSync(stagesPath, "utf8"));
82520
82599
  const registry2 = readStageRegistry(repoPath);
82521
82600
  if (registry2.stages.length === 0) {
82522
82601
  issues.push({ file: "stages.json", message: "No harness stages declared", severity: "warning" });
@@ -82539,8 +82618,8 @@ function validateHarness(repoPath) {
82539
82618
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
82540
82619
  }
82541
82620
  const readmePath = path62.join(harnessDir, "README.md");
82542
- if (fs53.existsSync(readmePath)) {
82543
- const content = fs53.readFileSync(readmePath, "utf8");
82621
+ if (fs54.existsSync(readmePath)) {
82622
+ const content = fs54.readFileSync(readmePath, "utf8");
82544
82623
  if (!content.includes(".har")) {
82545
82624
  issues.push({ file: "README.md", message: "README should document .har/ paths", severity: "warning" });
82546
82625
  }
@@ -82555,7 +82634,7 @@ async function smokeTestHarness(repoPath) {
82555
82634
  const harnessDir = getHarnessDir(repoPath);
82556
82635
  const issues = [];
82557
82636
  const setupScript = path62.join(harnessDir, "setup-infra.sh");
82558
- if (fs53.existsSync(setupScript)) {
82637
+ if (fs54.existsSync(setupScript)) {
82559
82638
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
82560
82639
  if (result.code !== 0) {
82561
82640
  issues.push({
@@ -82570,7 +82649,7 @@ async function smokeTestHarness(repoPath) {
82570
82649
  }
82571
82650
 
82572
82651
  // src/harness/maintain-bundle.ts
82573
- var fs59 = __toESM(require("fs"));
82652
+ var fs60 = __toESM(require("fs"));
82574
82653
  var os21 = __toESM(require("os"));
82575
82654
  var path67 = __toESM(require("path"));
82576
82655
  init_file_ops();
@@ -82578,34 +82657,34 @@ init_shell();
82578
82657
  init_manifest();
82579
82658
 
82580
82659
  // src/harness/plugin-drift.ts
82581
- var fs58 = __toESM(require("fs"));
82660
+ var fs59 = __toESM(require("fs"));
82582
82661
  var path66 = __toESM(require("path"));
82583
82662
  init_manifest();
82584
82663
 
82585
82664
  // src/harness/plugins.ts
82586
- var fs57 = __toESM(require("fs"));
82665
+ var fs58 = __toESM(require("fs"));
82587
82666
  var path65 = __toESM(require("path"));
82588
82667
  init_zod();
82589
82668
  init_logging();
82590
82669
  init_paths();
82591
82670
 
82592
82671
  // src/harness/parser.ts
82593
- var fs54 = __toESM(require("fs"));
82672
+ var fs55 = __toESM(require("fs"));
82594
82673
  init_manifest();
82595
82674
  function harnessExists(repoPath) {
82596
- return fs54.existsSync(`${repoPath}/.har/stages.json`);
82675
+ return fs55.existsSync(`${repoPath}/.har/stages.json`);
82597
82676
  }
82598
82677
 
82599
82678
  // src/harness/bundle-resolve.ts
82600
82679
  var import_child_process16 = require("child_process");
82601
- var fs55 = __toESM(require("fs"));
82680
+ var fs56 = __toESM(require("fs"));
82602
82681
  var os20 = __toESM(require("os"));
82603
82682
  var path63 = __toESM(require("path"));
82604
82683
  init_paths();
82605
82684
  function findManifestPath(dir, config2) {
82606
82685
  for (const name of config2.manifestFiles) {
82607
82686
  const candidate = path63.join(dir, name);
82608
- if (fs55.existsSync(candidate)) return candidate;
82687
+ if (fs56.existsSync(candidate)) return candidate;
82609
82688
  }
82610
82689
  return null;
82611
82690
  }
@@ -82614,9 +82693,9 @@ function hasManifest(dir, config2) {
82614
82693
  }
82615
82694
  function readPackageVersion(dir) {
82616
82695
  const pkgPath = path63.join(dir, "package.json");
82617
- if (!fs55.existsSync(pkgPath)) return void 0;
82696
+ if (!fs56.existsSync(pkgPath)) return void 0;
82618
82697
  try {
82619
- const pkg = JSON.parse(fs55.readFileSync(pkgPath, "utf8"));
82698
+ const pkg = JSON.parse(fs56.readFileSync(pkgPath, "utf8"));
82620
82699
  return typeof pkg.version === "string" ? pkg.version : void 0;
82621
82700
  } catch {
82622
82701
  return void 0;
@@ -82626,7 +82705,7 @@ function readManifestId(dir, config2) {
82626
82705
  const manifestPath = findManifestPath(dir, config2);
82627
82706
  if (!manifestPath) return void 0;
82628
82707
  try {
82629
- const raw = JSON.parse(fs55.readFileSync(manifestPath, "utf8"));
82708
+ const raw = JSON.parse(fs56.readFileSync(manifestPath, "utf8"));
82630
82709
  return typeof raw.id === "string" ? raw.id : void 0;
82631
82710
  } catch {
82632
82711
  return void 0;
@@ -82649,7 +82728,7 @@ function expandHome(p) {
82649
82728
  return p;
82650
82729
  }
82651
82730
  function makeTempDir(prefix) {
82652
- return fs55.mkdtempSync(path63.join(os20.tmpdir(), prefix));
82731
+ return fs56.mkdtempSync(path63.join(os20.tmpdir(), prefix));
82653
82732
  }
82654
82733
  function manifestNames(config2) {
82655
82734
  return config2.manifestFiles.join(" or ");
@@ -82668,7 +82747,7 @@ function isLocalBundleDir(dir, repoPath, config2) {
82668
82747
  function resolvePathSpec(spec, repoPath, config2) {
82669
82748
  const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
82670
82749
  const dir = path63.resolve(expandHome(raw));
82671
- if (!fs55.existsSync(dir) || !fs55.statSync(dir).isDirectory()) {
82750
+ if (!fs56.existsSync(dir) || !fs56.statSync(dir).isDirectory()) {
82672
82751
  throw new Error(`${config2.label} path not found: ${spec}`);
82673
82752
  }
82674
82753
  if (!hasManifest(dir, config2)) {
@@ -82692,19 +82771,19 @@ function resolveNpmSpec(spec, config2) {
82692
82771
  stdio: ["ignore", "pipe", "pipe"],
82693
82772
  timeout: 12e4
82694
82773
  });
82695
- const tarballs = fs55.readdirSync(tmp).filter((f2) => f2.endsWith(".tgz"));
82774
+ const tarballs = fs56.readdirSync(tmp).filter((f2) => f2.endsWith(".tgz"));
82696
82775
  if (tarballs.length === 0) {
82697
82776
  throw new Error(`npm pack produced no tarball for ${spec}`);
82698
82777
  }
82699
82778
  const extractDir = path63.join(tmp, "extract");
82700
- fs55.mkdirSync(extractDir);
82779
+ fs56.mkdirSync(extractDir);
82701
82780
  (0, import_child_process16.execFileSync)("tar", ["-xzf", path63.join(tmp, tarballs[0]), "-C", extractDir], {
82702
82781
  encoding: "utf8",
82703
82782
  stdio: ["ignore", "pipe", "pipe"]
82704
82783
  });
82705
82784
  let dir = path63.join(extractDir, "package");
82706
82785
  if (!hasManifest(dir, config2)) {
82707
- const nested = fs55.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path63.join(extractDir, e.name)).find((d) => hasManifest(d, config2));
82786
+ const nested = fs56.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path63.join(extractDir, e.name)).find((d) => hasManifest(d, config2));
82708
82787
  if (!nested) {
82709
82788
  throw new Error(
82710
82789
  `npm package ${spec} has no ${manifestNames(config2)} (not a HAR ${config2.label} bundle)`
@@ -82722,7 +82801,7 @@ function resolveNpmSpec(spec, config2) {
82722
82801
  };
82723
82802
  } catch (err) {
82724
82803
  for (const d of cleanupDirs) {
82725
- fs55.rmSync(d, { recursive: true, force: true });
82804
+ fs56.rmSync(d, { recursive: true, force: true });
82726
82805
  }
82727
82806
  const message = err instanceof Error ? err.message : String(err);
82728
82807
  throw new Error(`Failed to install ${config2.label} from npm (${spec}): ${message}`);
@@ -82751,8 +82830,8 @@ function resolveGitSpec(spec, config2) {
82751
82830
  let dir = cloneDir;
82752
82831
  if (!hasManifest(dir, config2)) {
82753
82832
  const nestedRoot = path63.join(cloneDir, config2.gitNestedDir);
82754
- if (fs55.existsSync(nestedRoot)) {
82755
- const child = fs55.readdirSync(nestedRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path63.join(nestedRoot, e.name)).find((d) => hasManifest(d, config2));
82833
+ if (fs56.existsSync(nestedRoot)) {
82834
+ const child = fs56.readdirSync(nestedRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path63.join(nestedRoot, e.name)).find((d) => hasManifest(d, config2));
82756
82835
  if (child) dir = child;
82757
82836
  }
82758
82837
  }
@@ -82771,7 +82850,7 @@ function resolveGitSpec(spec, config2) {
82771
82850
  };
82772
82851
  } catch (err) {
82773
82852
  for (const d of cleanupDirs) {
82774
- fs55.rmSync(d, { recursive: true, force: true });
82853
+ fs56.rmSync(d, { recursive: true, force: true });
82775
82854
  }
82776
82855
  const message = err instanceof Error ? err.message : String(err);
82777
82856
  throw new Error(`Failed to install ${config2.label} from git (${spec}): ${message}`);
@@ -82828,17 +82907,17 @@ function resolveBundleSource(spec, repoPath, config2) {
82828
82907
  }
82829
82908
  function listTemplateBundleIds(config2) {
82830
82909
  const root = path63.join(resolveTemplatesDir(), config2.templatesSubdir);
82831
- if (!fs55.existsSync(root)) return [];
82832
- return fs55.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path63.join(root, name), config2)).sort();
82910
+ if (!fs56.existsSync(root)) return [];
82911
+ return fs56.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path63.join(root, name), config2)).sort();
82833
82912
  }
82834
82913
  function listLocalBundleIds(repoPath, config2) {
82835
82914
  const root = path63.resolve(repoPath, config2.localDir);
82836
- if (!fs55.existsSync(root)) return [];
82837
- return fs55.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path63.join(root, name), config2)).sort();
82915
+ if (!fs56.existsSync(root)) return [];
82916
+ return fs56.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path63.join(root, name), config2)).sort();
82838
82917
  }
82839
82918
  function cleanupResolvedBundle(source) {
82840
82919
  for (const dir of source.cleanupDirs) {
82841
- fs55.rmSync(dir, { recursive: true, force: true });
82920
+ fs56.rmSync(dir, { recursive: true, force: true });
82842
82921
  }
82843
82922
  }
82844
82923
 
@@ -82880,7 +82959,7 @@ function cleanupResolvedPlugin(source) {
82880
82959
  }
82881
82960
 
82882
82961
  // src/harness/plugin-prompt.ts
82883
- var fs56 = __toESM(require("fs"));
82962
+ var fs57 = __toESM(require("fs"));
82884
82963
  var path64 = __toESM(require("path"));
82885
82964
  init_paths();
82886
82965
  init_file_ops();
@@ -82897,7 +82976,7 @@ function loadTemplate() {
82897
82976
  "Plugin adaptation prompt template not found: adaptation-prompt-plugin.md. Run npm run build."
82898
82977
  );
82899
82978
  }
82900
- return fs56.readFileSync(filePath, "utf8");
82979
+ return fs57.readFileSync(filePath, "utf8");
82901
82980
  }
82902
82981
  function resolveInstallCommand(repoPath) {
82903
82982
  const env3 = readHarnessEnv(repoPath);
@@ -82978,7 +83057,7 @@ function primaryStageId(manifest) {
82978
83057
  }
82979
83058
  function resolveBundledPluginDir(pluginId) {
82980
83059
  const dir = path65.join(resolveTemplatesDir(), "plugins", pluginId);
82981
- if (!fs57.existsSync(dir)) {
83060
+ if (!fs58.existsSync(dir)) {
82982
83061
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
82983
83062
  }
82984
83063
  return dir;
@@ -82988,7 +83067,7 @@ function readPluginManifestFromDir(pluginDir, expectedId) {
82988
83067
  if (!manifestPath) {
82989
83068
  throw new Error(`No template.manifest.json in ${pluginDir}`);
82990
83069
  }
82991
- const raw = JSON.parse(fs57.readFileSync(manifestPath, "utf8"));
83070
+ const raw = JSON.parse(fs58.readFileSync(manifestPath, "utf8"));
82992
83071
  if (raw.kind === LINE_BUNDLE_KIND || path65.basename(manifestPath) === "line.manifest.json") {
82993
83072
  throw new Error(
82994
83073
  `${path65.basename(manifestPath)} declares "kind": "line" \u2014 this is a factory line bundle, not a verification plugin. Install it with: har line add <spec>`
@@ -83008,39 +83087,39 @@ function readPluginManifest(pluginId) {
83008
83087
  }
83009
83088
  function ensureParentDir(filePath) {
83010
83089
  const parent = path65.dirname(filePath);
83011
- if (!fs57.existsSync(parent)) {
83012
- fs57.mkdirSync(parent, { recursive: true });
83090
+ if (!fs58.existsSync(parent)) {
83091
+ fs58.mkdirSync(parent, { recursive: true });
83013
83092
  }
83014
83093
  }
83015
83094
  function copyPluginFile(pluginDir, file, repoPath, force) {
83016
83095
  const srcPath = path65.join(pluginDir, file.src);
83017
83096
  const destPath = path65.join(repoPath, file.dest);
83018
- if (!fs57.existsSync(srcPath)) {
83097
+ if (!fs58.existsSync(srcPath)) {
83019
83098
  throw new Error(`Plugin file missing: ${file.src}`);
83020
83099
  }
83021
- if (fs57.existsSync(destPath) && !force) {
83100
+ if (fs58.existsSync(destPath) && !force) {
83022
83101
  throw new Error(
83023
83102
  `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
83024
83103
  );
83025
83104
  }
83026
83105
  ensureParentDir(destPath);
83027
- fs57.copyFileSync(srcPath, destPath);
83106
+ fs58.copyFileSync(srcPath, destPath);
83028
83107
  if (file.executable) {
83029
- fs57.chmodSync(destPath, 493);
83108
+ fs58.chmodSync(destPath, 493);
83030
83109
  }
83031
83110
  return { written: true, path: file.dest };
83032
83111
  }
83033
83112
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
83034
83113
  const packagePath = path65.join(repoPath, "package.json");
83035
- if (!fs57.existsSync(packagePath)) {
83114
+ if (!fs58.existsSync(packagePath)) {
83036
83115
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
83037
83116
  }
83038
83117
  const fragmentPath = path65.join(pluginDir, fragmentRelPath);
83039
- if (!fs57.existsSync(fragmentPath)) {
83118
+ if (!fs58.existsSync(fragmentPath)) {
83040
83119
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
83041
83120
  }
83042
- const pkg = JSON.parse(fs57.readFileSync(packagePath, "utf8"));
83043
- const fragment = JSON.parse(fs57.readFileSync(fragmentPath, "utf8"));
83121
+ const pkg = JSON.parse(fs58.readFileSync(packagePath, "utf8"));
83122
+ const fragment = JSON.parse(fs58.readFileSync(fragmentPath, "utf8"));
83044
83123
  for (const section of ["scripts", "devDependencies"]) {
83045
83124
  const existing = pkg[section] ?? {};
83046
83125
  const incoming = fragment[section] ?? {};
@@ -83053,7 +83132,7 @@ function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
83053
83132
  }
83054
83133
  pkg[section] = existing;
83055
83134
  }
83056
- fs57.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
83135
+ fs58.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
83057
83136
  }
83058
83137
  function patchStageRegistry(repoPath, stages, verificationStageIds, force) {
83059
83138
  const registry2 = readStageRegistry(repoPath);
@@ -83090,7 +83169,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
83090
83169
  const registry2 = readStageRegistry(repoPath);
83091
83170
  for (const stageId of stageIds) {
83092
83171
  const scriptPath = path65.join(repoPath, ".har", "stages", `${stageId}.sh`);
83093
- if (fs57.existsSync(scriptPath)) {
83172
+ if (fs58.existsSync(scriptPath)) {
83094
83173
  throw new Error(
83095
83174
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
83096
83175
  );
@@ -83123,7 +83202,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
83123
83202
  if (file.skipFlag === "skipCi" && options.skipCi) {
83124
83203
  continue;
83125
83204
  }
83126
- if (fs57.existsSync(path65.join(resolved, file.dest)) && !force) {
83205
+ if (fs58.existsSync(path65.join(resolved, file.dest)) && !force) {
83127
83206
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
83128
83207
  continue;
83129
83208
  }
@@ -83205,7 +83284,7 @@ function detectInstalledPlugins(repoPath) {
83205
83284
  return ledger.plugins.map((p) => p.id).sort();
83206
83285
  }
83207
83286
  const registryPath = path66.join(resolved, ".har", "stages.json");
83208
- if (!fs58.existsSync(registryPath)) return [];
83287
+ if (!fs59.existsSync(registryPath)) return [];
83209
83288
  const registry2 = readStageRegistry(resolved);
83210
83289
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
83211
83290
  const installed = [];
@@ -83227,13 +83306,13 @@ function resolvePluginBaseline(repoPath, pluginId) {
83227
83306
  const entry = ledger?.plugins.find((p) => p.id === pluginId);
83228
83307
  if (entry?.source === "local") {
83229
83308
  const localDir = path66.join(resolved, LOCAL_PLUGINS_DIR, pluginId);
83230
- if (fs58.existsSync(path66.join(localDir, "template.manifest.json"))) {
83309
+ if (fs59.existsSync(path66.join(localDir, "template.manifest.json"))) {
83231
83310
  return { kind: "local", dir: localDir, manifest: readPluginManifestFromDir(localDir) };
83232
83311
  }
83233
83312
  return null;
83234
83313
  }
83235
83314
  const bundled = path66.join(resolveTemplatesDir(), "plugins", pluginId);
83236
- if (fs58.existsSync(path66.join(bundled, "template.manifest.json"))) {
83315
+ if (fs59.existsSync(path66.join(bundled, "template.manifest.json"))) {
83237
83316
  return { kind: "bundled", dir: bundled, manifest: readPluginManifestFromDir(bundled) };
83238
83317
  }
83239
83318
  return null;
@@ -83246,14 +83325,14 @@ function requireBaseline(repoPath, pluginId) {
83246
83325
  return baseline;
83247
83326
  }
83248
83327
  function readBaselineFile(baseline, srcRel) {
83249
- return fs58.readFileSync(path66.join(baseline.dir, srcRel), "utf8");
83328
+ return fs59.readFileSync(path66.join(baseline.dir, srcRel), "utf8");
83250
83329
  }
83251
83330
  function listPluginDestPaths(baseline, repoPath) {
83252
83331
  const manifest = baseline.manifest;
83253
83332
  const paths = manifest.files.map((file) => file.dest);
83254
83333
  if (manifest.optionalFiles) {
83255
83334
  for (const file of manifest.optionalFiles) {
83256
- if (fs58.existsSync(path66.join(repoPath, file.dest))) {
83335
+ if (fs59.existsSync(path66.join(repoPath, file.dest))) {
83257
83336
  paths.push(file.dest);
83258
83337
  }
83259
83338
  }
@@ -83313,8 +83392,8 @@ function readTemplatePluginFile(repoPath, pluginId, dest) {
83313
83392
  }
83314
83393
  function readInstalledPluginFile(repoPath, pluginId, dest) {
83315
83394
  const installedPath = path66.join(path66.resolve(repoPath), dest);
83316
- if (!fs58.existsSync(installedPath)) return null;
83317
- const content = fs58.readFileSync(installedPath, "utf8");
83395
+ if (!fs59.existsSync(installedPath)) return null;
83396
+ const content = fs59.readFileSync(installedPath, "utf8");
83318
83397
  const baseline = requireBaseline(repoPath, pluginId);
83319
83398
  const fragmentRel = baseline.manifest.merge?.[dest];
83320
83399
  if (fragmentRel) {
@@ -83356,7 +83435,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
83356
83435
  if (dest === "package.json") {
83357
83436
  const fragmentRel = manifest.merge?.[dest];
83358
83437
  const installedPath = path66.join(resolved, dest);
83359
- const installedRaw = fs58.readFileSync(installedPath, "utf8");
83438
+ const installedRaw = fs59.readFileSync(installedPath, "utf8");
83360
83439
  if (fragmentRel && pluginKeysMatch(installedRaw, readBaselineFile(baseline, fragmentRel))) {
83361
83440
  unchanged.push(dest);
83362
83441
  } else if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
@@ -83456,12 +83535,12 @@ function actionHint(file, kind) {
83456
83535
  return `Upstream template updated since your last finalize \u2014 read maintain/diffs/${file}.diff and apply into .har/${file}.`;
83457
83536
  }
83458
83537
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
83459
- const tmpDir = fs59.mkdtempSync(path67.join(os21.tmpdir(), "har-maintain-diff-"));
83538
+ const tmpDir = fs60.mkdtempSync(path67.join(os21.tmpdir(), "har-maintain-diff-"));
83460
83539
  try {
83461
83540
  const installedPath = path67.join(tmpDir, "installed");
83462
83541
  const templatePath = path67.join(tmpDir, "template");
83463
- fs59.writeFileSync(installedPath, installedContent);
83464
- fs59.writeFileSync(templatePath, templateContent);
83542
+ fs60.writeFileSync(installedPath, installedContent);
83543
+ fs60.writeFileSync(templatePath, templateContent);
83465
83544
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
83466
83545
  const body = result.stdout.trim();
83467
83546
  if (!body) return "";
@@ -83470,7 +83549,7 @@ function createUnifiedDiff(installedContent, templateContent, installedLabel, te
83470
83549
  ${body.split("\n").slice(2).join("\n")}
83471
83550
  `;
83472
83551
  } finally {
83473
- fs59.rmSync(tmpDir, { recursive: true, force: true });
83552
+ fs60.rmSync(tmpDir, { recursive: true, force: true });
83474
83553
  }
83475
83554
  }
83476
83555
  function buildActions(repoPath, profile, drift) {
@@ -83494,7 +83573,7 @@ function buildActions(repoPath, profile, drift) {
83494
83573
  file,
83495
83574
  kind,
83496
83575
  template: `maintain/templates/${file}`,
83497
- installed: fs59.existsSync(installedPath) ? `maintain/installed/${file}` : void 0,
83576
+ installed: fs60.existsSync(installedPath) ? `maintain/installed/${file}` : void 0,
83498
83577
  diff: `maintain/diffs/${file}.diff`,
83499
83578
  hint: actionHint(file, kind)
83500
83579
  });
@@ -83666,8 +83745,8 @@ function buildReadme(report) {
83666
83745
  function writeBundleArtifacts(repoPath, profile, drift, report) {
83667
83746
  const harnessDir = getHarnessDir(repoPath);
83668
83747
  const bundleDir = path67.join(harnessDir, MAINTAIN_DIR);
83669
- if (fs59.existsSync(bundleDir)) {
83670
- fs59.rmSync(bundleDir, { recursive: true, force: true });
83748
+ if (fs60.existsSync(bundleDir)) {
83749
+ fs60.rmSync(bundleDir, { recursive: true, force: true });
83671
83750
  }
83672
83751
  const dirs = [
83673
83752
  bundleDir,
@@ -83677,15 +83756,15 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
83677
83756
  path67.join(bundleDir, "stale")
83678
83757
  ];
83679
83758
  for (const dir of dirs) {
83680
- fs59.mkdirSync(dir, { recursive: true });
83759
+ fs60.mkdirSync(dir, { recursive: true });
83681
83760
  }
83682
83761
  const affectedFiles = [...drift.missing, ...drift.upstreamUpdated, ...drift.conflict];
83683
83762
  for (const file of affectedFiles) {
83684
83763
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
83685
83764
  writeFileSafe(path67.join(bundleDir, "templates", file), templateContent);
83686
83765
  const harnessPath = path67.join(harnessDir, file);
83687
- if (fs59.existsSync(harnessPath)) {
83688
- const installedContent = fs59.readFileSync(harnessPath, "utf8");
83766
+ if (fs60.existsSync(harnessPath)) {
83767
+ const installedContent = fs60.readFileSync(harnessPath, "utf8");
83689
83768
  writeFileSafe(path67.join(bundleDir, "installed", file), installedContent);
83690
83769
  const diff = createUnifiedDiff(
83691
83770
  installedContent,
@@ -83719,8 +83798,8 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
83719
83798
  }
83720
83799
  function ensureParentDir2(filePath) {
83721
83800
  const parent = path67.dirname(filePath);
83722
- if (!fs59.existsSync(parent)) {
83723
- fs59.mkdirSync(parent, { recursive: true });
83801
+ if (!fs60.existsSync(parent)) {
83802
+ fs60.mkdirSync(parent, { recursive: true });
83724
83803
  }
83725
83804
  }
83726
83805
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
@@ -83731,7 +83810,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
83731
83810
  const installedDir = path67.join(pluginRoot, "installed");
83732
83811
  const diffsDir = path67.join(pluginRoot, "diffs");
83733
83812
  for (const dir of [templatesDir, installedDir, diffsDir]) {
83734
- fs59.mkdirSync(dir, { recursive: true });
83813
+ fs60.mkdirSync(dir, { recursive: true });
83735
83814
  }
83736
83815
  const templateContent = readTemplatePluginFile(repoPath, action.pluginId, action.file);
83737
83816
  if (templateContent === null) continue;
@@ -83787,8 +83866,8 @@ function buildMaintainBundle(repoPath, validation2, drift) {
83787
83866
  }
83788
83867
  function removeMaintainBundle(repoPath) {
83789
83868
  const bundleDir = path67.join(getHarnessDir(repoPath), MAINTAIN_DIR);
83790
- if (fs59.existsSync(bundleDir)) {
83791
- fs59.rmSync(bundleDir, { recursive: true, force: true });
83869
+ if (fs60.existsSync(bundleDir)) {
83870
+ fs60.rmSync(bundleDir, { recursive: true, force: true });
83792
83871
  }
83793
83872
  }
83794
83873
  function formatMaintainBundlePromptSection(report) {
@@ -83897,7 +83976,7 @@ init_manifest();
83897
83976
  init_stages();
83898
83977
 
83899
83978
  // src/harness/doctor.ts
83900
- var fs64 = __toESM(require("fs"));
83979
+ var fs65 = __toESM(require("fs"));
83901
83980
  var path73 = __toESM(require("path"));
83902
83981
  init_package_version();
83903
83982
  init_slot_registry();
@@ -83914,7 +83993,7 @@ function compareSemver(a, b2) {
83914
83993
  }
83915
83994
 
83916
83995
  // src/harness/eject.ts
83917
- var fs60 = __toESM(require("fs"));
83996
+ var fs61 = __toESM(require("fs"));
83918
83997
  var path68 = __toESM(require("path"));
83919
83998
  init_package_version();
83920
83999
  init_manifest();
@@ -83922,7 +84001,7 @@ var EJECTED_RUNTIME_DIR = "runtime";
83922
84001
  var EJECTED_RUNTIME_BUNDLE = "har.cjs";
83923
84002
  function resolveRuntimeBundleSource() {
83924
84003
  if (process.env.HAR_EJECT_RUNTIME_SOURCE) {
83925
- return fs60.existsSync(process.env.HAR_EJECT_RUNTIME_SOURCE) ? process.env.HAR_EJECT_RUNTIME_SOURCE : null;
84004
+ return fs61.existsSync(process.env.HAR_EJECT_RUNTIME_SOURCE) ? process.env.HAR_EJECT_RUNTIME_SOURCE : null;
83926
84005
  }
83927
84006
  const candidates = [
83928
84007
  // Bundled CLI: __dirname is dist/ and index.js is the self-contained runtime.
@@ -83931,7 +84010,7 @@ function resolveRuntimeBundleSource() {
83931
84010
  path68.resolve(__dirname, "..", "..", "dist", "index.js")
83932
84011
  ];
83933
84012
  for (const candidate of candidates) {
83934
- if (fs60.existsSync(candidate)) return candidate;
84013
+ if (fs61.existsSync(candidate)) return candidate;
83935
84014
  }
83936
84015
  return null;
83937
84016
  }
@@ -83973,11 +84052,11 @@ function ejectHarness(repoPath) {
83973
84052
  }
83974
84053
  const version2 = getHarPackageVersion();
83975
84054
  const runtimeDir = path68.join(harnessDir, EJECTED_RUNTIME_DIR);
83976
- fs60.mkdirSync(runtimeDir, { recursive: true });
84055
+ fs61.mkdirSync(runtimeDir, { recursive: true });
83977
84056
  const runtimeFile = path68.join(runtimeDir, EJECTED_RUNTIME_BUNDLE);
83978
- fs60.copyFileSync(bundleSource, runtimeFile);
83979
- fs60.chmodSync(runtimeFile, 493);
83980
- fs60.writeFileSync(path68.join(runtimeDir, "README.md"), RUNTIME_README(version2));
84057
+ fs61.copyFileSync(bundleSource, runtimeFile);
84058
+ fs61.chmodSync(runtimeFile, 493);
84059
+ fs61.writeFileSync(path68.join(runtimeDir, "README.md"), RUNTIME_README(version2));
83981
84060
  retireLifecycleShims(resolved);
83982
84061
  writeManifest(resolved, {
83983
84062
  ...manifest,
@@ -83998,7 +84077,7 @@ function adoptHarness(repoPath) {
83998
84077
  if (!manifest.ejected) {
83999
84078
  throw new Error("Harness is not ejected \u2014 the packaged runtime is already in use.");
84000
84079
  }
84001
- fs60.rmSync(path68.join(harnessDir, EJECTED_RUNTIME_DIR), { recursive: true, force: true });
84080
+ fs61.rmSync(path68.join(harnessDir, EJECTED_RUNTIME_DIR), { recursive: true, force: true });
84002
84081
  const retired = retireLifecycleShims(resolved);
84003
84082
  const rest = { ...manifest };
84004
84083
  delete rest.ejected;
@@ -84016,7 +84095,7 @@ init_env();
84016
84095
  init_manifest();
84017
84096
 
84018
84097
  // src/harness/line-ledger.ts
84019
- var fs61 = __toESM(require("fs"));
84098
+ var fs62 = __toESM(require("fs"));
84020
84099
  var path69 = __toESM(require("path"));
84021
84100
  init_file_ops();
84022
84101
  init_manifest();
@@ -84026,9 +84105,9 @@ function getLineLedgerPath(repoPath) {
84026
84105
  }
84027
84106
  function readLineLedger(repoPath) {
84028
84107
  const ledgerPath = getLineLedgerPath(repoPath);
84029
- if (!fs61.existsSync(ledgerPath)) return null;
84108
+ if (!fs62.existsSync(ledgerPath)) return null;
84030
84109
  try {
84031
- const parsed = LineLedgerSchema.safeParse(JSON.parse(fs61.readFileSync(ledgerPath, "utf8")));
84110
+ const parsed = LineLedgerSchema.safeParse(JSON.parse(fs62.readFileSync(ledgerPath, "utf8")));
84032
84111
  return parsed.success ? parsed.data : null;
84033
84112
  } catch {
84034
84113
  return null;
@@ -84037,8 +84116,8 @@ function readLineLedger(repoPath) {
84037
84116
  function writeLineLedger(repoPath, ledger) {
84038
84117
  const ledgerPath = getLineLedgerPath(repoPath);
84039
84118
  const harnessDir = path69.dirname(ledgerPath);
84040
- if (!fs61.existsSync(harnessDir)) {
84041
- fs61.mkdirSync(harnessDir, { recursive: true });
84119
+ if (!fs62.existsSync(harnessDir)) {
84120
+ fs62.mkdirSync(harnessDir, { recursive: true });
84042
84121
  }
84043
84122
  writeFileSafe(ledgerPath, `${JSON.stringify(ledger, null, 2)}
84044
84123
  `);
@@ -84054,7 +84133,7 @@ function upsertLineLedgerEntry(repoPath, entry) {
84054
84133
  }
84055
84134
 
84056
84135
  // src/harness/lines.ts
84057
- var fs62 = __toESM(require("fs"));
84136
+ var fs63 = __toESM(require("fs"));
84058
84137
  var path71 = __toESM(require("path"));
84059
84138
  init_logging();
84060
84139
 
@@ -84198,7 +84277,7 @@ function readLineManifestFromDir(bundleDir, expectedId) {
84198
84277
  if (!manifestPath) {
84199
84278
  throw new Error(`No ${LINE_MANIFEST_FILES.join(" or ")} in ${bundleDir}`);
84200
84279
  }
84201
- const raw = JSON.parse(fs62.readFileSync(manifestPath, "utf8"));
84280
+ const raw = JSON.parse(fs63.readFileSync(manifestPath, "utf8"));
84202
84281
  if (raw.kind !== LINE_BUNDLE_KIND) {
84203
84282
  throw new Error(
84204
84283
  `${path71.basename(manifestPath)} is not a factory line bundle (missing "kind": "line"). Verification plugins install with: har env add-plugin <spec>`
@@ -84215,10 +84294,10 @@ function readLineManifestFromDir(bundleDir, expectedId) {
84215
84294
  }
84216
84295
  function readLineProgramFromDir(bundleDir, manifest) {
84217
84296
  const programPath = path71.join(bundleDir, manifest.program);
84218
- if (!fs62.existsSync(programPath)) {
84297
+ if (!fs63.existsSync(programPath)) {
84219
84298
  throw new Error(`Line program missing: ${manifest.program} (referenced by line.manifest.json)`);
84220
84299
  }
84221
- const parsed = LineProgramSchema.safeParse(JSON.parse(fs62.readFileSync(programPath, "utf8")));
84300
+ const parsed = LineProgramSchema.safeParse(JSON.parse(fs63.readFileSync(programPath, "utf8")));
84222
84301
  if (!parsed.success) {
84223
84302
  throw new Error(`Invalid line program (${manifest.program}): ${parsed.error.message}`);
84224
84303
  }
@@ -84231,31 +84310,31 @@ function readLineProgramFromDir(bundleDir, manifest) {
84231
84310
  }
84232
84311
  function readInstalledLineProgram(repoPath, lineId) {
84233
84312
  const programPath = path71.join(path71.resolve(repoPath), lineProgramPathRel(lineId));
84234
- if (!fs62.existsSync(programPath)) return null;
84235
- const parsed = LineProgramSchema.safeParse(JSON.parse(fs62.readFileSync(programPath, "utf8")));
84313
+ if (!fs63.existsSync(programPath)) return null;
84314
+ const parsed = LineProgramSchema.safeParse(JSON.parse(fs63.readFileSync(programPath, "utf8")));
84236
84315
  return parsed.success ? parsed.data : null;
84237
84316
  }
84238
84317
  function ensureParentDir3(filePath) {
84239
- fs62.mkdirSync(path71.dirname(filePath), { recursive: true });
84318
+ fs63.mkdirSync(path71.dirname(filePath), { recursive: true });
84240
84319
  }
84241
84320
  function copyBundleFile(bundleDir, file, repoPath, force) {
84242
84321
  const srcPath = path71.join(bundleDir, file.src);
84243
84322
  const destPath = path71.join(repoPath, file.dest);
84244
- if (!fs62.existsSync(srcPath)) {
84323
+ if (!fs63.existsSync(srcPath)) {
84245
84324
  throw new Error(`Line file missing: ${file.src}`);
84246
84325
  }
84247
84326
  if (path71.resolve(srcPath) === path71.resolve(destPath)) {
84248
84327
  return file.dest;
84249
84328
  }
84250
- if (fs62.existsSync(destPath) && !force) {
84329
+ if (fs63.existsSync(destPath) && !force) {
84251
84330
  throw new Error(
84252
84331
  `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
84253
84332
  );
84254
84333
  }
84255
84334
  ensureParentDir3(destPath);
84256
- fs62.copyFileSync(srcPath, destPath);
84335
+ fs63.copyFileSync(srcPath, destPath);
84257
84336
  if (file.executable) {
84258
- fs62.chmodSync(destPath, 493);
84337
+ fs63.chmodSync(destPath, 493);
84259
84338
  }
84260
84339
  return file.dest;
84261
84340
  }
@@ -84314,20 +84393,20 @@ function applyLineFromDir(repoPath, bundleDir, options, meta) {
84314
84393
  const programDest = path71.join(resolved, lineProgramPathRel(manifest.id));
84315
84394
  const programSrc = path71.join(bundleDir, manifest.program);
84316
84395
  if (path71.resolve(programSrc) !== path71.resolve(programDest)) {
84317
- if (fs62.existsSync(programDest) && !force) {
84396
+ if (fs63.existsSync(programDest) && !force) {
84318
84397
  throw new Error(
84319
84398
  `Line already installed: ${lineProgramPathRel(manifest.id)}. Use --force to replace.`
84320
84399
  );
84321
84400
  }
84322
84401
  ensureParentDir3(programDest);
84323
- fs62.copyFileSync(programSrc, programDest);
84402
+ fs63.copyFileSync(programSrc, programDest);
84324
84403
  }
84325
84404
  filesWritten.push(lineProgramPathRel(manifest.id));
84326
84405
  const manifestDest = path71.join(resolved, lineDirRel(manifest.id), "line.manifest.json");
84327
84406
  const manifestSrc = findManifestPath(bundleDir, LINE_BUNDLE_CONFIG);
84328
84407
  if (path71.resolve(manifestSrc) !== path71.resolve(manifestDest)) {
84329
84408
  ensureParentDir3(manifestDest);
84330
- fs62.copyFileSync(manifestSrc, manifestDest);
84409
+ fs63.copyFileSync(manifestSrc, manifestDest);
84331
84410
  filesWritten.push(`${lineDirRel(manifest.id)}/line.manifest.json`);
84332
84411
  }
84333
84412
  registerStagesOnly(resolved, stages, force);
@@ -84408,7 +84487,7 @@ init_stages();
84408
84487
  init_hooks2();
84409
84488
 
84410
84489
  // src/harness/migrations.ts
84411
- var fs63 = __toESM(require("fs"));
84490
+ var fs64 = __toESM(require("fs"));
84412
84491
  var path72 = __toESM(require("path"));
84413
84492
  init_schema2();
84414
84493
  init_manifest();
@@ -84459,24 +84538,24 @@ function harnessEnvIsPre10(content) {
84459
84538
  }
84460
84539
  function scriptIsVendored(harnessDir, script) {
84461
84540
  const file = path72.join(harnessDir, script);
84462
- if (!fs63.existsSync(file)) return false;
84463
- const content = fs63.readFileSync(file, "utf8");
84541
+ if (!fs64.existsSync(file)) return false;
84542
+ const content = fs64.readFileSync(file, "utf8");
84464
84543
  return !content.includes("exec har env") && !content.includes("runtime/har.cjs");
84465
84544
  }
84466
84545
  function isPre10Harness(repoPath) {
84467
84546
  const resolved = path72.resolve(repoPath);
84468
84547
  const harnessDir = getHarnessDir(resolved);
84469
- if (!fs63.existsSync(harnessDir)) return false;
84548
+ if (!fs64.existsSync(harnessDir)) return false;
84470
84549
  const manifest = readManifest(resolved);
84471
84550
  if (manifest?.ejected) return false;
84472
84551
  for (const file of LEGACY_MACHINERY_FILES) {
84473
- if (fs63.existsSync(path72.join(harnessDir, file))) return true;
84552
+ if (fs64.existsSync(path72.join(harnessDir, file))) return true;
84474
84553
  }
84475
84554
  for (const script of MANAGED_SHIM_FILES) {
84476
84555
  if (scriptIsVendored(harnessDir, script)) return true;
84477
84556
  }
84478
84557
  const envPath = path72.join(harnessDir, "harness.env");
84479
- if (fs63.existsSync(envPath) && harnessEnvIsPre10(fs63.readFileSync(envPath, "utf8"))) {
84558
+ if (fs64.existsSync(envPath) && harnessEnvIsPre10(fs64.readFileSync(envPath, "utf8"))) {
84480
84559
  return true;
84481
84560
  }
84482
84561
  return false;
@@ -84621,7 +84700,7 @@ function buildPre10Plan(repoPath) {
84621
84700
  const deleteLifecycleScripts = [];
84622
84701
  const residue = [];
84623
84702
  for (const script of MANAGED_SHIM_FILES) {
84624
- if (!fs63.existsSync(path72.join(harnessDir, script))) continue;
84703
+ if (!fs64.existsSync(path72.join(harnessDir, script))) continue;
84625
84704
  deleteLifecycleScripts.push(script);
84626
84705
  if (scriptIsVendored(harnessDir, script)) {
84627
84706
  const target = SCRIPT_RESIDUE_TARGET[script] ?? "review";
@@ -84636,16 +84715,16 @@ function buildPre10Plan(repoPath) {
84636
84715
  const survivingScripts = [];
84637
84716
  for (const dir of ["stages", "hooks"]) {
84638
84717
  const full = path72.join(harnessDir, dir);
84639
- if (!fs63.existsSync(full)) continue;
84640
- for (const entry of fs63.readdirSync(full)) {
84718
+ if (!fs64.existsSync(full)) continue;
84719
+ for (const entry of fs64.readdirSync(full)) {
84641
84720
  if (entry.endsWith(".sh") || entry.endsWith(".mjs")) survivingScripts.push(path72.join(dir, entry));
84642
84721
  }
84643
84722
  }
84644
- for (const entry of fs63.readdirSync(harnessDir)) {
84723
+ for (const entry of fs64.readdirSync(harnessDir)) {
84645
84724
  if (!entry.endsWith(".sh")) continue;
84646
84725
  if (MANAGED_SHIM_FILES.includes(entry)) continue;
84647
84726
  if (LEGACY_MACHINERY_FILES.includes(entry)) continue;
84648
- if (!fs63.statSync(path72.join(harnessDir, entry)).isFile()) continue;
84727
+ if (!fs64.statSync(path72.join(harnessDir, entry)).isFile()) continue;
84649
84728
  survivingScripts.push(entry);
84650
84729
  }
84651
84730
  const referencedBy = (machineryFile) => {
@@ -84654,12 +84733,12 @@ function buildPre10Plan(repoPath) {
84654
84733
  `(?:\\bsource\\b|\\bbash\\b|\\bexec\\b|(?:^|[;&|(])\\s*\\.\\s)[^\\n#]*${base}`
84655
84734
  );
84656
84735
  return survivingScripts.filter(
84657
- (script) => fs63.readFileSync(path72.join(harnessDir, script), "utf8").split("\n").some((line) => !/^\s*#/.test(line) && loadRe.test(line))
84736
+ (script) => fs64.readFileSync(path72.join(harnessDir, script), "utf8").split("\n").some((line) => !/^\s*#/.test(line) && loadRe.test(line))
84658
84737
  );
84659
84738
  };
84660
84739
  const retireDocs = [];
84661
84740
  for (const doc of RETIRED_DOC_FILES) {
84662
- if (!fs63.existsSync(path72.join(harnessDir, doc))) continue;
84741
+ if (!fs64.existsSync(path72.join(harnessDir, doc))) continue;
84663
84742
  retireDocs.push(doc);
84664
84743
  residue.push({
84665
84744
  source: doc,
@@ -84673,7 +84752,7 @@ function buildPre10Plan(repoPath) {
84673
84752
  const retainMachinery = [];
84674
84753
  for (const file of LEGACY_MACHINERY_FILES) {
84675
84754
  const full = path72.join(harnessDir, file);
84676
- if (!fs63.existsSync(full)) continue;
84755
+ if (!fs64.existsSync(full)) continue;
84677
84756
  const refs = referencedBy(file);
84678
84757
  if (refs.length > 0) {
84679
84758
  retainMachinery.push(file);
@@ -84687,7 +84766,7 @@ function buildPre10Plan(repoPath) {
84687
84766
  }
84688
84767
  deleteMachinery.push(file);
84689
84768
  const recorded = fileBaseline[file];
84690
- const installed = computeFileChecksum(fs63.readFileSync(full, "utf8"));
84769
+ const installed = computeFileChecksum(fs64.readFileSync(full, "utf8"));
84691
84770
  if (recorded !== void 0 && installed !== recorded) {
84692
84771
  editedMachinery.push(file);
84693
84772
  residue.push({
@@ -84700,8 +84779,8 @@ function buildPre10Plan(repoPath) {
84700
84779
  }
84701
84780
  let env3 = null;
84702
84781
  const envPath = path72.join(harnessDir, "harness.env");
84703
- if (fs63.existsSync(envPath)) {
84704
- const content = fs63.readFileSync(envPath, "utf8");
84782
+ if (fs64.existsSync(envPath)) {
84783
+ const content = fs64.readFileSync(envPath, "utf8");
84705
84784
  if (harnessEnvIsPre10(content) || migrateHarnessEnvContent(content).commentedKeys.length > 0) {
84706
84785
  env3 = migrateHarnessEnvContent(content);
84707
84786
  for (const fn of env3.customFunctions) {
@@ -84726,7 +84805,7 @@ function buildPre10Plan(repoPath) {
84726
84805
  for (const file of composed.keys()) {
84727
84806
  if (MANAGED_SHIM_FILES.includes(file)) continue;
84728
84807
  if (file === "gitignore.template") continue;
84729
- if (!fs63.existsSync(path72.join(harnessDir, file))) installMissing.push(file);
84808
+ if (!fs64.existsSync(path72.join(harnessDir, file))) installMissing.push(file);
84730
84809
  }
84731
84810
  let phantomVerificationIds = [];
84732
84811
  try {
@@ -84761,13 +84840,13 @@ function applyPre10Plan(repoPath, plan) {
84761
84840
  const harnessDir = getHarnessDir(resolved);
84762
84841
  const effective = plan ?? buildPre10Plan(resolved);
84763
84842
  const backupDir = path72.join(harnessDir, MIGRATE_BACKUP_DIR);
84764
- fs63.mkdirSync(backupDir, { recursive: true });
84843
+ fs64.mkdirSync(backupDir, { recursive: true });
84765
84844
  const backup = (file) => {
84766
84845
  const src = path72.join(harnessDir, file);
84767
- if (!fs63.existsSync(src)) return;
84846
+ if (!fs64.existsSync(src)) return;
84768
84847
  const dest = path72.join(backupDir, file);
84769
- fs63.mkdirSync(path72.dirname(dest), { recursive: true });
84770
- fs63.copyFileSync(src, dest);
84848
+ fs64.mkdirSync(path72.dirname(dest), { recursive: true });
84849
+ fs64.copyFileSync(src, dest);
84771
84850
  };
84772
84851
  const written = [];
84773
84852
  const deleted = [];
@@ -84775,7 +84854,7 @@ function applyPre10Plan(repoPath, plan) {
84775
84854
  const composed = composeProfileTemplateMap(effective.profile);
84776
84855
  for (const script of effective.deleteLifecycleScripts) {
84777
84856
  backup(script);
84778
- fs63.rmSync(path72.join(harnessDir, script), { force: true });
84857
+ fs64.rmSync(path72.join(harnessDir, script), { force: true });
84779
84858
  deleted.push(script);
84780
84859
  }
84781
84860
  if (stripLifecycleShimCommands(resolved)) {
@@ -84783,26 +84862,26 @@ function applyPre10Plan(repoPath, plan) {
84783
84862
  }
84784
84863
  for (const file of effective.deleteMachinery) {
84785
84864
  backup(file);
84786
- fs63.rmSync(path72.join(harnessDir, file), { force: true });
84865
+ fs64.rmSync(path72.join(harnessDir, file), { force: true });
84787
84866
  deleted.push(file);
84788
84867
  }
84789
84868
  for (const doc of effective.retireDocs ?? []) {
84790
84869
  backup(doc);
84791
84870
  }
84792
84871
  const libDir = path72.join(harnessDir, "lib");
84793
- if (fs63.existsSync(libDir) && fs63.readdirSync(libDir).length === 0) {
84794
- fs63.rmdirSync(libDir);
84872
+ if (fs64.existsSync(libDir) && fs64.readdirSync(libDir).length === 0) {
84873
+ fs64.rmdirSync(libDir);
84795
84874
  deleted.push("lib/");
84796
84875
  }
84797
84876
  for (const file of effective.installMissing ?? []) {
84798
84877
  const source = composed.get(file);
84799
84878
  if (!source) continue;
84800
84879
  const dest = path72.join(harnessDir, file);
84801
- if (fs63.existsSync(dest)) continue;
84880
+ if (fs64.existsSync(dest)) continue;
84802
84881
  const rendered = substituteTemplateTokens(readComposedTemplateContent(source), projectName);
84803
- fs63.mkdirSync(path72.dirname(dest), { recursive: true });
84804
- fs63.writeFileSync(dest, rendered);
84805
- if (/\.(sh|mjs)$/.test(file)) fs63.chmodSync(dest, 493);
84882
+ fs64.mkdirSync(path72.dirname(dest), { recursive: true });
84883
+ fs64.writeFileSync(dest, rendered);
84884
+ if (/\.(sh|mjs)$/.test(file)) fs64.chmodSync(dest, 493);
84806
84885
  written.push(file);
84807
84886
  }
84808
84887
  if (effective.phantomVerificationIds.length > 0) {
@@ -84817,7 +84896,7 @@ function applyPre10Plan(repoPath, plan) {
84817
84896
  }
84818
84897
  if (effective.env) {
84819
84898
  backup("harness.env");
84820
- fs63.writeFileSync(path72.join(harnessDir, "harness.env"), effective.env.content);
84899
+ fs64.writeFileSync(path72.join(harnessDir, "harness.env"), effective.env.content);
84821
84900
  written.push("harness.env");
84822
84901
  }
84823
84902
  const manifest = readManifest(resolved);
@@ -84832,7 +84911,7 @@ function applyPre10Plan(repoPath, plan) {
84832
84911
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
84833
84912
  });
84834
84913
  }
84835
- fs63.writeFileSync(
84914
+ fs64.writeFileSync(
84836
84915
  path72.join(harnessDir, MIGRATE_PLAN_FILE),
84837
84916
  JSON.stringify({ ...effective, appliedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
84838
84917
  );
@@ -84855,25 +84934,25 @@ function pendingMigrations(repoPath) {
84855
84934
  function writeMigrationPlan(repoPath, plan) {
84856
84935
  const harnessDir = getHarnessDir(path72.resolve(repoPath));
84857
84936
  const planPath = path72.join(harnessDir, MIGRATE_PLAN_FILE);
84858
- fs63.mkdirSync(path72.dirname(planPath), { recursive: true });
84859
- fs63.writeFileSync(planPath, JSON.stringify(plan, null, 2) + "\n");
84937
+ fs64.mkdirSync(path72.dirname(planPath), { recursive: true });
84938
+ fs64.writeFileSync(planPath, JSON.stringify(plan, null, 2) + "\n");
84860
84939
  return planPath;
84861
84940
  }
84862
84941
  function removeMigrationArtifacts(repoPath) {
84863
84942
  const harnessDir = getHarnessDir(path72.resolve(repoPath));
84864
- fs63.rmSync(path72.join(harnessDir, MIGRATE_DIR), { recursive: true, force: true });
84865
- fs63.rmSync(path72.join(harnessDir, "MIGRATE-PROMPT.md"), { force: true });
84943
+ fs64.rmSync(path72.join(harnessDir, MIGRATE_DIR), { recursive: true, force: true });
84944
+ fs64.rmSync(path72.join(harnessDir, "MIGRATE-PROMPT.md"), { force: true });
84866
84945
  }
84867
84946
 
84868
84947
  // src/harness/doctor.ts
84869
84948
  function listHarnessShellScripts(harnessDir) {
84870
84949
  const out = [];
84871
84950
  const push = (dir, prefix) => {
84872
- if (!fs64.existsSync(dir)) return;
84873
- for (const entry of fs64.readdirSync(dir).sort()) {
84951
+ if (!fs65.existsSync(dir)) return;
84952
+ for (const entry of fs65.readdirSync(dir).sort()) {
84874
84953
  if (!entry.endsWith(".sh")) continue;
84875
84954
  const full = path73.join(dir, entry);
84876
- if (!fs64.statSync(full).isFile()) continue;
84955
+ if (!fs65.statSync(full).isFile()) continue;
84877
84956
  out.push(prefix ? `${prefix}/${entry}` : entry);
84878
84957
  }
84879
84958
  };
@@ -84900,8 +84979,8 @@ var PRE_1_0_FUNCTION_RE = /^\s*(har_infra_enabled|har_pg|har_node_[a-z_]+|har_pk
84900
84979
  var LEGACY_TRIPLET_RE = /^export\s+HARNESS_[A-Z0-9_]+_PORT_(DEFAULT|SCAN_START|SCAN_END)=/m;
84901
84980
  function detectContract(harnessDir) {
84902
84981
  const envPath = path73.join(harnessDir, "harness.env");
84903
- if (!fs64.existsSync(envPath)) return "none";
84904
- const content = fs64.readFileSync(envPath, "utf8");
84982
+ if (!fs65.existsSync(envPath)) return "none";
84983
+ const content = fs65.readFileSync(envPath, "utf8");
84905
84984
  if (PRE_1_0_FUNCTION_RE.test(content) || LEGACY_TRIPLET_RE.test(content)) {
84906
84985
  return "pre-1.0";
84907
84986
  }
@@ -84934,7 +85013,7 @@ function runDoctor(repoPath) {
84934
85013
  const harnessDir = getHarnessDir(repoPath);
84935
85014
  const findings = [];
84936
85015
  const skipped = /* @__PURE__ */ new Set();
84937
- if (!fs64.existsSync(harnessDir)) {
85016
+ if (!fs65.existsSync(harnessDir)) {
84938
85017
  return {
84939
85018
  ok: false,
84940
85019
  contract: "none",
@@ -85004,8 +85083,8 @@ function runDoctor(repoPath) {
85004
85083
  let registry2 = null;
85005
85084
  try {
85006
85085
  const stagesPath = path73.join(harnessDir, "stages.json");
85007
- if (fs64.existsSync(stagesPath)) {
85008
- const raw = JSON.parse(fs64.readFileSync(stagesPath, "utf8"));
85086
+ if (fs65.existsSync(stagesPath)) {
85087
+ const raw = JSON.parse(fs65.readFileSync(stagesPath, "utf8"));
85009
85088
  if (typeof raw !== "object" || raw === null || !Array.isArray(raw.stages)) {
85010
85089
  throw new Error("stages.json has no `stages` array \u2014 the registry is structurally invalid");
85011
85090
  }
@@ -85037,7 +85116,7 @@ function runDoctor(repoPath) {
85037
85116
  const file = resolveStageFile(harnessDir, stage);
85038
85117
  if (!file) continue;
85039
85118
  const rel = path73.relative(harnessDir, file);
85040
- if (!fs64.existsSync(file)) {
85119
+ if (!fs65.existsSync(file)) {
85041
85120
  findings.push({
85042
85121
  check: "stage-files",
85043
85122
  severity: contractSeverity,
@@ -85047,7 +85126,7 @@ function runDoctor(repoPath) {
85047
85126
  });
85048
85127
  continue;
85049
85128
  }
85050
- if (rel.endsWith(".sh") && !(fs64.statSync(file).mode & 73)) {
85129
+ if (rel.endsWith(".sh") && !(fs65.statSync(file).mode & 73)) {
85051
85130
  findings.push({
85052
85131
  check: "stage-files",
85053
85132
  severity: "warning",
@@ -85070,7 +85149,7 @@ function runDoctor(repoPath) {
85070
85149
  continue;
85071
85150
  }
85072
85151
  const file = resolveStageFile(harnessDir, stage);
85073
- if (file && !fs64.existsSync(file)) {
85152
+ if (file && !fs65.existsSync(file)) {
85074
85153
  findings.push({
85075
85154
  check: "lifecycle-stages",
85076
85155
  severity: contractSeverity,
@@ -85123,7 +85202,7 @@ function runDoctor(repoPath) {
85123
85202
  } else {
85124
85203
  const runtimeRel = path73.join(EJECTED_RUNTIME_DIR, EJECTED_RUNTIME_BUNDLE);
85125
85204
  const runtimePath = path73.join(harnessDir, runtimeRel);
85126
- if (!fs64.existsSync(runtimePath)) {
85205
+ if (!fs65.existsSync(runtimePath)) {
85127
85206
  findings.push({
85128
85207
  check: "ejected-runtime",
85129
85208
  severity: "error",
@@ -85136,7 +85215,7 @@ function runDoctor(repoPath) {
85136
85215
  for (const entry of listSlotRegistryEntries(repoPath)) {
85137
85216
  if (entry.status === "completed") continue;
85138
85217
  const dir = entry.worktreePath ?? entry.workDir;
85139
- if (dir && !fs64.existsSync(dir)) {
85218
+ if (dir && !fs65.existsSync(dir)) {
85140
85219
  findings.push({
85141
85220
  check: "slot-registry",
85142
85221
  severity: "warning",
@@ -85147,10 +85226,10 @@ function runDoctor(repoPath) {
85147
85226
  }
85148
85227
  }
85149
85228
  const hooksDir = path73.join(harnessDir, "hooks");
85150
- if (fs64.existsSync(hooksDir)) {
85151
- for (const file of fs64.readdirSync(hooksDir).sort()) {
85229
+ if (fs65.existsSync(hooksDir)) {
85230
+ for (const file of fs65.readdirSync(hooksDir).sort()) {
85152
85231
  const full = path73.join(hooksDir, file);
85153
- if (!fs64.statSync(full).isFile() || !file.endsWith(".sh")) continue;
85232
+ if (!fs65.statSync(full).isFile() || !file.endsWith(".sh")) continue;
85154
85233
  if (!LIFECYCLE_HOOKS.includes(file.replace(/\.sh$/, ""))) {
85155
85234
  findings.push({
85156
85235
  check: "hooks",
@@ -85161,7 +85240,7 @@ function runDoctor(repoPath) {
85161
85240
  });
85162
85241
  continue;
85163
85242
  }
85164
- if (!(fs64.statSync(full).mode & 73)) {
85243
+ if (!(fs65.statSync(full).mode & 73)) {
85165
85244
  findings.push({
85166
85245
  check: "hooks",
85167
85246
  severity: "warning",
@@ -85176,12 +85255,12 @@ function runDoctor(repoPath) {
85176
85255
  const full = path73.join(harnessDir, rel);
85177
85256
  let content;
85178
85257
  try {
85179
- content = fs64.readFileSync(full, "utf8");
85258
+ content = fs65.readFileSync(full, "utf8");
85180
85259
  } catch {
85181
85260
  continue;
85182
85261
  }
85183
85262
  for (const machinery of LEGACY_MACHINERY_FILES) {
85184
- if (fs64.existsSync(path73.join(harnessDir, machinery))) continue;
85263
+ if (fs65.existsSync(path73.join(harnessDir, machinery))) continue;
85185
85264
  const base = machinery.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
85186
85265
  const loadRe = new RegExp(
85187
85266
  `(?:\\bsource\\b|\\bbash\\b|\\bexec\\b|(?:^|[;&|(])\\s*\\.\\s)[^\\n#]*${base}`
@@ -85285,7 +85364,7 @@ function summarizeDoctorReport(report) {
85285
85364
  }
85286
85365
 
85287
85366
  // src/harness/migrate-prompt.ts
85288
- var fs65 = __toESM(require("fs"));
85367
+ var fs66 = __toESM(require("fs"));
85289
85368
  var path74 = __toESM(require("path"));
85290
85369
  init_paths();
85291
85370
  init_file_ops();
@@ -85400,7 +85479,7 @@ function loadTemplate2() {
85400
85479
  if (!filePath) {
85401
85480
  throw new Error("Migration prompt template not found: migration-prompt.md. Run npm run build.");
85402
85481
  }
85403
- return fs65.readFileSync(filePath, "utf8");
85482
+ return fs66.readFileSync(filePath, "utf8");
85404
85483
  }
85405
85484
  function buildMigrationPrompt(plan, applied) {
85406
85485
  return loadTemplate2().replace("{{MIGRATION_SECTION}}", buildMigrationSection(plan, applied));
@@ -85414,8 +85493,8 @@ function writeMigrationPrompt(repoPath, content) {
85414
85493
  // src/core/harness.ts
85415
85494
  function listHarnessScripts(repoPath) {
85416
85495
  const harnessDir = getHarnessDir(repoPath);
85417
- if (!fs66.existsSync(harnessDir)) return [];
85418
- return fs66.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
85496
+ if (!fs67.existsSync(harnessDir)) return [];
85497
+ return fs67.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
85419
85498
  }
85420
85499
  function describeProject(repoPath) {
85421
85500
  const resolved = path75.resolve(repoPath);
@@ -85439,7 +85518,7 @@ function describeProject(repoPath) {
85439
85518
  }
85440
85519
  async function initHarness(options) {
85441
85520
  const repoPath = path75.resolve(options.repoPath);
85442
- if (!fs66.existsSync(repoPath)) {
85521
+ if (!fs67.existsSync(repoPath)) {
85443
85522
  throw new Error(`Path not found: ${repoPath}`);
85444
85523
  }
85445
85524
  const scaffold = scaffoldHarnessBoilerplate(repoPath, {
@@ -85462,7 +85541,7 @@ async function initHarness(options) {
85462
85541
  async function maintainHarness(options) {
85463
85542
  const repoPath = path75.resolve(options.repoPath);
85464
85543
  const harnessDir = getHarnessDir(repoPath);
85465
- if (!fs66.existsSync(harnessDir)) {
85544
+ if (!fs67.existsSync(harnessDir)) {
85466
85545
  throw new Error('No .har/ found. Run "har onboard" first.');
85467
85546
  }
85468
85547
  let migration;
@@ -85540,7 +85619,7 @@ function addPlugin(repoPath, pluginId, options = {}) {
85540
85619
  }
85541
85620
 
85542
85621
  // src/harness/adaptation-prompt.ts
85543
- var fs67 = __toESM(require("fs"));
85622
+ var fs68 = __toESM(require("fs"));
85544
85623
  var path76 = __toESM(require("path"));
85545
85624
  var readline5 = __toESM(require("readline"));
85546
85625
 
@@ -85632,7 +85711,7 @@ function loadTemplate3(name) {
85632
85711
  if (!filePath) {
85633
85712
  throw new Error(`Adaptation prompt template not found: ${name}. Run npm run build.`);
85634
85713
  }
85635
- return fs67.readFileSync(filePath, "utf8");
85714
+ return fs68.readFileSync(filePath, "utf8");
85636
85715
  }
85637
85716
  function applyProfilePlaceholders(content, profile) {
85638
85717
  return content.replace(/\{\{PROFILE\}\}/g, profile).replace(/\{\{PROFILE_HINT\}\}/g, PROFILE_HINTS[profile]);
@@ -85710,7 +85789,7 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
85710
85789
  }
85711
85790
 
85712
85791
  // src/harness/cursor-rule.ts
85713
- var fs68 = __toESM(require("fs"));
85792
+ var fs69 = __toESM(require("fs"));
85714
85793
  var path77 = __toESM(require("path"));
85715
85794
  var readline6 = __toESM(require("readline"));
85716
85795
  init_file_ops();
@@ -85721,17 +85800,17 @@ function getCursorRulePath(repoPath) {
85721
85800
  return path77.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
85722
85801
  }
85723
85802
  function isCursorWorkspace(repoPath) {
85724
- return fs68.existsSync(path77.join(repoPath, ".cursor"));
85803
+ return fs69.existsSync(path77.join(repoPath, ".cursor"));
85725
85804
  }
85726
85805
  function cursorRuleExists(repoPath) {
85727
- return fs68.existsSync(getCursorRulePath(repoPath));
85806
+ return fs69.existsSync(getCursorRulePath(repoPath));
85728
85807
  }
85729
85808
  function scaffoldCursorRule(repoPath) {
85730
85809
  const templatePath = resolveTemplateFile("cursor-rule.mdc.template");
85731
85810
  if (!templatePath) {
85732
85811
  throw new Error("Cursor rule template not found (cursor-rule.mdc.template). Run npm run build.");
85733
85812
  }
85734
- const content = fs68.readFileSync(templatePath, "utf8");
85813
+ const content = fs69.readFileSync(templatePath, "utf8");
85735
85814
  writeFileSafe(getCursorRulePath(repoPath), content);
85736
85815
  }
85737
85816
  async function handleCursorRule(options) {
@@ -86564,7 +86643,7 @@ init_work_units();
86564
86643
  init_manifest();
86565
86644
 
86566
86645
  // src/core/cleanup-service.ts
86567
- var fs70 = __toESM(require("fs"));
86646
+ var fs71 = __toESM(require("fs"));
86568
86647
  var os23 = __toESM(require("os"));
86569
86648
  var path81 = __toESM(require("path"));
86570
86649
  var import_child_process20 = require("child_process");
@@ -86663,7 +86742,7 @@ function classifySlotCandidate(repoPath, projectName, slot, options) {
86663
86742
  return candidate;
86664
86743
  }
86665
86744
  function resolveRepoForWorktree(worktreePath) {
86666
- if (!fs70.existsSync(worktreePath)) return void 0;
86745
+ if (!fs71.existsSync(worktreePath)) return void 0;
86667
86746
  const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
86668
86747
  if (!commonDir) return void 0;
86669
86748
  const gitRoot = path81.resolve(worktreePath, commonDir, "..");
@@ -86672,9 +86751,9 @@ function resolveRepoForWorktree(worktreePath) {
86672
86751
  }
86673
86752
  function discoverOrphanWorktrees(knownPaths) {
86674
86753
  const worktreesRoot = getWorktreesRoot();
86675
- if (!fs70.existsSync(worktreesRoot)) return [];
86754
+ if (!fs71.existsSync(worktreesRoot)) return [];
86676
86755
  const orphans = [];
86677
- for (const entry of fs70.readdirSync(worktreesRoot, { withFileTypes: true })) {
86756
+ for (const entry of fs71.readdirSync(worktreesRoot, { withFileTypes: true })) {
86678
86757
  if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
86679
86758
  const worktreePath = path81.resolve(path81.join(worktreesRoot, entry.name));
86680
86759
  if (knownPaths.has(worktreePath)) continue;
@@ -86701,7 +86780,7 @@ async function discoverCleanupCandidates(options = {}) {
86701
86780
  const candidates = [];
86702
86781
  const knownWorktreePaths = /* @__PURE__ */ new Set();
86703
86782
  for (const repoPath of repoPaths) {
86704
- if (!fs70.existsSync(repoPath) || !readManifest(repoPath)) continue;
86783
+ if (!fs71.existsSync(repoPath) || !readManifest(repoPath)) continue;
86705
86784
  const harnessRoot = resolveHarnessRoot(repoPath);
86706
86785
  const canonicalRepo = canonicalizeControlRepoPath(harnessRoot);
86707
86786
  const status = collectEnvironmentStatus(harnessRoot);
@@ -86814,7 +86893,7 @@ async function executeCleanupCandidates(candidates, options = {}) {
86814
86893
  continue;
86815
86894
  }
86816
86895
  if (candidate.kind === "orphan_worktree" && candidate.worktreePath) {
86817
- if (fs70.existsSync(candidate.worktreePath)) {
86896
+ if (fs71.existsSync(candidate.worktreePath)) {
86818
86897
  const repoRoot = candidate.repoPath !== getWorktreesRoot() ? candidate.repoPath : resolveRepoForWorktree(candidate.worktreePath);
86819
86898
  if (repoRoot) {
86820
86899
  try {
@@ -86825,8 +86904,8 @@ async function executeCleanupCandidates(candidates, options = {}) {
86825
86904
  } catch {
86826
86905
  }
86827
86906
  }
86828
- if (fs70.existsSync(candidate.worktreePath)) {
86829
- fs70.rmSync(candidate.worktreePath, { recursive: true, force: true });
86907
+ if (fs71.existsSync(candidate.worktreePath)) {
86908
+ fs71.rmSync(candidate.worktreePath, { recursive: true, force: true });
86830
86909
  }
86831
86910
  }
86832
86911
  outcomes.push({ candidate, ok: true });
@@ -86972,7 +87051,7 @@ function warnIfDockerUnavailable(status = detectDockerStatus()) {
86972
87051
  }
86973
87052
 
86974
87053
  // src/core/onboarding-preferences.ts
86975
- var fs71 = __toESM(require("fs"));
87054
+ var fs72 = __toESM(require("fs"));
86976
87055
  var os24 = __toESM(require("os"));
86977
87056
  var path82 = __toESM(require("path"));
86978
87057
  init_schema2();
@@ -86985,8 +87064,8 @@ function getOnboardingPreferencesPath() {
86985
87064
  function readOnboardingPreferences() {
86986
87065
  const preferencePath = getOnboardingPreferencesPath();
86987
87066
  try {
86988
- if (!fs71.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
86989
- return OnboardingPreferencesSchema.parse(JSON.parse(fs71.readFileSync(preferencePath, "utf8")));
87067
+ if (!fs72.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
87068
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs72.readFileSync(preferencePath, "utf8")));
86990
87069
  } catch {
86991
87070
  return OnboardingPreferencesSchema.parse({});
86992
87071
  }
@@ -87011,8 +87090,8 @@ function writeOnboardingPreferences(overrides) {
87011
87090
  };
87012
87091
  const parsed = OnboardingPreferencesSchema.parse(preference);
87013
87092
  const preferencePath = getOnboardingPreferencesPath();
87014
- fs71.mkdirSync(path82.dirname(preferencePath), { recursive: true });
87015
- fs71.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
87093
+ fs72.mkdirSync(path82.dirname(preferencePath), { recursive: true });
87094
+ fs72.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
87016
87095
  `);
87017
87096
  return parsed;
87018
87097
  }
@@ -87640,7 +87719,7 @@ async function handleAddPlugin(argv) {
87640
87719
  console.error(` Docs: ${result.docsPath}`);
87641
87720
  console.error("");
87642
87721
  info(`Adaptation prompt saved to ${result.adaptPromptPath}`);
87643
- const promptContent = fs72.readFileSync(path83.join(repoPath, result.adaptPromptPath), "utf8");
87722
+ const promptContent = fs73.readFileSync(path83.join(repoPath, result.adaptPromptPath), "utf8");
87644
87723
  await offerAdaptationPromptClipboard(promptContent, { fileLabel: result.adaptPromptPath });
87645
87724
  } catch (err) {
87646
87725
  error(err.message);
@@ -88185,7 +88264,7 @@ init_portal_targets();
88185
88264
  init_control_config();
88186
88265
 
88187
88266
  // src/core/portal-connect.ts
88188
- var fs73 = __toESM(require("fs"));
88267
+ var fs74 = __toESM(require("fs"));
88189
88268
  var path84 = __toESM(require("path"));
88190
88269
  var import_crypto2 = require("crypto");
88191
88270
  init_control_repo_path();
@@ -88356,7 +88435,7 @@ function remainingConnections(connections, usedAliases) {
88356
88435
  init_portal_targets();
88357
88436
  function attachRepoIfPresent(alias, repoPath) {
88358
88437
  const resolved = path84.resolve(repoPath ?? ".");
88359
- if (!fs73.existsSync(resolved)) return null;
88438
+ if (!fs74.existsSync(resolved)) return null;
88360
88439
  const canonical = canonicalizeControlRepoPath(resolved);
88361
88440
  attachRepoPortalTarget(canonical, alias);
88362
88441
  recordRepoForControlSync(canonical);
@@ -88424,7 +88503,7 @@ async function runPortalConnect(input) {
88424
88503
  }
88425
88504
  function listRegisteredReposForConnect(repoPath) {
88426
88505
  const resolved = repoPath ? path84.resolve(repoPath) : null;
88427
- const current = resolved && fs73.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
88506
+ const current = resolved && fs74.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
88428
88507
  return [.../* @__PURE__ */ new Set([...current ? [current] : [], ...listRegisteredRepos()])];
88429
88508
  }
88430
88509
 
@@ -88740,7 +88819,7 @@ init_control_port();
88740
88819
  init_control_sync();
88741
88820
 
88742
88821
  // src/core/control-sync-selection.ts
88743
- var fs74 = __toESM(require("fs"));
88822
+ var fs75 = __toESM(require("fs"));
88744
88823
  var os25 = __toESM(require("os"));
88745
88824
  var path85 = __toESM(require("path"));
88746
88825
  init_control_repo_path();
@@ -88753,8 +88832,8 @@ function getSelectionPath() {
88753
88832
  function readSyncSelection() {
88754
88833
  const selectionPath = getSelectionPath();
88755
88834
  try {
88756
- if (!fs74.existsSync(selectionPath)) return null;
88757
- const parsed = JSON.parse(fs74.readFileSync(selectionPath, "utf8"));
88835
+ if (!fs75.existsSync(selectionPath)) return null;
88836
+ const parsed = JSON.parse(fs75.readFileSync(selectionPath, "utf8"));
88758
88837
  if (!Array.isArray(parsed.repos)) return null;
88759
88838
  return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
88760
88839
  } catch {
@@ -88764,8 +88843,8 @@ function readSyncSelection() {
88764
88843
  function writeSyncSelection(repos) {
88765
88844
  const selectionPath = getSelectionPath();
88766
88845
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
88767
- fs74.mkdirSync(path85.dirname(selectionPath), { recursive: true });
88768
- fs74.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
88846
+ fs75.mkdirSync(path85.dirname(selectionPath), { recursive: true });
88847
+ fs75.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
88769
88848
  }
88770
88849
  function resolveSyncSelection(input) {
88771
88850
  const { discovered, stored, forceSelect, isTTY } = input;
@@ -88792,7 +88871,7 @@ function resolveSyncSelection(input) {
88792
88871
  }
88793
88872
 
88794
88873
  // src/core/control-unregister.ts
88795
- var fs75 = __toESM(require("fs"));
88874
+ var fs76 = __toESM(require("fs"));
88796
88875
  var path86 = __toESM(require("path"));
88797
88876
  init_control_repo_path();
88798
88877
  init_control_registry();
@@ -88805,7 +88884,7 @@ function listUnregisterWorktreeCandidates(repoPath) {
88805
88884
  const add = (partial2) => {
88806
88885
  const resolved = path86.resolve(partial2.worktreePath);
88807
88886
  if (!resolved || resolved === harnessRoot) return;
88808
- const exists = partial2.exists ?? fs75.existsSync(resolved);
88887
+ const exists = partial2.exists ?? fs76.existsSync(resolved);
88809
88888
  const prev = byPath.get(resolved);
88810
88889
  if (prev) {
88811
88890
  byPath.set(resolved, {
@@ -88919,28 +88998,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
88919
88998
  trigger: "cli"
88920
88999
  });
88921
89000
  if (result.code !== 0) {
88922
- if (fs75.existsSync(candidate.worktreePath)) {
88923
- fs75.rmSync(candidate.worktreePath, { recursive: true, force: true });
89001
+ if (fs76.existsSync(candidate.worktreePath)) {
89002
+ fs76.rmSync(candidate.worktreePath, { recursive: true, force: true });
88924
89003
  }
88925
89004
  }
88926
89005
  outcomes.push({
88927
89006
  path: candidate.worktreePath,
88928
89007
  agentId: candidate.agentId,
88929
- deleted: !fs75.existsSync(candidate.worktreePath),
88930
- error: result.code !== 0 && fs75.existsSync(candidate.worktreePath) ? result.stderr : void 0
89008
+ deleted: !fs76.existsSync(candidate.worktreePath),
89009
+ error: result.code !== 0 && fs76.existsSync(candidate.worktreePath) ? result.stderr : void 0
88931
89010
  });
88932
89011
  } catch (err) {
88933
89012
  const message = err instanceof Error ? err.message : String(err);
88934
89013
  try {
88935
- if (fs75.existsSync(candidate.worktreePath)) {
88936
- fs75.rmSync(candidate.worktreePath, { recursive: true, force: true });
89014
+ if (fs76.existsSync(candidate.worktreePath)) {
89015
+ fs76.rmSync(candidate.worktreePath, { recursive: true, force: true });
88937
89016
  }
88938
89017
  } catch {
88939
89018
  }
88940
89019
  outcomes.push({
88941
89020
  path: candidate.worktreePath,
88942
89021
  agentId: candidate.agentId,
88943
- deleted: !fs75.existsSync(candidate.worktreePath),
89022
+ deleted: !fs76.existsSync(candidate.worktreePath),
88944
89023
  error: message
88945
89024
  });
88946
89025
  }
@@ -89003,13 +89082,13 @@ init_control_config();
89003
89082
  init_control_registry();
89004
89083
 
89005
89084
  // src/core/harness-scrub.ts
89006
- var fs76 = __toESM(require("fs"));
89085
+ var fs77 = __toESM(require("fs"));
89007
89086
  var path87 = __toESM(require("path"));
89008
89087
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "commit-bindings", "state", "slots"];
89009
89088
  function scrubLocalHarnessDirs(repoPath) {
89010
89089
  const results = [];
89011
89090
  const resolved = path87.resolve(repoPath);
89012
- if (!fs76.existsSync(resolved)) {
89091
+ if (!fs77.existsSync(resolved)) {
89013
89092
  for (const directory of HARNESS_SCRUB_DIRS) {
89014
89093
  results.push({
89015
89094
  path: path87.join(resolved, ".har", directory),
@@ -89022,23 +89101,23 @@ function scrubLocalHarnessDirs(repoPath) {
89022
89101
  }
89023
89102
  for (const directory of HARNESS_SCRUB_DIRS) {
89024
89103
  const target = path87.join(resolved, ".har", directory);
89025
- if (!fs76.existsSync(target)) {
89104
+ if (!fs77.existsSync(target)) {
89026
89105
  results.push({ path: target, directory, deleted: true });
89027
89106
  continue;
89028
89107
  }
89029
89108
  try {
89030
- fs76.rmSync(target, { recursive: true, force: true });
89109
+ fs77.rmSync(target, { recursive: true, force: true });
89031
89110
  results.push({
89032
89111
  path: target,
89033
89112
  directory,
89034
- deleted: !fs76.existsSync(target),
89035
- error: fs76.existsSync(target) ? "failed to remove directory" : void 0
89113
+ deleted: !fs77.existsSync(target),
89114
+ error: fs77.existsSync(target) ? "failed to remove directory" : void 0
89036
89115
  });
89037
89116
  } catch (err) {
89038
89117
  results.push({
89039
89118
  path: target,
89040
89119
  directory,
89041
- deleted: !fs76.existsSync(target),
89120
+ deleted: !fs77.existsSync(target),
89042
89121
  error: err instanceof Error ? err.message : String(err)
89043
89122
  });
89044
89123
  }
@@ -89725,7 +89804,7 @@ var path90 = __toESM(require("path"));
89725
89804
  init_hooks();
89726
89805
 
89727
89806
  // src/core/claude-hooks.ts
89728
- var fs77 = __toESM(require("fs"));
89807
+ var fs78 = __toESM(require("fs"));
89729
89808
  var path89 = __toESM(require("path"));
89730
89809
  init_paths();
89731
89810
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
@@ -89738,8 +89817,8 @@ function isHarGuardEntry(entry) {
89738
89817
  );
89739
89818
  }
89740
89819
  function readSettings(settingsPath) {
89741
- if (!fs77.existsSync(settingsPath)) return {};
89742
- const raw = fs77.readFileSync(settingsPath, "utf8").trim();
89820
+ if (!fs78.existsSync(settingsPath)) return {};
89821
+ const raw = fs78.readFileSync(settingsPath, "utf8").trim();
89743
89822
  if (raw === "") return {};
89744
89823
  const parsed = JSON.parse(raw);
89745
89824
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -89748,8 +89827,8 @@ function readSettings(settingsPath) {
89748
89827
  return parsed;
89749
89828
  }
89750
89829
  function writeSettings(settingsPath, settings) {
89751
- fs77.mkdirSync(path89.dirname(settingsPath), { recursive: true });
89752
- fs77.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
89830
+ fs78.mkdirSync(path89.dirname(settingsPath), { recursive: true });
89831
+ fs78.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
89753
89832
  }
89754
89833
  function installClaudeGuard(repoPath) {
89755
89834
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
@@ -89757,9 +89836,9 @@ function installClaudeGuard(repoPath) {
89757
89836
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
89758
89837
  }
89759
89838
  const guardScript = path89.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
89760
- fs77.mkdirSync(path89.dirname(guardScript), { recursive: true });
89761
- fs77.copyFileSync(templatePath, guardScript);
89762
- fs77.chmodSync(guardScript, 493);
89839
+ fs78.mkdirSync(path89.dirname(guardScript), { recursive: true });
89840
+ fs78.copyFileSync(templatePath, guardScript);
89841
+ fs78.chmodSync(guardScript, 493);
89763
89842
  const settingsPath = path89.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
89764
89843
  const settings = readSettings(settingsPath);
89765
89844
  const hooks = settings.hooks ?? {};
@@ -89775,14 +89854,14 @@ function installClaudeGuard(repoPath) {
89775
89854
  function uninstallClaudeGuard(repoPath) {
89776
89855
  let removed = false;
89777
89856
  const guardScript = path89.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
89778
- if (fs77.existsSync(guardScript)) {
89779
- fs77.rmSync(guardScript);
89857
+ if (fs78.existsSync(guardScript)) {
89858
+ fs78.rmSync(guardScript);
89780
89859
  removed = true;
89781
89860
  const parent = path89.dirname(guardScript);
89782
- if (fs77.existsSync(parent) && fs77.readdirSync(parent).length === 0) fs77.rmdirSync(parent);
89861
+ if (fs78.existsSync(parent) && fs78.readdirSync(parent).length === 0) fs78.rmdirSync(parent);
89783
89862
  }
89784
89863
  const settingsPath = path89.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
89785
- if (fs77.existsSync(settingsPath)) {
89864
+ if (fs78.existsSync(settingsPath)) {
89786
89865
  const settings = readSettings(settingsPath);
89787
89866
  const preToolUse = settings.hooks?.PreToolUse;
89788
89867
  if (preToolUse) {
@@ -89808,7 +89887,7 @@ function uninstallClaudeGuard(repoPath) {
89808
89887
  }
89809
89888
  function claudeGuardInstalled(repoPath) {
89810
89889
  const settingsPath = path89.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
89811
- if (!fs77.existsSync(settingsPath)) return false;
89890
+ if (!fs78.existsSync(settingsPath)) return false;
89812
89891
  try {
89813
89892
  const settings = readSettings(settingsPath);
89814
89893
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -97050,13 +97129,13 @@ init_runs();
97050
97129
  var path92 = __toESM(require("path"));
97051
97130
 
97052
97131
  // src/harness/line-create.ts
97053
- var fs78 = __toESM(require("fs"));
97132
+ var fs79 = __toESM(require("fs"));
97054
97133
  var path91 = __toESM(require("path"));
97055
97134
  init_paths();
97056
97135
  init_schema2();
97057
97136
  var LINE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
97058
97137
  function renderSkeleton(templatePath, tokens) {
97059
- let content = fs78.readFileSync(templatePath, "utf8");
97138
+ let content = fs79.readFileSync(templatePath, "utf8");
97060
97139
  for (const [token, value] of Object.entries(tokens)) {
97061
97140
  content = content.replace(new RegExp(token, "g"), value);
97062
97141
  }
@@ -97075,7 +97154,7 @@ function createLine(repoPath, options) {
97075
97154
  }
97076
97155
  const lineDir = path91.join(resolved, LOCAL_LINES_DIR, id);
97077
97156
  const lineDirRel2 = `${LOCAL_LINES_DIR}/${id}`;
97078
- if (fs78.existsSync(lineDir) && !options.force) {
97157
+ if (fs79.existsSync(lineDir) && !options.force) {
97079
97158
  throw new Error(`Line already exists: ${lineDirRel2}/. Use --force to overwrite.`);
97080
97159
  }
97081
97160
  const stationIds = options.stations?.length ? options.stations : ["S1", "S2"];
@@ -97149,9 +97228,9 @@ function createLine(repoPath, options) {
97149
97228
  const filesWritten = [];
97150
97229
  const write = (rel, content, executable = false) => {
97151
97230
  const abs = path91.join(lineDir, rel);
97152
- fs78.mkdirSync(path91.dirname(abs), { recursive: true });
97153
- fs78.writeFileSync(abs, content);
97154
- if (executable) fs78.chmodSync(abs, 493);
97231
+ fs79.mkdirSync(path91.dirname(abs), { recursive: true });
97232
+ fs79.writeFileSync(abs, content);
97233
+ if (executable) fs79.chmodSync(abs, 493);
97155
97234
  filesWritten.push(`${lineDirRel2}/${rel}`);
97156
97235
  };
97157
97236
  write("line.manifest.json", `${JSON.stringify(manifest, null, 2)}
@@ -99224,13 +99303,13 @@ var lineCommand = {
99224
99303
  var path98 = __toESM(require("path"));
99225
99304
 
99226
99305
  // src/harness/plugin-create.ts
99227
- var fs79 = __toESM(require("fs"));
99306
+ var fs80 = __toESM(require("fs"));
99228
99307
  var path97 = __toESM(require("path"));
99229
99308
  init_paths();
99230
99309
  init_schema2();
99231
99310
  var PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
99232
99311
  function renderSkeleton2(templatePath, tokens) {
99233
- let content = fs79.readFileSync(templatePath, "utf8");
99312
+ let content = fs80.readFileSync(templatePath, "utf8");
99234
99313
  for (const [token, value] of Object.entries(tokens)) {
99235
99314
  content = content.replace(new RegExp(token, "g"), value);
99236
99315
  }
@@ -99255,7 +99334,7 @@ function createLocalPlugin(repoPath, options) {
99255
99334
  }
99256
99335
  const pluginDir = path97.join(resolved, LOCAL_PLUGINS_DIR, id);
99257
99336
  const pluginDirRel = `${LOCAL_PLUGINS_DIR}/${id}`;
99258
- if (fs79.existsSync(pluginDir) && !options.force) {
99337
+ if (fs80.existsSync(pluginDir) && !options.force) {
99259
99338
  throw new Error(`Plugin already exists: ${pluginDirRel}/. Use --force to overwrite.`);
99260
99339
  }
99261
99340
  const description = options.description ?? `Custom ${kind} stage (local plugin: ${id})`;
@@ -99298,9 +99377,9 @@ function createLocalPlugin(repoPath, options) {
99298
99377
  const filesWritten = [];
99299
99378
  const write = (rel, content, executable = false) => {
99300
99379
  const abs = path97.join(pluginDir, rel);
99301
- fs79.mkdirSync(path97.dirname(abs), { recursive: true });
99302
- fs79.writeFileSync(abs, content);
99303
- if (executable) fs79.chmodSync(abs, 493);
99380
+ fs80.mkdirSync(path97.dirname(abs), { recursive: true });
99381
+ fs80.writeFileSync(abs, content);
99382
+ if (executable) fs80.chmodSync(abs, 493);
99304
99383
  filesWritten.push(`${pluginDirRel}/${rel}`);
99305
99384
  };
99306
99385
  write("template.manifest.json", `${JSON.stringify(manifest, null, 2)}
@@ -99800,16 +99879,16 @@ async function runCli() {
99800
99879
  }
99801
99880
 
99802
99881
  // src/core/prefer-local-runtime.ts
99803
- var fs80 = __toESM(require("fs"));
99882
+ var fs81 = __toESM(require("fs"));
99804
99883
  var path100 = __toESM(require("path"));
99805
99884
  var import_child_process22 = require("child_process");
99806
99885
  init_package_version();
99807
99886
  var PACKAGE_NAME = "@osfactory/har";
99808
99887
  function readPackageJson(dir) {
99809
99888
  const pkgPath = path100.join(dir, "package.json");
99810
- if (!fs80.existsSync(pkgPath)) return null;
99889
+ if (!fs81.existsSync(pkgPath)) return null;
99811
99890
  try {
99812
- return JSON.parse(fs80.readFileSync(pkgPath, "utf8"));
99891
+ return JSON.parse(fs81.readFileSync(pkgPath, "utf8"));
99813
99892
  } catch {
99814
99893
  return null;
99815
99894
  }
@@ -99823,11 +99902,11 @@ function resolveHarEntry(pkgDir, pkg) {
99823
99902
  rel = pkg.bin;
99824
99903
  }
99825
99904
  const entry = path100.resolve(pkgDir, rel);
99826
- return fs80.existsSync(entry) ? entry : null;
99905
+ return fs81.existsSync(entry) ? entry : null;
99827
99906
  }
99828
99907
  function sameFile(a, b2) {
99829
99908
  try {
99830
- return fs80.realpathSync(a) === fs80.realpathSync(b2);
99909
+ return fs81.realpathSync(a) === fs81.realpathSync(b2);
99831
99910
  } catch {
99832
99911
  return path100.resolve(a) === path100.resolve(b2);
99833
99912
  }