@osfactory/har 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/index.js +815 -820
  2. package/dist/templates/AGENTS.md.template +1 -1
  3. package/dist/templates/adaptation-prompt-init.md +18 -23
  4. package/dist/templates/adaptation-prompt-maintain.md +1 -1
  5. package/dist/templates/adaptation-prompt-plugin.md +1 -1
  6. package/dist/templates/agent-skills/factory-line.md +96 -0
  7. package/dist/templates/agent-skills/har-wt.md +1 -1
  8. package/dist/templates/agent-skills/setup-har.md +4 -4
  9. package/dist/templates/agent-skills/skills.manifest.json +13 -0
  10. package/dist/templates/har-boilerplate/harness.env +1 -1
  11. package/dist/templates/har-boilerplate/justfile +11 -12
  12. package/dist/templates/har-boilerplate/stages.json +3 -9
  13. package/dist/templates/har-boilerplate-cli/harness.env +1 -1
  14. package/dist/templates/har-boilerplate-cli/justfile +9 -10
  15. package/dist/templates/har-boilerplate-cli/stages.json +2 -7
  16. package/dist/templates/har-boilerplate-ios/harness.env +1 -1
  17. package/dist/templates/har-boilerplate-ios/justfile +9 -10
  18. package/dist/templates/har-boilerplate-ios/stages.json +3 -8
  19. package/dist/templates/migration-prompt.md +2 -2
  20. package/dist/templates/plugins/custom-stage-skeleton.sh +2 -2
  21. package/dist/templates/plugins/gitleaks/.har/stages/secrets-scan.sh +2 -2
  22. package/dist/templates/plugins/gitleaks/template.manifest.json +1 -1
  23. package/dist/templates/plugins/kerno/.github/workflows/kerno.yml +1 -1
  24. package/dist/templates/plugins/kerno/.har/stages/KERNO.md +2 -2
  25. package/dist/templates/plugins/kerno/.har/stages/backend-validation.sh +3 -3
  26. package/dist/templates/plugins/kerno/README.md +2 -2
  27. package/dist/templates/plugins/kerno/template.manifest.json +1 -1
  28. package/dist/templates/plugins/playwright/.har/stages/PLAYWRIGHT.md +2 -2
  29. package/dist/templates/plugins/playwright/.har/stages/browser-e2e.sh +3 -3
  30. package/dist/templates/plugins/playwright/README.md +1 -1
  31. package/dist/templates/plugins/playwright/playwright.config.js +2 -2
  32. package/dist/templates/plugins/playwright/template.manifest.json +1 -1
  33. package/dist/templates/plugins/rocketsim/.har/stages/ROCKETSIM.md +1 -1
  34. package/dist/templates/plugins/rocketsim/.har/stages/rocketsim-flows.sh +3 -3
  35. package/dist/templates/plugins/rocketsim/README.md +1 -1
  36. package/dist/templates/plugins/rocketsim/flows/example-smoke.sh +1 -1
  37. package/dist/templates/plugins/rocketsim/template.manifest.json +1 -1
  38. package/dist/templates/plugins/semgrep/.har/stages/SEMGREP.md +1 -1
  39. package/dist/templates/plugins/semgrep/.har/stages/sast.sh +3 -3
  40. package/dist/templates/plugins/semgrep/README.md +2 -2
  41. package/dist/templates/plugins/semgrep/template.manifest.json +1 -1
  42. package/dist/templates/plugins/trivy/.har/stages/TRIVY.md +1 -1
  43. package/dist/templates/plugins/trivy/.har/stages/vuln-scan.sh +3 -3
  44. package/dist/templates/plugins/trivy/template.manifest.json +1 -1
  45. package/dist/templates/profiles/cli/docs/readme/quick-start.md +2 -3
  46. package/dist/templates/profiles/cli/docs/readme/verification-contract.md +3 -3
  47. package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +1 -2
  48. package/dist/templates/profiles/default/docs/readme/quick-start.md +2 -3
  49. package/dist/templates/profiles/default/docs/readme/verification-contract.md +3 -3
  50. package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +1 -2
  51. package/dist/templates/profiles/ios/docs/readme/quick-start.md +2 -3
  52. package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +1 -2
  53. package/dist/templates/runtime-bundles/shared-kernel/STAGES.md +1 -1
  54. package/dist/templates/runtime-bundles/shared-kernel/lib/verify-runner.mjs +1 -1
  55. package/dist/templates/shared-docs/readme/maintaining-this-harness.md +3 -3
  56. package/package.json +1 -1
  57. package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +0 -53
  58. package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +0 -52
  59. package/dist/templates/runtime-bundles/shared-kernel/launch.sh +0 -52
  60. package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +0 -52
  61. package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +0 -52
  62. package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +0 -52
  63. package/dist/templates/runtime-bundles/shared-kernel/verify.sh +0 -52
package/dist/index.js CHANGED
@@ -593,8 +593,8 @@ var init_parseUtil = __esm({
593
593
  init_errors();
594
594
  init_en();
595
595
  makeIssue = (params) => {
596
- const { data, path: path90, errorMaps, issueData } = params;
597
- const fullPath = [...path90, ...issueData.path || []];
596
+ const { data, path: path91, errorMaps, issueData } = params;
597
+ const fullPath = [...path91, ...issueData.path || []];
598
598
  const fullIssue = {
599
599
  ...issueData,
600
600
  path: fullPath
@@ -902,11 +902,11 @@ var init_types = __esm({
902
902
  init_parseUtil();
903
903
  init_util();
904
904
  ParseInputLazyPath = class {
905
- constructor(parent, value, path90, key) {
905
+ constructor(parent, value, path91, key) {
906
906
  this._cachedPath = [];
907
907
  this.parent = parent;
908
908
  this.data = value;
909
- this._path = path90;
909
+ this._path = path91;
910
910
  this._key = key;
911
911
  }
912
912
  get path() {
@@ -28802,49 +28802,42 @@ function getStageRegistryPath(repoPath) {
28802
28802
  return path6.join(getHarnessDir(repoPath), STAGE_REGISTRY_FILE);
28803
28803
  }
28804
28804
  function synthesizeStageRegistry(repoPath) {
28805
- const harnessDir = getHarnessDir(repoPath);
28806
28805
  const stages = [];
28807
- addStageIfRunnable(stages, harnessDir, {
28806
+ addKindDispatchedStage(stages, {
28808
28807
  id: "setup-infra",
28809
28808
  kind: "setup",
28810
28809
  description: "Start shared harness infrastructure.",
28811
- command: "./.har/setup-infra.sh",
28812
28810
  requiresAgentId: false
28813
28811
  });
28814
- addStageIfRunnable(stages, harnessDir, {
28812
+ addKindDispatchedStage(stages, {
28815
28813
  id: "launch",
28816
28814
  kind: "launch",
28817
28815
  description: "Launch an isolated agent environment slot.",
28818
- command: "./.har/launch.sh {agentId}",
28819
28816
  requiresAgentId: true
28820
28817
  });
28821
- addStageIfRunnable(stages, harnessDir, {
28818
+ addKindDispatchedStage(stages, {
28822
28819
  id: "verify",
28823
28820
  kind: "verify",
28824
28821
  description: "Run the project verification pipeline.",
28825
- command: "./.har/verify.sh {agentId}",
28826
28822
  requiresAgentId: true,
28827
28823
  acceptsArgs: ["--full"]
28828
28824
  });
28829
- addStageIfRunnable(stages, harnessDir, {
28825
+ addKindDispatchedStage(stages, {
28830
28826
  id: "status",
28831
28827
  kind: "inspect",
28832
28828
  description: "Inspect a running agent environment slot.",
28833
- command: "./.har/agent-cli.sh {agentId} status",
28834
28829
  requiresAgentId: true
28835
28830
  });
28836
- addStageIfRunnable(stages, harnessDir, {
28831
+ addKindDispatchedStage(stages, {
28837
28832
  id: "logs",
28838
28833
  kind: "inspect",
28839
28834
  description: "Read recent logs for an agent slot.",
28840
- command: "./.har/agent-cli.sh {agentId} logs",
28841
28835
  requiresAgentId: true
28842
28836
  });
28843
- addStageIfRunnable(stages, harnessDir, {
28837
+ addKindDispatchedStage(stages, {
28844
28838
  id: "teardown",
28845
28839
  kind: "teardown",
28846
28840
  description: "Tear down an isolated agent environment slot.",
28847
- command: "./.har/teardown.sh {agentId}",
28848
28841
  requiresAgentId: true
28849
28842
  });
28850
28843
  const harnessEnv = readHarnessEnv(repoPath);
@@ -28872,21 +28865,8 @@ function readAgentSlotsFromHarnessEnv(harnessEnv) {
28872
28865
  }
28873
28866
  return { min, max };
28874
28867
  }
28875
- function stageScriptExists(harnessDir, stage) {
28876
- if (stage.script) {
28877
- return fs6.existsSync(path6.join(harnessDir, stage.script));
28878
- }
28879
- if (stage.command) {
28880
- const scriptName = stage.command.split(/\s+/)[0].replace(/^\.\/\.har\//, "").replace(/^\.\//, "");
28881
- return fs6.existsSync(path6.join(harnessDir, scriptName));
28882
- }
28883
- return fs6.existsSync(path6.join(harnessDir, "stages", `${stage.id}.sh`));
28884
- }
28885
- function addStageIfRunnable(stages, harnessDir, stage) {
28886
- const parsed = HarnessStageSchema.parse(stage);
28887
- if (stageScriptExists(harnessDir, parsed)) {
28888
- stages.push(parsed);
28889
- }
28868
+ function addKindDispatchedStage(stages, stage) {
28869
+ stages.push(HarnessStageSchema.parse(stage));
28890
28870
  }
28891
28871
  function readStageRegistry(repoPath) {
28892
28872
  const registryPath = getStageRegistryPath(repoPath);
@@ -29063,7 +29043,7 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
29063
29043
  const stream = options.stream ?? false;
29064
29044
  const echoStdout = stream && (options.streamStdout ?? true);
29065
29045
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
29066
- return new Promise((resolve59) => {
29046
+ return new Promise((resolve60) => {
29067
29047
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
29068
29048
  ...spawnOptions,
29069
29049
  stdio: ["inherit", "pipe", "pipe"]
@@ -29078,14 +29058,14 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
29078
29058
  stderr += d;
29079
29059
  if (stream) process.stderr.write(d);
29080
29060
  });
29081
- proc.on("close", (code) => resolve59({ stdout, stderr, code: code ?? 0 }));
29061
+ proc.on("close", (code) => resolve60({ stdout, stderr, code: code ?? 0 }));
29082
29062
  });
29083
29063
  }
29084
29064
  function runShellCommand(command2, options = {}) {
29085
29065
  const stream = options.stream ?? false;
29086
29066
  const echoStdout = stream && (options.streamStdout ?? true);
29087
29067
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
29088
- return new Promise((resolve59) => {
29068
+ return new Promise((resolve60) => {
29089
29069
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
29090
29070
  ...spawnOptions,
29091
29071
  stdio: ["inherit", "pipe", "pipe"]
@@ -29100,7 +29080,7 @@ function runShellCommand(command2, options = {}) {
29100
29080
  stderr += d;
29101
29081
  if (stream) process.stderr.write(d);
29102
29082
  });
29103
- proc.on("close", (code) => resolve59({ stdout, stderr, code: code ?? 0 }));
29083
+ proc.on("close", (code) => resolve60({ stdout, stderr, code: code ?? 0 }));
29104
29084
  });
29105
29085
  }
29106
29086
  var import_child_process;
@@ -30091,7 +30071,7 @@ var init_slot_registry = __esm({
30091
30071
 
30092
30072
  // src/runtime/exec.ts
30093
30073
  function spawnResult(cmd, args, opts, shell) {
30094
- return new Promise((resolve59) => {
30074
+ return new Promise((resolve60) => {
30095
30075
  const stream = opts.stream ?? false;
30096
30076
  const proc = (0, import_child_process3.spawn)(cmd, args, {
30097
30077
  cwd: opts.cwd,
@@ -30103,8 +30083,8 @@ function spawnResult(cmd, args, opts, shell) {
30103
30083
  let stderr = "";
30104
30084
  proc.stdout?.on("data", (c) => stdout += c.toString());
30105
30085
  proc.stderr?.on("data", (c) => stderr += c.toString());
30106
- proc.on("error", (err) => resolve59({ code: 127, stdout, stderr: stderr || String(err) }));
30107
- proc.on("close", (code) => resolve59({ code: code ?? 1, stdout, stderr }));
30086
+ proc.on("error", (err) => resolve60({ code: 127, stdout, stderr: stderr || String(err) }));
30087
+ proc.on("close", (code) => resolve60({ code: code ?? 1, stdout, stderr }));
30108
30088
  });
30109
30089
  }
30110
30090
  var import_child_process3, fs13, path13, realSystemOps, defaultExec, stderrLog, realSleep;
@@ -30167,7 +30147,7 @@ var init_exec = __esm({
30167
30147
  process.stderr.write(`==> ${message}
30168
30148
  `);
30169
30149
  };
30170
- realSleep = (seconds) => new Promise((resolve59) => setTimeout(resolve59, seconds * 1e3));
30150
+ realSleep = (seconds) => new Promise((resolve60) => setTimeout(resolve60, seconds * 1e3));
30171
30151
  }
30172
30152
  });
30173
30153
 
@@ -32396,7 +32376,6 @@ function formatOccupiedSlot(slot, repoPath, resume) {
32396
32376
  "This session failed partway through launch. Resume without a new launch:",
32397
32377
  ` har env launch ${slot.agentId} --resume`,
32398
32378
  ` har env recover ${slot.agentId}`,
32399
- ` ./.har/launch.sh ${slot.agentId} --resume`,
32400
32379
  ""
32401
32380
  );
32402
32381
  } else {
@@ -33100,7 +33079,7 @@ function inspectSlotReadiness(repoPath, agentId, options = {}) {
33100
33079
  blockers.push({
33101
33080
  code: "foreign_pm2",
33102
33081
  message: `Foreign PM2 processes match agent ${agentId}: ${names}`,
33103
- remediation: "Stop the other harness session (./.har/teardown.sh in that repo) or use a different agent slot.",
33082
+ remediation: "Stop the other harness session (`har env teardown` in that repo) or use a different agent slot.",
33104
33083
  details: { processes: foreign.processes }
33105
33084
  });
33106
33085
  remediations.push(`Inspect with: ${packageRunner()} pm2 jlist | grep agent-${agentId}`);
@@ -33903,8 +33882,8 @@ async function launchSession(options) {
33903
33882
  log(" Edits under the work dir hot-reload in the running slot;");
33904
33883
  log(` use har env agent ${agentId} restart if a change doesn't take.`);
33905
33884
  }
33906
- log(` Verify: ./.har/verify.sh ${agentId}`);
33907
- log(` Teardown: ./.har/teardown.sh ${agentId} (keeps the branch)`);
33885
+ log(` Verify: har env verify ${agentId}`);
33886
+ log(` Teardown: har env teardown ${agentId} (keeps the branch)`);
33908
33887
  return {
33909
33888
  code: 0,
33910
33889
  workDir: session.workDir,
@@ -33930,7 +33909,7 @@ async function launchSession(options) {
33930
33909
  }
33931
33910
  log(` Work dir: ${session.workDir}`);
33932
33911
  log(` Env file: ${session.envFile}`);
33933
- log(` Recovery: har env launch ${agentId} --resume # or ./.har/launch.sh ${agentId} --resume`);
33912
+ log(` Recovery: har env launch ${agentId} --resume`);
33934
33913
  errorLine(`ERROR: ${message}`);
33935
33914
  return { code: 1 };
33936
33915
  }
@@ -34114,7 +34093,7 @@ function buildVerifyPlan(repoPath, agentId, args, baseEnv) {
34114
34093
  if (!envFile) {
34115
34094
  throw new VerifyPlanError(`No .env.agent.${agentId} found.`, [
34116
34095
  ` Launch: har env launch ${agentId} # or har_launch_environment (MCP)`,
34117
- ` Fallback: ./.har/launch.sh ${agentId} # when har CLI/MCP unavailable`
34096
+ ` Fallback: npx @osfactory/har env launch ${agentId} # when har is not on PATH`
34118
34097
  ]);
34119
34098
  }
34120
34099
  const session = readSlotRegistry(repoRoot, agentId);
@@ -34495,6 +34474,11 @@ function resolveStageScriptPath(repoPath, stage) {
34495
34474
  if (fs35.existsSync(stageScript)) {
34496
34475
  return stageScript;
34497
34476
  }
34477
+ const fallback = stage.kind === "inspect" ? "agent-cli.sh" : RUNTIME_SCRIPT_FOR_KIND[stage.kind];
34478
+ if (fallback) {
34479
+ const fallbackPath = path36.join(harnessDir, fallback);
34480
+ if (fs35.existsSync(fallbackPath)) return fallbackPath;
34481
+ }
34498
34482
  throw new Error(
34499
34483
  `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.`
34500
34484
  );
@@ -34564,6 +34548,14 @@ function agentCliOp(stage) {
34564
34548
  if (scriptIndex < 0) return [];
34565
34549
  return tokens.slice(scriptIndex + 1).filter((token) => token !== "{agentId}");
34566
34550
  }
34551
+ function inspectOp(stage) {
34552
+ const fromShim = agentCliOp(stage);
34553
+ if (fromShim !== void 0) return fromShim;
34554
+ if (stage.kind === "inspect" && !stage.command && !stage.script) {
34555
+ return [stage.id];
34556
+ }
34557
+ return void 0;
34558
+ }
34567
34559
  function harnessScriptIsLegacy(repoPath, scriptName) {
34568
34560
  const file = path36.join(getHarnessDir(resolveHarnessRoot(repoPath)), scriptName);
34569
34561
  if (!fs35.existsSync(file)) return false;
@@ -34580,7 +34572,7 @@ function warnLegacyRuntimeScript(repoPath, scriptName) {
34580
34572
  }
34581
34573
  async function runPackageRuntimeStage(repoPath, stage, options, capture) {
34582
34574
  const legacyScript = RUNTIME_SCRIPT_FOR_KIND[stage.kind];
34583
- if (legacyScript && harnessScriptIsLegacy(repoPath, legacyScript)) {
34575
+ if (legacyScript && (stage.command || stage.script) && harnessScriptIsLegacy(repoPath, legacyScript)) {
34584
34576
  warnLegacyRuntimeScript(repoPath, legacyScript);
34585
34577
  return void 0;
34586
34578
  }
@@ -34660,8 +34652,10 @@ async function runPackageRuntimeStage(repoPath, stage, options, capture) {
34660
34652
  verification: parseVerificationResult(result.stdout)
34661
34653
  });
34662
34654
  }
34663
- const op = agentCliOp(stage);
34664
- if (op !== void 0 && harnessScriptIsLegacy(repoPath, "agent-cli.sh")) return void 0;
34655
+ const op = inspectOp(stage);
34656
+ if (op !== void 0 && (stage.command || stage.script) && harnessScriptIsLegacy(repoPath, "agent-cli.sh")) {
34657
+ return void 0;
34658
+ }
34665
34659
  if (op !== void 0 && options.agentId !== void 0) {
34666
34660
  const command2 = op[0] ?? options.args?.[0] ?? "status";
34667
34661
  const args = op.length > 0 ? [...op.slice(1), ...options.args ?? []] : (options.args ?? []).slice(1);
@@ -36669,7 +36663,7 @@ async function attempt(url) {
36669
36663
  async function readControlJson(url) {
36670
36664
  const first = await attempt(url);
36671
36665
  if (first.read.ok || !first.retryable) return first.read;
36672
- await new Promise((resolve59) => setTimeout(resolve59, RETRY_DELAY_MS));
36666
+ await new Promise((resolve60) => setTimeout(resolve60, RETRY_DELAY_MS));
36673
36667
  return (await attempt(url)).read;
36674
36668
  }
36675
36669
  async function readControlPages(options) {
@@ -37154,7 +37148,7 @@ async function postForResponse(url, headers, payload) {
37154
37148
  } catch (err) {
37155
37149
  lastErr = err;
37156
37150
  if (attempt2 < MAX_FETCH_ATTEMPTS) {
37157
- await new Promise((resolve59) => setTimeout(resolve59, attempt2 * 100));
37151
+ await new Promise((resolve60) => setTimeout(resolve60, attempt2 * 100));
37158
37152
  }
37159
37153
  }
37160
37154
  }
@@ -37394,7 +37388,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
37394
37388
  const deadline = Date.now() + timeoutMs;
37395
37389
  while (Date.now() < deadline) {
37396
37390
  if (await isControlApiReachable(apiUrl)) return true;
37397
- await new Promise((resolve59) => setTimeout(resolve59, intervalMs));
37391
+ await new Promise((resolve60) => setTimeout(resolve60, intervalMs));
37398
37392
  }
37399
37393
  return false;
37400
37394
  }
@@ -39043,15 +39037,15 @@ var require_route = __commonJS({
39043
39037
  };
39044
39038
  }
39045
39039
  function wrapConversion(toModel, graph) {
39046
- const path90 = [graph[toModel].parent, toModel];
39040
+ const path91 = [graph[toModel].parent, toModel];
39047
39041
  let fn = conversions[graph[toModel].parent][toModel];
39048
39042
  let cur = graph[toModel].parent;
39049
39043
  while (graph[cur].parent) {
39050
- path90.unshift(graph[cur].parent);
39044
+ path91.unshift(graph[cur].parent);
39051
39045
  fn = link(conversions[graph[cur].parent][cur], fn);
39052
39046
  cur = graph[cur].parent;
39053
39047
  }
39054
- fn.conversion = path90;
39048
+ fn.conversion = path91;
39055
39049
  return fn;
39056
39050
  }
39057
39051
  module2.exports = function(fromModel) {
@@ -45545,26 +45539,26 @@ var require_lib2 = __commonJS({
45545
45539
  return matches;
45546
45540
  };
45547
45541
  exports2.analyse = analyse;
45548
- var detectFile = (filepath, opts = {}) => new Promise((resolve59, reject) => {
45542
+ var detectFile = (filepath, opts = {}) => new Promise((resolve60, reject) => {
45549
45543
  let fd;
45550
- const fs75 = (0, node_1.default)();
45544
+ const fs76 = (0, node_1.default)();
45551
45545
  const handler = (err, buffer) => {
45552
45546
  if (fd) {
45553
- fs75.closeSync(fd);
45547
+ fs76.closeSync(fd);
45554
45548
  }
45555
45549
  if (err) {
45556
45550
  reject(err);
45557
45551
  } else if (buffer) {
45558
- resolve59((0, exports2.detect)(buffer));
45552
+ resolve60((0, exports2.detect)(buffer));
45559
45553
  } else {
45560
45554
  reject(new Error("No error and no buffer received"));
45561
45555
  }
45562
45556
  };
45563
45557
  const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
45564
45558
  if (sampleSize > 0) {
45565
- fd = fs75.openSync(filepath, "r");
45559
+ fd = fs76.openSync(filepath, "r");
45566
45560
  let sample = Buffer.allocUnsafe(sampleSize);
45567
- fs75.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
45561
+ fs76.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
45568
45562
  if (err) {
45569
45563
  handler(err, null);
45570
45564
  } else {
@@ -45576,22 +45570,22 @@ var require_lib2 = __commonJS({
45576
45570
  });
45577
45571
  return;
45578
45572
  }
45579
- fs75.readFile(filepath, handler);
45573
+ fs76.readFile(filepath, handler);
45580
45574
  });
45581
45575
  exports2.detectFile = detectFile;
45582
45576
  var detectFileSync = (filepath, opts = {}) => {
45583
- const fs75 = (0, node_1.default)();
45577
+ const fs76 = (0, node_1.default)();
45584
45578
  if (opts && opts.sampleSize) {
45585
- const fd = fs75.openSync(filepath, "r");
45579
+ const fd = fs76.openSync(filepath, "r");
45586
45580
  let sample = Buffer.allocUnsafe(opts.sampleSize);
45587
- const bytesRead = fs75.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
45581
+ const bytesRead = fs76.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
45588
45582
  if (bytesRead < opts.sampleSize) {
45589
45583
  sample = sample.subarray(0, bytesRead);
45590
45584
  }
45591
- fs75.closeSync(fd);
45585
+ fs76.closeSync(fd);
45592
45586
  return (0, exports2.detect)(sample);
45593
45587
  }
45594
- return (0, exports2.detect)(fs75.readFileSync(filepath));
45588
+ return (0, exports2.detect)(fs76.readFileSync(filepath));
45595
45589
  };
45596
45590
  exports2.detectFileSync = detectFileSync;
45597
45591
  exports2.default = {
@@ -50104,7 +50098,7 @@ var require_Observable = __commonJS({
50104
50098
  Observable2.prototype.forEach = function(next, promiseCtor) {
50105
50099
  var _this = this;
50106
50100
  promiseCtor = getPromiseCtor(promiseCtor);
50107
- return new promiseCtor(function(resolve59, reject) {
50101
+ return new promiseCtor(function(resolve60, reject) {
50108
50102
  var subscriber = new Subscriber_1.SafeSubscriber({
50109
50103
  next: function(value) {
50110
50104
  try {
@@ -50115,7 +50109,7 @@ var require_Observable = __commonJS({
50115
50109
  }
50116
50110
  },
50117
50111
  error: reject,
50118
- complete: resolve59
50112
+ complete: resolve60
50119
50113
  });
50120
50114
  _this.subscribe(subscriber);
50121
50115
  });
@@ -50137,14 +50131,14 @@ var require_Observable = __commonJS({
50137
50131
  Observable2.prototype.toPromise = function(promiseCtor) {
50138
50132
  var _this = this;
50139
50133
  promiseCtor = getPromiseCtor(promiseCtor);
50140
- return new promiseCtor(function(resolve59, reject) {
50134
+ return new promiseCtor(function(resolve60, reject) {
50141
50135
  var value;
50142
50136
  _this.subscribe(function(x) {
50143
50137
  return value = x;
50144
50138
  }, function(err) {
50145
50139
  return reject(err);
50146
50140
  }, function() {
50147
- return resolve59(value);
50141
+ return resolve60(value);
50148
50142
  });
50149
50143
  });
50150
50144
  };
@@ -52240,11 +52234,11 @@ var require_innerFrom = __commonJS({
52240
52234
  "use strict";
52241
52235
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
52242
52236
  function adopt(value) {
52243
- return value instanceof P2 ? value : new P2(function(resolve59) {
52244
- resolve59(value);
52237
+ return value instanceof P2 ? value : new P2(function(resolve60) {
52238
+ resolve60(value);
52245
52239
  });
52246
52240
  }
52247
- return new (P2 || (P2 = Promise))(function(resolve59, reject) {
52241
+ return new (P2 || (P2 = Promise))(function(resolve60, reject) {
52248
52242
  function fulfilled(value) {
52249
52243
  try {
52250
52244
  step(generator.next(value));
@@ -52260,7 +52254,7 @@ var require_innerFrom = __commonJS({
52260
52254
  }
52261
52255
  }
52262
52256
  function step(result) {
52263
- result.done ? resolve59(result.value) : adopt(result.value).then(fulfilled, rejected);
52257
+ result.done ? resolve60(result.value) : adopt(result.value).then(fulfilled, rejected);
52264
52258
  }
52265
52259
  step((generator = generator.apply(thisArg, _arguments || [])).next());
52266
52260
  });
@@ -52342,14 +52336,14 @@ var require_innerFrom = __commonJS({
52342
52336
  }, i);
52343
52337
  function verb(n) {
52344
52338
  i[n] = o[n] && function(v2) {
52345
- return new Promise(function(resolve59, reject) {
52346
- v2 = o[n](v2), settle(resolve59, reject, v2.done, v2.value);
52339
+ return new Promise(function(resolve60, reject) {
52340
+ v2 = o[n](v2), settle(resolve60, reject, v2.done, v2.value);
52347
52341
  });
52348
52342
  };
52349
52343
  }
52350
- function settle(resolve59, reject, d, v2) {
52344
+ function settle(resolve60, reject, d, v2) {
52351
52345
  Promise.resolve(v2).then(function(v3) {
52352
- resolve59({ value: v3, done: d });
52346
+ resolve60({ value: v3, done: d });
52353
52347
  }, reject);
52354
52348
  }
52355
52349
  };
@@ -52968,7 +52962,7 @@ var require_lastValueFrom = __commonJS({
52968
52962
  var EmptyError_1 = require_EmptyError();
52969
52963
  function lastValueFrom2(source, config2) {
52970
52964
  var hasConfig = typeof config2 === "object";
52971
- return new Promise(function(resolve59, reject) {
52965
+ return new Promise(function(resolve60, reject) {
52972
52966
  var _hasValue = false;
52973
52967
  var _value;
52974
52968
  source.subscribe({
@@ -52979,9 +52973,9 @@ var require_lastValueFrom = __commonJS({
52979
52973
  error: reject,
52980
52974
  complete: function() {
52981
52975
  if (_hasValue) {
52982
- resolve59(_value);
52976
+ resolve60(_value);
52983
52977
  } else if (hasConfig) {
52984
- resolve59(config2.defaultValue);
52978
+ resolve60(config2.defaultValue);
52985
52979
  } else {
52986
52980
  reject(new EmptyError_1.EmptyError());
52987
52981
  }
@@ -53003,16 +52997,16 @@ var require_firstValueFrom = __commonJS({
53003
52997
  var Subscriber_1 = require_Subscriber();
53004
52998
  function firstValueFrom(source, config2) {
53005
52999
  var hasConfig = typeof config2 === "object";
53006
- return new Promise(function(resolve59, reject) {
53000
+ return new Promise(function(resolve60, reject) {
53007
53001
  var subscriber = new Subscriber_1.SafeSubscriber({
53008
53002
  next: function(value) {
53009
- resolve59(value);
53003
+ resolve60(value);
53010
53004
  subscriber.unsubscribe();
53011
53005
  },
53012
53006
  error: reject,
53013
53007
  complete: function() {
53014
53008
  if (hasConfig) {
53015
- resolve59(config2.defaultValue);
53009
+ resolve60(config2.defaultValue);
53016
53010
  } else {
53017
53011
  reject(new EmptyError_1.EmptyError());
53018
53012
  }
@@ -58804,14 +58798,14 @@ var require_run_async = __commonJS({
58804
58798
  return function() {
58805
58799
  var args = arguments;
58806
58800
  var originalThis = this;
58807
- var promise = new Promise(function(resolve59, reject) {
58801
+ var promise = new Promise(function(resolve60, reject) {
58808
58802
  var resolved = false;
58809
58803
  const wrappedResolve = function(value) {
58810
58804
  if (resolved) {
58811
58805
  console.warn("Run-async promise already resolved.");
58812
58806
  }
58813
58807
  resolved = true;
58814
- resolve59(value);
58808
+ resolve60(value);
58815
58809
  };
58816
58810
  var rejected = false;
58817
58811
  const wrappedReject = function(value) {
@@ -58919,32 +58913,32 @@ __export(otel_hooks_exports, {
58919
58913
  });
58920
58914
  function getOtelHooksHome() {
58921
58915
  if (process.env.HAR_OTEL_HOOKS_HOME) {
58922
- return path72.resolve(process.env.HAR_OTEL_HOOKS_HOME);
58916
+ return path73.resolve(process.env.HAR_OTEL_HOOKS_HOME);
58923
58917
  }
58924
- return path72.join(os22.homedir(), ".har", "otel-hooks");
58918
+ return path73.join(os22.homedir(), ".har", "otel-hooks");
58925
58919
  }
58926
58920
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
58927
- return path72.join(hooksHome, "otel_config.json");
58921
+ return path73.join(hooksHome, "otel_config.json");
58928
58922
  }
58929
58923
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
58930
- return path72.join(hooksHome, "run-otel-hook.sh");
58924
+ return path73.join(hooksHome, "run-otel-hook.sh");
58931
58925
  }
58932
58926
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
58933
- return path72.join(hooksHome, "state");
58927
+ return path73.join(hooksHome, "state");
58934
58928
  }
58935
58929
  function localOtelHookBin(hooksHome) {
58936
- return path72.join(hooksHome, "node_modules", ".bin", "otel-hook");
58930
+ return path73.join(hooksHome, "node_modules", ".bin", "otel-hook");
58937
58931
  }
58938
58932
  function installedPackageVersion(hooksHome) {
58939
58933
  try {
58940
- const pkgPath = path72.join(
58934
+ const pkgPath = path73.join(
58941
58935
  hooksHome,
58942
58936
  "node_modules",
58943
58937
  "@osfactory",
58944
58938
  "otel-hook",
58945
58939
  "package.json"
58946
58940
  );
58947
- const pkg = JSON.parse(fs65.readFileSync(pkgPath, "utf8"));
58941
+ const pkg = JSON.parse(fs66.readFileSync(pkgPath, "utf8"));
58948
58942
  return typeof pkg.version === "string" ? pkg.version : null;
58949
58943
  } catch {
58950
58944
  return null;
@@ -58995,15 +58989,15 @@ function buildOtelHooksConfig(options) {
58995
58989
  };
58996
58990
  }
58997
58991
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
58998
- fs65.mkdirSync(hooksHome, { recursive: true });
58992
+ fs66.mkdirSync(hooksHome, { recursive: true });
58999
58993
  const configPath = getOtelHooksConfigPath(hooksHome);
59000
- fs65.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
58994
+ fs66.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
59001
58995
  `);
59002
58996
  return configPath;
59003
58997
  }
59004
58998
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
59005
- fs65.mkdirSync(hooksHome, { recursive: true });
59006
- fs65.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
58999
+ fs66.mkdirSync(hooksHome, { recursive: true });
59000
+ fs66.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
59007
59001
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
59008
59002
  const configPath = getOtelHooksConfigPath(hooksHome);
59009
59003
  const stateDir = getOtelHooksStateDir(hooksHome);
@@ -59015,9 +59009,9 @@ exec "${otelHookCommand}" run \\
59015
59009
  --state-dir "${stateDir}" \\
59016
59010
  "$@"
59017
59011
  `;
59018
- fs65.writeFileSync(wrapperPath, script, { mode: 493 });
59012
+ fs66.writeFileSync(wrapperPath, script, { mode: 493 });
59019
59013
  try {
59020
- fs65.chmodSync(wrapperPath, 493);
59014
+ fs66.chmodSync(wrapperPath, 493);
59021
59015
  } catch {
59022
59016
  }
59023
59017
  return wrapperPath;
@@ -59030,7 +59024,7 @@ function commandExists3(command2) {
59030
59024
  }
59031
59025
  function resolveOtelHookCommand(hooksHome) {
59032
59026
  const local = localOtelHookBin(hooksHome);
59033
- if (fs65.existsSync(local)) return local;
59027
+ if (fs66.existsSync(local)) return local;
59034
59028
  return null;
59035
59029
  }
59036
59030
  function resolveHooksInstaller(hooksHome) {
@@ -59045,7 +59039,7 @@ function resolveHooksInstaller(hooksHome) {
59045
59039
  return candidates.find((candidate) => commandExists3(candidate.command)) ?? null;
59046
59040
  }
59047
59041
  function tryInstallPackage(hooksHome) {
59048
- fs65.mkdirSync(hooksHome, { recursive: true });
59042
+ fs66.mkdirSync(hooksHome, { recursive: true });
59049
59043
  const installer = resolveHooksInstaller(hooksHome);
59050
59044
  if (!installer) {
59051
59045
  return {
@@ -59058,7 +59052,7 @@ function tryInstallPackage(hooksHome) {
59058
59052
  encoding: "utf8",
59059
59053
  timeout: 18e4
59060
59054
  });
59061
- if (result.status === 0 && fs65.existsSync(localOtelHookBin(hooksHome))) {
59055
+ if (result.status === 0 && fs66.existsSync(localOtelHookBin(hooksHome))) {
59062
59056
  return { ok: true, detail: described };
59063
59057
  }
59064
59058
  return {
@@ -59084,14 +59078,14 @@ function uninstallLegacyPythonHooks(hooksHome) {
59084
59078
  }
59085
59079
  function removeLegacyPythonArtifacts(hooksHome) {
59086
59080
  const legacyPaths = [
59087
- path72.join(hooksHome, ".venv"),
59088
- path72.join(hooksHome, "otel_config.yaml"),
59089
- path72.join(hooksHome, "venv")
59081
+ path73.join(hooksHome, ".venv"),
59082
+ path73.join(hooksHome, "otel_config.yaml"),
59083
+ path73.join(hooksHome, "venv")
59090
59084
  ];
59091
59085
  for (const target of legacyPaths) {
59092
59086
  try {
59093
- if (fs65.existsSync(target)) {
59094
- fs65.rmSync(target, { recursive: true, force: true });
59087
+ if (fs66.existsSync(target)) {
59088
+ fs66.rmSync(target, { recursive: true, force: true });
59095
59089
  }
59096
59090
  } catch {
59097
59091
  }
@@ -59132,10 +59126,10 @@ function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
59132
59126
  };
59133
59127
  }
59134
59128
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
59135
- if (!fs65.existsSync(filePath)) return false;
59129
+ if (!fs66.existsSync(filePath)) return false;
59136
59130
  let raw;
59137
59131
  try {
59138
- raw = fs65.readFileSync(filePath, "utf8");
59132
+ raw = fs66.readFileSync(filePath, "utf8");
59139
59133
  } catch {
59140
59134
  return false;
59141
59135
  }
@@ -59182,15 +59176,15 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
59182
59176
  return changed;
59183
59177
  };
59184
59178
  if (!walk(parsed)) return false;
59185
- fs65.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
59179
+ fs66.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
59186
59180
  `);
59187
59181
  return true;
59188
59182
  }
59189
59183
  function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
59190
- if (!fs65.existsSync(filePath)) return false;
59184
+ if (!fs66.existsSync(filePath)) return false;
59191
59185
  let raw;
59192
59186
  try {
59193
- raw = fs65.readFileSync(filePath, "utf8");
59187
+ raw = fs66.readFileSync(filePath, "utf8");
59194
59188
  } catch {
59195
59189
  return false;
59196
59190
  }
@@ -59225,21 +59219,21 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
59225
59219
  }
59226
59220
  }
59227
59221
  if (!changed) return false;
59228
- fs65.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
59222
+ fs66.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
59229
59223
  `);
59230
59224
  return true;
59231
59225
  }
59232
59226
  function rewriteKnownHookRegistrations(wrapperPath) {
59233
59227
  const home = os22.homedir();
59234
59228
  const candidates = [
59235
- path72.join(home, ".cursor", "hooks.json"),
59236
- path72.join(home, ".claude", "settings.json"),
59237
- path72.join(home, ".codex", "hooks.json")
59229
+ path73.join(home, ".cursor", "hooks.json"),
59230
+ path73.join(home, ".claude", "settings.json"),
59231
+ path73.join(home, ".codex", "hooks.json")
59238
59232
  ];
59239
59233
  for (const filePath of candidates) {
59240
59234
  try {
59241
59235
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
59242
- if (filePath.endsWith(`${path72.sep}.cursor${path72.sep}hooks.json`)) {
59236
+ if (filePath.endsWith(`${path73.sep}.cursor${path73.sep}hooks.json`)) {
59243
59237
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
59244
59238
  }
59245
59239
  } catch {
@@ -59255,7 +59249,7 @@ function ensureOtelHooks(options) {
59255
59249
  const hooksHome = getOtelHooksHome();
59256
59250
  const errors = [];
59257
59251
  const providersSetup = [];
59258
- fs65.mkdirSync(hooksHome, { recursive: true });
59252
+ fs66.mkdirSync(hooksHome, { recursive: true });
59259
59253
  let otelHookCommand = resolveOtelHookCommand(hooksHome);
59260
59254
  const needsInstall = !otelHookCommand || installedPackageVersion(hooksHome) !== pinnedVersion();
59261
59255
  if (needsInstall) {
@@ -59349,14 +59343,14 @@ function ensureOtelHooks(options) {
59349
59343
  function disableOtelHooksExport() {
59350
59344
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
59351
59345
  }
59352
- var import_child_process19, fs65, os22, path72, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
59346
+ var import_child_process19, fs66, os22, path73, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
59353
59347
  var init_otel_hooks = __esm({
59354
59348
  "src/core/otel-hooks.ts"() {
59355
59349
  "use strict";
59356
59350
  import_child_process19 = require("child_process");
59357
- fs65 = __toESM(require("fs"));
59351
+ fs66 = __toESM(require("fs"));
59358
59352
  os22 = __toESM(require("os"));
59359
- path72 = __toESM(require("path"));
59353
+ path73 = __toESM(require("path"));
59360
59354
  init_control_config();
59361
59355
  init_telemetry_config();
59362
59356
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.2.0";
@@ -62331,7 +62325,7 @@ var require_compile = __commonJS({
62331
62325
  const schOrFunc = root.refs[ref];
62332
62326
  if (schOrFunc)
62333
62327
  return schOrFunc;
62334
- let _sch = resolve59.call(this, root, ref);
62328
+ let _sch = resolve60.call(this, root, ref);
62335
62329
  if (_sch === void 0) {
62336
62330
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
62337
62331
  const { schemaId } = this.opts;
@@ -62358,7 +62352,7 @@ var require_compile = __commonJS({
62358
62352
  function sameSchemaEnv(s1, s2) {
62359
62353
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
62360
62354
  }
62361
- function resolve59(root, ref) {
62355
+ function resolve60(root, ref) {
62362
62356
  let sch;
62363
62357
  while (typeof (sch = this.refs[ref]) == "string")
62364
62358
  ref = sch;
@@ -62576,8 +62570,8 @@ var require_utils2 = __commonJS({
62576
62570
  }
62577
62571
  return ind;
62578
62572
  }
62579
- function removeDotSegments(path90) {
62580
- let input = path90;
62573
+ function removeDotSegments(path91) {
62574
+ let input = path91;
62581
62575
  const output = [];
62582
62576
  let nextSlash = -1;
62583
62577
  let len = 0;
@@ -62829,8 +62823,8 @@ var require_schemes = __commonJS({
62829
62823
  wsComponent.secure = void 0;
62830
62824
  }
62831
62825
  if (wsComponent.resourceName) {
62832
- const [path90, query] = wsComponent.resourceName.split("?");
62833
- wsComponent.path = path90 && path90 !== "/" ? path90 : void 0;
62826
+ const [path91, query] = wsComponent.resourceName.split("?");
62827
+ wsComponent.path = path91 && path91 !== "/" ? path91 : void 0;
62834
62828
  wsComponent.query = query;
62835
62829
  wsComponent.resourceName = void 0;
62836
62830
  }
@@ -62989,7 +62983,7 @@ var require_fast_uri = __commonJS({
62989
62983
  }
62990
62984
  return uri;
62991
62985
  }
62992
- function resolve59(baseURI, relativeURI, options) {
62986
+ function resolve60(baseURI, relativeURI, options) {
62993
62987
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
62994
62988
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
62995
62989
  schemelessOptions.skipEscape = true;
@@ -63247,7 +63241,7 @@ var require_fast_uri = __commonJS({
63247
63241
  var fastUri = {
63248
63242
  SCHEMES,
63249
63243
  normalize: normalize3,
63250
- resolve: resolve59,
63244
+ resolve: resolve60,
63251
63245
  resolveComponent,
63252
63246
  equal,
63253
63247
  serialize,
@@ -66223,12 +66217,12 @@ var require_dist = __commonJS({
66223
66217
  throw new Error(`Unknown format "${name}"`);
66224
66218
  return f;
66225
66219
  };
66226
- function addFormats(ajv, list, fs75, exportName) {
66220
+ function addFormats(ajv, list, fs76, exportName) {
66227
66221
  var _a2;
66228
66222
  var _b2;
66229
66223
  (_a2 = (_b2 = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
66230
66224
  for (const f of list)
66231
- ajv.addFormat(f, fs75[f]);
66225
+ ajv.addFormat(f, fs76[f]);
66232
66226
  }
66233
66227
  module2.exports = exports2 = formatsPlugin;
66234
66228
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -67512,11 +67506,11 @@ var parser = new YargsParser({
67512
67506
  resolve: import_path2.resolve,
67513
67507
  // TODO: figure out a way to combine ESM and CJS coverage, such that
67514
67508
  // we can exercise all the lines below:
67515
- require: (path90) => {
67509
+ require: (path91) => {
67516
67510
  if (typeof require !== "undefined") {
67517
- return require(path90);
67518
- } else if (path90.match(/\.json$/)) {
67519
- return JSON.parse((0, import_fs2.readFileSync)(path90, "utf8"));
67511
+ return require(path91);
67512
+ } else if (path91.match(/\.json$/)) {
67513
+ return JSON.parse((0, import_fs2.readFileSync)(path91, "utf8"));
67520
67514
  } else {
67521
67515
  throw Error("only .json config files are supported in ESM");
67522
67516
  }
@@ -70042,12 +70036,12 @@ var YargsInstance = class {
70042
70036
  async getCompletion(args, done) {
70043
70037
  argsert("<array> [function]", [args, done], arguments.length);
70044
70038
  if (!done) {
70045
- return new Promise((resolve59, reject) => {
70039
+ return new Promise((resolve60, reject) => {
70046
70040
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
70047
70041
  if (err)
70048
70042
  reject(err);
70049
70043
  else
70050
- resolve59(completions);
70044
+ resolve60(completions);
70051
70045
  });
70052
70046
  });
70053
70047
  } else {
@@ -71280,7 +71274,7 @@ async function handleAgentSkills(options) {
71280
71274
  const shouldPrompt = !options.autoYes && !(mode === "maintain" && alreadyScaffolded);
71281
71275
  if (shouldPrompt) {
71282
71276
  const accepted = await askYesNo(
71283
- `Scaffold agent skills (/setup-har, /har-wt, /har-maintain) for: ${targets.join(", ")}? [Y/n]`
71277
+ `Scaffold agent skills (/setup-har, /har-wt, /har-maintain, /factory-line) for: ${targets.join(", ")}? [Y/n]`
71284
71278
  );
71285
71279
  if (!accepted) {
71286
71280
  info("Skipped agent skills");
@@ -71297,16 +71291,16 @@ async function handleAgentSkills(options) {
71297
71291
  }
71298
71292
  async function askYesNo(question) {
71299
71293
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
71300
- return new Promise((resolve59) => {
71294
+ return new Promise((resolve60) => {
71301
71295
  process.stderr.write(`${question} `);
71302
71296
  rl.once("line", (answer) => {
71303
71297
  rl.close();
71304
71298
  const trimmed = answer.trim();
71305
71299
  if (trimmed === "") {
71306
- resolve59(true);
71300
+ resolve60(true);
71307
71301
  return;
71308
71302
  }
71309
- resolve59(/^y(es)?$/i.test(trimmed));
71303
+ resolve60(/^y(es)?$/i.test(trimmed));
71310
71304
  });
71311
71305
  });
71312
71306
  }
@@ -71325,7 +71319,7 @@ function resolveTargets(argv, repoPath) {
71325
71319
  }
71326
71320
  var agentsCommand = {
71327
71321
  command: "agents <subcommand>",
71328
- describe: "Manage scaffolded agent skills (/setup-har, /har-wt, /har-maintain)",
71322
+ describe: "Manage scaffolded agent skills (/setup-har, /har-wt, /har-maintain, /factory-line)",
71329
71323
  builder: (yargs) => yargs.command(
71330
71324
  "install",
71331
71325
  "Scaffold agent skills into this repo (Claude/Cursor) and globally (Codex)",
@@ -71386,8 +71380,8 @@ function handleRemove(argv) {
71386
71380
  }
71387
71381
 
71388
71382
  // src/cli/commands/env.ts
71389
- var fs68 = __toESM(require("fs"));
71390
- var path76 = __toESM(require("path"));
71383
+ var fs69 = __toESM(require("fs"));
71384
+ var path77 = __toESM(require("path"));
71391
71385
 
71392
71386
  // src/cli/finish-command.ts
71393
71387
  init_sync_context();
@@ -71397,12 +71391,12 @@ async function finishCommand(code) {
71397
71391
  }
71398
71392
 
71399
71393
  // src/core/harness.ts
71400
- var fs62 = __toESM(require("fs"));
71401
- var path68 = __toESM(require("path"));
71394
+ var fs63 = __toESM(require("fs"));
71395
+ var path69 = __toESM(require("path"));
71402
71396
 
71403
71397
  // src/harness/generator.ts
71404
- var fs47 = __toESM(require("fs"));
71405
- var path53 = __toESM(require("path"));
71398
+ var fs48 = __toESM(require("fs"));
71399
+ var path54 = __toESM(require("path"));
71406
71400
  init_file_ops();
71407
71401
  init_logging();
71408
71402
 
@@ -71419,7 +71413,7 @@ function ensureRootGitignorePatterns(checkoutDir) {
71419
71413
  const lines = content.split("\n").map((line) => line.trim());
71420
71414
  const missing = HARNESS_ROOT_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
71421
71415
  if (missing.length === 0) return;
71422
- const header2 = lines.length === 0 || content.trim().length === 0 ? "# HAR agent slot artifacts (generated by .har/launch.sh)\n" : "";
71416
+ const header2 = lines.length === 0 || content.trim().length === 0 ? "# HAR agent slot artifacts (generated by har env launch)\n" : "";
71423
71417
  const suffix = content.length === 0 || content.endsWith("\n") ? "" : "\n";
71424
71418
  const block = lines.some((line) => line.includes("HAR agent slot artifacts")) || header2.length === 0 ? `${missing.join("\n")}
71425
71419
  ` : `${header2}${missing.join("\n")}
@@ -71581,7 +71575,7 @@ function compareHarnessToTemplate(repoPath) {
71581
71575
  const unchanged = [];
71582
71576
  const ownedByUser = [];
71583
71577
  const ejected = manifest?.ejected === true;
71584
- const userOwnedFiles = new Set(ejected ? MANAGED_SHIM_FILES : []);
71578
+ const userOwnedFiles = new Set(ejected ? ["runtime/har.cjs", "runtime/README.md"] : []);
71585
71579
  for (const file of templateFiles) {
71586
71580
  const harnessFile = harnessFileForTemplate(file);
71587
71581
  const harnessPath = path51.join(harnessDir, harnessFile);
@@ -71726,45 +71720,107 @@ function ensurePluginLedgerScaffold(repoPath, options) {
71726
71720
  init_profiles();
71727
71721
  init_schema2();
71728
71722
  init_stages();
71723
+
71724
+ // src/harness/lifecycle-shims.ts
71725
+ var fs47 = __toESM(require("fs"));
71726
+ var path53 = __toESM(require("path"));
71727
+ init_manifest();
71728
+ init_stages();
71729
+ var LIFECYCLE_SHIM_FILES = MANAGED_SHIM_FILES;
71730
+ var LIFECYCLE_SHIM_SET = new Set(LIFECYCLE_SHIM_FILES);
71731
+ var PACKAGE_RUNTIME_KINDS = /* @__PURE__ */ new Set([
71732
+ "launch",
71733
+ "verify",
71734
+ "teardown",
71735
+ "setup",
71736
+ "inspect"
71737
+ ]);
71738
+ function isLifecycleShimFile(name) {
71739
+ return LIFECYCLE_SHIM_SET.has(path53.basename(name.replace(/^\.\/\.har\//, "").replace(/^\.\//, "")));
71740
+ }
71741
+ function stageCommandFile(stage) {
71742
+ const raw = (stage.command ?? stage.script ?? "").trim();
71743
+ if (!raw) return null;
71744
+ return raw.split(/\s+/)[0].replace(/^\.\/\.har\//, "").replace(/^\.har\//, "").replace(/^\.\//, "");
71745
+ }
71746
+ function stagePointsAtLifecycleShim(stage) {
71747
+ const file = stageCommandFile(stage);
71748
+ return file !== null && isLifecycleShimFile(file);
71749
+ }
71750
+ function isManagedShimContent(content) {
71751
+ return content.includes("exec har env") || content.includes("EJECTED runtime");
71752
+ }
71753
+ function retireLifecycleShims(repoPath) {
71754
+ const harnessDir = getHarnessDir(path53.resolve(repoPath));
71755
+ const pruned = [];
71756
+ for (const shim3 of LIFECYCLE_SHIM_FILES) {
71757
+ const file = path53.join(harnessDir, shim3);
71758
+ if (!fs47.existsSync(file) || !fs47.statSync(file).isFile()) continue;
71759
+ const content = fs47.readFileSync(file, "utf8");
71760
+ if (!isManagedShimContent(content)) continue;
71761
+ fs47.rmSync(file);
71762
+ pruned.push(shim3);
71763
+ }
71764
+ const stagesRewritten = stripLifecycleShimCommands(repoPath);
71765
+ return { pruned, stagesRewritten };
71766
+ }
71767
+ function stripLifecycleShimCommands(repoPath) {
71768
+ const resolved = path53.resolve(repoPath);
71769
+ let registry2;
71770
+ try {
71771
+ registry2 = readStageRegistry(resolved);
71772
+ } catch {
71773
+ return false;
71774
+ }
71775
+ let changed = false;
71776
+ const stages = registry2.stages.map((stage) => {
71777
+ if (!stagePointsAtLifecycleShim(stage)) return stage;
71778
+ changed = true;
71779
+ const rest = { ...stage };
71780
+ delete rest.command;
71781
+ delete rest.script;
71782
+ return rest;
71783
+ });
71784
+ if (!changed) return false;
71785
+ writeStageRegistry(resolved, { ...registry2, stages });
71786
+ return true;
71787
+ }
71788
+
71789
+ // src/harness/generator.ts
71729
71790
  init_profiles();
71730
71791
  function scaffoldHarnessBoilerplate(repoPath, options = {}) {
71731
- const harnessDir = path53.join(repoPath, DEFAULT_HAR_DIR);
71732
- const projectName = path53.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
71792
+ const harnessDir = path54.join(repoPath, DEFAULT_HAR_DIR);
71793
+ const projectName = path54.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
71733
71794
  const profile = options.profile ?? "default";
71734
71795
  const profileManifest = readProfileManifest(profile);
71735
71796
  const bundleIds = profileManifest.bundles.map((b2) => b2.id);
71736
- if (fs47.existsSync(harnessDir) && !options.force) {
71797
+ if (fs48.existsSync(harnessDir) && !options.force) {
71737
71798
  throw new Error(
71738
71799
  '.har/ already exists. Use --force to overwrite or run "har env maintain" to update in place.'
71739
71800
  );
71740
71801
  }
71741
- if (options.force && fs47.existsSync(harnessDir)) {
71742
- fs47.rmSync(harnessDir, { recursive: true, force: true });
71802
+ if (options.force && fs48.existsSync(harnessDir)) {
71803
+ fs48.rmSync(harnessDir, { recursive: true, force: true });
71743
71804
  }
71744
- fs47.mkdirSync(harnessDir, { recursive: true });
71805
+ fs48.mkdirSync(harnessDir, { recursive: true });
71745
71806
  for (const bundle of profileManifest.bundles) {
71746
71807
  const bundleDir = resolveProfileBundleDir(bundle);
71747
71808
  copyDirRecursive(bundleDir, harnessDir);
71748
71809
  }
71749
71810
  for (const docName of Object.keys(profileManifest.docs)) {
71750
- fs47.writeFileSync(path53.join(harnessDir, docName), renderProfileDoc(profile, docName));
71811
+ fs48.writeFileSync(path54.join(harnessDir, docName), renderProfileDoc(profile, docName));
71751
71812
  }
71752
71813
  const gitignoreSource = composeProfileTemplateMap(profile).get(HARNESS_GITIGNORE_TEMPLATE);
71753
71814
  if (gitignoreSource) {
71754
- writeHarnessGitignore(harnessDir, path53.dirname(gitignoreSource.sourcePath));
71815
+ writeHarnessGitignore(harnessDir, path54.dirname(gitignoreSource.sourcePath));
71755
71816
  }
71756
71817
  syncAgentSlotsToHarnessEnv(repoPath);
71757
- for (const shim3 of MANAGED_SHIM_FILES) {
71758
- const shimPath = path53.join(harnessDir, shim3);
71759
- if (!fs47.existsSync(shimPath)) continue;
71760
- const rendered = substituteTemplateTokens(fs47.readFileSync(shimPath, "utf8"), projectName);
71761
- fs47.writeFileSync(shimPath, rendered);
71762
- }
71763
- const harnessEnvPath = path53.join(harnessDir, "harness.env");
71764
- if (fs47.existsSync(harnessEnvPath)) {
71765
- let content = fs47.readFileSync(harnessEnvPath, "utf8");
71818
+ retireLifecycleShims(repoPath);
71819
+ const harnessEnvPath = path54.join(harnessDir, "harness.env");
71820
+ if (fs48.existsSync(harnessEnvPath)) {
71821
+ let content = fs48.readFileSync(harnessEnvPath, "utf8");
71766
71822
  content = substituteTemplateTokens(content, projectName);
71767
- fs47.writeFileSync(harnessEnvPath, content);
71823
+ fs48.writeFileSync(harnessEnvPath, content);
71768
71824
  const validation2 = validateHarnessEnvSource(content);
71769
71825
  if (!validation2.ok) {
71770
71826
  const details = validation2.issues.filter((i) => i.severity === "error").map((i) => i.line !== void 0 ? `line ${i.line}: ${i.message}` : i.message).join("\n ");
@@ -71802,16 +71858,16 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
71802
71858
  }
71803
71859
 
71804
71860
  // src/harness/agent-md.ts
71805
- var fs49 = __toESM(require("fs"));
71806
- var path56 = __toESM(require("path"));
71861
+ var fs50 = __toESM(require("fs"));
71862
+ var path57 = __toESM(require("path"));
71807
71863
  init_file_ops();
71808
71864
  init_logging();
71809
71865
  init_manifest();
71810
71866
 
71811
71867
  // src/harness/instruction-files.ts
71812
- var fs48 = __toESM(require("fs"));
71868
+ var fs49 = __toESM(require("fs"));
71813
71869
  var os19 = __toESM(require("os"));
71814
- var path55 = __toESM(require("path"));
71870
+ var path56 = __toESM(require("path"));
71815
71871
 
71816
71872
  // node_modules/@inquirer/core/dist/esm/lib/key.js
71817
71873
  var isUpKey = (key, keybindings = []) => (
@@ -72845,13 +72901,13 @@ var PromisePolyfill = class extends Promise {
72845
72901
  // Available starting from Node 22
72846
72902
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
72847
72903
  static withResolver() {
72848
- let resolve59;
72904
+ let resolve60;
72849
72905
  let reject;
72850
72906
  const promise = new Promise((res, rej) => {
72851
- resolve59 = res;
72907
+ resolve60 = res;
72852
72908
  reject = rej;
72853
72909
  });
72854
- return { promise, resolve: resolve59, reject };
72910
+ return { promise, resolve: resolve60, reject };
72855
72911
  }
72856
72912
  };
72857
72913
 
@@ -72885,7 +72941,7 @@ function createPrompt(view) {
72885
72941
  output
72886
72942
  });
72887
72943
  const screen = new ScreenManager(rl);
72888
- const { promise, resolve: resolve59, reject } = PromisePolyfill.withResolver();
72944
+ const { promise, resolve: resolve60, reject } = PromisePolyfill.withResolver();
72889
72945
  const cancel = () => reject(new CancelPromptError());
72890
72946
  if (signal) {
72891
72947
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -72912,7 +72968,7 @@ function createPrompt(view) {
72912
72968
  cycle(() => {
72913
72969
  try {
72914
72970
  const nextView = view(config2, (value) => {
72915
- setImmediate(() => resolve59(value));
72971
+ setImmediate(() => resolve60(value));
72916
72972
  });
72917
72973
  if (nextView === void 0) {
72918
72974
  const callerFilename = callSites[1]?.getFileName();
@@ -74221,9 +74277,9 @@ var import_rxjs = __toESM(require_cjs(), 1);
74221
74277
  var import_run_async = __toESM(require_run_async(), 1);
74222
74278
  var import_mute_stream2 = __toESM(require_lib(), 1);
74223
74279
  var _ = {
74224
- set: (obj, path90 = "", value) => {
74280
+ set: (obj, path91 = "", value) => {
74225
74281
  let pointer = obj;
74226
- path90.split(".").forEach((key, index, arr) => {
74282
+ path91.split(".").forEach((key, index, arr) => {
74227
74283
  if (key === "__proto__" || key === "constructor")
74228
74284
  return;
74229
74285
  if (index === arr.length - 1) {
@@ -74234,8 +74290,8 @@ var _ = {
74234
74290
  pointer = pointer[key];
74235
74291
  });
74236
74292
  },
74237
- get: (obj, path90 = "", defaultValue) => {
74238
- const travel = (regexp) => String.prototype.split.call(path90, regexp).filter(Boolean).reduce(
74293
+ get: (obj, path91 = "", defaultValue) => {
74294
+ const travel = (regexp) => String.prototype.split.call(path91, regexp).filter(Boolean).reduce(
74239
74295
  // @ts-expect-error implicit any on res[key]
74240
74296
  (res, key) => res == null ? res : res[key],
74241
74297
  obj
@@ -74353,7 +74409,7 @@ var PromptsRunner = class {
74353
74409
  throw new Error(`Prompt for type ${question.type} not found`);
74354
74410
  }
74355
74411
  let cleanupSignal;
74356
- const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve59, reject) => {
74412
+ const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve60, reject) => {
74357
74413
  const { signal: signal2 } = opt;
74358
74414
  if (signal2.aborted) {
74359
74415
  reject(new AbortPromptError({ cause: signal2.reason }));
@@ -74390,7 +74446,7 @@ var PromptsRunner = class {
74390
74446
  signal2.removeEventListener("abort", abort);
74391
74447
  cleanupSignal = void 0;
74392
74448
  };
74393
- activePrompt.run().then(resolve59, reject).finally(cleanup);
74449
+ activePrompt.run().then(resolve60, reject).finally(cleanup);
74394
74450
  }) : prompt2;
74395
74451
  let cleanupModuleSignal;
74396
74452
  const { signal: moduleSignal } = this.opt;
@@ -74561,12 +74617,12 @@ function outsideContentShrinkMessage(beforeLines, afterLines) {
74561
74617
  }
74562
74618
  function detectInstructionFiles(repoPath) {
74563
74619
  return {
74564
- agentsMd: fs48.existsSync(path55.join(repoPath, AGENTS_MD)),
74565
- agentMd: fs48.existsSync(path55.join(repoPath, LEGACY_AGENT_MD)),
74566
- claudeMd: fs48.existsSync(path55.join(repoPath, CLAUDE_MD)),
74567
- cursorDir: fs48.existsSync(path55.join(repoPath, ".cursor")),
74568
- claudeDir: fs48.existsSync(path55.join(repoPath, ".claude")),
74569
- codexHome: fs48.existsSync(path55.join(os19.homedir(), ".codex"))
74620
+ agentsMd: fs49.existsSync(path56.join(repoPath, AGENTS_MD)),
74621
+ agentMd: fs49.existsSync(path56.join(repoPath, LEGACY_AGENT_MD)),
74622
+ claudeMd: fs49.existsSync(path56.join(repoPath, CLAUDE_MD)),
74623
+ cursorDir: fs49.existsSync(path56.join(repoPath, ".cursor")),
74624
+ claudeDir: fs49.existsSync(path56.join(repoPath, ".claude")),
74625
+ codexHome: fs49.existsSync(path56.join(os19.homedir(), ".codex"))
74570
74626
  };
74571
74627
  }
74572
74628
  function formatDetectionReport(detection) {
@@ -74619,21 +74675,19 @@ function formatInstallPlan(plan, detection) {
74619
74675
  var HAR_EJECTED_SHELL_SECTION = `
74620
74676
  ### Ejected harness
74621
74677
 
74622
- This harness is **ejected** (\`har env eject\`): \`.har/*.sh\` are yours and execute
74623
- the vendored runtime in \`.har/runtime/\` directly, so they work with no \`har\`
74624
- install present.
74625
-
74626
- - \`./.har/launch.sh <id>\` \xB7 \`./.har/verify.sh <id> --full\` \xB7 \`./.har/teardown.sh <id>\`
74678
+ This harness is **ejected** (\`har env eject\`): the runtime is vendored in
74679
+ \`.har/runtime/\`. Drive it with \`har env \u2026\` or
74680
+ \`node .har/runtime/har.cjs env \u2026\` (no \`har\` install required).
74627
74681
 
74628
- You own these files \u2014 HAR will not update them. Return to managed shims with
74629
- \`har env adopt\`.
74682
+ You own \`.har/runtime/\` \u2014 HAR will not update it. Return to the packaged
74683
+ runtime with \`har env adopt\`.
74630
74684
  `;
74631
74685
  function loadHarAgentsSectionFromTemplate(options = {}) {
74632
74686
  const templatePath = resolveTemplateFile("AGENTS.md.template");
74633
74687
  if (!templatePath) {
74634
74688
  throw new Error("AGENTS.md.template not found. Run npm run build.");
74635
74689
  }
74636
- const content = fs48.readFileSync(templatePath, "utf8");
74690
+ const content = fs49.readFileSync(templatePath, "utf8");
74637
74691
  const start = content.indexOf(HAR_SECTION_START);
74638
74692
  const end = content.indexOf(HAR_SECTION_END);
74639
74693
  if (start === -1 || end === -1 || end < start) {
@@ -74651,7 +74705,7 @@ function loadAgentsMdTemplate() {
74651
74705
  if (!templatePath) {
74652
74706
  throw new Error("AGENTS.md.template not found. Run npm run build.");
74653
74707
  }
74654
- return fs48.readFileSync(templatePath, "utf8");
74708
+ return fs49.readFileSync(templatePath, "utf8");
74655
74709
  }
74656
74710
  function upsertMarkedBlock2(content, block, startMarker, endMarker) {
74657
74711
  const existingBlock = findLastCompleteMarkedBlock(content, startMarker, endMarker);
@@ -74684,14 +74738,14 @@ function mergeAgentsMdContent(existing, incoming, options = {}) {
74684
74738
  return content;
74685
74739
  }
74686
74740
  function upsertAgentsMdHarSection(repoPath, options = {}) {
74687
- const dest = path55.join(repoPath, AGENTS_MD);
74741
+ const dest = path56.join(repoPath, AGENTS_MD);
74688
74742
  const ejected = readManifest(repoPath)?.ejected === true;
74689
74743
  const section = loadHarAgentsSectionFromTemplate({ ejected });
74690
- if (!fs48.existsSync(dest)) {
74744
+ if (!fs49.existsSync(dest)) {
74691
74745
  writeFileSafe(dest, loadAgentsMdTemplate());
74692
74746
  return "created";
74693
74747
  }
74694
- const existing = fs48.readFileSync(dest, "utf8");
74748
+ const existing = fs49.readFileSync(dest, "utf8");
74695
74749
  const sanitized = stripClaudePointerFromAgentsMd(existing);
74696
74750
  const { content, action } = upsertMarkedBlock2(
74697
74751
  sanitized,
@@ -74716,15 +74770,15 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
74716
74770
  return action;
74717
74771
  }
74718
74772
  function migrateLegacyAgentMd(repoPath) {
74719
- const legacyPath = path55.join(repoPath, LEGACY_AGENT_MD);
74720
- const agentsPath = path55.join(repoPath, AGENTS_MD);
74721
- if (!fs48.existsSync(legacyPath)) return false;
74722
- const legacy = fs48.readFileSync(legacyPath, "utf8");
74723
- if (!fs48.existsSync(agentsPath)) {
74773
+ const legacyPath = path56.join(repoPath, LEGACY_AGENT_MD);
74774
+ const agentsPath = path56.join(repoPath, AGENTS_MD);
74775
+ if (!fs49.existsSync(legacyPath)) return false;
74776
+ const legacy = fs49.readFileSync(legacyPath, "utf8");
74777
+ if (!fs49.existsSync(agentsPath)) {
74724
74778
  writeFileSafe(agentsPath, legacy);
74725
74779
  upsertAgentsMdHarSection(repoPath);
74726
74780
  } else {
74727
- const agents = fs48.readFileSync(agentsPath, "utf8");
74781
+ const agents = fs49.readFileSync(agentsPath, "utf8");
74728
74782
  const legacyTrimmed = legacy.trim();
74729
74783
  if (legacyTrimmed.length > 0 && !agents.includes(legacyTrimmed)) {
74730
74784
  const suffix = agents.endsWith("\n") ? "" : "\n";
@@ -74734,7 +74788,7 @@ ${legacyTrimmed}
74734
74788
  }
74735
74789
  upsertAgentsMdHarSection(repoPath);
74736
74790
  }
74737
- fs48.unlinkSync(legacyPath);
74791
+ fs49.unlinkSync(legacyPath);
74738
74792
  info(`Migrated ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD} (removed legacy file)`);
74739
74793
  return true;
74740
74794
  }
@@ -74744,7 +74798,7 @@ function loadClaudeMdTemplate() {
74744
74798
  if (!templatePath) {
74745
74799
  throw new Error("CLAUDE.md.template not found. Run npm run build.");
74746
74800
  }
74747
- return fs48.readFileSync(templatePath, "utf8");
74801
+ return fs49.readFileSync(templatePath, "utf8");
74748
74802
  }
74749
74803
  function isHarOwnedClaudeMd(content) {
74750
74804
  const trimmed = content.trim();
@@ -74756,13 +74810,13 @@ function hasAgentsImport(content) {
74756
74810
  return content.split("\n").some((line) => line.trim() === CLAUDE_MD_IMPORT);
74757
74811
  }
74758
74812
  function ensureClaudeMdPointer(repoPath, options = {}) {
74759
- const dest = path55.join(repoPath, CLAUDE_MD);
74813
+ const dest = path56.join(repoPath, CLAUDE_MD);
74760
74814
  const thin = loadClaudeMdTemplate();
74761
- if (!fs48.existsSync(dest)) {
74815
+ if (!fs49.existsSync(dest)) {
74762
74816
  writeFileSafe(dest, thin);
74763
74817
  return "created";
74764
74818
  }
74765
- const existing = fs48.readFileSync(dest, "utf8");
74819
+ const existing = fs49.readFileSync(dest, "utf8");
74766
74820
  if (isHarOwnedClaudeMd(existing) || options.force) {
74767
74821
  if (existing.trim() === CLAUDE_MD_IMPORT) return "skipped";
74768
74822
  writeFileSafe(dest, thin);
@@ -74896,19 +74950,19 @@ var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
74896
74950
  var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
74897
74951
  function readAgentMdProposal(repoPath) {
74898
74952
  const harnessDir = getHarnessDir(repoPath);
74899
- const proposalPath = path56.join(harnessDir, AGENTS_MD_PROPOSAL);
74900
- const metaPath = path56.join(harnessDir, AGENTS_MD_PROPOSAL_META);
74901
- const legacyProposalPath = path56.join(harnessDir, AGENT_MD_PROPOSAL);
74902
- const legacyMetaPath = path56.join(harnessDir, AGENT_MD_PROPOSAL_META);
74903
- const resolvedProposal = fs49.existsSync(proposalPath) ? proposalPath : fs49.existsSync(legacyProposalPath) ? legacyProposalPath : null;
74953
+ const proposalPath = path57.join(harnessDir, AGENTS_MD_PROPOSAL);
74954
+ const metaPath = path57.join(harnessDir, AGENTS_MD_PROPOSAL_META);
74955
+ const legacyProposalPath = path57.join(harnessDir, AGENT_MD_PROPOSAL);
74956
+ const legacyMetaPath = path57.join(harnessDir, AGENT_MD_PROPOSAL_META);
74957
+ const resolvedProposal = fs50.existsSync(proposalPath) ? proposalPath : fs50.existsSync(legacyProposalPath) ? legacyProposalPath : null;
74904
74958
  if (!resolvedProposal) return null;
74905
74959
  const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
74906
- const content = fs49.readFileSync(resolvedProposal, "utf8");
74960
+ const content = fs50.readFileSync(resolvedProposal, "utf8");
74907
74961
  let rationale = "";
74908
74962
  let createdAt = (/* @__PURE__ */ new Date()).toISOString();
74909
- if (fs49.existsSync(resolvedMeta)) {
74963
+ if (fs50.existsSync(resolvedMeta)) {
74910
74964
  try {
74911
- const meta = JSON.parse(fs49.readFileSync(resolvedMeta, "utf8"));
74965
+ const meta = JSON.parse(fs50.readFileSync(resolvedMeta, "utf8"));
74912
74966
  rationale = meta.rationale ?? "";
74913
74967
  createdAt = meta.createdAt ?? createdAt;
74914
74968
  } catch {
@@ -74925,8 +74979,8 @@ function clearAgentMdProposal(repoPath) {
74925
74979
  AGENT_MD_PROPOSAL,
74926
74980
  AGENT_MD_PROPOSAL_META
74927
74981
  ]) {
74928
- const p = path56.join(harnessDir, file);
74929
- if (fs49.existsSync(p)) fs49.unlinkSync(p);
74982
+ const p = path57.join(harnessDir, file);
74983
+ if (fs50.existsSync(p)) fs50.unlinkSync(p);
74930
74984
  }
74931
74985
  }
74932
74986
  function wouldProposalShrinkExisting(existing, proposal) {
@@ -74939,9 +74993,9 @@ function wouldProposalShrinkExisting(existing, proposal) {
74939
74993
  function applyAgentMdProposalMerge(repoPath, options = {}) {
74940
74994
  const proposal = readAgentMdProposal(repoPath);
74941
74995
  if (!proposal) return false;
74942
- const agentsMdPath = path56.join(repoPath, AGENTS_MD);
74943
- if (fs49.existsSync(agentsMdPath)) {
74944
- const existing = fs49.readFileSync(agentsMdPath, "utf8");
74996
+ const agentsMdPath = path57.join(repoPath, AGENTS_MD);
74997
+ if (fs50.existsSync(agentsMdPath)) {
74998
+ const existing = fs50.readFileSync(agentsMdPath, "utf8");
74945
74999
  if (wouldProposalShrinkExisting(existing, proposal.content)) {
74946
75000
  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.`;
74947
75001
  if (options.rejectSignificantShrink) {
@@ -74964,16 +75018,16 @@ function finalizeAgentsMdInstructionFiles(repoPath) {
74964
75018
  }
74965
75019
 
74966
75020
  // src/harness/validator.ts
74967
- var fs51 = __toESM(require("fs"));
74968
- var path58 = __toESM(require("path"));
75021
+ var fs52 = __toESM(require("fs"));
75022
+ var path59 = __toESM(require("path"));
74969
75023
  init_shell();
74970
75024
  init_env();
74971
75025
  init_manifest();
74972
75026
  init_stages();
74973
75027
 
74974
75028
  // src/harness/verification.ts
74975
- var fs50 = __toESM(require("fs"));
74976
- var path57 = __toESM(require("path"));
75029
+ var fs51 = __toESM(require("fs"));
75030
+ var path58 = __toESM(require("path"));
74977
75031
  init_env();
74978
75032
  init_provision();
74979
75033
  init_manifest();
@@ -74998,10 +75052,10 @@ function findPhantomVerificationStageIds(registry2) {
74998
75052
  return resolveVerificationPlan(registry2, { full: true }).phantomIds;
74999
75053
  }
75000
75054
  function nodeSmokeCommand(repoPath) {
75001
- const pkgPath = path57.join(repoPath, "package.json");
75055
+ const pkgPath = path58.join(repoPath, "package.json");
75002
75056
  let scripts = {};
75003
75057
  try {
75004
- scripts = JSON.parse(fs50.readFileSync(pkgPath, "utf8")).scripts ?? {};
75058
+ scripts = JSON.parse(fs51.readFileSync(pkgPath, "utf8")).scripts ?? {};
75005
75059
  } catch {
75006
75060
  scripts = {};
75007
75061
  }
@@ -75030,9 +75084,9 @@ function nodeSmokeCommand(repoPath) {
75030
75084
  };
75031
75085
  }
75032
75086
  function nodeScriptOrSkip(repoPath, script) {
75033
- const pkgPath = path57.join(repoPath, "package.json");
75087
+ const pkgPath = path58.join(repoPath, "package.json");
75034
75088
  try {
75035
- const scripts = JSON.parse(fs50.readFileSync(pkgPath, "utf8")).scripts ?? {};
75089
+ const scripts = JSON.parse(fs51.readFileSync(pkgPath, "utf8")).scripts ?? {};
75036
75090
  if (scripts[script]) {
75037
75091
  return script === "test" ? "${NPM_BIN:-npm} test" : `\${NPM_BIN:-npm} run ${script}`;
75038
75092
  }
@@ -75157,7 +75211,7 @@ function ensureEcosystemVerificationStages(repoPath) {
75157
75211
  const skipped = /* @__PURE__ */ new Set();
75158
75212
  for (const stage of defaults.stages) {
75159
75213
  if (stages.some((s) => s.id === stage.id)) continue;
75160
- if (stage.script && !fs50.existsSync(path57.join(harnessDir, stage.script))) {
75214
+ if (stage.script && !fs51.existsSync(path58.join(harnessDir, stage.script))) {
75161
75215
  skipped.add(stage.id);
75162
75216
  continue;
75163
75217
  }
@@ -75215,22 +75269,22 @@ var SHELL_SCRIPTS = [
75215
75269
  function validateHarness(repoPath) {
75216
75270
  const harnessDir = getHarnessDir(repoPath);
75217
75271
  const issues = [];
75218
- if (!fs51.existsSync(harnessDir)) {
75272
+ if (!fs52.existsSync(harnessDir)) {
75219
75273
  return {
75220
75274
  pass: false,
75221
75275
  issues: [{ file: ".har", message: "Harness directory not found", severity: "error" }]
75222
75276
  };
75223
75277
  }
75224
75278
  for (const file of getRequiredFiles(repoPath)) {
75225
- const filePath = path58.join(harnessDir, file);
75226
- if (!fs51.existsSync(filePath)) {
75279
+ const filePath = path59.join(harnessDir, file);
75280
+ if (!fs52.existsSync(filePath)) {
75227
75281
  issues.push({ file, message: "Required file missing", severity: "error" });
75228
75282
  }
75229
75283
  }
75230
75284
  for (const script of SHELL_SCRIPTS) {
75231
- const scriptPath = path58.join(harnessDir, script);
75232
- if (!fs51.existsSync(scriptPath)) continue;
75233
- const stat = fs51.statSync(scriptPath);
75285
+ const scriptPath = path59.join(harnessDir, script);
75286
+ if (!fs52.existsSync(scriptPath)) continue;
75287
+ const stat = fs52.statSync(scriptPath);
75234
75288
  if (!(stat.mode & 73)) {
75235
75289
  issues.push({ file: script, message: "Script is not executable", severity: "warning" });
75236
75290
  }
@@ -75245,9 +75299,9 @@ function validateHarness(repoPath) {
75245
75299
  }
75246
75300
  const manifest = readManifest(repoPath);
75247
75301
  const profile = manifest?.profile ?? "default";
75248
- const ecosystemPath = path58.join(harnessDir, "ecosystem.agent.template.cjs");
75249
- if (profile !== "cli" && fs51.existsSync(ecosystemPath)) {
75250
- const content = fs51.readFileSync(ecosystemPath, "utf8");
75302
+ const ecosystemPath = path59.join(harnessDir, "ecosystem.agent.template.cjs");
75303
+ if (profile !== "cli" && fs52.existsSync(ecosystemPath)) {
75304
+ const content = fs52.readFileSync(ecosystemPath, "utf8");
75251
75305
  if (!content.includes("module.exports")) {
75252
75306
  issues.push({
75253
75307
  file: "ecosystem.agent.template.cjs",
@@ -75256,9 +75310,9 @@ function validateHarness(repoPath) {
75256
75310
  });
75257
75311
  }
75258
75312
  }
75259
- const harnessEnvPath = path58.join(harnessDir, "harness.env");
75260
- if (fs51.existsSync(harnessEnvPath)) {
75261
- const content = fs51.readFileSync(harnessEnvPath, "utf8");
75313
+ const harnessEnvPath = path59.join(harnessDir, "harness.env");
75314
+ if (fs52.existsSync(harnessEnvPath)) {
75315
+ const content = fs52.readFileSync(harnessEnvPath, "utf8");
75262
75316
  if (content.includes("TODO: set migrate command")) {
75263
75317
  issues.push({ file: "harness.env", message: "Migrate command still has TODO", severity: "warning" });
75264
75318
  }
@@ -75274,17 +75328,17 @@ function validateHarness(repoPath) {
75274
75328
  });
75275
75329
  }
75276
75330
  }
75277
- const verifyPath = path58.join(harnessDir, "verify.sh");
75278
- if (fs51.existsSync(verifyPath)) {
75279
- const content = fs51.readFileSync(verifyPath, "utf8");
75331
+ const verifyPath = path59.join(harnessDir, "verify.sh");
75332
+ if (fs52.existsSync(verifyPath)) {
75333
+ const content = fs52.readFileSync(verifyPath, "utf8");
75280
75334
  if (content.includes("echo 'TODO:")) {
75281
75335
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
75282
75336
  }
75283
75337
  }
75284
- const stagesPath = path58.join(harnessDir, "stages.json");
75285
- if (fs51.existsSync(stagesPath)) {
75338
+ const stagesPath = path59.join(harnessDir, "stages.json");
75339
+ if (fs52.existsSync(stagesPath)) {
75286
75340
  try {
75287
- JSON.parse(fs51.readFileSync(stagesPath, "utf8"));
75341
+ JSON.parse(fs52.readFileSync(stagesPath, "utf8"));
75288
75342
  const registry2 = readStageRegistry(repoPath);
75289
75343
  if (registry2.stages.length === 0) {
75290
75344
  issues.push({ file: "stages.json", message: "No harness stages declared", severity: "warning" });
@@ -75306,9 +75360,9 @@ function validateHarness(repoPath) {
75306
75360
  } else {
75307
75361
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
75308
75362
  }
75309
- const readmePath = path58.join(harnessDir, "README.md");
75310
- if (fs51.existsSync(readmePath)) {
75311
- const content = fs51.readFileSync(readmePath, "utf8");
75363
+ const readmePath = path59.join(harnessDir, "README.md");
75364
+ if (fs52.existsSync(readmePath)) {
75365
+ const content = fs52.readFileSync(readmePath, "utf8");
75312
75366
  if (!content.includes(".har")) {
75313
75367
  issues.push({ file: "README.md", message: "README should document .har/ paths", severity: "warning" });
75314
75368
  }
@@ -75322,8 +75376,8 @@ function validateHarness(repoPath) {
75322
75376
  async function smokeTestHarness(repoPath) {
75323
75377
  const harnessDir = getHarnessDir(repoPath);
75324
75378
  const issues = [];
75325
- const setupScript = path58.join(harnessDir, "setup-infra.sh");
75326
- if (fs51.existsSync(setupScript)) {
75379
+ const setupScript = path59.join(harnessDir, "setup-infra.sh");
75380
+ if (fs52.existsSync(setupScript)) {
75327
75381
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
75328
75382
  if (result.code !== 0) {
75329
75383
  issues.push({
@@ -75338,57 +75392,57 @@ async function smokeTestHarness(repoPath) {
75338
75392
  }
75339
75393
 
75340
75394
  // src/harness/maintain-bundle.ts
75341
- var fs57 = __toESM(require("fs"));
75395
+ var fs58 = __toESM(require("fs"));
75342
75396
  var os21 = __toESM(require("os"));
75343
- var path63 = __toESM(require("path"));
75397
+ var path64 = __toESM(require("path"));
75344
75398
  init_file_ops();
75345
75399
  init_shell();
75346
75400
  init_manifest();
75347
75401
 
75348
75402
  // src/harness/plugin-drift.ts
75349
- var fs56 = __toESM(require("fs"));
75350
- var path62 = __toESM(require("path"));
75403
+ var fs57 = __toESM(require("fs"));
75404
+ var path63 = __toESM(require("path"));
75351
75405
  init_manifest();
75352
75406
 
75353
75407
  // src/harness/plugins.ts
75354
- var fs55 = __toESM(require("fs"));
75355
- var path61 = __toESM(require("path"));
75408
+ var fs56 = __toESM(require("fs"));
75409
+ var path62 = __toESM(require("path"));
75356
75410
  init_zod();
75357
75411
  init_logging();
75358
75412
  init_paths();
75359
75413
 
75360
75414
  // src/harness/parser.ts
75361
- var fs52 = __toESM(require("fs"));
75415
+ var fs53 = __toESM(require("fs"));
75362
75416
  init_manifest();
75363
75417
  function harnessExists(repoPath) {
75364
- return fs52.existsSync(`${repoPath}/.har/setup-infra.sh`);
75418
+ return fs53.existsSync(`${repoPath}/.har/stages.json`);
75365
75419
  }
75366
75420
 
75367
75421
  // src/harness/plugin-resolve.ts
75368
75422
  var import_child_process16 = require("child_process");
75369
- var fs53 = __toESM(require("fs"));
75423
+ var fs54 = __toESM(require("fs"));
75370
75424
  var os20 = __toESM(require("os"));
75371
- var path59 = __toESM(require("path"));
75425
+ var path60 = __toESM(require("path"));
75372
75426
  init_paths();
75373
75427
  var LOCAL_PLUGINS_DIR = ".har/plugins";
75374
75428
  function hasManifest(dir) {
75375
- return fs53.existsSync(path59.join(dir, "template.manifest.json"));
75429
+ return fs54.existsSync(path60.join(dir, "template.manifest.json"));
75376
75430
  }
75377
75431
  function readPackageVersion(dir) {
75378
- const pkgPath = path59.join(dir, "package.json");
75379
- if (!fs53.existsSync(pkgPath)) return void 0;
75432
+ const pkgPath = path60.join(dir, "package.json");
75433
+ if (!fs54.existsSync(pkgPath)) return void 0;
75380
75434
  try {
75381
- const pkg = JSON.parse(fs53.readFileSync(pkgPath, "utf8"));
75435
+ const pkg = JSON.parse(fs54.readFileSync(pkgPath, "utf8"));
75382
75436
  return typeof pkg.version === "string" ? pkg.version : void 0;
75383
75437
  } catch {
75384
75438
  return void 0;
75385
75439
  }
75386
75440
  }
75387
75441
  function readManifestId(dir) {
75388
- const manifestPath = path59.join(dir, "template.manifest.json");
75389
- if (!fs53.existsSync(manifestPath)) return void 0;
75442
+ const manifestPath = path60.join(dir, "template.manifest.json");
75443
+ if (!fs54.existsSync(manifestPath)) return void 0;
75390
75444
  try {
75391
- const raw = JSON.parse(fs53.readFileSync(manifestPath, "utf8"));
75445
+ const raw = JSON.parse(fs54.readFileSync(manifestPath, "utf8"));
75392
75446
  return typeof raw.id === "string" ? raw.id : void 0;
75393
75447
  } catch {
75394
75448
  return void 0;
@@ -75406,28 +75460,28 @@ function looksLikeNpm(spec) {
75406
75460
  return /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(@.+)?$/i.test(spec);
75407
75461
  }
75408
75462
  function resolveBundledDir(pluginId) {
75409
- const dir = path59.join(resolveTemplatesDir(), "plugins", pluginId);
75463
+ const dir = path60.join(resolveTemplatesDir(), "plugins", pluginId);
75410
75464
  return hasManifest(dir) ? dir : null;
75411
75465
  }
75412
75466
  function expandHome(p) {
75413
- if (p.startsWith("~/")) return path59.join(os20.homedir(), p.slice(2));
75467
+ if (p.startsWith("~/")) return path60.join(os20.homedir(), p.slice(2));
75414
75468
  if (p === "~") return os20.homedir();
75415
75469
  return p;
75416
75470
  }
75417
75471
  function isLocalPluginDir(dir, repoPath) {
75418
- const localRoot = path59.resolve(repoPath, LOCAL_PLUGINS_DIR);
75419
- return path59.dirname(dir) === localRoot;
75472
+ const localRoot = path60.resolve(repoPath, LOCAL_PLUGINS_DIR);
75473
+ return path60.dirname(dir) === localRoot;
75420
75474
  }
75421
75475
  function resolvePathSpec(spec, repoPath) {
75422
75476
  const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
75423
- const dir = path59.resolve(expandHome(raw));
75424
- if (!fs53.existsSync(dir) || !fs53.statSync(dir).isDirectory()) {
75477
+ const dir = path60.resolve(expandHome(raw));
75478
+ if (!fs54.existsSync(dir) || !fs54.statSync(dir).isDirectory()) {
75425
75479
  throw new Error(`Plugin path not found: ${spec}`);
75426
75480
  }
75427
75481
  if (!hasManifest(dir)) {
75428
75482
  throw new Error(`No template.manifest.json in ${dir}`);
75429
75483
  }
75430
- const id = readManifestId(dir) ?? path59.basename(dir);
75484
+ const id = readManifestId(dir) ?? path60.basename(dir);
75431
75485
  return {
75432
75486
  id,
75433
75487
  kind: isLocalPluginDir(dir, repoPath) ? "local" : "path",
@@ -75438,11 +75492,11 @@ function resolvePathSpec(spec, repoPath) {
75438
75492
  };
75439
75493
  }
75440
75494
  function resolveLocalDir(pluginId, repoPath) {
75441
- const dir = path59.resolve(repoPath, LOCAL_PLUGINS_DIR, pluginId);
75495
+ const dir = path60.resolve(repoPath, LOCAL_PLUGINS_DIR, pluginId);
75442
75496
  return hasManifest(dir) ? dir : null;
75443
75497
  }
75444
75498
  function makeTempDir(prefix) {
75445
- return fs53.mkdtempSync(path59.join(os20.tmpdir(), prefix));
75499
+ return fs54.mkdtempSync(path60.join(os20.tmpdir(), prefix));
75446
75500
  }
75447
75501
  function resolveNpmSpec(spec) {
75448
75502
  const tmp = makeTempDir("har-plugin-npm-");
@@ -75453,20 +75507,20 @@ function resolveNpmSpec(spec) {
75453
75507
  stdio: ["ignore", "pipe", "pipe"],
75454
75508
  timeout: 12e4
75455
75509
  });
75456
- const tarballs = fs53.readdirSync(tmp).filter((f) => f.endsWith(".tgz"));
75510
+ const tarballs = fs54.readdirSync(tmp).filter((f) => f.endsWith(".tgz"));
75457
75511
  if (tarballs.length === 0) {
75458
75512
  throw new Error(`npm pack produced no tarball for ${spec}`);
75459
75513
  }
75460
- const extractDir = path59.join(tmp, "extract");
75461
- fs53.mkdirSync(extractDir);
75462
- (0, import_child_process16.execFileSync)("tar", ["-xzf", path59.join(tmp, tarballs[0]), "-C", extractDir], {
75514
+ const extractDir = path60.join(tmp, "extract");
75515
+ fs54.mkdirSync(extractDir);
75516
+ (0, import_child_process16.execFileSync)("tar", ["-xzf", path60.join(tmp, tarballs[0]), "-C", extractDir], {
75463
75517
  encoding: "utf8",
75464
75518
  stdio: ["ignore", "pipe", "pipe"]
75465
75519
  });
75466
- const packageDir = path59.join(extractDir, "package");
75520
+ const packageDir = path60.join(extractDir, "package");
75467
75521
  let dir = packageDir;
75468
75522
  if (!hasManifest(dir)) {
75469
- const nested = fs53.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path59.join(extractDir, e.name)).find((d) => hasManifest(d));
75523
+ const nested = fs54.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path60.join(extractDir, e.name)).find((d) => hasManifest(d));
75470
75524
  if (!nested) {
75471
75525
  throw new Error(
75472
75526
  `npm package ${spec} has no template.manifest.json (not a HAR plugin bundle)`
@@ -75485,7 +75539,7 @@ function resolveNpmSpec(spec) {
75485
75539
  };
75486
75540
  } catch (err) {
75487
75541
  for (const d of cleanupDirs) {
75488
- fs53.rmSync(d, { recursive: true, force: true });
75542
+ fs54.rmSync(d, { recursive: true, force: true });
75489
75543
  }
75490
75544
  const message = err instanceof Error ? err.message : String(err);
75491
75545
  throw new Error(`Failed to install plugin from npm (${spec}): ${message}`);
@@ -75494,7 +75548,7 @@ function resolveNpmSpec(spec) {
75494
75548
  function resolveGitSpec(spec) {
75495
75549
  const tmp = makeTempDir("har-plugin-git-");
75496
75550
  const cleanupDirs = [tmp];
75497
- const cloneDir = path59.join(tmp, "repo");
75551
+ const cloneDir = path60.join(tmp, "repo");
75498
75552
  try {
75499
75553
  let url = spec;
75500
75554
  if (spec.startsWith("github:")) {
@@ -75513,16 +75567,16 @@ function resolveGitSpec(spec) {
75513
75567
  });
75514
75568
  let dir = cloneDir;
75515
75569
  if (!hasManifest(dir)) {
75516
- const pluginsRoot = path59.join(cloneDir, "plugins");
75517
- if (fs53.existsSync(pluginsRoot)) {
75518
- const child = fs53.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path59.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
75570
+ const pluginsRoot = path60.join(cloneDir, "plugins");
75571
+ if (fs54.existsSync(pluginsRoot)) {
75572
+ const child = fs54.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path60.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
75519
75573
  if (child) dir = child;
75520
75574
  }
75521
75575
  }
75522
75576
  if (!hasManifest(dir)) {
75523
75577
  throw new Error(`Git repo ${spec} has no template.manifest.json (not a HAR plugin bundle)`);
75524
75578
  }
75525
- const id = readManifestId(dir) ?? path59.basename(url.replace(/\.git$/, ""));
75579
+ const id = readManifestId(dir) ?? path60.basename(url.replace(/\.git$/, ""));
75526
75580
  return {
75527
75581
  id,
75528
75582
  kind: "git",
@@ -75533,7 +75587,7 @@ function resolveGitSpec(spec) {
75533
75587
  };
75534
75588
  } catch (err) {
75535
75589
  for (const d of cleanupDirs) {
75536
- fs53.rmSync(d, { recursive: true, force: true });
75590
+ fs54.rmSync(d, { recursive: true, force: true });
75537
75591
  }
75538
75592
  const message = err instanceof Error ? err.message : String(err);
75539
75593
  throw new Error(`Failed to install plugin from git (${spec}): ${message}`);
@@ -75601,24 +75655,24 @@ function knownPluginsHint(repoPath) {
75601
75655
  return parts.join(" ");
75602
75656
  }
75603
75657
  function listLocalPluginIds(repoPath = ".") {
75604
- const root = path59.resolve(repoPath, LOCAL_PLUGINS_DIR);
75605
- if (!fs53.existsSync(root)) return [];
75606
- return fs53.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path59.join(root, name))).sort();
75658
+ const root = path60.resolve(repoPath, LOCAL_PLUGINS_DIR);
75659
+ if (!fs54.existsSync(root)) return [];
75660
+ return fs54.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path60.join(root, name))).sort();
75607
75661
  }
75608
75662
  function listBundledPluginIds() {
75609
- const root = path59.join(resolveTemplatesDir(), "plugins");
75610
- if (!fs53.existsSync(root)) return [];
75611
- return fs53.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path59.join(root, name))).sort();
75663
+ const root = path60.join(resolveTemplatesDir(), "plugins");
75664
+ if (!fs54.existsSync(root)) return [];
75665
+ return fs54.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path60.join(root, name))).sort();
75612
75666
  }
75613
75667
  function cleanupResolvedPlugin(source) {
75614
75668
  for (const dir of source.cleanupDirs) {
75615
- fs53.rmSync(dir, { recursive: true, force: true });
75669
+ fs54.rmSync(dir, { recursive: true, force: true });
75616
75670
  }
75617
75671
  }
75618
75672
 
75619
75673
  // src/harness/plugin-prompt.ts
75620
- var fs54 = __toESM(require("fs"));
75621
- var path60 = __toESM(require("path"));
75674
+ var fs55 = __toESM(require("fs"));
75675
+ var path61 = __toESM(require("path"));
75622
75676
  init_paths();
75623
75677
  init_file_ops();
75624
75678
  init_node_pm();
@@ -75634,7 +75688,7 @@ function loadTemplate() {
75634
75688
  "Plugin adaptation prompt template not found: adaptation-prompt-plugin.md. Run npm run build."
75635
75689
  );
75636
75690
  }
75637
- return fs54.readFileSync(filePath, "utf8");
75691
+ return fs55.readFileSync(filePath, "utf8");
75638
75692
  }
75639
75693
  function resolveInstallCommand(repoPath) {
75640
75694
  const env3 = readHarnessEnv(repoPath);
@@ -75660,7 +75714,7 @@ function buildPluginAdaptationPrompt(repoPath, result) {
75660
75714
  return loadTemplate().replace(/\{\{PLUGIN_ID\}\}/g, result.pluginId).replace(/\{\{STAGE_IDS\}\}/g, result.stageIds.map((id) => `\`${id}\``).join(", ")).replace(/\{\{DOCS_PATH\}\}/g, result.docsPath).replace("{{PACKAGE_MERGE_NOTE}}", packageMergeNote).replace("{{PLUGIN_SETUP_STEPS}}", setupSteps || "_No plugin-specific setup steps declared._").replace("{{FILES_WRITTEN}}", filesWritten || " - _(no scaffolded files)_");
75661
75715
  }
75662
75716
  function writePluginAdaptationPrompt(repoPath, pluginId, content) {
75663
- const filePath = path60.join(getHarnessDir(repoPath), pluginAdaptationPromptFile(pluginId));
75717
+ const filePath = path61.join(getHarnessDir(repoPath), pluginAdaptationPromptFile(pluginId));
75664
75718
  writeFileSafe(filePath, content);
75665
75719
  return filePath;
75666
75720
  }
@@ -75713,19 +75767,19 @@ function primaryStageId(manifest) {
75713
75767
  return manifest.stageId ?? stages[0].id;
75714
75768
  }
75715
75769
  function resolveBundledPluginDir(pluginId) {
75716
- const dir = path61.join(resolveTemplatesDir(), "plugins", pluginId);
75717
- if (!fs55.existsSync(dir)) {
75770
+ const dir = path62.join(resolveTemplatesDir(), "plugins", pluginId);
75771
+ if (!fs56.existsSync(dir)) {
75718
75772
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
75719
75773
  }
75720
75774
  return dir;
75721
75775
  }
75722
75776
  function readPluginManifestFromDir(pluginDir, expectedId) {
75723
- const manifestPath = path61.join(pluginDir, "template.manifest.json");
75724
- if (!fs55.existsSync(manifestPath)) {
75777
+ const manifestPath = path62.join(pluginDir, "template.manifest.json");
75778
+ if (!fs56.existsSync(manifestPath)) {
75725
75779
  throw new Error(`No template.manifest.json in ${pluginDir}`);
75726
75780
  }
75727
75781
  const parsed = PluginManifestSchema.safeParse(
75728
- JSON.parse(fs55.readFileSync(manifestPath, "utf8"))
75782
+ JSON.parse(fs56.readFileSync(manifestPath, "utf8"))
75729
75783
  );
75730
75784
  if (!parsed.success) {
75731
75785
  throw new Error(`Invalid plugin manifest: ${parsed.error.message}`);
@@ -75739,40 +75793,40 @@ function readPluginManifest(pluginId) {
75739
75793
  return readPluginManifestFromDir(resolveBundledPluginDir(pluginId), pluginId);
75740
75794
  }
75741
75795
  function ensureParentDir(filePath) {
75742
- const parent = path61.dirname(filePath);
75743
- if (!fs55.existsSync(parent)) {
75744
- fs55.mkdirSync(parent, { recursive: true });
75796
+ const parent = path62.dirname(filePath);
75797
+ if (!fs56.existsSync(parent)) {
75798
+ fs56.mkdirSync(parent, { recursive: true });
75745
75799
  }
75746
75800
  }
75747
75801
  function copyPluginFile(pluginDir, file, repoPath, force) {
75748
- const srcPath = path61.join(pluginDir, file.src);
75749
- const destPath = path61.join(repoPath, file.dest);
75750
- if (!fs55.existsSync(srcPath)) {
75802
+ const srcPath = path62.join(pluginDir, file.src);
75803
+ const destPath = path62.join(repoPath, file.dest);
75804
+ if (!fs56.existsSync(srcPath)) {
75751
75805
  throw new Error(`Plugin file missing: ${file.src}`);
75752
75806
  }
75753
- if (fs55.existsSync(destPath) && !force) {
75807
+ if (fs56.existsSync(destPath) && !force) {
75754
75808
  throw new Error(
75755
75809
  `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
75756
75810
  );
75757
75811
  }
75758
75812
  ensureParentDir(destPath);
75759
- fs55.copyFileSync(srcPath, destPath);
75813
+ fs56.copyFileSync(srcPath, destPath);
75760
75814
  if (file.executable) {
75761
- fs55.chmodSync(destPath, 493);
75815
+ fs56.chmodSync(destPath, 493);
75762
75816
  }
75763
75817
  return { written: true, path: file.dest };
75764
75818
  }
75765
75819
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
75766
- const packagePath = path61.join(repoPath, "package.json");
75767
- if (!fs55.existsSync(packagePath)) {
75820
+ const packagePath = path62.join(repoPath, "package.json");
75821
+ if (!fs56.existsSync(packagePath)) {
75768
75822
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
75769
75823
  }
75770
- const fragmentPath = path61.join(pluginDir, fragmentRelPath);
75771
- if (!fs55.existsSync(fragmentPath)) {
75824
+ const fragmentPath = path62.join(pluginDir, fragmentRelPath);
75825
+ if (!fs56.existsSync(fragmentPath)) {
75772
75826
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
75773
75827
  }
75774
- const pkg = JSON.parse(fs55.readFileSync(packagePath, "utf8"));
75775
- const fragment = JSON.parse(fs55.readFileSync(fragmentPath, "utf8"));
75828
+ const pkg = JSON.parse(fs56.readFileSync(packagePath, "utf8"));
75829
+ const fragment = JSON.parse(fs56.readFileSync(fragmentPath, "utf8"));
75776
75830
  for (const section of ["scripts", "devDependencies"]) {
75777
75831
  const existing = pkg[section] ?? {};
75778
75832
  const incoming = fragment[section] ?? {};
@@ -75785,7 +75839,7 @@ function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
75785
75839
  }
75786
75840
  pkg[section] = existing;
75787
75841
  }
75788
- fs55.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
75842
+ fs56.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
75789
75843
  }
75790
75844
  function patchStageRegistry(repoPath, stages, verificationStageIds, force) {
75791
75845
  const registry2 = readStageRegistry(repoPath);
@@ -75814,15 +75868,15 @@ function patchStageRegistry(repoPath, stages, verificationStageIds, force) {
75814
75868
  }
75815
75869
  function assertHarnessPresent(repoPath) {
75816
75870
  if (!harnessExists(repoPath)) {
75817
- throw new Error('No .har/ harness found. Run "har env init" first.');
75871
+ throw new Error('No .har/ harness found. Run "har onboard" first.');
75818
75872
  }
75819
75873
  }
75820
75874
  function assertStagesNotPresent(repoPath, stageIds, force) {
75821
75875
  if (force) return;
75822
75876
  const registry2 = readStageRegistry(repoPath);
75823
75877
  for (const stageId of stageIds) {
75824
- const scriptPath = path61.join(repoPath, ".har", "stages", `${stageId}.sh`);
75825
- if (fs55.existsSync(scriptPath)) {
75878
+ const scriptPath = path62.join(repoPath, ".har", "stages", `${stageId}.sh`);
75879
+ if (fs56.existsSync(scriptPath)) {
75826
75880
  throw new Error(
75827
75881
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
75828
75882
  );
@@ -75835,7 +75889,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
75835
75889
  }
75836
75890
  }
75837
75891
  function applyPluginFromDir(repoPath, pluginDir, options, meta) {
75838
- const resolved = path61.resolve(repoPath);
75892
+ const resolved = path62.resolve(repoPath);
75839
75893
  const force = options.force ?? false;
75840
75894
  const warnings = [];
75841
75895
  const filesWritten = [];
@@ -75855,7 +75909,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
75855
75909
  if (file.skipFlag === "skipCi" && options.skipCi) {
75856
75910
  continue;
75857
75911
  }
75858
- if (fs55.existsSync(path61.join(resolved, file.dest)) && !force) {
75912
+ if (fs56.existsSync(path62.join(resolved, file.dest)) && !force) {
75859
75913
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
75860
75914
  continue;
75861
75915
  }
@@ -75896,7 +75950,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
75896
75950
  adaptPromptPath: ""
75897
75951
  });
75898
75952
  const promptAbsPath = writePluginAdaptationPrompt(resolved, manifest.id, promptContent);
75899
- const adaptPromptPath = path61.relative(resolved, promptAbsPath);
75953
+ const adaptPromptPath = path62.relative(resolved, promptAbsPath);
75900
75954
  success(`Applied plugin: ${manifest.id}`);
75901
75955
  info(`Registered stage(s): ${stageIds.join(", ")}`);
75902
75956
  for (const file of filesWritten) {
@@ -75930,13 +75984,13 @@ init_stages();
75930
75984
  init_paths();
75931
75985
  var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
75932
75986
  function detectInstalledPlugins(repoPath) {
75933
- const resolved = path62.resolve(repoPath);
75987
+ const resolved = path63.resolve(repoPath);
75934
75988
  const ledger = readPluginLedger(resolved);
75935
75989
  if (ledger && ledger.plugins.length > 0) {
75936
75990
  return ledger.plugins.map((p) => p.id).sort();
75937
75991
  }
75938
- const registryPath = path62.join(resolved, ".har", "stages.json");
75939
- if (!fs56.existsSync(registryPath)) return [];
75992
+ const registryPath = path63.join(resolved, ".har", "stages.json");
75993
+ if (!fs57.existsSync(registryPath)) return [];
75940
75994
  const registry2 = readStageRegistry(resolved);
75941
75995
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
75942
75996
  const installed = [];
@@ -75953,18 +76007,18 @@ function detectInstalledPlugins(repoPath) {
75953
76007
  return installed.sort();
75954
76008
  }
75955
76009
  function resolvePluginBaseline(repoPath, pluginId) {
75956
- const resolved = path62.resolve(repoPath);
76010
+ const resolved = path63.resolve(repoPath);
75957
76011
  const ledger = readPluginLedger(resolved);
75958
76012
  const entry = ledger?.plugins.find((p) => p.id === pluginId);
75959
76013
  if (entry?.source === "local") {
75960
- const localDir = path62.join(resolved, LOCAL_PLUGINS_DIR, pluginId);
75961
- if (fs56.existsSync(path62.join(localDir, "template.manifest.json"))) {
76014
+ const localDir = path63.join(resolved, LOCAL_PLUGINS_DIR, pluginId);
76015
+ if (fs57.existsSync(path63.join(localDir, "template.manifest.json"))) {
75962
76016
  return { kind: "local", dir: localDir, manifest: readPluginManifestFromDir(localDir) };
75963
76017
  }
75964
76018
  return null;
75965
76019
  }
75966
- const bundled = path62.join(resolveTemplatesDir(), "plugins", pluginId);
75967
- if (fs56.existsSync(path62.join(bundled, "template.manifest.json"))) {
76020
+ const bundled = path63.join(resolveTemplatesDir(), "plugins", pluginId);
76021
+ if (fs57.existsSync(path63.join(bundled, "template.manifest.json"))) {
75968
76022
  return { kind: "bundled", dir: bundled, manifest: readPluginManifestFromDir(bundled) };
75969
76023
  }
75970
76024
  return null;
@@ -75977,14 +76031,14 @@ function requireBaseline(repoPath, pluginId) {
75977
76031
  return baseline;
75978
76032
  }
75979
76033
  function readBaselineFile(baseline, srcRel) {
75980
- return fs56.readFileSync(path62.join(baseline.dir, srcRel), "utf8");
76034
+ return fs57.readFileSync(path63.join(baseline.dir, srcRel), "utf8");
75981
76035
  }
75982
76036
  function listPluginDestPaths(baseline, repoPath) {
75983
76037
  const manifest = baseline.manifest;
75984
76038
  const paths = manifest.files.map((file) => file.dest);
75985
76039
  if (manifest.optionalFiles) {
75986
76040
  for (const file of manifest.optionalFiles) {
75987
- if (fs56.existsSync(path62.join(repoPath, file.dest))) {
76041
+ if (fs57.existsSync(path63.join(repoPath, file.dest))) {
75988
76042
  paths.push(file.dest);
75989
76043
  }
75990
76044
  }
@@ -76043,9 +76097,9 @@ function readTemplatePluginFile(repoPath, pluginId, dest) {
76043
76097
  return null;
76044
76098
  }
76045
76099
  function readInstalledPluginFile(repoPath, pluginId, dest) {
76046
- const installedPath = path62.join(path62.resolve(repoPath), dest);
76047
- if (!fs56.existsSync(installedPath)) return null;
76048
- const content = fs56.readFileSync(installedPath, "utf8");
76100
+ const installedPath = path63.join(path63.resolve(repoPath), dest);
76101
+ if (!fs57.existsSync(installedPath)) return null;
76102
+ const content = fs57.readFileSync(installedPath, "utf8");
76049
76103
  const baseline = requireBaseline(repoPath, pluginId);
76050
76104
  const fragmentRel = baseline.manifest.merge?.[dest];
76051
76105
  if (fragmentRel) {
@@ -76069,7 +76123,7 @@ function pluginActionHint(pluginId, dest, kind, baseline) {
76069
76123
  return `Merge maintain/plugins/${pluginId}/diffs/${dest}.diff or run: har env add-plugin ${pluginId} --force`;
76070
76124
  }
76071
76125
  function comparePluginToTemplate(repoPath, pluginId) {
76072
- const resolved = path62.resolve(repoPath);
76126
+ const resolved = path63.resolve(repoPath);
76073
76127
  const baseline = requireBaseline(resolved, pluginId);
76074
76128
  const manifest = baseline.manifest;
76075
76129
  const destPaths = listPluginDestPaths(baseline, resolved);
@@ -76086,8 +76140,8 @@ function comparePluginToTemplate(repoPath, pluginId) {
76086
76140
  }
76087
76141
  if (dest === "package.json") {
76088
76142
  const fragmentRel = manifest.merge?.[dest];
76089
- const installedPath = path62.join(resolved, dest);
76090
- const installedRaw = fs56.readFileSync(installedPath, "utf8");
76143
+ const installedPath = path63.join(resolved, dest);
76144
+ const installedRaw = fs57.readFileSync(installedPath, "utf8");
76091
76145
  if (fragmentRel && pluginKeysMatch(installedRaw, readBaselineFile(baseline, fragmentRel))) {
76092
76146
  unchanged.push(dest);
76093
76147
  } else if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
@@ -76149,7 +76203,7 @@ init_profiles();
76149
76203
  var MAINTAIN_DIR = "maintain";
76150
76204
  var substituteProjectName2 = substituteTemplateTokens;
76151
76205
  function projectNameFromRepo(repoPath) {
76152
- return path63.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
76206
+ return path64.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
76153
76207
  }
76154
76208
  function readBundledTemplateContent(repoPath, profile, file) {
76155
76209
  const entry = composeProfileTemplateMap(profile).get(templateFileForHarness(file));
@@ -76174,7 +76228,7 @@ function staleFileHint(file) {
76174
76228
  function actionHint(file, kind) {
76175
76229
  if (kind === "missing") {
76176
76230
  if (file === "provision-toolchain.sh") {
76177
- return "Add this file and ensure launch.sh calls it to provision the toolchain.";
76231
+ return "Add this file and ensure a post-launch hook (or HARNESS_INSTALL_CMD) provisions the toolchain.";
76178
76232
  }
76179
76233
  return `Copy/adapt from maintain/templates/${file} into .har/${file}.`;
76180
76234
  }
@@ -76187,12 +76241,12 @@ function actionHint(file, kind) {
76187
76241
  return `Upstream template updated since your last finalize \u2014 read maintain/diffs/${file}.diff and apply into .har/${file}.`;
76188
76242
  }
76189
76243
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
76190
- const tmpDir = fs57.mkdtempSync(path63.join(os21.tmpdir(), "har-maintain-diff-"));
76244
+ const tmpDir = fs58.mkdtempSync(path64.join(os21.tmpdir(), "har-maintain-diff-"));
76191
76245
  try {
76192
- const installedPath = path63.join(tmpDir, "installed");
76193
- const templatePath = path63.join(tmpDir, "template");
76194
- fs57.writeFileSync(installedPath, installedContent);
76195
- fs57.writeFileSync(templatePath, templateContent);
76246
+ const installedPath = path64.join(tmpDir, "installed");
76247
+ const templatePath = path64.join(tmpDir, "template");
76248
+ fs58.writeFileSync(installedPath, installedContent);
76249
+ fs58.writeFileSync(templatePath, templateContent);
76196
76250
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
76197
76251
  const body = result.stdout.trim();
76198
76252
  if (!body) return "";
@@ -76201,7 +76255,7 @@ function createUnifiedDiff(installedContent, templateContent, installedLabel, te
76201
76255
  ${body.split("\n").slice(2).join("\n")}
76202
76256
  `;
76203
76257
  } finally {
76204
- fs57.rmSync(tmpDir, { recursive: true, force: true });
76258
+ fs58.rmSync(tmpDir, { recursive: true, force: true });
76205
76259
  }
76206
76260
  }
76207
76261
  function buildActions(repoPath, profile, drift) {
@@ -76220,12 +76274,12 @@ function buildActions(repoPath, profile, drift) {
76220
76274
  ...drift.conflict.map((f) => [f, "conflict"])
76221
76275
  ];
76222
76276
  for (const [file, kind] of upstreamAffected) {
76223
- const installedPath = path63.join(harnessDir, file);
76277
+ const installedPath = path64.join(harnessDir, file);
76224
76278
  actions.push({
76225
76279
  file,
76226
76280
  kind,
76227
76281
  template: `maintain/templates/${file}`,
76228
- installed: fs57.existsSync(installedPath) ? `maintain/installed/${file}` : void 0,
76282
+ installed: fs58.existsSync(installedPath) ? `maintain/installed/${file}` : void 0,
76229
76283
  diff: `maintain/diffs/${file}.diff`,
76230
76284
  hint: actionHint(file, kind)
76231
76285
  });
@@ -76396,28 +76450,28 @@ function buildReadme(report) {
76396
76450
  }
76397
76451
  function writeBundleArtifacts(repoPath, profile, drift, report) {
76398
76452
  const harnessDir = getHarnessDir(repoPath);
76399
- const bundleDir = path63.join(harnessDir, MAINTAIN_DIR);
76400
- if (fs57.existsSync(bundleDir)) {
76401
- fs57.rmSync(bundleDir, { recursive: true, force: true });
76453
+ const bundleDir = path64.join(harnessDir, MAINTAIN_DIR);
76454
+ if (fs58.existsSync(bundleDir)) {
76455
+ fs58.rmSync(bundleDir, { recursive: true, force: true });
76402
76456
  }
76403
76457
  const dirs = [
76404
76458
  bundleDir,
76405
- path63.join(bundleDir, "templates"),
76406
- path63.join(bundleDir, "installed"),
76407
- path63.join(bundleDir, "diffs"),
76408
- path63.join(bundleDir, "stale")
76459
+ path64.join(bundleDir, "templates"),
76460
+ path64.join(bundleDir, "installed"),
76461
+ path64.join(bundleDir, "diffs"),
76462
+ path64.join(bundleDir, "stale")
76409
76463
  ];
76410
76464
  for (const dir of dirs) {
76411
- fs57.mkdirSync(dir, { recursive: true });
76465
+ fs58.mkdirSync(dir, { recursive: true });
76412
76466
  }
76413
76467
  const affectedFiles = [...drift.missing, ...drift.upstreamUpdated, ...drift.conflict];
76414
76468
  for (const file of affectedFiles) {
76415
76469
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
76416
- writeFileSafe(path63.join(bundleDir, "templates", file), templateContent);
76417
- const harnessPath = path63.join(harnessDir, file);
76418
- if (fs57.existsSync(harnessPath)) {
76419
- const installedContent = fs57.readFileSync(harnessPath, "utf8");
76420
- writeFileSafe(path63.join(bundleDir, "installed", file), installedContent);
76470
+ writeFileSafe(path64.join(bundleDir, "templates", file), templateContent);
76471
+ const harnessPath = path64.join(harnessDir, file);
76472
+ if (fs58.existsSync(harnessPath)) {
76473
+ const installedContent = fs58.readFileSync(harnessPath, "utf8");
76474
+ writeFileSafe(path64.join(bundleDir, "installed", file), installedContent);
76421
76475
  const diff = createUnifiedDiff(
76422
76476
  installedContent,
76423
76477
  templateContent,
@@ -76425,14 +76479,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
76425
76479
  `templates/${file}`
76426
76480
  );
76427
76481
  if (diff) {
76428
- writeFileSafe(path63.join(bundleDir, "diffs", `${file}.diff`), diff);
76482
+ writeFileSafe(path64.join(bundleDir, "diffs", `${file}.diff`), diff);
76429
76483
  }
76430
76484
  }
76431
76485
  }
76432
- writeFileSafe(path63.join(bundleDir, "README.md"), buildReadme(report));
76433
- writeFileSafe(path63.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
76486
+ writeFileSafe(path64.join(bundleDir, "README.md"), buildReadme(report));
76487
+ writeFileSafe(path64.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
76434
76488
  writeFileSafe(
76435
- path63.join(bundleDir, "validation.json"),
76489
+ path64.join(bundleDir, "validation.json"),
76436
76490
  JSON.stringify(report.validation, null, 2) + "\n"
76437
76491
  );
76438
76492
  if (report.stale.length > 0) {
@@ -76444,34 +76498,34 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
76444
76498
  ...report.stale.map((s) => `- **${s.file}** \u2014 ${s.hint}`),
76445
76499
  ""
76446
76500
  ];
76447
- writeFileSafe(path63.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
76501
+ writeFileSafe(path64.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
76448
76502
  }
76449
76503
  return bundleDir;
76450
76504
  }
76451
76505
  function ensureParentDir2(filePath) {
76452
- const parent = path63.dirname(filePath);
76453
- if (!fs57.existsSync(parent)) {
76454
- fs57.mkdirSync(parent, { recursive: true });
76506
+ const parent = path64.dirname(filePath);
76507
+ if (!fs58.existsSync(parent)) {
76508
+ fs58.mkdirSync(parent, { recursive: true });
76455
76509
  }
76456
76510
  }
76457
76511
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
76458
76512
  if (report.pluginActions.length === 0) return;
76459
76513
  for (const action of report.pluginActions) {
76460
- const pluginRoot = path63.join(bundleDir, "plugins", action.pluginId);
76461
- const templatesDir = path63.join(pluginRoot, "templates");
76462
- const installedDir = path63.join(pluginRoot, "installed");
76463
- const diffsDir = path63.join(pluginRoot, "diffs");
76514
+ const pluginRoot = path64.join(bundleDir, "plugins", action.pluginId);
76515
+ const templatesDir = path64.join(pluginRoot, "templates");
76516
+ const installedDir = path64.join(pluginRoot, "installed");
76517
+ const diffsDir = path64.join(pluginRoot, "diffs");
76464
76518
  for (const dir of [templatesDir, installedDir, diffsDir]) {
76465
- fs57.mkdirSync(dir, { recursive: true });
76519
+ fs58.mkdirSync(dir, { recursive: true });
76466
76520
  }
76467
76521
  const templateContent = readTemplatePluginFile(repoPath, action.pluginId, action.file);
76468
76522
  if (templateContent === null) continue;
76469
- const templatePath = path63.join(templatesDir, action.file);
76523
+ const templatePath = path64.join(templatesDir, action.file);
76470
76524
  ensureParentDir2(templatePath);
76471
76525
  writeFileSafe(templatePath, templateContent);
76472
76526
  const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
76473
76527
  if (installedContent !== null) {
76474
- const installedPath = path63.join(installedDir, action.file);
76528
+ const installedPath = path64.join(installedDir, action.file);
76475
76529
  ensureParentDir2(installedPath);
76476
76530
  writeFileSafe(installedPath, installedContent);
76477
76531
  const diff = createUnifiedDiff(
@@ -76481,7 +76535,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
76481
76535
  `templates/${action.file}`
76482
76536
  );
76483
76537
  if (diff) {
76484
- const diffPath = path63.join(diffsDir, `${action.file}.diff`);
76538
+ const diffPath = path64.join(diffsDir, `${action.file}.diff`);
76485
76539
  ensureParentDir2(diffPath);
76486
76540
  writeFileSafe(diffPath, diff);
76487
76541
  }
@@ -76517,9 +76571,9 @@ function buildMaintainBundle(repoPath, validation2, drift) {
76517
76571
  return { bundleDir, report };
76518
76572
  }
76519
76573
  function removeMaintainBundle(repoPath) {
76520
- const bundleDir = path63.join(getHarnessDir(repoPath), MAINTAIN_DIR);
76521
- if (fs57.existsSync(bundleDir)) {
76522
- fs57.rmSync(bundleDir, { recursive: true, force: true });
76574
+ const bundleDir = path64.join(getHarnessDir(repoPath), MAINTAIN_DIR);
76575
+ if (fs58.existsSync(bundleDir)) {
76576
+ fs58.rmSync(bundleDir, { recursive: true, force: true });
76523
76577
  }
76524
76578
  }
76525
76579
  function formatMaintainBundlePromptSection(report) {
@@ -76628,85 +76682,62 @@ init_manifest();
76628
76682
  init_stages();
76629
76683
 
76630
76684
  // src/harness/doctor.ts
76631
- var fs60 = __toESM(require("fs"));
76632
- var path66 = __toESM(require("path"));
76685
+ var fs61 = __toESM(require("fs"));
76686
+ var path67 = __toESM(require("path"));
76633
76687
  init_slot_registry();
76634
76688
 
76635
76689
  // src/harness/eject.ts
76636
- var fs58 = __toESM(require("fs"));
76637
- var path64 = __toESM(require("path"));
76690
+ var fs59 = __toESM(require("fs"));
76691
+ var path65 = __toESM(require("path"));
76638
76692
  init_package_version();
76639
76693
  init_manifest();
76640
- init_profiles();
76641
76694
  var EJECTED_RUNTIME_DIR = "runtime";
76642
76695
  var EJECTED_RUNTIME_BUNDLE = "har.cjs";
76643
76696
  function resolveRuntimeBundleSource() {
76644
76697
  if (process.env.HAR_EJECT_RUNTIME_SOURCE) {
76645
- return fs58.existsSync(process.env.HAR_EJECT_RUNTIME_SOURCE) ? process.env.HAR_EJECT_RUNTIME_SOURCE : null;
76698
+ return fs59.existsSync(process.env.HAR_EJECT_RUNTIME_SOURCE) ? process.env.HAR_EJECT_RUNTIME_SOURCE : null;
76646
76699
  }
76647
76700
  const candidates = [
76648
76701
  // Bundled CLI: __dirname is dist/ and index.js is the self-contained runtime.
76649
- path64.join(__dirname, "index.js"),
76702
+ path65.join(__dirname, "index.js"),
76650
76703
  // Dev (tsx src/…): fall back to a previously built dist/ at the repo root.
76651
- path64.resolve(__dirname, "..", "..", "dist", "index.js")
76704
+ path65.resolve(__dirname, "..", "..", "dist", "index.js")
76652
76705
  ];
76653
76706
  for (const candidate of candidates) {
76654
- if (fs58.existsSync(candidate)) return candidate;
76707
+ if (fs59.existsSync(candidate)) return candidate;
76655
76708
  }
76656
76709
  return null;
76657
76710
  }
76658
- function shimDelegateArgs(templateContent) {
76659
- const match = templateContent.match(/^\s*exec har env (.+)$/m);
76660
- return match ? match[1].trim() : null;
76661
- }
76662
- function usageLine(templateContent) {
76663
- const match = templateContent.match(/^# Usage: (.+)$/m);
76664
- return match ? `# Usage: ${match[1].trim()}` : null;
76665
- }
76666
- function buildEjectedScript(name, delegateArgs, usage2, version2) {
76667
- return [
76668
- "#!/usr/bin/env bash",
76669
- `# EJECTED runtime (har env eject, @osfactory/har@${version2}) \u2014 you own this file`,
76670
- "# and .har/runtime/. HAR maintain/drift will not update them; har env doctor",
76671
- "# still validates the harness contract. Return to managed shims: har env adopt.",
76672
- ...usage2 ? [usage2] : [],
76673
- "set -euo pipefail",
76674
- 'SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"',
76675
- `export HAR_PACKAGE_VERSION="\${HAR_PACKAGE_VERSION:-${version2}}"`,
76676
- `exec node "$SCRIPT_DIR/${EJECTED_RUNTIME_DIR}/${EJECTED_RUNTIME_BUNDLE}" env ${delegateArgs}`,
76677
- ""
76678
- ].join("\n");
76679
- }
76680
76711
  var RUNTIME_README = (version2) => `# .har/runtime/ \u2014 ejected HAR runtime
76681
76712
 
76682
76713
  This directory was created by \`har env eject\`. It contains the complete HAR
76683
- runtime bundle (@osfactory/har@${version2}) that the \`.har/*.sh\` scripts execute
76684
- directly with node. You own these files:
76714
+ runtime bundle (@osfactory/har@${version2}). You own these files:
76685
76715
 
76686
- - HAR will never update them \u2014 \`har env maintain\` treats them as user-owned
76687
- and reports no upstream drift for them.
76716
+ - Drive the harness with \`har env \u2026\` or \`node .har/runtime/har.cjs env \u2026\`.
76717
+ - HAR will never update this directory \u2014 \`har env maintain\` treats it as
76718
+ user-owned and reports no upstream drift for it.
76688
76719
  - \`har env doctor\` still validates the harness contract (harness.env schema,
76689
76720
  stages.json registry, stage scripts, port lanes).
76690
- - Support expectation: issues reproducible with the managed shims are
76721
+ - Support expectation: issues reproducible with the packaged runtime are
76691
76722
  supported; behavior you change in an ejected runtime is yours to maintain.
76692
76723
  - Lifecycle commands that manage templates (\`init\`, \`maintain\`, \`eject\`,
76693
76724
  \`adopt\`, plugins) still require an installed \`har\`.
76694
76725
 
76695
- Return to managed shims (removes this directory, regenerates \`.har/*.sh\`):
76726
+ Return to the packaged runtime (removes this directory):
76696
76727
 
76697
76728
  har env adopt
76698
76729
 
76699
76730
  `;
76700
76731
  function ejectHarness(repoPath) {
76701
- const resolved = path64.resolve(repoPath);
76732
+ const resolved = path65.resolve(repoPath);
76702
76733
  const harnessDir = getHarnessDir(resolved);
76703
76734
  const manifest = readManifest(resolved);
76704
76735
  if (!manifest) {
76705
- throw new Error('No .har/manifest.json found. Run "har env init" first.');
76736
+ throw new Error('No .har/manifest.json found. Run "har onboard" first.');
76706
76737
  }
76707
76738
  if (manifest.ejected) {
76708
76739
  throw new Error(
76709
- `Harness is already ejected (@osfactory/har@${manifest.ejectedVersion ?? "unknown"}). Run "har env adopt" first to return to managed shims.`
76740
+ `Harness is already ejected (@osfactory/har@${manifest.ejectedVersion ?? "unknown"}). Run "har env adopt" first to return to the packaged runtime.`
76710
76741
  );
76711
76742
  }
76712
76743
  const bundleSource = resolveRuntimeBundleSource();
@@ -76714,26 +76745,13 @@ function ejectHarness(repoPath) {
76714
76745
  throw new Error("Cannot locate the built HAR runtime bundle (dist/index.js). Run npm run build.");
76715
76746
  }
76716
76747
  const version2 = getHarPackageVersion();
76717
- const profile = manifest.profile ?? "default";
76718
- const composed = composeProfileTemplateMap(profile);
76719
- const runtimeDir = path64.join(harnessDir, EJECTED_RUNTIME_DIR);
76720
- fs58.mkdirSync(runtimeDir, { recursive: true });
76721
- const runtimeFile = path64.join(runtimeDir, EJECTED_RUNTIME_BUNDLE);
76722
- fs58.copyFileSync(bundleSource, runtimeFile);
76723
- fs58.chmodSync(runtimeFile, 493);
76724
- fs58.writeFileSync(path64.join(runtimeDir, "README.md"), RUNTIME_README(version2));
76725
- const scripts = [];
76726
- for (const shim3 of MANAGED_SHIM_FILES) {
76727
- const source = composed.get(shim3);
76728
- if (!source) continue;
76729
- const templateContent = readComposedTemplateContent(source);
76730
- const delegateArgs = shimDelegateArgs(templateContent);
76731
- if (!delegateArgs) continue;
76732
- const scriptPath = path64.join(harnessDir, shim3);
76733
- fs58.writeFileSync(scriptPath, buildEjectedScript(shim3, delegateArgs, usageLine(templateContent), version2));
76734
- fs58.chmodSync(scriptPath, 493);
76735
- scripts.push(shim3);
76736
- }
76748
+ const runtimeDir = path65.join(harnessDir, EJECTED_RUNTIME_DIR);
76749
+ fs59.mkdirSync(runtimeDir, { recursive: true });
76750
+ const runtimeFile = path65.join(runtimeDir, EJECTED_RUNTIME_BUNDLE);
76751
+ fs59.copyFileSync(bundleSource, runtimeFile);
76752
+ fs59.chmodSync(runtimeFile, 493);
76753
+ fs59.writeFileSync(path65.join(runtimeDir, "README.md"), RUNTIME_README(version2));
76754
+ retireLifecycleShims(resolved);
76737
76755
  writeManifest(resolved, {
76738
76756
  ...manifest,
76739
76757
  ejected: true,
@@ -76741,32 +76759,20 @@ function ejectHarness(repoPath) {
76741
76759
  fileChecksums: computeHarnessChecksums(harnessDir),
76742
76760
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
76743
76761
  });
76744
- return { scripts, runtimeFile, version: version2 };
76762
+ return { scripts: [], runtimeFile, version: version2 };
76745
76763
  }
76746
76764
  function adoptHarness(repoPath) {
76747
- const resolved = path64.resolve(repoPath);
76765
+ const resolved = path65.resolve(repoPath);
76748
76766
  const harnessDir = getHarnessDir(resolved);
76749
76767
  const manifest = readManifest(resolved);
76750
76768
  if (!manifest) {
76751
- throw new Error('No .har/manifest.json found. Run "har env init" first.');
76769
+ throw new Error('No .har/manifest.json found. Run "har onboard" first.');
76752
76770
  }
76753
76771
  if (!manifest.ejected) {
76754
- throw new Error("Harness is not ejected \u2014 the managed shims are already in place.");
76755
- }
76756
- const profile = manifest.profile ?? "default";
76757
- const composed = composeProfileTemplateMap(profile);
76758
- const projectName = path64.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
76759
- const scripts = [];
76760
- for (const shim3 of MANAGED_SHIM_FILES) {
76761
- const source = composed.get(shim3);
76762
- if (!source) continue;
76763
- const rendered = substituteTemplateTokens(readComposedTemplateContent(source), projectName);
76764
- const scriptPath = path64.join(harnessDir, shim3);
76765
- fs58.writeFileSync(scriptPath, rendered);
76766
- fs58.chmodSync(scriptPath, 493);
76767
- scripts.push(shim3);
76772
+ throw new Error("Harness is not ejected \u2014 the packaged runtime is already in use.");
76768
76773
  }
76769
- fs58.rmSync(path64.join(harnessDir, EJECTED_RUNTIME_DIR), { recursive: true, force: true });
76774
+ fs59.rmSync(path65.join(harnessDir, EJECTED_RUNTIME_DIR), { recursive: true, force: true });
76775
+ const retired = retireLifecycleShims(resolved);
76770
76776
  const rest = { ...manifest };
76771
76777
  delete rest.ejected;
76772
76778
  delete rest.ejectedVersion;
@@ -76775,7 +76781,7 @@ function adoptHarness(repoPath) {
76775
76781
  fileChecksums: computeHarnessChecksums(harnessDir),
76776
76782
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
76777
76783
  });
76778
- return { scripts };
76784
+ return { scripts: retired.pruned };
76779
76785
  }
76780
76786
 
76781
76787
  // src/harness/doctor.ts
@@ -76785,16 +76791,16 @@ init_stages();
76785
76791
  init_hooks2();
76786
76792
 
76787
76793
  // src/harness/migrations.ts
76788
- var fs59 = __toESM(require("fs"));
76789
- var path65 = __toESM(require("path"));
76794
+ var fs60 = __toESM(require("fs"));
76795
+ var path66 = __toESM(require("path"));
76790
76796
  init_schema2();
76791
76797
  init_manifest();
76792
76798
  init_profiles();
76793
76799
  init_stages();
76794
76800
  init_manifest();
76795
76801
  var MIGRATE_DIR = "migrate";
76796
- var MIGRATE_BACKUP_DIR = path65.join(MIGRATE_DIR, "backup");
76797
- var MIGRATE_PLAN_FILE = path65.join(MIGRATE_DIR, "plan.json");
76802
+ var MIGRATE_BACKUP_DIR = path66.join(MIGRATE_DIR, "backup");
76803
+ var MIGRATE_PLAN_FILE = path66.join(MIGRATE_DIR, "plan.json");
76798
76804
  var LEGACY_MACHINERY_FILES = [
76799
76805
  "agent-slot.sh",
76800
76806
  "provision-toolchain.sh",
@@ -76835,25 +76841,25 @@ function harnessEnvIsPre10(content) {
76835
76841
  return /^\s*(har_infra_enabled|har_pg|har_node_[a-z_]+|har_pkg_exec)\s*\(\)/m.test(content) || /^export\s+HARNESS_[A-Z0-9_]+_PORT_(DEFAULT|SCAN_START|SCAN_END)=/m.test(content);
76836
76842
  }
76837
76843
  function scriptIsVendored(harnessDir, script) {
76838
- const file = path65.join(harnessDir, script);
76839
- if (!fs59.existsSync(file)) return false;
76840
- const content = fs59.readFileSync(file, "utf8");
76844
+ const file = path66.join(harnessDir, script);
76845
+ if (!fs60.existsSync(file)) return false;
76846
+ const content = fs60.readFileSync(file, "utf8");
76841
76847
  return !content.includes("exec har env") && !content.includes("runtime/har.cjs");
76842
76848
  }
76843
76849
  function isPre10Harness(repoPath) {
76844
- const resolved = path65.resolve(repoPath);
76850
+ const resolved = path66.resolve(repoPath);
76845
76851
  const harnessDir = getHarnessDir(resolved);
76846
- if (!fs59.existsSync(harnessDir)) return false;
76852
+ if (!fs60.existsSync(harnessDir)) return false;
76847
76853
  const manifest = readManifest(resolved);
76848
76854
  if (manifest?.ejected) return false;
76849
76855
  for (const file of LEGACY_MACHINERY_FILES) {
76850
- if (fs59.existsSync(path65.join(harnessDir, file))) return true;
76856
+ if (fs60.existsSync(path66.join(harnessDir, file))) return true;
76851
76857
  }
76852
76858
  for (const script of MANAGED_SHIM_FILES) {
76853
76859
  if (scriptIsVendored(harnessDir, script)) return true;
76854
76860
  }
76855
- const envPath = path65.join(harnessDir, "harness.env");
76856
- if (fs59.existsSync(envPath) && harnessEnvIsPre10(fs59.readFileSync(envPath, "utf8"))) {
76861
+ const envPath = path66.join(harnessDir, "harness.env");
76862
+ if (fs60.existsSync(envPath) && harnessEnvIsPre10(fs60.readFileSync(envPath, "utf8"))) {
76857
76863
  return true;
76858
76864
  }
76859
76865
  return false;
@@ -76986,60 +76992,57 @@ var SCRIPT_RESIDUE_TARGET = {
76986
76992
  "agent-cli.sh": "review"
76987
76993
  };
76988
76994
  function backupRel(file) {
76989
- return path65.join(MIGRATE_BACKUP_DIR, file);
76995
+ return path66.join(MIGRATE_BACKUP_DIR, file);
76990
76996
  }
76991
76997
  function buildPre10Plan(repoPath) {
76992
- const resolved = path65.resolve(repoPath);
76998
+ const resolved = path66.resolve(repoPath);
76993
76999
  const harnessDir = getHarnessDir(resolved);
76994
77000
  const manifest = readManifest(resolved);
76995
77001
  const profile = manifest?.profile ?? "default";
76996
77002
  const composed = composeProfileTemplateMap(profile);
76997
77003
  const fileBaseline = manifest?.fileChecksums ?? {};
76998
- const replaceWithShims = [];
77004
+ const deleteLifecycleScripts = [];
76999
77005
  const residue = [];
77000
77006
  for (const script of MANAGED_SHIM_FILES) {
77001
- if (!composed.has(script)) continue;
77002
- if (!scriptIsVendored(harnessDir, script) && fs59.existsSync(path65.join(harnessDir, script))) {
77003
- continue;
77004
- }
77005
- replaceWithShims.push(script);
77006
- if (fs59.existsSync(path65.join(harnessDir, script))) {
77007
+ if (!fs60.existsSync(path66.join(harnessDir, script))) continue;
77008
+ deleteLifecycleScripts.push(script);
77009
+ if (scriptIsVendored(harnessDir, script)) {
77007
77010
  const target = SCRIPT_RESIDUE_TARGET[script] ?? "review";
77008
77011
  residue.push({
77009
77012
  source: script,
77010
77013
  backup: backupRel(script),
77011
77014
  target,
77012
- reason: target === "stage" ? "Vendored verify pipeline replaced by the managed shim \u2014 project-specific verification steps belong in stages.json / .har/stages/ (bigger checks: a local plugin)." : target === "hook" ? "Vendored script replaced by the managed shim \u2014 project-specific launch/teardown/infra behavior belongs in .har/hooks/ lifecycle hooks." : "Vendored script replaced by the managed shim \u2014 review the backup for project-specific behavior worth keeping."
77015
+ reason: target === "stage" ? "Vendored verify pipeline deleted \u2014 project-specific verification steps belong in stages.json / .har/stages/ (bigger checks: a local plugin). Drive verify with `har env verify`." : target === "hook" ? "Vendored script deleted \u2014 project-specific launch/teardown/infra behavior belongs in .har/hooks/ lifecycle hooks. Drive the slot with `har env launch` / `har env teardown`." : "Vendored script deleted \u2014 review the backup for project-specific behavior worth keeping. Invocation is `har env \u2026`."
77013
77016
  });
77014
77017
  }
77015
77018
  }
77016
77019
  const survivingScripts = [];
77017
77020
  for (const dir of ["stages", "hooks"]) {
77018
- const full = path65.join(harnessDir, dir);
77019
- if (!fs59.existsSync(full)) continue;
77020
- for (const entry of fs59.readdirSync(full)) {
77021
- if (entry.endsWith(".sh") || entry.endsWith(".mjs")) survivingScripts.push(path65.join(dir, entry));
77021
+ const full = path66.join(harnessDir, dir);
77022
+ if (!fs60.existsSync(full)) continue;
77023
+ for (const entry of fs60.readdirSync(full)) {
77024
+ if (entry.endsWith(".sh") || entry.endsWith(".mjs")) survivingScripts.push(path66.join(dir, entry));
77022
77025
  }
77023
77026
  }
77024
- for (const entry of fs59.readdirSync(harnessDir)) {
77027
+ for (const entry of fs60.readdirSync(harnessDir)) {
77025
77028
  if (!entry.endsWith(".sh")) continue;
77026
77029
  if (MANAGED_SHIM_FILES.includes(entry)) continue;
77027
77030
  if (LEGACY_MACHINERY_FILES.includes(entry)) continue;
77028
- if (!fs59.statSync(path65.join(harnessDir, entry)).isFile()) continue;
77031
+ if (!fs60.statSync(path66.join(harnessDir, entry)).isFile()) continue;
77029
77032
  survivingScripts.push(entry);
77030
77033
  }
77031
77034
  const referencedBy = (machineryFile) => {
77032
- const base = path65.basename(machineryFile).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
77035
+ const base = path66.basename(machineryFile).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
77033
77036
  const loadRe = new RegExp(
77034
77037
  `(?:\\bsource\\b|\\bbash\\b|\\bexec\\b|(?:^|[;&|(])\\s*\\.\\s)[^\\n#]*${base}`
77035
77038
  );
77036
77039
  return survivingScripts.filter(
77037
- (script) => fs59.readFileSync(path65.join(harnessDir, script), "utf8").split("\n").some((line) => !/^\s*#/.test(line) && loadRe.test(line))
77040
+ (script) => fs60.readFileSync(path66.join(harnessDir, script), "utf8").split("\n").some((line) => !/^\s*#/.test(line) && loadRe.test(line))
77038
77041
  );
77039
77042
  };
77040
77043
  const retireDocs = [];
77041
77044
  for (const doc of RETIRED_DOC_FILES) {
77042
- if (!fs59.existsSync(path65.join(harnessDir, doc))) continue;
77045
+ if (!fs60.existsSync(path66.join(harnessDir, doc))) continue;
77043
77046
  retireDocs.push(doc);
77044
77047
  residue.push({
77045
77048
  source: doc,
@@ -77052,8 +77055,8 @@ function buildPre10Plan(repoPath) {
77052
77055
  const editedMachinery = [];
77053
77056
  const retainMachinery = [];
77054
77057
  for (const file of LEGACY_MACHINERY_FILES) {
77055
- const full = path65.join(harnessDir, file);
77056
- if (!fs59.existsSync(full)) continue;
77058
+ const full = path66.join(harnessDir, file);
77059
+ if (!fs60.existsSync(full)) continue;
77057
77060
  const refs = referencedBy(file);
77058
77061
  if (refs.length > 0) {
77059
77062
  retainMachinery.push(file);
@@ -77067,7 +77070,7 @@ function buildPre10Plan(repoPath) {
77067
77070
  }
77068
77071
  deleteMachinery.push(file);
77069
77072
  const recorded = fileBaseline[file];
77070
- const installed = computeFileChecksum(fs59.readFileSync(full, "utf8"));
77073
+ const installed = computeFileChecksum(fs60.readFileSync(full, "utf8"));
77071
77074
  if (recorded !== void 0 && installed !== recorded) {
77072
77075
  editedMachinery.push(file);
77073
77076
  residue.push({
@@ -77079,9 +77082,9 @@ function buildPre10Plan(repoPath) {
77079
77082
  }
77080
77083
  }
77081
77084
  let env3 = null;
77082
- const envPath = path65.join(harnessDir, "harness.env");
77083
- if (fs59.existsSync(envPath)) {
77084
- const content = fs59.readFileSync(envPath, "utf8");
77085
+ const envPath = path66.join(harnessDir, "harness.env");
77086
+ if (fs60.existsSync(envPath)) {
77087
+ const content = fs60.readFileSync(envPath, "utf8");
77085
77088
  if (harnessEnvIsPre10(content) || migrateHarnessEnvContent(content).commentedKeys.length > 0) {
77086
77089
  env3 = migrateHarnessEnvContent(content);
77087
77090
  for (const fn of env3.customFunctions) {
@@ -77106,7 +77109,7 @@ function buildPre10Plan(repoPath) {
77106
77109
  for (const file of composed.keys()) {
77107
77110
  if (MANAGED_SHIM_FILES.includes(file)) continue;
77108
77111
  if (file === "gitignore.template") continue;
77109
- if (!fs59.existsSync(path65.join(harnessDir, file))) installMissing.push(file);
77112
+ if (!fs60.existsSync(path66.join(harnessDir, file))) installMissing.push(file);
77110
77113
  }
77111
77114
  let phantomVerificationIds = [];
77112
77115
  try {
@@ -77125,7 +77128,7 @@ function buildPre10Plan(repoPath) {
77125
77128
  id: "config-surface",
77126
77129
  to: HARNESS_RUNTIME_VERSION,
77127
77130
  profile,
77128
- replaceWithShims,
77131
+ deleteLifecycleScripts,
77129
77132
  deleteMachinery,
77130
77133
  retireDocs,
77131
77134
  installMissing,
@@ -77137,54 +77140,52 @@ function buildPre10Plan(repoPath) {
77137
77140
  };
77138
77141
  }
77139
77142
  function applyPre10Plan(repoPath, plan) {
77140
- const resolved = path65.resolve(repoPath);
77143
+ const resolved = path66.resolve(repoPath);
77141
77144
  const harnessDir = getHarnessDir(resolved);
77142
77145
  const effective = plan ?? buildPre10Plan(resolved);
77143
- const backupDir = path65.join(harnessDir, MIGRATE_BACKUP_DIR);
77144
- fs59.mkdirSync(backupDir, { recursive: true });
77146
+ const backupDir = path66.join(harnessDir, MIGRATE_BACKUP_DIR);
77147
+ fs60.mkdirSync(backupDir, { recursive: true });
77145
77148
  const backup = (file) => {
77146
- const src = path65.join(harnessDir, file);
77147
- if (!fs59.existsSync(src)) return;
77148
- const dest = path65.join(backupDir, file);
77149
- fs59.mkdirSync(path65.dirname(dest), { recursive: true });
77150
- fs59.copyFileSync(src, dest);
77149
+ const src = path66.join(harnessDir, file);
77150
+ if (!fs60.existsSync(src)) return;
77151
+ const dest = path66.join(backupDir, file);
77152
+ fs60.mkdirSync(path66.dirname(dest), { recursive: true });
77153
+ fs60.copyFileSync(src, dest);
77151
77154
  };
77152
77155
  const written = [];
77153
77156
  const deleted = [];
77154
- const projectName = path65.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
77157
+ const projectName = path66.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
77155
77158
  const composed = composeProfileTemplateMap(effective.profile);
77156
- for (const script of effective.replaceWithShims) {
77157
- const source = composed.get(script);
77158
- if (!source) continue;
77159
+ for (const script of effective.deleteLifecycleScripts) {
77159
77160
  backup(script);
77160
- const rendered = substituteTemplateTokens(readComposedTemplateContent(source), projectName);
77161
- const dest = path65.join(harnessDir, script);
77162
- fs59.writeFileSync(dest, rendered);
77163
- fs59.chmodSync(dest, 493);
77164
- written.push(script);
77161
+ fs60.rmSync(path66.join(harnessDir, script), { force: true });
77162
+ deleted.push(script);
77163
+ }
77164
+ if (stripLifecycleShimCommands(resolved)) {
77165
+ written.push("stages.json");
77165
77166
  }
77166
77167
  for (const file of effective.deleteMachinery) {
77167
77168
  backup(file);
77168
- fs59.rmSync(path65.join(harnessDir, file), { force: true });
77169
+ fs60.rmSync(path66.join(harnessDir, file), { force: true });
77169
77170
  deleted.push(file);
77170
77171
  }
77171
77172
  for (const doc of effective.retireDocs ?? []) {
77172
77173
  backup(doc);
77173
77174
  }
77174
- const libDir = path65.join(harnessDir, "lib");
77175
- if (fs59.existsSync(libDir) && fs59.readdirSync(libDir).length === 0) {
77176
- fs59.rmdirSync(libDir);
77175
+ const libDir = path66.join(harnessDir, "lib");
77176
+ if (fs60.existsSync(libDir) && fs60.readdirSync(libDir).length === 0) {
77177
+ fs60.rmdirSync(libDir);
77177
77178
  deleted.push("lib/");
77178
77179
  }
77179
77180
  for (const file of effective.installMissing ?? []) {
77180
77181
  const source = composed.get(file);
77181
77182
  if (!source) continue;
77182
- const dest = path65.join(harnessDir, file);
77183
- if (fs59.existsSync(dest)) continue;
77183
+ const dest = path66.join(harnessDir, file);
77184
+ if (fs60.existsSync(dest)) continue;
77184
77185
  const rendered = substituteTemplateTokens(readComposedTemplateContent(source), projectName);
77185
- fs59.mkdirSync(path65.dirname(dest), { recursive: true });
77186
- fs59.writeFileSync(dest, rendered);
77187
- if (/\.(sh|mjs)$/.test(file)) fs59.chmodSync(dest, 493);
77186
+ fs60.mkdirSync(path66.dirname(dest), { recursive: true });
77187
+ fs60.writeFileSync(dest, rendered);
77188
+ if (/\.(sh|mjs)$/.test(file)) fs60.chmodSync(dest, 493);
77188
77189
  written.push(file);
77189
77190
  }
77190
77191
  if (effective.phantomVerificationIds.length > 0) {
@@ -77199,7 +77200,7 @@ function applyPre10Plan(repoPath, plan) {
77199
77200
  }
77200
77201
  if (effective.env) {
77201
77202
  backup("harness.env");
77202
- fs59.writeFileSync(path65.join(harnessDir, "harness.env"), effective.env.content);
77203
+ fs60.writeFileSync(path66.join(harnessDir, "harness.env"), effective.env.content);
77203
77204
  written.push("harness.env");
77204
77205
  }
77205
77206
  const manifest = readManifest(resolved);
@@ -77214,8 +77215,8 @@ function applyPre10Plan(repoPath, plan) {
77214
77215
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
77215
77216
  });
77216
77217
  }
77217
- fs59.writeFileSync(
77218
- path65.join(harnessDir, MIGRATE_PLAN_FILE),
77218
+ fs60.writeFileSync(
77219
+ path66.join(harnessDir, MIGRATE_PLAN_FILE),
77219
77220
  JSON.stringify({ ...effective, appliedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
77220
77221
  );
77221
77222
  return { plan: effective, backupDir, written, deleted };
@@ -77235,33 +77236,33 @@ function pendingMigrations(repoPath) {
77235
77236
  );
77236
77237
  }
77237
77238
  function writeMigrationPlan(repoPath, plan) {
77238
- const harnessDir = getHarnessDir(path65.resolve(repoPath));
77239
- const planPath = path65.join(harnessDir, MIGRATE_PLAN_FILE);
77240
- fs59.mkdirSync(path65.dirname(planPath), { recursive: true });
77241
- fs59.writeFileSync(planPath, JSON.stringify(plan, null, 2) + "\n");
77239
+ const harnessDir = getHarnessDir(path66.resolve(repoPath));
77240
+ const planPath = path66.join(harnessDir, MIGRATE_PLAN_FILE);
77241
+ fs60.mkdirSync(path66.dirname(planPath), { recursive: true });
77242
+ fs60.writeFileSync(planPath, JSON.stringify(plan, null, 2) + "\n");
77242
77243
  return planPath;
77243
77244
  }
77244
77245
  function removeMigrationArtifacts(repoPath) {
77245
- const harnessDir = getHarnessDir(path65.resolve(repoPath));
77246
- fs59.rmSync(path65.join(harnessDir, MIGRATE_DIR), { recursive: true, force: true });
77247
- fs59.rmSync(path65.join(harnessDir, "MIGRATE-PROMPT.md"), { force: true });
77246
+ const harnessDir = getHarnessDir(path66.resolve(repoPath));
77247
+ fs60.rmSync(path66.join(harnessDir, MIGRATE_DIR), { recursive: true, force: true });
77248
+ fs60.rmSync(path66.join(harnessDir, "MIGRATE-PROMPT.md"), { force: true });
77248
77249
  }
77249
77250
 
77250
77251
  // src/harness/doctor.ts
77251
77252
  function listHarnessShellScripts(harnessDir) {
77252
77253
  const out = [];
77253
77254
  const push = (dir, prefix) => {
77254
- if (!fs60.existsSync(dir)) return;
77255
- for (const entry of fs60.readdirSync(dir).sort()) {
77255
+ if (!fs61.existsSync(dir)) return;
77256
+ for (const entry of fs61.readdirSync(dir).sort()) {
77256
77257
  if (!entry.endsWith(".sh")) continue;
77257
- const full = path66.join(dir, entry);
77258
- if (!fs60.statSync(full).isFile()) continue;
77258
+ const full = path67.join(dir, entry);
77259
+ if (!fs61.statSync(full).isFile()) continue;
77259
77260
  out.push(prefix ? `${prefix}/${entry}` : entry);
77260
77261
  }
77261
77262
  };
77262
77263
  push(harnessDir, "");
77263
- push(path66.join(harnessDir, "stages"), "stages");
77264
- push(path66.join(harnessDir, "hooks"), "hooks");
77264
+ push(path67.join(harnessDir, "stages"), "stages");
77265
+ push(path67.join(harnessDir, "hooks"), "hooks");
77265
77266
  return out;
77266
77267
  }
77267
77268
  var CHECK_LABELS = {
@@ -77279,27 +77280,30 @@ var CHECK_LABELS = {
77279
77280
  var PRE_1_0_FUNCTION_RE = /^\s*(har_infra_enabled|har_pg|har_node_[a-z_]+|har_pkg_exec)\s*\(\)/m;
77280
77281
  var LEGACY_TRIPLET_RE = /^export\s+HARNESS_[A-Z0-9_]+_PORT_(DEFAULT|SCAN_START|SCAN_END)=/m;
77281
77282
  function detectContract(harnessDir) {
77282
- const envPath = path66.join(harnessDir, "harness.env");
77283
- if (!fs60.existsSync(envPath)) return "none";
77284
- const content = fs60.readFileSync(envPath, "utf8");
77283
+ const envPath = path67.join(harnessDir, "harness.env");
77284
+ if (!fs61.existsSync(envPath)) return "none";
77285
+ const content = fs61.readFileSync(envPath, "utf8");
77285
77286
  if (PRE_1_0_FUNCTION_RE.test(content) || LEGACY_TRIPLET_RE.test(content)) {
77286
77287
  return "pre-1.0";
77287
77288
  }
77288
77289
  return "1.0";
77289
77290
  }
77290
77291
  function resolveStageFile(harnessDir, stage) {
77291
- if (stage.script) return path66.join(harnessDir, stage.script);
77292
+ if (PACKAGE_RUNTIME_KINDS.has(stage.kind) && (!stage.command && !stage.script || stagePointsAtLifecycleShim(stage))) {
77293
+ return null;
77294
+ }
77295
+ if (stage.script) return path67.join(harnessDir, stage.script);
77292
77296
  if (stage.command) {
77293
77297
  const first = stage.command.trim().split(/\s+/)[0];
77294
77298
  if (first.startsWith("./.har/")) {
77295
- return path66.join(harnessDir, first.replace(/^\.\/\.har\//, ""));
77299
+ return path67.join(harnessDir, first.replace(/^\.\/\.har\//, ""));
77296
77300
  }
77297
77301
  if (first.startsWith(".har/")) {
77298
- return path66.join(harnessDir, first.replace(/^\.har\//, ""));
77302
+ return path67.join(harnessDir, first.replace(/^\.har\//, ""));
77299
77303
  }
77300
77304
  return null;
77301
77305
  }
77302
- return path66.join(harnessDir, "stages", `${stage.id}.sh`);
77306
+ return path67.join(harnessDir, "stages", `${stage.id}.sh`);
77303
77307
  }
77304
77308
  function checkStatus(findings, id) {
77305
77309
  const mine = findings.filter((f) => f.check === id);
@@ -77311,7 +77315,7 @@ function runDoctor(repoPath) {
77311
77315
  const harnessDir = getHarnessDir(repoPath);
77312
77316
  const findings = [];
77313
77317
  const skipped = /* @__PURE__ */ new Set();
77314
- if (!fs60.existsSync(harnessDir)) {
77318
+ if (!fs61.existsSync(harnessDir)) {
77315
77319
  return {
77316
77320
  ok: false,
77317
77321
  contract: "none",
@@ -77326,7 +77330,7 @@ function runDoctor(repoPath) {
77326
77330
  severity: "error",
77327
77331
  file: ".har",
77328
77332
  message: "Harness directory .har/ not found",
77329
- remedy: "Run `har env init` to scaffold the harness"
77333
+ remedy: "Run `har onboard` to scaffold the harness"
77330
77334
  }
77331
77335
  ]
77332
77336
  };
@@ -77358,9 +77362,9 @@ function runDoctor(repoPath) {
77358
77362
  }
77359
77363
  let registry2 = null;
77360
77364
  try {
77361
- const stagesPath = path66.join(harnessDir, "stages.json");
77362
- if (fs60.existsSync(stagesPath)) {
77363
- const raw = JSON.parse(fs60.readFileSync(stagesPath, "utf8"));
77365
+ const stagesPath = path67.join(harnessDir, "stages.json");
77366
+ if (fs61.existsSync(stagesPath)) {
77367
+ const raw = JSON.parse(fs61.readFileSync(stagesPath, "utf8"));
77364
77368
  if (typeof raw !== "object" || raw === null || !Array.isArray(raw.stages)) {
77365
77369
  throw new Error("stages.json has no `stages` array \u2014 the registry is structurally invalid");
77366
77370
  }
@@ -77391,8 +77395,8 @@ function runDoctor(repoPath) {
77391
77395
  for (const stage of registry2.stages) {
77392
77396
  const file = resolveStageFile(harnessDir, stage);
77393
77397
  if (!file) continue;
77394
- const rel = path66.relative(harnessDir, file);
77395
- if (!fs60.existsSync(file)) {
77398
+ const rel = path67.relative(harnessDir, file);
77399
+ if (!fs61.existsSync(file)) {
77396
77400
  findings.push({
77397
77401
  check: "stage-files",
77398
77402
  severity: contractSeverity,
@@ -77402,7 +77406,7 @@ function runDoctor(repoPath) {
77402
77406
  });
77403
77407
  continue;
77404
77408
  }
77405
- if (rel.endsWith(".sh") && !(fs60.statSync(file).mode & 73)) {
77409
+ if (rel.endsWith(".sh") && !(fs61.statSync(file).mode & 73)) {
77406
77410
  findings.push({
77407
77411
  check: "stage-files",
77408
77412
  severity: "warning",
@@ -77425,13 +77429,13 @@ function runDoctor(repoPath) {
77425
77429
  continue;
77426
77430
  }
77427
77431
  const file = resolveStageFile(harnessDir, stage);
77428
- if (file && !fs60.existsSync(file)) {
77432
+ if (file && !fs61.existsSync(file)) {
77429
77433
  findings.push({
77430
77434
  check: "lifecycle-stages",
77431
77435
  severity: contractSeverity,
77432
- file: path66.relative(harnessDir, file),
77436
+ file: path67.relative(harnessDir, file),
77433
77437
  message: `Lifecycle stage \`${stage.id}\` (${kind}) points at a missing file`,
77434
- remedy: `Restore .har/${path66.relative(harnessDir, file)} or fix the \`${stage.id}\` entry in stages.json`
77438
+ remedy: `Restore .har/${path67.relative(harnessDir, file)} or fix the \`${stage.id}\` entry in stages.json`
77435
77439
  });
77436
77440
  }
77437
77441
  }
@@ -77476,35 +77480,22 @@ function runDoctor(repoPath) {
77476
77480
  if (!manifest?.ejected) {
77477
77481
  skipped.add("ejected-runtime");
77478
77482
  } else {
77479
- const runtimeRel = path66.join(EJECTED_RUNTIME_DIR, EJECTED_RUNTIME_BUNDLE);
77480
- const runtimePath = path66.join(harnessDir, runtimeRel);
77481
- if (!fs60.existsSync(runtimePath)) {
77483
+ const runtimeRel = path67.join(EJECTED_RUNTIME_DIR, EJECTED_RUNTIME_BUNDLE);
77484
+ const runtimePath = path67.join(harnessDir, runtimeRel);
77485
+ if (!fs61.existsSync(runtimePath)) {
77482
77486
  findings.push({
77483
77487
  check: "ejected-runtime",
77484
77488
  severity: "error",
77485
77489
  file: runtimeRel,
77486
77490
  message: `Harness is ejected but the vendored runtime .har/${runtimeRel} is missing`,
77487
- remedy: "Restore it from git, re-run `har env eject`, or return to managed shims with `har env adopt`"
77491
+ remedy: "Restore it from git, re-run `har env eject`, or return to the packaged runtime with `har env adopt`"
77488
77492
  });
77489
77493
  }
77490
- for (const shim3 of MANAGED_SHIM_FILES) {
77491
- const shimPath = path66.join(harnessDir, shim3);
77492
- if (!fs60.existsSync(shimPath)) continue;
77493
- if (!(fs60.statSync(shimPath).mode & 73)) {
77494
- findings.push({
77495
- check: "ejected-runtime",
77496
- severity: "warning",
77497
- file: shim3,
77498
- message: `Ejected script ${shim3} is not executable`,
77499
- remedy: `chmod +x .har/${shim3}`
77500
- });
77501
- }
77502
- }
77503
77494
  }
77504
77495
  for (const entry of listSlotRegistryEntries(repoPath)) {
77505
77496
  if (entry.status === "completed") continue;
77506
77497
  const dir = entry.worktreePath ?? entry.workDir;
77507
- if (dir && !fs60.existsSync(dir)) {
77498
+ if (dir && !fs61.existsSync(dir)) {
77508
77499
  findings.push({
77509
77500
  check: "slot-registry",
77510
77501
  severity: "warning",
@@ -77514,11 +77505,11 @@ function runDoctor(repoPath) {
77514
77505
  });
77515
77506
  }
77516
77507
  }
77517
- const hooksDir = path66.join(harnessDir, "hooks");
77518
- if (fs60.existsSync(hooksDir)) {
77519
- for (const file of fs60.readdirSync(hooksDir).sort()) {
77520
- const full = path66.join(hooksDir, file);
77521
- if (!fs60.statSync(full).isFile() || !file.endsWith(".sh")) continue;
77508
+ const hooksDir = path67.join(harnessDir, "hooks");
77509
+ if (fs61.existsSync(hooksDir)) {
77510
+ for (const file of fs61.readdirSync(hooksDir).sort()) {
77511
+ const full = path67.join(hooksDir, file);
77512
+ if (!fs61.statSync(full).isFile() || !file.endsWith(".sh")) continue;
77522
77513
  if (!LIFECYCLE_HOOKS.includes(file.replace(/\.sh$/, ""))) {
77523
77514
  findings.push({
77524
77515
  check: "hooks",
@@ -77529,7 +77520,7 @@ function runDoctor(repoPath) {
77529
77520
  });
77530
77521
  continue;
77531
77522
  }
77532
- if (!(fs60.statSync(full).mode & 73)) {
77523
+ if (!(fs61.statSync(full).mode & 73)) {
77533
77524
  findings.push({
77534
77525
  check: "hooks",
77535
77526
  severity: "warning",
@@ -77541,15 +77532,15 @@ function runDoctor(repoPath) {
77541
77532
  }
77542
77533
  }
77543
77534
  for (const rel of listHarnessShellScripts(harnessDir)) {
77544
- const full = path66.join(harnessDir, rel);
77535
+ const full = path67.join(harnessDir, rel);
77545
77536
  let content;
77546
77537
  try {
77547
- content = fs60.readFileSync(full, "utf8");
77538
+ content = fs61.readFileSync(full, "utf8");
77548
77539
  } catch {
77549
77540
  continue;
77550
77541
  }
77551
77542
  for (const machinery of LEGACY_MACHINERY_FILES) {
77552
- if (fs60.existsSync(path66.join(harnessDir, machinery))) continue;
77543
+ if (fs61.existsSync(path67.join(harnessDir, machinery))) continue;
77553
77544
  const base = machinery.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
77554
77545
  const loadRe = new RegExp(
77555
77546
  `(?:\\bsource\\b|\\bbash\\b|\\bexec\\b|(?:^|[;&|(])\\s*\\.\\s)[^\\n#]*${base}`
@@ -77563,7 +77554,7 @@ function runDoctor(repoPath) {
77563
77554
  file: rel,
77564
77555
  line: idx + 1,
77565
77556
  message: `${rel} loads .har/${machinery}, which 1.0 retired and this harness no longer has`,
77566
- remedy: "Rewrite the script against the 1.0 stage surface (WORK_DIR, ENV_FILE, AGENT_ID and the slot env file are already exported), or run `har env maintain --migrate` to regenerate a managed shim"
77557
+ remedy: "Rewrite the script against the 1.0 stage surface (WORK_DIR, ENV_FILE, AGENT_ID and the slot env file are already exported), or run `har env maintain --migrate`"
77567
77558
  });
77568
77559
  break;
77569
77560
  }
@@ -77613,8 +77604,8 @@ function summarizeDoctorReport(report) {
77613
77604
  }
77614
77605
 
77615
77606
  // src/harness/migrate-prompt.ts
77616
- var fs61 = __toESM(require("fs"));
77617
- var path67 = __toESM(require("path"));
77607
+ var fs62 = __toESM(require("fs"));
77608
+ var path68 = __toESM(require("path"));
77618
77609
  init_paths();
77619
77610
  init_file_ops();
77620
77611
  init_manifest();
@@ -77669,9 +77660,9 @@ function buildMigrationSection(plan, applied) {
77669
77660
  );
77670
77661
  }
77671
77662
  lines.push(`What the mechanical migration ${applied ? "did" : "will do"}:`, "");
77672
- if (plan.replaceWithShims.length > 0) {
77663
+ if (plan.deleteLifecycleScripts.length > 0) {
77673
77664
  lines.push(
77674
- `- Replace${applied ? "d" : ""} with managed shims (same argument conventions): ${plan.replaceWithShims.map((f) => `\`${f}\``).join(", ")}`
77665
+ `- Delete${applied ? "d" : ""} lifecycle wrappers (drive the harness with \`har env \u2026\`): ${plan.deleteLifecycleScripts.map((f) => `\`${f}\``).join(", ")}`
77675
77666
  );
77676
77667
  }
77677
77668
  if (plan.deleteMachinery.length > 0) {
@@ -77728,13 +77719,13 @@ function loadTemplate2() {
77728
77719
  if (!filePath) {
77729
77720
  throw new Error("Migration prompt template not found: migration-prompt.md. Run npm run build.");
77730
77721
  }
77731
- return fs61.readFileSync(filePath, "utf8");
77722
+ return fs62.readFileSync(filePath, "utf8");
77732
77723
  }
77733
77724
  function buildMigrationPrompt(plan, applied) {
77734
77725
  return loadTemplate2().replace("{{MIGRATION_SECTION}}", buildMigrationSection(plan, applied));
77735
77726
  }
77736
77727
  function writeMigrationPrompt(repoPath, content) {
77737
- const filePath = path67.join(getHarnessDir(repoPath), MIGRATE_PROMPT_FILE);
77728
+ const filePath = path68.join(getHarnessDir(repoPath), MIGRATE_PROMPT_FILE);
77738
77729
  writeFileSafe(filePath, content);
77739
77730
  return filePath;
77740
77731
  }
@@ -77742,11 +77733,11 @@ function writeMigrationPrompt(repoPath, content) {
77742
77733
  // src/core/harness.ts
77743
77734
  function listHarnessScripts(repoPath) {
77744
77735
  const harnessDir = getHarnessDir(repoPath);
77745
- if (!fs62.existsSync(harnessDir)) return [];
77746
- return fs62.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
77736
+ if (!fs63.existsSync(harnessDir)) return [];
77737
+ return fs63.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
77747
77738
  }
77748
77739
  function describeProject(repoPath) {
77749
- const resolved = path68.resolve(repoPath);
77740
+ const resolved = path69.resolve(repoPath);
77750
77741
  const manifest = readManifest(resolved);
77751
77742
  const present = harnessExists(resolved);
77752
77743
  return {
@@ -77766,8 +77757,8 @@ function describeProject(repoPath) {
77766
77757
  };
77767
77758
  }
77768
77759
  async function initHarness(options) {
77769
- const repoPath = path68.resolve(options.repoPath);
77770
- if (!fs62.existsSync(repoPath)) {
77760
+ const repoPath = path69.resolve(options.repoPath);
77761
+ if (!fs63.existsSync(repoPath)) {
77771
77762
  throw new Error(`Path not found: ${repoPath}`);
77772
77763
  }
77773
77764
  const scaffold = scaffoldHarnessBoilerplate(repoPath, {
@@ -77788,10 +77779,10 @@ async function initHarness(options) {
77788
77779
  };
77789
77780
  }
77790
77781
  async function maintainHarness(options) {
77791
- const repoPath = path68.resolve(options.repoPath);
77782
+ const repoPath = path69.resolve(options.repoPath);
77792
77783
  const harnessDir = getHarnessDir(repoPath);
77793
- if (!fs62.existsSync(harnessDir)) {
77794
- throw new Error('No .har/ found. Run "har env init" first.');
77784
+ if (!fs63.existsSync(harnessDir)) {
77785
+ throw new Error('No .har/ found. Run "har onboard" first.');
77795
77786
  }
77796
77787
  let migration;
77797
77788
  const pending = pendingMigrations(repoPath);
@@ -77827,6 +77818,7 @@ async function maintainHarness(options) {
77827
77818
  };
77828
77819
  }
77829
77820
  }
77821
+ retireLifecycleShims(repoPath);
77830
77822
  ensureEcosystemVerificationStages(repoPath);
77831
77823
  const drift = compareHarnessToTemplate(repoPath);
77832
77824
  const validation2 = validateHarness(repoPath);
@@ -77866,8 +77858,8 @@ function addPlugin(repoPath, pluginId, options = {}) {
77866
77858
  }
77867
77859
 
77868
77860
  // src/harness/adaptation-prompt.ts
77869
- var fs63 = __toESM(require("fs"));
77870
- var path69 = __toESM(require("path"));
77861
+ var fs64 = __toESM(require("fs"));
77862
+ var path70 = __toESM(require("path"));
77871
77863
  var readline5 = __toESM(require("readline"));
77872
77864
 
77873
77865
  // src/utils/clipboard.ts
@@ -77958,7 +77950,7 @@ function loadTemplate3(name) {
77958
77950
  if (!filePath) {
77959
77951
  throw new Error(`Adaptation prompt template not found: ${name}. Run npm run build.`);
77960
77952
  }
77961
- return fs63.readFileSync(filePath, "utf8");
77953
+ return fs64.readFileSync(filePath, "utf8");
77962
77954
  }
77963
77955
  function applyProfilePlaceholders(content, profile) {
77964
77956
  return content.replace(/\{\{PROFILE\}\}/g, profile).replace(/\{\{PROFILE_HINT\}\}/g, PROFILE_HINTS[profile]);
@@ -77980,7 +77972,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
77980
77972
  }
77981
77973
  function writeAdaptationPrompt(repoPath, content) {
77982
77974
  const harnessDir = getHarnessDir(repoPath);
77983
- const filePath = path69.join(harnessDir, ADAPTATION_PROMPT_FILE);
77975
+ const filePath = path70.join(harnessDir, ADAPTATION_PROMPT_FILE);
77984
77976
  writeFileSafe(filePath, content);
77985
77977
  return filePath;
77986
77978
  }
@@ -77999,12 +77991,12 @@ function printAdaptationPrompt(content) {
77999
77991
  }
78000
77992
  function askYesNo2(question) {
78001
77993
  const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
78002
- return new Promise((resolve59) => {
77994
+ return new Promise((resolve60) => {
78003
77995
  process.stderr.write(`${question} `);
78004
77996
  rl.once("line", (answer) => {
78005
77997
  rl.close();
78006
77998
  const trimmed = answer.trim();
78007
- resolve59(trimmed === "" || /^y(es)?$/i.test(trimmed));
77999
+ resolve60(trimmed === "" || /^y(es)?$/i.test(trimmed));
78008
78000
  });
78009
78001
  });
78010
78002
  }
@@ -78036,28 +78028,28 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
78036
78028
  }
78037
78029
 
78038
78030
  // src/harness/cursor-rule.ts
78039
- var fs64 = __toESM(require("fs"));
78040
- var path70 = __toESM(require("path"));
78031
+ var fs65 = __toESM(require("fs"));
78032
+ var path71 = __toESM(require("path"));
78041
78033
  var readline6 = __toESM(require("readline"));
78042
78034
  init_file_ops();
78043
78035
  init_logging();
78044
78036
  init_paths();
78045
78037
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
78046
78038
  function getCursorRulePath(repoPath) {
78047
- return path70.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
78039
+ return path71.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
78048
78040
  }
78049
78041
  function isCursorWorkspace(repoPath) {
78050
- return fs64.existsSync(path70.join(repoPath, ".cursor"));
78042
+ return fs65.existsSync(path71.join(repoPath, ".cursor"));
78051
78043
  }
78052
78044
  function cursorRuleExists(repoPath) {
78053
- return fs64.existsSync(getCursorRulePath(repoPath));
78045
+ return fs65.existsSync(getCursorRulePath(repoPath));
78054
78046
  }
78055
78047
  function scaffoldCursorRule(repoPath) {
78056
78048
  const templatePath = resolveTemplateFile("cursor-rule.mdc.template");
78057
78049
  if (!templatePath) {
78058
78050
  throw new Error("Cursor rule template not found (cursor-rule.mdc.template). Run npm run build.");
78059
78051
  }
78060
- const content = fs64.readFileSync(templatePath, "utf8");
78052
+ const content = fs65.readFileSync(templatePath, "utf8");
78061
78053
  writeFileSafe(getCursorRulePath(repoPath), content);
78062
78054
  }
78063
78055
  async function handleCursorRule(options) {
@@ -78095,16 +78087,16 @@ async function promptScaffoldCursorRule(exists) {
78095
78087
  }
78096
78088
  async function askYesNo3(question) {
78097
78089
  const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
78098
- return new Promise((resolve59) => {
78090
+ return new Promise((resolve60) => {
78099
78091
  process.stderr.write(`${question} `);
78100
78092
  rl.once("line", (answer) => {
78101
78093
  rl.close();
78102
78094
  const trimmed = answer.trim();
78103
78095
  if (trimmed === "") {
78104
- resolve59(true);
78096
+ resolve60(true);
78105
78097
  return;
78106
78098
  }
78107
- resolve59(/^y(es)?$/i.test(trimmed));
78099
+ resolve60(/^y(es)?$/i.test(trimmed));
78108
78100
  });
78109
78101
  });
78110
78102
  }
@@ -78148,7 +78140,7 @@ init_control_config();
78148
78140
 
78149
78141
  // src/core/control-lifecycle.ts
78150
78142
  var import_child_process18 = require("child_process");
78151
- var path71 = __toESM(require("path"));
78143
+ var path72 = __toESM(require("path"));
78152
78144
 
78153
78145
  // src/core/control-image.ts
78154
78146
  init_package_version();
@@ -78175,10 +78167,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
78175
78167
  var CONTROL_CONTAINER_PORT = 3847;
78176
78168
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
78177
78169
  function resolveControlDir() {
78178
- return path71.resolve(__dirname, "..", "control");
78170
+ return path72.resolve(__dirname, "..", "control");
78179
78171
  }
78180
78172
  function resolveControlBuildContext() {
78181
- return path71.resolve(resolveControlDir(), "..");
78173
+ return path72.resolve(resolveControlDir(), "..");
78182
78174
  }
78183
78175
  function buildDockerRunArgs(options) {
78184
78176
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -78234,7 +78226,7 @@ async function startMissionControl(options) {
78234
78226
  "-t",
78235
78227
  imageRef,
78236
78228
  "-f",
78237
- path71.join(resolveControlDir(), "Dockerfile"),
78229
+ path72.join(resolveControlDir(), "Dockerfile"),
78238
78230
  resolveControlBuildContext()
78239
78231
  ]);
78240
78232
  if (buildCode !== 0) {
@@ -78381,7 +78373,7 @@ async function ensureTelemetryInfrastructure(options) {
78381
78373
  // src/core/run-service.ts
78382
78374
  init_telemetry_config();
78383
78375
  init_telemetry_env();
78384
- var path73 = __toESM(require("path"));
78376
+ var path74 = __toESM(require("path"));
78385
78377
  init_local_executor();
78386
78378
  function extractShellOutput(result) {
78387
78379
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
@@ -78604,12 +78596,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
78604
78596
  suffix: session.suffix,
78605
78597
  createdAt: session.createdAt
78606
78598
  });
78607
- const envFile = path73.join(session.workDir, `.env.agent.${options.agentId}`);
78599
+ const envFile = path74.join(session.workDir, `.env.agent.${options.agentId}`);
78608
78600
  try {
78609
78601
  appendTelemetryEnvToFile(envFile, {
78610
78602
  sessionKey,
78611
78603
  agentId: options.agentId,
78612
- repoPath: path73.resolve(options.repoPath),
78604
+ repoPath: path74.resolve(options.repoPath),
78613
78605
  workDir: session.workDir,
78614
78606
  branch: session.branch,
78615
78607
  suffix: session.suffix,
@@ -78851,9 +78843,9 @@ init_work_units();
78851
78843
  init_manifest();
78852
78844
 
78853
78845
  // src/core/cleanup-service.ts
78854
- var fs66 = __toESM(require("fs"));
78846
+ var fs67 = __toESM(require("fs"));
78855
78847
  var os23 = __toESM(require("os"));
78856
- var path74 = __toESM(require("path"));
78848
+ var path75 = __toESM(require("path"));
78857
78849
  var import_child_process20 = require("child_process");
78858
78850
  init_control_sync();
78859
78851
  init_control_repo_path();
@@ -78862,9 +78854,9 @@ init_manifest();
78862
78854
  var DEFAULT_STALE_DAYS = 7;
78863
78855
  function getWorktreesRoot() {
78864
78856
  if (process.env.HAR_WORKTREES_ROOT) {
78865
- return path74.resolve(process.env.HAR_WORKTREES_ROOT);
78857
+ return path75.resolve(process.env.HAR_WORKTREES_ROOT);
78866
78858
  }
78867
- return path74.join(process.env.HOME || os23.homedir(), "worktrees");
78859
+ return path75.join(process.env.HOME || os23.homedir(), "worktrees");
78868
78860
  }
78869
78861
  function runGit3(cwd, args) {
78870
78862
  try {
@@ -78878,7 +78870,7 @@ function runGit3(cwd, args) {
78878
78870
  }
78879
78871
  }
78880
78872
  function basenameRepo(repoPath) {
78881
- return path74.basename(canonicalizeControlRepoPath(repoPath));
78873
+ return path75.basename(canonicalizeControlRepoPath(repoPath));
78882
78874
  }
78883
78875
  function ageDaysFrom(iso) {
78884
78876
  if (!iso) return void 0;
@@ -78890,12 +78882,12 @@ function matchesKeep(candidate, keep) {
78890
78882
  if (!keep?.length) return false;
78891
78883
  for (const pin of keep) {
78892
78884
  if (pin.worktreePath && candidate.worktreePath) {
78893
- if (path74.resolve(pin.worktreePath) === path74.resolve(candidate.worktreePath)) return true;
78885
+ if (path75.resolve(pin.worktreePath) === path75.resolve(candidate.worktreePath)) return true;
78894
78886
  }
78895
78887
  if (pin.repoPath && pin.agentId !== void 0 && candidate.agentId !== void 0) {
78896
78888
  const repo = canonicalizeControlRepoPath(pin.repoPath);
78897
- const candidateRepo = path74.resolve(candidate.repoPath);
78898
- if ((repo === candidateRepo || path74.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
78889
+ const candidateRepo = path75.resolve(candidate.repoPath);
78890
+ if ((repo === candidateRepo || path75.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
78899
78891
  return true;
78900
78892
  }
78901
78893
  }
@@ -78950,20 +78942,20 @@ function classifySlotCandidate(repoPath, projectName, slot, options) {
78950
78942
  return candidate;
78951
78943
  }
78952
78944
  function resolveRepoForWorktree(worktreePath) {
78953
- if (!fs66.existsSync(worktreePath)) return void 0;
78945
+ if (!fs67.existsSync(worktreePath)) return void 0;
78954
78946
  const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
78955
78947
  if (!commonDir) return void 0;
78956
- const gitRoot = path74.resolve(worktreePath, commonDir, "..");
78948
+ const gitRoot = path75.resolve(worktreePath, commonDir, "..");
78957
78949
  if (!readManifest(gitRoot)) return void 0;
78958
78950
  return canonicalizeControlRepoPath(gitRoot);
78959
78951
  }
78960
78952
  function discoverOrphanWorktrees(knownPaths) {
78961
78953
  const worktreesRoot = getWorktreesRoot();
78962
- if (!fs66.existsSync(worktreesRoot)) return [];
78954
+ if (!fs67.existsSync(worktreesRoot)) return [];
78963
78955
  const orphans = [];
78964
- for (const entry of fs66.readdirSync(worktreesRoot, { withFileTypes: true })) {
78956
+ for (const entry of fs67.readdirSync(worktreesRoot, { withFileTypes: true })) {
78965
78957
  if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
78966
- const worktreePath = path74.resolve(path74.join(worktreesRoot, entry.name));
78958
+ const worktreePath = path75.resolve(path75.join(worktreesRoot, entry.name));
78967
78959
  if (knownPaths.has(worktreePath)) continue;
78968
78960
  const repoPath = resolveRepoForWorktree(worktreePath) ?? worktreesRoot;
78969
78961
  const porcelain = runGit3(worktreePath, "status --porcelain");
@@ -78988,14 +78980,14 @@ async function discoverCleanupCandidates(options = {}) {
78988
78980
  const candidates = [];
78989
78981
  const knownWorktreePaths = /* @__PURE__ */ new Set();
78990
78982
  for (const repoPath of repoPaths) {
78991
- if (!fs66.existsSync(repoPath) || !readManifest(repoPath)) continue;
78983
+ if (!fs67.existsSync(repoPath) || !readManifest(repoPath)) continue;
78992
78984
  const harnessRoot = resolveHarnessRoot(repoPath);
78993
78985
  const canonicalRepo = canonicalizeControlRepoPath(harnessRoot);
78994
78986
  const status = collectEnvironmentStatus(harnessRoot);
78995
78987
  const projectName = basenameRepo(harnessRoot);
78996
78988
  for (const slot of status.slots) {
78997
- if (slot.worktreePath) knownWorktreePaths.add(path74.resolve(slot.worktreePath));
78998
- if (slot.workDir) knownWorktreePaths.add(path74.resolve(slot.workDir));
78989
+ if (slot.worktreePath) knownWorktreePaths.add(path75.resolve(slot.worktreePath));
78990
+ if (slot.workDir) knownWorktreePaths.add(path75.resolve(slot.workDir));
78999
78991
  const candidate = classifySlotCandidate(canonicalRepo, projectName, slot, {
79000
78992
  staleDays: options.staleDays,
79001
78993
  keep: options.keep
@@ -79055,8 +79047,8 @@ async function askYesNo4(question) {
79055
79047
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
79056
79048
  const readline8 = await import("readline");
79057
79049
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
79058
- const answer = await new Promise((resolve59) => {
79059
- rl.question(question, resolve59);
79050
+ const answer = await new Promise((resolve60) => {
79051
+ rl.question(question, resolve60);
79060
79052
  });
79061
79053
  rl.close();
79062
79054
  return /^[Yy]$/.test(answer.trim());
@@ -79101,7 +79093,7 @@ async function executeCleanupCandidates(candidates, options = {}) {
79101
79093
  continue;
79102
79094
  }
79103
79095
  if (candidate.kind === "orphan_worktree" && candidate.worktreePath) {
79104
- if (fs66.existsSync(candidate.worktreePath)) {
79096
+ if (fs67.existsSync(candidate.worktreePath)) {
79105
79097
  const repoRoot = candidate.repoPath !== getWorktreesRoot() ? candidate.repoPath : resolveRepoForWorktree(candidate.worktreePath);
79106
79098
  if (repoRoot) {
79107
79099
  try {
@@ -79112,8 +79104,8 @@ async function executeCleanupCandidates(candidates, options = {}) {
79112
79104
  } catch {
79113
79105
  }
79114
79106
  }
79115
- if (fs66.existsSync(candidate.worktreePath)) {
79116
- fs66.rmSync(candidate.worktreePath, { recursive: true, force: true });
79107
+ if (fs67.existsSync(candidate.worktreePath)) {
79108
+ fs67.rmSync(candidate.worktreePath, { recursive: true, force: true });
79117
79109
  }
79118
79110
  }
79119
79111
  outcomes.push({ candidate, ok: true });
@@ -79139,7 +79131,7 @@ function parseCleanupKeepPins(values) {
79139
79131
  }
79140
79132
  if (raw.startsWith("/") || raw.startsWith("~")) {
79141
79133
  return {
79142
- worktreePath: raw.startsWith("~") ? path74.join(process.env.HOME || os23.homedir(), raw.slice(2)) : path74.resolve(raw)
79134
+ worktreePath: raw.startsWith("~") ? path75.join(process.env.HOME || os23.homedir(), raw.slice(2)) : path75.resolve(raw)
79143
79135
  };
79144
79136
  }
79145
79137
  return { repoPath: raw };
@@ -79153,12 +79145,12 @@ init_stages();
79153
79145
  init_logging();
79154
79146
  function askYesNo5(question) {
79155
79147
  const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
79156
- return new Promise((resolve59) => {
79148
+ return new Promise((resolve60) => {
79157
79149
  process.stderr.write(`${question} `);
79158
79150
  rl.once("line", (answer) => {
79159
79151
  rl.close();
79160
79152
  const trimmed = answer.trim();
79161
- resolve59(trimmed === "" || /^y(es)?$/i.test(trimmed));
79153
+ resolve60(trimmed === "" || /^y(es)?$/i.test(trimmed));
79162
79154
  });
79163
79155
  });
79164
79156
  }
@@ -79259,21 +79251,21 @@ function warnIfDockerUnavailable(status = detectDockerStatus()) {
79259
79251
  }
79260
79252
 
79261
79253
  // src/core/onboarding-preferences.ts
79262
- var fs67 = __toESM(require("fs"));
79254
+ var fs68 = __toESM(require("fs"));
79263
79255
  var os24 = __toESM(require("os"));
79264
- var path75 = __toESM(require("path"));
79256
+ var path76 = __toESM(require("path"));
79265
79257
  init_schema2();
79266
79258
  function getOnboardingPreferencesPath() {
79267
79259
  if (process.env.HAR_PREFERENCES_PATH) {
79268
- return path75.resolve(process.env.HAR_PREFERENCES_PATH);
79260
+ return path76.resolve(process.env.HAR_PREFERENCES_PATH);
79269
79261
  }
79270
- return path75.join(os24.homedir(), ".har", "preferences.json");
79262
+ return path76.join(os24.homedir(), ".har", "preferences.json");
79271
79263
  }
79272
79264
  function readOnboardingPreferences() {
79273
79265
  const preferencePath = getOnboardingPreferencesPath();
79274
79266
  try {
79275
- if (!fs67.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
79276
- return OnboardingPreferencesSchema.parse(JSON.parse(fs67.readFileSync(preferencePath, "utf8")));
79267
+ if (!fs68.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
79268
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs68.readFileSync(preferencePath, "utf8")));
79277
79269
  } catch {
79278
79270
  return OnboardingPreferencesSchema.parse({});
79279
79271
  }
@@ -79298,8 +79290,8 @@ function writeOnboardingPreferences(overrides) {
79298
79290
  };
79299
79291
  const parsed = OnboardingPreferencesSchema.parse(preference);
79300
79292
  const preferencePath = getOnboardingPreferencesPath();
79301
- fs67.mkdirSync(path75.dirname(preferencePath), { recursive: true });
79302
- fs67.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
79293
+ fs68.mkdirSync(path76.dirname(preferencePath), { recursive: true });
79294
+ fs68.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
79303
79295
  `);
79304
79296
  return parsed;
79305
79297
  }
@@ -79377,7 +79369,7 @@ var envCommand = {
79377
79369
  describe: "Manage agent environments (launch \u2192 verify \u2192 complete)",
79378
79370
  builder: (yargs) => yargs.command(
79379
79371
  "init",
79380
- "Copy harness boilerplate into .har/",
79372
+ "Mechanical scaffold of .har/ (fixtures / --force). Humans use har onboard.",
79381
79373
  (y) => y.option("repo", { type: "string", default: ".", describe: "Path to the repository" }).option("verbose", { alias: "v", type: "boolean", default: false }).option("force", { type: "boolean", default: false, describe: "Overwrite existing .har/" }).option("smoke", { type: "boolean", default: false, describe: "Run setup-infra.sh after adaptation" }).option("profile", {
79382
79374
  type: "string",
79383
79375
  choices: ["default", "cli", "ios"],
@@ -79592,7 +79584,7 @@ var envCommand = {
79592
79584
  handleDoctor
79593
79585
  ).command(
79594
79586
  "eject",
79595
- "Vendor the HAR runtime into .har/ and own the scripts yourself (reversible: har env adopt)",
79587
+ "Vendor the HAR runtime into .har/runtime/ (reversible: har env adopt)",
79596
79588
  (y) => y.option("repo", { type: "string", default: ".", describe: "Path to the repository" }).option("yes", {
79597
79589
  alias: "y",
79598
79590
  type: "boolean",
@@ -79602,7 +79594,7 @@ var envCommand = {
79602
79594
  handleEject
79603
79595
  ).command(
79604
79596
  "adopt",
79605
- "Return an ejected harness to managed shims (removes .har/runtime/, keeps your config)",
79597
+ "Return an ejected harness to the packaged runtime (removes .har/runtime/, keeps your config)",
79606
79598
  (y) => y.option("repo", { type: "string", default: ".", describe: "Path to the repository" }),
79607
79599
  handleAdopt
79608
79600
  ).command(
@@ -79685,7 +79677,7 @@ var envCommand = {
79685
79677
  }
79686
79678
  };
79687
79679
  async function handleInit(argv) {
79688
- const repoPath = path76.resolve(argv.repo);
79680
+ const repoPath = path77.resolve(argv.repo);
79689
79681
  const onboarding = resolveOnboardingOptions(argv);
79690
79682
  header("har env init");
79691
79683
  info(`Repository: ${repoPath}`);
@@ -79732,7 +79724,7 @@ async function handleInit(argv) {
79732
79724
  }
79733
79725
  }
79734
79726
  async function handleMaintain(argv) {
79735
- const repoPath = path76.resolve(argv.repo);
79727
+ const repoPath = path77.resolve(argv.repo);
79736
79728
  const onboarding = resolveOnboardingOptions(argv);
79737
79729
  header("har env maintain");
79738
79730
  info(`Repository: ${repoPath}`);
@@ -79887,7 +79879,7 @@ async function applyAgentIntegrations(options) {
79887
79879
  }
79888
79880
  }
79889
79881
  async function handleAddPlugin(argv) {
79890
- const repoPath = path76.resolve(argv.repo);
79882
+ const repoPath = path77.resolve(argv.repo);
79891
79883
  const available = listPluginIds();
79892
79884
  if (argv.list) {
79893
79885
  for (const id of available) {
@@ -79923,7 +79915,7 @@ async function handleAddPlugin(argv) {
79923
79915
  console.error(` Docs: ${result.docsPath}`);
79924
79916
  console.error("");
79925
79917
  info(`Adaptation prompt saved to ${result.adaptPromptPath}`);
79926
- const promptContent = fs68.readFileSync(path76.join(repoPath, result.adaptPromptPath), "utf8");
79918
+ const promptContent = fs69.readFileSync(path77.join(repoPath, result.adaptPromptPath), "utf8");
79927
79919
  await offerAdaptationPromptClipboard(promptContent, { fileLabel: result.adaptPromptPath });
79928
79920
  } catch (err) {
79929
79921
  error(err.message);
@@ -79965,7 +79957,7 @@ async function handleAddStage(argv) {
79965
79957
  });
79966
79958
  }
79967
79959
  async function handlePreflight(argv) {
79968
- const repo = path76.resolve(argv.repo);
79960
+ const repo = path77.resolve(argv.repo);
79969
79961
  const agentId = validateAgentId(argv.id, repo);
79970
79962
  const result = await preflightEnvironment({
79971
79963
  repoPath: repo,
@@ -79981,7 +79973,7 @@ async function handlePreflight(argv) {
79981
79973
  return finishCommand(result.code);
79982
79974
  }
79983
79975
  async function handleLaunch(argv) {
79984
- const repo = path76.resolve(argv.repo);
79976
+ const repo = path77.resolve(argv.repo);
79985
79977
  const agentId = validateAgentId(argv.id, repo);
79986
79978
  const result = await launchEnvironment({
79987
79979
  repoPath: repo,
@@ -80023,7 +80015,7 @@ async function handleWorkLink(argv) {
80023
80015
  error("Provide --link or both --source and --url");
80024
80016
  return finishCommand(1);
80025
80017
  }
80026
- const harnessRoot = resolveHarnessRoot(path76.resolve(argv.repo));
80018
+ const harnessRoot = resolveHarnessRoot(path77.resolve(argv.repo));
80027
80019
  const links = argv.link ? [parseWorkLinkSpec(argv.link)] : [{ source: argv.source, url: argv.url, label: argv.label }];
80028
80020
  try {
80029
80021
  const record2 = addWorkUnitLinks(harnessRoot, argv.workId, links);
@@ -80049,7 +80041,7 @@ async function handleRecover(argv) {
80049
80041
  });
80050
80042
  }
80051
80043
  async function handleVerify(argv) {
80052
- const repo = path76.resolve(argv.repo);
80044
+ const repo = path77.resolve(argv.repo);
80053
80045
  const agentId = validateAgentId(argv.id, repo);
80054
80046
  const result = await runVerification({
80055
80047
  repoPath: repo,
@@ -80078,7 +80070,7 @@ async function handleVerify(argv) {
80078
80070
  return finishCommand(result.code);
80079
80071
  }
80080
80072
  async function handleTeardown(argv) {
80081
- const repo = path76.resolve(argv.repo);
80073
+ const repo = path77.resolve(argv.repo);
80082
80074
  const agentId = validateAgentId(argv.id, repo);
80083
80075
  const result = await teardownEnvironment({
80084
80076
  repoPath: repo,
@@ -80089,7 +80081,7 @@ async function handleTeardown(argv) {
80089
80081
  return finishCommand(result.code);
80090
80082
  }
80091
80083
  async function handleComplete(argv) {
80092
- const repo = path76.resolve(argv.repo);
80084
+ const repo = path77.resolve(argv.repo);
80093
80085
  const agentId = validateAgentId(argv.id, repo);
80094
80086
  const result = await completeEnvironment({
80095
80087
  repoPath: repo,
@@ -80110,7 +80102,7 @@ async function handleComplete(argv) {
80110
80102
  return finishCommand(result.code);
80111
80103
  }
80112
80104
  async function handleSetupInfra(argv) {
80113
- const repo = path76.resolve(argv.repo);
80105
+ const repo = path77.resolve(argv.repo);
80114
80106
  const result = await runStage({
80115
80107
  repoPath: repo,
80116
80108
  kind: "setup",
@@ -80120,7 +80112,7 @@ async function handleSetupInfra(argv) {
80120
80112
  return finishCommand(result.code ?? (result.status === "pass" ? 0 : 1));
80121
80113
  }
80122
80114
  async function handleAgent(argv) {
80123
- const repo = path76.resolve(argv.repo);
80115
+ const repo = path77.resolve(argv.repo);
80124
80116
  const agentId = validateAgentId(argv.id, repo);
80125
80117
  const result = await runAgentOp({
80126
80118
  repoPath: repo,
@@ -80131,7 +80123,7 @@ async function handleAgent(argv) {
80131
80123
  return finishCommand(result.code);
80132
80124
  }
80133
80125
  async function handleDoctor(argv) {
80134
- const repoPath = path76.resolve(argv.repo);
80126
+ const repoPath = path77.resolve(argv.repo);
80135
80127
  const report = runDoctor(repoPath);
80136
80128
  if (argv.json) {
80137
80129
  console.log(JSON.stringify(report, null, 2));
@@ -80155,23 +80147,24 @@ async function confirm(question) {
80155
80147
  if (!process.stdin.isTTY) return false;
80156
80148
  const readline8 = await import("readline");
80157
80149
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
80158
- const answer = await new Promise((resolve59) => rl.question(question, resolve59));
80150
+ const answer = await new Promise((resolve60) => rl.question(question, resolve60));
80159
80151
  rl.close();
80160
80152
  return /^y(es)?$/i.test(answer.trim());
80161
80153
  }
80162
80154
  async function handleEject(argv) {
80163
- const repoPath = resolveHarnessRoot(path76.resolve(argv.repo));
80155
+ const repoPath = resolveHarnessRoot(path77.resolve(argv.repo));
80164
80156
  header("har env eject");
80165
- warn("This vendors the complete HAR runtime into .har/runtime/ and rewrites the");
80166
- warn(".har/*.sh scripts to execute it directly \u2014 from then on YOU OWN those files:");
80167
- warn(" \u2022 har env maintain will no longer update them (no upstream drift reports)");
80157
+ warn("This vendors the complete HAR runtime into .har/runtime/ \u2014 from then on");
80158
+ warn("YOU OWN that directory:");
80159
+ warn(" \u2022 drive it with `har env \u2026` or `node .har/runtime/har.cjs env \u2026`");
80160
+ warn(" \u2022 har env maintain will no longer update it (no upstream drift reports)");
80168
80161
  warn(" \u2022 upstream fixes and features reach you only by re-ejecting or adopting");
80169
- warn(" \u2022 support covers issues reproducible with managed shims; changes you make");
80170
- warn(" to the ejected runtime are yours to maintain");
80162
+ warn(" \u2022 support covers issues reproducible with the packaged runtime; changes");
80163
+ warn(" you make to the ejected runtime are yours to maintain");
80171
80164
  warn("Config files (harness.env, stages.json, stages/, hooks, docs) stay managed.");
80172
80165
  info("Reversible anytime: `har env adopt` (or `har env init --force`).");
80173
80166
  if (!argv.yes) {
80174
- const ok = await confirm("Eject the runtime and own the scripts yourself? [y/N] ");
80167
+ const ok = await confirm("Eject the runtime into .har/runtime/? [y/N] ");
80175
80168
  if (!ok) {
80176
80169
  info("Aborted \u2014 nothing changed. Pass --yes to skip this prompt.");
80177
80170
  return finishCommand(1);
@@ -80180,9 +80173,9 @@ async function handleEject(argv) {
80180
80173
  try {
80181
80174
  const result = ejectHarness(repoPath);
80182
80175
  success(`Ejected @osfactory/har@${result.version} \u2192 .har/runtime/`);
80183
- info(` Rewritten as user-owned: ${result.scripts.map((s) => `.har/${s}`).join(", ")}`);
80176
+ info(" Invocation: har env \u2026 or node .har/runtime/har.cjs env \u2026");
80184
80177
  info(" Recorded in .har/manifest.json (ejected: true) \u2014 commit .har/ to keep it.");
80185
- info(" Return to managed shims anytime: har env adopt");
80178
+ info(" Return to the packaged runtime anytime: har env adopt");
80186
80179
  } catch (err) {
80187
80180
  error(err instanceof Error ? err.message : String(err));
80188
80181
  return finishCommand(1);
@@ -80190,11 +80183,13 @@ async function handleEject(argv) {
80190
80183
  return finishCommand(0);
80191
80184
  }
80192
80185
  async function handleAdopt(argv) {
80193
- const repoPath = resolveHarnessRoot(path76.resolve(argv.repo));
80186
+ const repoPath = resolveHarnessRoot(path77.resolve(argv.repo));
80194
80187
  try {
80195
80188
  const result = adoptHarness(repoPath);
80196
- success("Returned to managed shims \u2014 .har/runtime/ removed, eject flag cleared.");
80197
- info(` Regenerated: ${result.scripts.map((s) => `.har/${s}`).join(", ")}`);
80189
+ success("Returned to the packaged runtime \u2014 .har/runtime/ removed, eject flag cleared.");
80190
+ if (result.scripts.length > 0) {
80191
+ info(` Pruned leftover wrappers: ${result.scripts.map((s) => `.har/${s}`).join(", ")}`);
80192
+ }
80198
80193
  info(" Config surface files (harness.env, stages.json, stages/, docs) were not touched.");
80199
80194
  } catch (err) {
80200
80195
  error(err instanceof Error ? err.message : String(err));
@@ -80203,7 +80198,7 @@ async function handleAdopt(argv) {
80203
80198
  return finishCommand(0);
80204
80199
  }
80205
80200
  async function handleStatus(argv) {
80206
- const repoPath = path76.resolve(argv.repo);
80201
+ const repoPath = path77.resolve(argv.repo);
80207
80202
  const result = await getEnvironmentStatus({
80208
80203
  repoPath,
80209
80204
  capture: false
@@ -80216,7 +80211,7 @@ async function handleStatus(argv) {
80216
80211
  if (result.stdout) process.stdout.write(result.stdout);
80217
80212
  }
80218
80213
  async function handleLogs(argv) {
80219
- const repo = path76.resolve(argv.repo);
80214
+ const repo = path77.resolve(argv.repo);
80220
80215
  const agentId = validateAgentId(argv.id, repo);
80221
80216
  const result = await getEnvironmentLogs({
80222
80217
  repoPath: repo,
@@ -80228,7 +80223,7 @@ async function handleLogs(argv) {
80228
80223
  return finishCommand(result.code);
80229
80224
  }
80230
80225
  async function handleRunStage(argv) {
80231
- const repo = path76.resolve(argv.repo);
80226
+ const repo = path77.resolve(argv.repo);
80232
80227
  const agentId = validateAgentId(argv.id, repo);
80233
80228
  if (!argv.stage) {
80234
80229
  error("Missing stage id. Usage: har env run-stage <id> <stage> [args..]");
@@ -80254,7 +80249,7 @@ async function handleRunStage(argv) {
80254
80249
  }
80255
80250
  async function handleArtifacts(argv) {
80256
80251
  const artifacts = listArtifacts({
80257
- repoPath: path76.resolve(argv.repo),
80252
+ repoPath: path77.resolve(argv.repo),
80258
80253
  stageId: argv.stage
80259
80254
  });
80260
80255
  if (argv.json) {
@@ -80273,7 +80268,7 @@ async function handleArtifacts(argv) {
80273
80268
  async function handleCleanup(argv) {
80274
80269
  const keepValues = argv.keep?.split(",").map((value) => value.trim()).filter(Boolean);
80275
80270
  const keep = parseCleanupKeepPins(keepValues);
80276
- const repoPaths = argv.repo ? [path76.resolve(argv.repo)] : void 0;
80271
+ const repoPaths = argv.repo ? [path77.resolve(argv.repo)] : void 0;
80277
80272
  const plan = await discoverCleanupCandidates({
80278
80273
  cwd: process.cwd(),
80279
80274
  repoPaths,
@@ -80322,7 +80317,7 @@ async function handleCleanup(argv) {
80322
80317
  return finishCommand(failed > 0 ? 1 : 0);
80323
80318
  }
80324
80319
  async function handleRunsList(argv) {
80325
- const repoPath = path76.resolve(argv.repo);
80320
+ const repoPath = path77.resolve(argv.repo);
80326
80321
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
80327
80322
  if (argv.json) {
80328
80323
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -80339,7 +80334,7 @@ async function handleRunsList(argv) {
80339
80334
  }
80340
80335
  }
80341
80336
  async function handleRunsGet(argv) {
80342
- const run2 = getRun(path76.resolve(argv.repo), argv.runId);
80337
+ const run2 = getRun(path77.resolve(argv.repo), argv.runId);
80343
80338
  if (!run2) {
80344
80339
  error(`Run not found: ${argv.runId}`);
80345
80340
  return finishCommand(1);
@@ -80456,7 +80451,7 @@ function printNextSteps() {
80456
80451
  }
80457
80452
 
80458
80453
  // src/cli/commands/control.ts
80459
- var path81 = __toESM(require("path"));
80454
+ var path82 = __toESM(require("path"));
80460
80455
  init_control_config();
80461
80456
  init_portal_targets();
80462
80457
 
@@ -80464,8 +80459,8 @@ init_portal_targets();
80464
80459
  init_control_config();
80465
80460
 
80466
80461
  // src/core/portal-connect.ts
80467
- var fs69 = __toESM(require("fs"));
80468
- var path77 = __toESM(require("path"));
80462
+ var fs70 = __toESM(require("fs"));
80463
+ var path78 = __toESM(require("path"));
80469
80464
  var import_crypto2 = require("crypto");
80470
80465
  init_control_repo_path();
80471
80466
  init_control_registry();
@@ -80511,7 +80506,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
80511
80506
  const options = typeof openUrlOrOptions === "function" ? { openUrl: openUrlOrOptions } : openUrlOrOptions;
80512
80507
  const openUrl = options.openUrl ?? openBrowser;
80513
80508
  const state = (0, import_crypto.randomUUID)();
80514
- return new Promise((resolve59, reject) => {
80509
+ return new Promise((resolve60, reject) => {
80515
80510
  let timer;
80516
80511
  const server = http.createServer((req, res) => {
80517
80512
  const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
@@ -80539,7 +80534,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
80539
80534
  res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
80540
80535
  cleanup();
80541
80536
  const targets = parseCliTargetsParam(requestUrl.searchParams.get("targets"));
80542
- resolve59({
80537
+ resolve60({
80543
80538
  portalUrl,
80544
80539
  token,
80545
80540
  workspace: workspaceSlug ?? workspace,
@@ -80634,8 +80629,8 @@ function remainingConnections(connections, usedAliases) {
80634
80629
  // src/core/portal-connect.ts
80635
80630
  init_portal_targets();
80636
80631
  function attachRepoIfPresent(alias, repoPath) {
80637
- const resolved = path77.resolve(repoPath ?? ".");
80638
- if (!fs69.existsSync(resolved)) return null;
80632
+ const resolved = path78.resolve(repoPath ?? ".");
80633
+ if (!fs70.existsSync(resolved)) return null;
80639
80634
  const canonical = canonicalizeControlRepoPath(resolved);
80640
80635
  attachRepoPortalTarget(canonical, alias);
80641
80636
  recordRepoForControlSync(canonical);
@@ -80702,8 +80697,8 @@ async function runPortalConnect(input) {
80702
80697
  return { record: record2, attachedRepo, extraAttached, mappedInBrowser: true };
80703
80698
  }
80704
80699
  function listRegisteredReposForConnect(repoPath) {
80705
- const resolved = repoPath ? path77.resolve(repoPath) : null;
80706
- const current = resolved && fs69.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
80700
+ const resolved = repoPath ? path78.resolve(repoPath) : null;
80701
+ const current = resolved && fs70.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
80707
80702
  return [.../* @__PURE__ */ new Set([...current ? [current] : [], ...listRegisteredRepos()])];
80708
80703
  }
80709
80704
 
@@ -81019,21 +81014,21 @@ init_control_port();
81019
81014
  init_control_sync();
81020
81015
 
81021
81016
  // src/core/control-sync-selection.ts
81022
- var fs70 = __toESM(require("fs"));
81017
+ var fs71 = __toESM(require("fs"));
81023
81018
  var os25 = __toESM(require("os"));
81024
- var path78 = __toESM(require("path"));
81019
+ var path79 = __toESM(require("path"));
81025
81020
  init_control_repo_path();
81026
81021
  function getSelectionPath() {
81027
81022
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
81028
- return path78.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
81023
+ return path79.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
81029
81024
  }
81030
- return path78.join(os25.homedir(), ".har", "sync-selection.json");
81025
+ return path79.join(os25.homedir(), ".har", "sync-selection.json");
81031
81026
  }
81032
81027
  function readSyncSelection() {
81033
81028
  const selectionPath = getSelectionPath();
81034
81029
  try {
81035
- if (!fs70.existsSync(selectionPath)) return null;
81036
- const parsed = JSON.parse(fs70.readFileSync(selectionPath, "utf8"));
81030
+ if (!fs71.existsSync(selectionPath)) return null;
81031
+ const parsed = JSON.parse(fs71.readFileSync(selectionPath, "utf8"));
81037
81032
  if (!Array.isArray(parsed.repos)) return null;
81038
81033
  return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
81039
81034
  } catch {
@@ -81043,8 +81038,8 @@ function readSyncSelection() {
81043
81038
  function writeSyncSelection(repos) {
81044
81039
  const selectionPath = getSelectionPath();
81045
81040
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
81046
- fs70.mkdirSync(path78.dirname(selectionPath), { recursive: true });
81047
- fs70.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
81041
+ fs71.mkdirSync(path79.dirname(selectionPath), { recursive: true });
81042
+ fs71.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
81048
81043
  }
81049
81044
  function resolveSyncSelection(input) {
81050
81045
  const { discovered, stored, forceSelect, isTTY } = input;
@@ -81071,8 +81066,8 @@ function resolveSyncSelection(input) {
81071
81066
  }
81072
81067
 
81073
81068
  // src/core/control-unregister.ts
81074
- var fs71 = __toESM(require("fs"));
81075
- var path79 = __toESM(require("path"));
81069
+ var fs72 = __toESM(require("fs"));
81070
+ var path80 = __toESM(require("path"));
81076
81071
  init_control_repo_path();
81077
81072
  init_control_registry();
81078
81073
  init_control_config();
@@ -81082,9 +81077,9 @@ function listUnregisterWorktreeCandidates(repoPath) {
81082
81077
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
81083
81078
  const byPath = /* @__PURE__ */ new Map();
81084
81079
  const add = (partial2) => {
81085
- const resolved = path79.resolve(partial2.worktreePath);
81080
+ const resolved = path80.resolve(partial2.worktreePath);
81086
81081
  if (!resolved || resolved === harnessRoot) return;
81087
- const exists = partial2.exists ?? fs71.existsSync(resolved);
81082
+ const exists = partial2.exists ?? fs72.existsSync(resolved);
81088
81083
  const prev = byPath.get(resolved);
81089
81084
  if (prev) {
81090
81085
  byPath.set(resolved, {
@@ -81135,8 +81130,8 @@ async function askYesNo6(question) {
81135
81130
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
81136
81131
  const readline8 = await import("readline");
81137
81132
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
81138
- const answer = await new Promise((resolve59) => {
81139
- rl.question(question, resolve59);
81133
+ const answer = await new Promise((resolve60) => {
81134
+ rl.question(question, resolve60);
81140
81135
  });
81141
81136
  rl.close();
81142
81137
  return /^[Yy]$/.test(answer.trim());
@@ -81198,28 +81193,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
81198
81193
  trigger: "cli"
81199
81194
  });
81200
81195
  if (result.code !== 0) {
81201
- if (fs71.existsSync(candidate.worktreePath)) {
81202
- fs71.rmSync(candidate.worktreePath, { recursive: true, force: true });
81196
+ if (fs72.existsSync(candidate.worktreePath)) {
81197
+ fs72.rmSync(candidate.worktreePath, { recursive: true, force: true });
81203
81198
  }
81204
81199
  }
81205
81200
  outcomes.push({
81206
81201
  path: candidate.worktreePath,
81207
81202
  agentId: candidate.agentId,
81208
- deleted: !fs71.existsSync(candidate.worktreePath),
81209
- error: result.code !== 0 && fs71.existsSync(candidate.worktreePath) ? result.stderr : void 0
81203
+ deleted: !fs72.existsSync(candidate.worktreePath),
81204
+ error: result.code !== 0 && fs72.existsSync(candidate.worktreePath) ? result.stderr : void 0
81210
81205
  });
81211
81206
  } catch (err) {
81212
81207
  const message = err instanceof Error ? err.message : String(err);
81213
81208
  try {
81214
- if (fs71.existsSync(candidate.worktreePath)) {
81215
- fs71.rmSync(candidate.worktreePath, { recursive: true, force: true });
81209
+ if (fs72.existsSync(candidate.worktreePath)) {
81210
+ fs72.rmSync(candidate.worktreePath, { recursive: true, force: true });
81216
81211
  }
81217
81212
  } catch {
81218
81213
  }
81219
81214
  outcomes.push({
81220
81215
  path: candidate.worktreePath,
81221
81216
  agentId: candidate.agentId,
81222
- deleted: !fs71.existsSync(candidate.worktreePath),
81217
+ deleted: !fs72.existsSync(candidate.worktreePath),
81223
81218
  error: message
81224
81219
  });
81225
81220
  }
@@ -81282,16 +81277,16 @@ init_control_config();
81282
81277
  init_control_registry();
81283
81278
 
81284
81279
  // src/core/harness-scrub.ts
81285
- var fs72 = __toESM(require("fs"));
81286
- var path80 = __toESM(require("path"));
81280
+ var fs73 = __toESM(require("fs"));
81281
+ var path81 = __toESM(require("path"));
81287
81282
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
81288
81283
  function scrubLocalHarnessDirs(repoPath) {
81289
81284
  const results = [];
81290
- const resolved = path80.resolve(repoPath);
81291
- if (!fs72.existsSync(resolved)) {
81285
+ const resolved = path81.resolve(repoPath);
81286
+ if (!fs73.existsSync(resolved)) {
81292
81287
  for (const directory of HARNESS_SCRUB_DIRS) {
81293
81288
  results.push({
81294
- path: path80.join(resolved, ".har", directory),
81289
+ path: path81.join(resolved, ".har", directory),
81295
81290
  directory,
81296
81291
  deleted: false,
81297
81292
  error: "repository path does not exist"
@@ -81300,24 +81295,24 @@ function scrubLocalHarnessDirs(repoPath) {
81300
81295
  return results;
81301
81296
  }
81302
81297
  for (const directory of HARNESS_SCRUB_DIRS) {
81303
- const target = path80.join(resolved, ".har", directory);
81304
- if (!fs72.existsSync(target)) {
81298
+ const target = path81.join(resolved, ".har", directory);
81299
+ if (!fs73.existsSync(target)) {
81305
81300
  results.push({ path: target, directory, deleted: true });
81306
81301
  continue;
81307
81302
  }
81308
81303
  try {
81309
- fs72.rmSync(target, { recursive: true, force: true });
81304
+ fs73.rmSync(target, { recursive: true, force: true });
81310
81305
  results.push({
81311
81306
  path: target,
81312
81307
  directory,
81313
- deleted: !fs72.existsSync(target),
81314
- error: fs72.existsSync(target) ? "failed to remove directory" : void 0
81308
+ deleted: !fs73.existsSync(target),
81309
+ error: fs73.existsSync(target) ? "failed to remove directory" : void 0
81315
81310
  });
81316
81311
  } catch (err) {
81317
81312
  results.push({
81318
81313
  path: target,
81319
81314
  directory,
81320
- deleted: !fs72.existsSync(target),
81315
+ deleted: !fs73.existsSync(target),
81321
81316
  error: err instanceof Error ? err.message : String(err)
81322
81317
  });
81323
81318
  }
@@ -81328,7 +81323,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
81328
81323
  const results = [];
81329
81324
  const seen = /* @__PURE__ */ new Set();
81330
81325
  for (const repoPath of repoPaths) {
81331
- const key = path80.resolve(repoPath);
81326
+ const key = path81.resolve(repoPath);
81332
81327
  if (seen.has(key)) continue;
81333
81328
  seen.add(key);
81334
81329
  results.push(...scrubLocalHarnessDirs(key));
@@ -81341,8 +81336,8 @@ async function askYesNo7(question) {
81341
81336
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
81342
81337
  const readline8 = await import("readline");
81343
81338
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
81344
- const answer = await new Promise((resolve59) => {
81345
- rl.question(question, resolve59);
81339
+ const answer = await new Promise((resolve60) => {
81340
+ rl.question(question, resolve60);
81346
81341
  });
81347
81342
  rl.close();
81348
81343
  return /^[Yy]$/.test(answer.trim());
@@ -81621,7 +81616,7 @@ async function handleDown() {
81621
81616
  return finishCommand(code);
81622
81617
  }
81623
81618
  async function handleRegister(argv) {
81624
- const repoPath = path81.resolve(argv.repo);
81619
+ const repoPath = path82.resolve(argv.repo);
81625
81620
  header("har control register");
81626
81621
  info(`Repository: ${repoPath}`);
81627
81622
  try {
@@ -81719,7 +81714,7 @@ async function handleReset(argv) {
81719
81714
  }
81720
81715
  }
81721
81716
  async function handleUnregister(argv) {
81722
- const repoPath = path81.resolve(argv.repo);
81717
+ const repoPath = path82.resolve(argv.repo);
81723
81718
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
81724
81719
  try {
81725
81720
  let deleteWorktrees = argv.deleteWorktrees;
@@ -82000,12 +81995,12 @@ async function handleTrajectory(argv) {
82000
81995
  }
82001
81996
 
82002
81997
  // src/cli/commands/hooks.ts
82003
- var path83 = __toESM(require("path"));
81998
+ var path84 = __toESM(require("path"));
82004
81999
  init_hooks();
82005
82000
 
82006
82001
  // src/core/claude-hooks.ts
82007
- var fs73 = __toESM(require("fs"));
82008
- var path82 = __toESM(require("path"));
82002
+ var fs74 = __toESM(require("fs"));
82003
+ var path83 = __toESM(require("path"));
82009
82004
  init_paths();
82010
82005
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
82011
82006
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
@@ -82017,8 +82012,8 @@ function isHarGuardEntry(entry) {
82017
82012
  );
82018
82013
  }
82019
82014
  function readSettings(settingsPath) {
82020
- if (!fs73.existsSync(settingsPath)) return {};
82021
- const raw = fs73.readFileSync(settingsPath, "utf8").trim();
82015
+ if (!fs74.existsSync(settingsPath)) return {};
82016
+ const raw = fs74.readFileSync(settingsPath, "utf8").trim();
82022
82017
  if (raw === "") return {};
82023
82018
  const parsed = JSON.parse(raw);
82024
82019
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -82027,19 +82022,19 @@ function readSettings(settingsPath) {
82027
82022
  return parsed;
82028
82023
  }
82029
82024
  function writeSettings(settingsPath, settings) {
82030
- fs73.mkdirSync(path82.dirname(settingsPath), { recursive: true });
82031
- fs73.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
82025
+ fs74.mkdirSync(path83.dirname(settingsPath), { recursive: true });
82026
+ fs74.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
82032
82027
  }
82033
82028
  function installClaudeGuard(repoPath) {
82034
82029
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
82035
82030
  if (!templatePath) {
82036
82031
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
82037
82032
  }
82038
- const guardScript = path82.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82039
- fs73.mkdirSync(path82.dirname(guardScript), { recursive: true });
82040
- fs73.copyFileSync(templatePath, guardScript);
82041
- fs73.chmodSync(guardScript, 493);
82042
- const settingsPath = path82.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82033
+ const guardScript = path83.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82034
+ fs74.mkdirSync(path83.dirname(guardScript), { recursive: true });
82035
+ fs74.copyFileSync(templatePath, guardScript);
82036
+ fs74.chmodSync(guardScript, 493);
82037
+ const settingsPath = path83.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82043
82038
  const settings = readSettings(settingsPath);
82044
82039
  const hooks = settings.hooks ?? {};
82045
82040
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -82053,15 +82048,15 @@ function installClaudeGuard(repoPath) {
82053
82048
  }
82054
82049
  function uninstallClaudeGuard(repoPath) {
82055
82050
  let removed = false;
82056
- const guardScript = path82.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82057
- if (fs73.existsSync(guardScript)) {
82058
- fs73.rmSync(guardScript);
82051
+ const guardScript = path83.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82052
+ if (fs74.existsSync(guardScript)) {
82053
+ fs74.rmSync(guardScript);
82059
82054
  removed = true;
82060
- const parent = path82.dirname(guardScript);
82061
- if (fs73.existsSync(parent) && fs73.readdirSync(parent).length === 0) fs73.rmdirSync(parent);
82055
+ const parent = path83.dirname(guardScript);
82056
+ if (fs74.existsSync(parent) && fs74.readdirSync(parent).length === 0) fs74.rmdirSync(parent);
82062
82057
  }
82063
- const settingsPath = path82.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82064
- if (fs73.existsSync(settingsPath)) {
82058
+ const settingsPath = path83.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82059
+ if (fs74.existsSync(settingsPath)) {
82065
82060
  const settings = readSettings(settingsPath);
82066
82061
  const preToolUse = settings.hooks?.PreToolUse;
82067
82062
  if (preToolUse) {
@@ -82086,8 +82081,8 @@ function uninstallClaudeGuard(repoPath) {
82086
82081
  return { removed };
82087
82082
  }
82088
82083
  function claudeGuardInstalled(repoPath) {
82089
- const settingsPath = path82.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82090
- if (!fs73.existsSync(settingsPath)) return false;
82084
+ const settingsPath = path83.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82085
+ if (!fs74.existsSync(settingsPath)) return false;
82091
82086
  try {
82092
82087
  const settings = readSettings(settingsPath);
82093
82088
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -82104,7 +82099,7 @@ function repoOption(y) {
82104
82099
  function handleInstall2(argv) {
82105
82100
  try {
82106
82101
  if (argv.claude) {
82107
- const result2 = installClaudeGuard(path83.resolve(argv.repo));
82102
+ const result2 = installClaudeGuard(path84.resolve(argv.repo));
82108
82103
  success("Claude Code worktree guard installed.");
82109
82104
  info(`Guard script: ${result2.guardScript}`);
82110
82105
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -82112,7 +82107,7 @@ function handleInstall2(argv) {
82112
82107
  info("Commit both files so the guard travels with the repo.");
82113
82108
  return;
82114
82109
  }
82115
- const result = installHooks({ repoPath: path83.resolve(argv.repo), force: argv.force });
82110
+ const result = installHooks({ repoPath: path84.resolve(argv.repo), force: argv.force });
82116
82111
  success(`Commit gate installed in ${result.hooksDir}`);
82117
82112
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
82118
82113
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -82125,7 +82120,7 @@ function handleInstall2(argv) {
82125
82120
  function handleUninstall(argv) {
82126
82121
  try {
82127
82122
  if (argv.claude) {
82128
- const result2 = uninstallClaudeGuard(path83.resolve(argv.repo));
82123
+ const result2 = uninstallClaudeGuard(path84.resolve(argv.repo));
82129
82124
  if (result2.removed) {
82130
82125
  success("Claude Code worktree guard removed.");
82131
82126
  } else {
@@ -82133,7 +82128,7 @@ function handleUninstall(argv) {
82133
82128
  }
82134
82129
  return;
82135
82130
  }
82136
- const result = uninstallHooks(path83.resolve(argv.repo));
82131
+ const result = uninstallHooks(path84.resolve(argv.repo));
82137
82132
  if (result.removed) {
82138
82133
  success(`Commit gate removed from ${result.hooksDir}`);
82139
82134
  } else {
@@ -82146,7 +82141,7 @@ function handleUninstall(argv) {
82146
82141
  }
82147
82142
  function handleStatus2(argv) {
82148
82143
  try {
82149
- const status = getHooksStatus(path83.resolve(argv.repo));
82144
+ const status = getHooksStatus(path84.resolve(argv.repo));
82150
82145
  if (argv.json) {
82151
82146
  process.stdout.write(`${JSON.stringify(status, null, 2)}
82152
82147
  `);
@@ -82164,7 +82159,7 @@ function handleStatus2(argv) {
82164
82159
  );
82165
82160
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
82166
82161
  info(
82167
- `Claude guard: ${claudeGuardInstalled(path83.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
82162
+ `Claude guard: ${claudeGuardInstalled(path84.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
82168
82163
  );
82169
82164
  } catch (err) {
82170
82165
  error(err instanceof Error ? err.message : String(err));
@@ -82425,10 +82420,10 @@ function assignProp(target, prop, value) {
82425
82420
  configurable: true
82426
82421
  });
82427
82422
  }
82428
- function getElementAtPath(obj, path90) {
82429
- if (!path90)
82423
+ function getElementAtPath(obj, path91) {
82424
+ if (!path91)
82430
82425
  return obj;
82431
- return path90.reduce((acc, key) => acc?.[key], obj);
82426
+ return path91.reduce((acc, key) => acc?.[key], obj);
82432
82427
  }
82433
82428
  function promiseAllObject(promisesObj) {
82434
82429
  const keys = Object.keys(promisesObj);
@@ -82748,11 +82743,11 @@ function aborted(x, startIndex = 0) {
82748
82743
  }
82749
82744
  return false;
82750
82745
  }
82751
- function prefixIssues(path90, issues) {
82746
+ function prefixIssues(path91, issues) {
82752
82747
  return issues.map((iss) => {
82753
82748
  var _a2;
82754
82749
  (_a2 = iss).path ?? (_a2.path = []);
82755
- iss.path.unshift(path90);
82750
+ iss.path.unshift(path91);
82756
82751
  return iss;
82757
82752
  });
82758
82753
  }
@@ -88075,7 +88070,7 @@ var Protocol = class {
88075
88070
  return;
88076
88071
  }
88077
88072
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
88078
- await new Promise((resolve59) => setTimeout(resolve59, pollInterval));
88073
+ await new Promise((resolve60) => setTimeout(resolve60, pollInterval));
88079
88074
  options?.signal?.throwIfAborted();
88080
88075
  }
88081
88076
  } catch (error3) {
@@ -88092,7 +88087,7 @@ var Protocol = class {
88092
88087
  */
88093
88088
  request(request, resultSchema, options) {
88094
88089
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
88095
- return new Promise((resolve59, reject) => {
88090
+ return new Promise((resolve60, reject) => {
88096
88091
  const earlyReject = (error3) => {
88097
88092
  reject(error3);
88098
88093
  };
@@ -88170,7 +88165,7 @@ var Protocol = class {
88170
88165
  if (!parseResult.success) {
88171
88166
  reject(parseResult.error);
88172
88167
  } else {
88173
- resolve59(parseResult.data);
88168
+ resolve60(parseResult.data);
88174
88169
  }
88175
88170
  } catch (error3) {
88176
88171
  reject(error3);
@@ -88431,12 +88426,12 @@ var Protocol = class {
88431
88426
  }
88432
88427
  } catch {
88433
88428
  }
88434
- return new Promise((resolve59, reject) => {
88429
+ return new Promise((resolve60, reject) => {
88435
88430
  if (signal.aborted) {
88436
88431
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
88437
88432
  return;
88438
88433
  }
88439
- const timeoutId = setTimeout(resolve59, interval);
88434
+ const timeoutId = setTimeout(resolve60, interval);
88440
88435
  signal.addEventListener("abort", () => {
88441
88436
  clearTimeout(timeoutId);
88442
88437
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -89226,7 +89221,7 @@ var Server = class extends Protocol {
89226
89221
  };
89227
89222
 
89228
89223
  // src/mcp/server.ts
89229
- var path84 = __toESM(require("path"));
89224
+ var path85 = __toESM(require("path"));
89230
89225
 
89231
89226
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
89232
89227
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -89309,12 +89304,12 @@ var StdioServerTransport = class {
89309
89304
  this.onclose?.();
89310
89305
  }
89311
89306
  send(message) {
89312
- return new Promise((resolve59) => {
89307
+ return new Promise((resolve60) => {
89313
89308
  const json = serializeMessage(message);
89314
89309
  if (this._stdout.write(json)) {
89315
- resolve59();
89310
+ resolve60();
89316
89311
  } else {
89317
- this._stdout.once("drain", resolve59);
89312
+ this._stdout.once("drain", resolve60);
89318
89313
  }
89319
89314
  });
89320
89315
  }
@@ -89780,7 +89775,7 @@ var HAR_MCP_TOOLS = [
89780
89775
  },
89781
89776
  {
89782
89777
  name: "har_control_up",
89783
- description: "Start local Mission Control (a single self-contained Docker container backed by SQLite) and sync all harness repositories that were initialized with har env init.",
89778
+ description: "Start local Mission Control (a single self-contained Docker container backed by SQLite) and sync all harness repositories that were scaffolded with har onboard or har_init_harness.",
89784
89779
  inputSchema: objectJsonSchema({
89785
89780
  repo: repoJsonProperty,
89786
89781
  detach: { type: "boolean", description: "Run the container in detached mode (default true)" }
@@ -90050,7 +90045,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
90050
90045
  const input = ControlUpInputSchema.parse({ ...args, repo });
90051
90046
  const result = await startControlAndSync({
90052
90047
  detach: input.detach,
90053
- cwd: path84.resolve(input.repo)
90048
+ cwd: path85.resolve(input.repo)
90054
90049
  });
90055
90050
  if (result.code !== 0) {
90056
90051
  return {
@@ -90114,11 +90109,11 @@ var mcpCommand = {
90114
90109
  };
90115
90110
 
90116
90111
  // src/cli/commands/onboard.ts
90117
- var path86 = __toESM(require("path"));
90112
+ var path87 = __toESM(require("path"));
90118
90113
  init_stages();
90119
90114
 
90120
90115
  // src/core/onboarding.ts
90121
- var path85 = __toESM(require("path"));
90116
+ var path86 = __toESM(require("path"));
90122
90117
  init_control_config();
90123
90118
  init_control_sync();
90124
90119
  init_otel_hooks();
@@ -90262,7 +90257,7 @@ async function defaultEnsureControl(options) {
90262
90257
  return { started: true, apiUrl: result.apiUrl };
90263
90258
  }
90264
90259
  async function runOnboarding(options, deps = {}) {
90265
- const repoPath = path85.resolve(options.repoPath);
90260
+ const repoPath = path86.resolve(options.repoPath);
90266
90261
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
90267
90262
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
90268
90263
  const init = deps.initHarness ?? initHarness;
@@ -90460,7 +90455,7 @@ async function promptChoices(args, docker) {
90460
90455
  };
90461
90456
  }
90462
90457
  const pluginChoices = listPluginChoices();
90463
- const repoPath = path86.resolve(args.repo);
90458
+ const repoPath = path87.resolve(args.repo);
90464
90459
  const alreadyPresent = harnessExists(repoPath);
90465
90460
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
90466
90461
  const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
@@ -90581,7 +90576,7 @@ function printSummary(result) {
90581
90576
  console.error("");
90582
90577
  }
90583
90578
  async function handleOnboard(argv) {
90584
- const repoPath = path86.resolve(argv.repo);
90579
+ const repoPath = path87.resolve(argv.repo);
90585
90580
  header("har onboard");
90586
90581
  info(`Repository: ${repoPath}`);
90587
90582
  try {
@@ -90699,25 +90694,25 @@ var onboardCommand = {
90699
90694
  };
90700
90695
 
90701
90696
  // src/cli/commands/plugin.ts
90702
- var path88 = __toESM(require("path"));
90697
+ var path89 = __toESM(require("path"));
90703
90698
 
90704
90699
  // src/harness/plugin-create.ts
90705
- var fs74 = __toESM(require("fs"));
90706
- var path87 = __toESM(require("path"));
90700
+ var fs75 = __toESM(require("fs"));
90701
+ var path88 = __toESM(require("path"));
90707
90702
  init_paths();
90708
90703
  init_schema2();
90709
90704
  var PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
90710
90705
  function renderSkeleton(templatePath, tokens) {
90711
- let content = fs74.readFileSync(templatePath, "utf8");
90706
+ let content = fs75.readFileSync(templatePath, "utf8");
90712
90707
  for (const [token, value] of Object.entries(tokens)) {
90713
90708
  content = content.replace(new RegExp(token, "g"), value);
90714
90709
  }
90715
90710
  return content;
90716
90711
  }
90717
90712
  function createLocalPlugin(repoPath, options) {
90718
- const resolved = path87.resolve(repoPath);
90713
+ const resolved = path88.resolve(repoPath);
90719
90714
  if (!harnessExists(resolved)) {
90720
- throw new Error('No .har/ harness found. Run "har env init" first.');
90715
+ throw new Error('No .har/ harness found. Run "har onboard" first.');
90721
90716
  }
90722
90717
  const id = options.id.trim();
90723
90718
  if (!PLUGIN_ID_PATTERN.test(id)) {
@@ -90731,9 +90726,9 @@ function createLocalPlugin(repoPath, options) {
90731
90726
  `Invalid stage kind "${kind}". Available: ${HarnessStageKindSchema.options.join(", ")}`
90732
90727
  );
90733
90728
  }
90734
- const pluginDir = path87.join(resolved, LOCAL_PLUGINS_DIR, id);
90729
+ const pluginDir = path88.join(resolved, LOCAL_PLUGINS_DIR, id);
90735
90730
  const pluginDirRel = `${LOCAL_PLUGINS_DIR}/${id}`;
90736
- if (fs74.existsSync(pluginDir) && !options.force) {
90731
+ if (fs75.existsSync(pluginDir) && !options.force) {
90737
90732
  throw new Error(`Plugin already exists: ${pluginDirRel}/. Use --force to overwrite.`);
90738
90733
  }
90739
90734
  const description = options.description ?? `Custom ${kind} stage (local plugin: ${id})`;
@@ -90767,24 +90762,24 @@ function createLocalPlugin(repoPath, options) {
90767
90762
  ...options.packageFragment ? { merge: { "package.json": "package.fragment.json" } } : {},
90768
90763
  nextSteps: [
90769
90764
  `Edit ${pluginDirRel}/stages/${id}.sh \u2014 replace the TODO block with the real check`,
90770
- "./.har/launch.sh 1",
90765
+ "har env launch 1",
90771
90766
  `./.har/stages/${id}.sh 1`,
90772
- "./.har/verify.sh 1 --full # runs it as part of full verification"
90767
+ "har env verify 1 --full # runs it as part of full verification"
90773
90768
  ],
90774
90769
  docsPath: `${pluginDirRel}/README.md`
90775
90770
  });
90776
90771
  const filesWritten = [];
90777
90772
  const write = (rel, content, executable = false) => {
90778
- const abs = path87.join(pluginDir, rel);
90779
- fs74.mkdirSync(path87.dirname(abs), { recursive: true });
90780
- fs74.writeFileSync(abs, content);
90781
- if (executable) fs74.chmodSync(abs, 493);
90773
+ const abs = path88.join(pluginDir, rel);
90774
+ fs75.mkdirSync(path88.dirname(abs), { recursive: true });
90775
+ fs75.writeFileSync(abs, content);
90776
+ if (executable) fs75.chmodSync(abs, 493);
90782
90777
  filesWritten.push(`${pluginDirRel}/${rel}`);
90783
90778
  };
90784
90779
  write("template.manifest.json", `${JSON.stringify(manifest, null, 2)}
90785
90780
  `);
90786
90781
  const stageScript = renderSkeleton(
90787
- path87.join(resolveTemplatesDir(), "plugins", "custom-stage-skeleton.sh"),
90782
+ path88.join(resolveTemplatesDir(), "plugins", "custom-stage-skeleton.sh"),
90788
90783
  {
90789
90784
  __STAGE_ID__: id,
90790
90785
  __STAGE_KIND__: kind,
@@ -90793,7 +90788,7 @@ function createLocalPlugin(repoPath, options) {
90793
90788
  );
90794
90789
  write(`stages/${id}.sh`, stageScript, true);
90795
90790
  const readme = renderSkeleton(
90796
- path87.join(resolveTemplatesDir(), "plugins", "local-plugin-skeleton", "README.md"),
90791
+ path88.join(resolveTemplatesDir(), "plugins", "local-plugin-skeleton", "README.md"),
90797
90792
  { __PLUGIN_ID__: id }
90798
90793
  );
90799
90794
  write("README.md", readme);
@@ -90825,7 +90820,7 @@ async function handlePluginCreate(argv) {
90825
90820
  error('Missing plugin id. Usage: har plugin create <id> [--kind test] [--description "..."]');
90826
90821
  return finishCommand(1);
90827
90822
  }
90828
- const repoPath = path88.resolve(argv.repo);
90823
+ const repoPath = path89.resolve(argv.repo);
90829
90824
  header("har plugin create");
90830
90825
  info(`Repository: ${repoPath}`);
90831
90826
  info(`Plugin: ${argv.id}`);
@@ -90856,7 +90851,7 @@ async function handlePluginCreate(argv) {
90856
90851
  }
90857
90852
  }
90858
90853
  function handlePluginList(argv) {
90859
- const repoPath = path88.resolve(argv.repo);
90854
+ const repoPath = path89.resolve(argv.repo);
90860
90855
  for (const id of listPluginIds()) {
90861
90856
  console.log(`${id} (bundled)`);
90862
90857
  }
@@ -91023,7 +91018,7 @@ var preferencesCommand = {
91023
91018
  };
91024
91019
 
91025
91020
  // src/cli/commands/telemetry.ts
91026
- var path89 = __toESM(require("path"));
91021
+ var path90 = __toESM(require("path"));
91027
91022
  init_control_config();
91028
91023
  init_control_sync();
91029
91024
  init_manifest();
@@ -91116,7 +91111,7 @@ async function handleOff() {
91116
91111
  info("Mission Control will not auto-start. Existing usage rows are kept.");
91117
91112
  }
91118
91113
  async function handleWriteEnv(argv) {
91119
- const repoPath = path89.resolve(argv.repo);
91114
+ const repoPath = path90.resolve(argv.repo);
91120
91115
  const harnessRoot = resolveHarnessRoot(repoPath);
91121
91116
  const session = readSlotRegistry(harnessRoot, argv.agentId);
91122
91117
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -91128,7 +91123,7 @@ async function handleWriteEnv(argv) {
91128
91123
  suffix,
91129
91124
  createdAt: session?.createdAt
91130
91125
  });
91131
- const envFile = argv.envFile ?? path89.join(workDir, `.env.agent.${argv.agentId}`);
91126
+ const envFile = argv.envFile ?? path90.join(workDir, `.env.agent.${argv.agentId}`);
91132
91127
  const attrs = {
91133
91128
  sessionKey,
91134
91129
  agentId: argv.agentId,
@@ -91144,7 +91139,7 @@ async function handleWriteEnv(argv) {
91144
91139
  success(`Wrote session attribution to ${envFile}`);
91145
91140
  }
91146
91141
  function handlePrintEnv(argv) {
91147
- const repoPath = path89.resolve(argv.repo);
91142
+ const repoPath = path90.resolve(argv.repo);
91148
91143
  const workDir = argv.workDir ?? repoPath;
91149
91144
  const sessionKey = buildSessionKey({
91150
91145
  branch: argv.branch,