@osfactory/har 0.43.1 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -553,8 +553,8 @@ var init_parseUtil = __esm({
553
553
  init_errors();
554
554
  init_en();
555
555
  makeIssue = (params) => {
556
- const { data, path: path63, errorMaps, issueData } = params;
557
- const fullPath = [...path63, ...issueData.path || []];
556
+ const { data, path: path64, errorMaps, issueData } = params;
557
+ const fullPath = [...path64, ...issueData.path || []];
558
558
  const fullIssue = {
559
559
  ...issueData,
560
560
  path: fullPath
@@ -862,11 +862,11 @@ var init_types = __esm({
862
862
  init_parseUtil();
863
863
  init_util();
864
864
  ParseInputLazyPath = class {
865
- constructor(parent, value, path63, key) {
865
+ constructor(parent, value, path64, key) {
866
866
  this._cachedPath = [];
867
867
  this.parent = parent;
868
868
  this.data = value;
869
- this._path = path63;
869
+ this._path = path64;
870
870
  this._key = key;
871
871
  }
872
872
  get path() {
@@ -28236,11 +28236,13 @@ var init_manifest = __esm({
28236
28236
  path4 = __toESM(require("path"));
28237
28237
  init_schema2();
28238
28238
  init_file_ops();
28239
- GENERATOR_VERSION = "0.4.0";
28239
+ GENERATOR_VERSION = "0.5.0";
28240
28240
  MANIFEST_VERSION = "1";
28241
28241
  DEFAULT_HAR_DIR = ".har";
28242
28242
  CHECKSUM_SKIP = /* @__PURE__ */ new Set([
28243
28243
  "manifest.json",
28244
+ "AGENTS.md.proposed",
28245
+ "AGENTS.md.proposed.meta.json",
28244
28246
  "AGENT.md.proposed",
28245
28247
  "AGENT.md.proposed.meta.json",
28246
28248
  "ADAPT-PROMPT.md"
@@ -32102,6 +32104,7 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false)
32102
32104
  }
32103
32105
  const syncBody = {
32104
32106
  path: repoPath,
32107
+ ...status.gitRemote ? { gitRemote: status.gitRemote } : {},
32105
32108
  ...manifest ? { manifest } : {},
32106
32109
  ...stagesRegistry ? { stagesRegistry } : {},
32107
32110
  slots: status.slots,
@@ -33265,14 +33268,14 @@ var require_url_state_machine = __commonJS({
33265
33268
  return url.replace(/\u0009|\u000A|\u000D/g, "");
33266
33269
  }
33267
33270
  function shortenPath(url) {
33268
- const path63 = url.path;
33269
- if (path63.length === 0) {
33271
+ const path64 = url.path;
33272
+ if (path64.length === 0) {
33270
33273
  return;
33271
33274
  }
33272
- if (url.scheme === "file" && path63.length === 1 && isNormalizedWindowsDriveLetter(path63[0])) {
33275
+ if (url.scheme === "file" && path64.length === 1 && isNormalizedWindowsDriveLetter(path64[0])) {
33273
33276
  return;
33274
33277
  }
33275
- path63.pop();
33278
+ path64.pop();
33276
33279
  }
33277
33280
  function includesCredentials(url) {
33278
33281
  return url.username !== "" || url.password !== "";
@@ -38851,14 +38854,14 @@ __export(fileFromPath_exports, {
38851
38854
  fileFromPathSync: () => fileFromPathSync,
38852
38855
  isFile: () => isFile
38853
38856
  });
38854
- function createFileFromPath(path63, { mtimeMs, size }, filenameOrOptions, options = {}) {
38857
+ function createFileFromPath(path64, { mtimeMs, size }, filenameOrOptions, options = {}) {
38855
38858
  let filename;
38856
38859
  if (isPlainObject_default2(filenameOrOptions)) {
38857
38860
  [options, filename] = [filenameOrOptions, void 0];
38858
38861
  } else {
38859
38862
  filename = filenameOrOptions;
38860
38863
  }
38861
- const file = new FileFromPath({ path: path63, size, lastModified: mtimeMs });
38864
+ const file = new FileFromPath({ path: path64, size, lastModified: mtimeMs });
38862
38865
  if (!filename) {
38863
38866
  filename = file.name;
38864
38867
  }
@@ -38867,13 +38870,13 @@ function createFileFromPath(path63, { mtimeMs, size }, filenameOrOptions, option
38867
38870
  lastModified: file.lastModified
38868
38871
  });
38869
38872
  }
38870
- function fileFromPathSync(path63, filenameOrOptions, options = {}) {
38871
- const stats = (0, import_fs5.statSync)(path63);
38872
- return createFileFromPath(path63, stats, filenameOrOptions, options);
38873
+ function fileFromPathSync(path64, filenameOrOptions, options = {}) {
38874
+ const stats = (0, import_fs5.statSync)(path64);
38875
+ return createFileFromPath(path64, stats, filenameOrOptions, options);
38873
38876
  }
38874
- async function fileFromPath2(path63, filenameOrOptions, options) {
38875
- const stats = await import_fs5.promises.stat(path63);
38876
- return createFileFromPath(path63, stats, filenameOrOptions, options);
38877
+ async function fileFromPath2(path64, filenameOrOptions, options) {
38878
+ const stats = await import_fs5.promises.stat(path64);
38879
+ return createFileFromPath(path64, stats, filenameOrOptions, options);
38877
38880
  }
38878
38881
  var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
38879
38882
  var init_fileFromPath = __esm({
@@ -38955,32 +38958,32 @@ __export(otel_hooks_exports, {
38955
38958
  });
38956
38959
  function getOtelHooksHome() {
38957
38960
  if (process.env.HAR_OTEL_HOOKS_HOME) {
38958
- return path48.resolve(process.env.HAR_OTEL_HOOKS_HOME);
38961
+ return path49.resolve(process.env.HAR_OTEL_HOOKS_HOME);
38959
38962
  }
38960
- return path48.join(os14.homedir(), ".har", "otel-hooks");
38963
+ return path49.join(os15.homedir(), ".har", "otel-hooks");
38961
38964
  }
38962
38965
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
38963
- return path48.join(hooksHome, "otel_config.json");
38966
+ return path49.join(hooksHome, "otel_config.json");
38964
38967
  }
38965
38968
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
38966
- return path48.join(hooksHome, "run-otel-hook.sh");
38969
+ return path49.join(hooksHome, "run-otel-hook.sh");
38967
38970
  }
38968
38971
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
38969
- return path48.join(hooksHome, "state");
38972
+ return path49.join(hooksHome, "state");
38970
38973
  }
38971
38974
  function localOtelHookBin(hooksHome) {
38972
- return path48.join(hooksHome, "node_modules", ".bin", "otel-hook");
38975
+ return path49.join(hooksHome, "node_modules", ".bin", "otel-hook");
38973
38976
  }
38974
38977
  function installedPackageVersion(hooksHome) {
38975
38978
  try {
38976
- const pkgPath = path48.join(
38979
+ const pkgPath = path49.join(
38977
38980
  hooksHome,
38978
38981
  "node_modules",
38979
38982
  "@osfactory",
38980
38983
  "otel-hook",
38981
38984
  "package.json"
38982
38985
  );
38983
- const pkg = JSON.parse(fs43.readFileSync(pkgPath, "utf8"));
38986
+ const pkg = JSON.parse(fs44.readFileSync(pkgPath, "utf8"));
38984
38987
  return typeof pkg.version === "string" ? pkg.version : null;
38985
38988
  } catch {
38986
38989
  return null;
@@ -39031,15 +39034,15 @@ function buildOtelHooksConfig(options) {
39031
39034
  };
39032
39035
  }
39033
39036
  function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
39034
- fs43.mkdirSync(hooksHome, { recursive: true });
39037
+ fs44.mkdirSync(hooksHome, { recursive: true });
39035
39038
  const configPath = getOtelHooksConfigPath(hooksHome);
39036
- fs43.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
39039
+ fs44.writeFileSync(configPath, `${JSON.stringify(config2, null, 2)}
39037
39040
  `);
39038
39041
  return configPath;
39039
39042
  }
39040
39043
  function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
39041
- fs43.mkdirSync(hooksHome, { recursive: true });
39042
- fs43.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
39044
+ fs44.mkdirSync(hooksHome, { recursive: true });
39045
+ fs44.mkdirSync(getOtelHooksStateDir(hooksHome), { recursive: true });
39043
39046
  const wrapperPath = getOtelHooksWrapperPath(hooksHome);
39044
39047
  const configPath = getOtelHooksConfigPath(hooksHome);
39045
39048
  const stateDir = getOtelHooksStateDir(hooksHome);
@@ -39051,9 +39054,9 @@ exec "${otelHookCommand}" run \\
39051
39054
  --state-dir "${stateDir}" \\
39052
39055
  "$@"
39053
39056
  `;
39054
- fs43.writeFileSync(wrapperPath, script, { mode: 493 });
39057
+ fs44.writeFileSync(wrapperPath, script, { mode: 493 });
39055
39058
  try {
39056
- fs43.chmodSync(wrapperPath, 493);
39059
+ fs44.chmodSync(wrapperPath, 493);
39057
39060
  } catch {
39058
39061
  }
39059
39062
  return wrapperPath;
@@ -39066,11 +39069,11 @@ function commandExists2(command2) {
39066
39069
  }
39067
39070
  function resolveOtelHookCommand(hooksHome) {
39068
39071
  const local = localOtelHookBin(hooksHome);
39069
- if (fs43.existsSync(local)) return local;
39072
+ if (fs44.existsSync(local)) return local;
39070
39073
  return null;
39071
39074
  }
39072
39075
  function tryInstallPackage(hooksHome) {
39073
- fs43.mkdirSync(hooksHome, { recursive: true });
39076
+ fs44.mkdirSync(hooksHome, { recursive: true });
39074
39077
  if (!commandExists2("npm")) {
39075
39078
  return {
39076
39079
  ok: false,
@@ -39082,7 +39085,7 @@ function tryInstallPackage(hooksHome) {
39082
39085
  ["install", "--prefix", hooksHome, "--no-fund", "--no-audit", OTEL_HOOKS_PACKAGE],
39083
39086
  { encoding: "utf8", timeout: 18e4 }
39084
39087
  );
39085
- if (result.status === 0 && fs43.existsSync(localOtelHookBin(hooksHome))) {
39088
+ if (result.status === 0 && fs44.existsSync(localOtelHookBin(hooksHome))) {
39086
39089
  return { ok: true, detail: `npm install --prefix ${hooksHome} ${OTEL_HOOKS_PACKAGE}` };
39087
39090
  }
39088
39091
  return {
@@ -39108,14 +39111,14 @@ function uninstallLegacyPythonHooks(hooksHome) {
39108
39111
  }
39109
39112
  function removeLegacyPythonArtifacts(hooksHome) {
39110
39113
  const legacyPaths = [
39111
- path48.join(hooksHome, ".venv"),
39112
- path48.join(hooksHome, "otel_config.yaml"),
39113
- path48.join(hooksHome, "venv")
39114
+ path49.join(hooksHome, ".venv"),
39115
+ path49.join(hooksHome, "otel_config.yaml"),
39116
+ path49.join(hooksHome, "venv")
39114
39117
  ];
39115
39118
  for (const target of legacyPaths) {
39116
39119
  try {
39117
- if (fs43.existsSync(target)) {
39118
- fs43.rmSync(target, { recursive: true, force: true });
39120
+ if (fs44.existsSync(target)) {
39121
+ fs44.rmSync(target, { recursive: true, force: true });
39119
39122
  }
39120
39123
  } catch {
39121
39124
  }
@@ -39156,10 +39159,10 @@ function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
39156
39159
  };
39157
39160
  }
39158
39161
  function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
39159
- if (!fs43.existsSync(filePath)) return false;
39162
+ if (!fs44.existsSync(filePath)) return false;
39160
39163
  let raw;
39161
39164
  try {
39162
- raw = fs43.readFileSync(filePath, "utf8");
39165
+ raw = fs44.readFileSync(filePath, "utf8");
39163
39166
  } catch {
39164
39167
  return false;
39165
39168
  }
@@ -39206,15 +39209,15 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
39206
39209
  return changed;
39207
39210
  };
39208
39211
  if (!walk(parsed)) return false;
39209
- fs43.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
39212
+ fs44.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
39210
39213
  `);
39211
39214
  return true;
39212
39215
  }
39213
39216
  function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
39214
- if (!fs43.existsSync(filePath)) return false;
39217
+ if (!fs44.existsSync(filePath)) return false;
39215
39218
  let raw;
39216
39219
  try {
39217
- raw = fs43.readFileSync(filePath, "utf8");
39220
+ raw = fs44.readFileSync(filePath, "utf8");
39218
39221
  } catch {
39219
39222
  return false;
39220
39223
  }
@@ -39249,21 +39252,21 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
39249
39252
  }
39250
39253
  }
39251
39254
  if (!changed) return false;
39252
- fs43.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
39255
+ fs44.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
39253
39256
  `);
39254
39257
  return true;
39255
39258
  }
39256
39259
  function rewriteKnownHookRegistrations(wrapperPath) {
39257
- const home = os14.homedir();
39260
+ const home = os15.homedir();
39258
39261
  const candidates = [
39259
- path48.join(home, ".cursor", "hooks.json"),
39260
- path48.join(home, ".claude", "settings.json"),
39261
- path48.join(home, ".codex", "hooks.json")
39262
+ path49.join(home, ".cursor", "hooks.json"),
39263
+ path49.join(home, ".claude", "settings.json"),
39264
+ path49.join(home, ".codex", "hooks.json")
39262
39265
  ];
39263
39266
  for (const filePath of candidates) {
39264
39267
  try {
39265
39268
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
39266
- if (filePath.endsWith(`${path48.sep}.cursor${path48.sep}hooks.json`)) {
39269
+ if (filePath.endsWith(`${path49.sep}.cursor${path49.sep}hooks.json`)) {
39267
39270
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
39268
39271
  }
39269
39272
  } catch {
@@ -39279,7 +39282,7 @@ function ensureOtelHooks(options) {
39279
39282
  const hooksHome = getOtelHooksHome();
39280
39283
  const errors = [];
39281
39284
  const providersSetup = [];
39282
- fs43.mkdirSync(hooksHome, { recursive: true });
39285
+ fs44.mkdirSync(hooksHome, { recursive: true });
39283
39286
  let otelHookCommand = resolveOtelHookCommand(hooksHome);
39284
39287
  const needsInstall = !otelHookCommand || installedPackageVersion(hooksHome) !== pinnedVersion();
39285
39288
  if (needsInstall) {
@@ -39373,14 +39376,14 @@ function ensureOtelHooks(options) {
39373
39376
  function disableOtelHooksExport() {
39374
39377
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
39375
39378
  }
39376
- var import_child_process10, fs43, os14, path48, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
39379
+ var import_child_process10, fs44, os15, path49, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
39377
39380
  var init_otel_hooks = __esm({
39378
39381
  "src/core/otel-hooks.ts"() {
39379
39382
  "use strict";
39380
39383
  import_child_process10 = require("child_process");
39381
- fs43 = __toESM(require("fs"));
39382
- os14 = __toESM(require("os"));
39383
- path48 = __toESM(require("path"));
39384
+ fs44 = __toESM(require("fs"));
39385
+ os15 = __toESM(require("os"));
39386
+ path49 = __toESM(require("path"));
39384
39387
  init_control_config();
39385
39388
  init_telemetry_config();
39386
39389
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.1.2";
@@ -40496,15 +40499,15 @@ var require_route = __commonJS({
40496
40499
  };
40497
40500
  }
40498
40501
  function wrapConversion(toModel, graph) {
40499
- const path63 = [graph[toModel].parent, toModel];
40502
+ const path64 = [graph[toModel].parent, toModel];
40500
40503
  let fn = conversions[graph[toModel].parent][toModel];
40501
40504
  let cur = graph[toModel].parent;
40502
40505
  while (graph[cur].parent) {
40503
- path63.unshift(graph[cur].parent);
40506
+ path64.unshift(graph[cur].parent);
40504
40507
  fn = link(conversions[graph[cur].parent][cur], fn);
40505
40508
  cur = graph[cur].parent;
40506
40509
  }
40507
- fn.conversion = path63;
40510
+ fn.conversion = path64;
40508
40511
  return fn;
40509
40512
  }
40510
40513
  module2.exports = function(fromModel) {
@@ -46434,7 +46437,7 @@ var require_iso2022 = __commonJS({
46434
46437
  // node_modules/chardet/index.js
46435
46438
  var require_chardet = __commonJS({
46436
46439
  "node_modules/chardet/index.js"(exports2, module2) {
46437
- var fs50 = require("fs");
46440
+ var fs51 = require("fs");
46438
46441
  var utf8 = require_utf8();
46439
46442
  var unicode = require_unicode();
46440
46443
  var mbcs = require_mbcs();
@@ -46508,28 +46511,28 @@ var require_chardet = __commonJS({
46508
46511
  var fd;
46509
46512
  var handler = function(err, buffer) {
46510
46513
  if (fd) {
46511
- fs50.closeSync(fd);
46514
+ fs51.closeSync(fd);
46512
46515
  }
46513
46516
  if (err) return cb(err, null);
46514
46517
  cb(null, self.detect(buffer, opts));
46515
46518
  };
46516
46519
  if (opts && opts.sampleSize) {
46517
- fd = fs50.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
46518
- fs50.read(fd, sample, 0, opts.sampleSize, null, function(err) {
46520
+ fd = fs51.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
46521
+ fs51.read(fd, sample, 0, opts.sampleSize, null, function(err) {
46519
46522
  handler(err, sample);
46520
46523
  });
46521
46524
  return;
46522
46525
  }
46523
- fs50.readFile(filepath, handler);
46526
+ fs51.readFile(filepath, handler);
46524
46527
  };
46525
46528
  module2.exports.detectFileSync = function(filepath, opts) {
46526
46529
  if (opts && opts.sampleSize) {
46527
- var fd = fs50.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
46528
- fs50.readSync(fd, sample2, 0, opts.sampleSize);
46529
- fs50.closeSync(fd);
46530
+ var fd = fs51.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
46531
+ fs51.readSync(fd, sample2, 0, opts.sampleSize);
46532
+ fs51.closeSync(fd);
46530
46533
  return self.detect(sample2, opts);
46531
46534
  }
46532
- return self.detect(fs50.readFileSync(filepath), opts);
46535
+ return self.detect(fs51.readFileSync(filepath), opts);
46533
46536
  };
46534
46537
  module2.exports.detectAll = function(buffer, opts) {
46535
46538
  if (typeof opts !== "object") {
@@ -49994,16 +49997,16 @@ var require_os_tmpdir = __commonJS({
49994
49997
  var isWindows = process.platform === "win32";
49995
49998
  var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
49996
49999
  module2.exports = function() {
49997
- var path63;
50000
+ var path64;
49998
50001
  if (isWindows) {
49999
- path63 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
50002
+ path64 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
50000
50003
  } else {
50001
- path63 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
50004
+ path64 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
50002
50005
  }
50003
- if (trailingSlashRe.test(path63)) {
50004
- path63 = path63.slice(0, -1);
50006
+ if (trailingSlashRe.test(path64)) {
50007
+ path64 = path64.slice(0, -1);
50005
50008
  }
50006
- return path63;
50009
+ return path64;
50007
50010
  };
50008
50011
  }
50009
50012
  });
@@ -50011,8 +50014,8 @@ var require_os_tmpdir = __commonJS({
50011
50014
  // node_modules/tmp/lib/tmp.js
50012
50015
  var require_tmp = __commonJS({
50013
50016
  "node_modules/tmp/lib/tmp.js"(exports2, module2) {
50014
- var fs50 = require("fs");
50015
- var path63 = require("path");
50017
+ var fs51 = require("fs");
50018
+ var path64 = require("path");
50016
50019
  var crypto6 = require("crypto");
50017
50020
  var osTmpDir = require_os_tmpdir();
50018
50021
  var _c2 = process.binding("constants");
@@ -50054,7 +50057,7 @@ var require_tmp = __commonJS({
50054
50057
  }
50055
50058
  function _generateTmpName(opts) {
50056
50059
  if (opts.name) {
50057
- return path63.join(opts.dir || tmpDir, opts.name);
50060
+ return path64.join(opts.dir || tmpDir, opts.name);
50058
50061
  }
50059
50062
  if (opts.template) {
50060
50063
  return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
@@ -50065,7 +50068,7 @@ var require_tmp = __commonJS({
50065
50068
  _randomChars(12),
50066
50069
  opts.postfix || ""
50067
50070
  ].join("");
50068
- return path63.join(opts.dir || tmpDir, name);
50071
+ return path64.join(opts.dir || tmpDir, name);
50069
50072
  }
50070
50073
  function tmpName(options, callback) {
50071
50074
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
@@ -50075,7 +50078,7 @@ var require_tmp = __commonJS({
50075
50078
  return cb(new Error("Invalid template provided"));
50076
50079
  (function _getUniqueName() {
50077
50080
  const name = _generateTmpName(opts);
50078
- fs50.stat(name, function(err) {
50081
+ fs51.stat(name, function(err) {
50079
50082
  if (!err) {
50080
50083
  if (tries-- > 0) return _getUniqueName();
50081
50084
  return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
@@ -50093,7 +50096,7 @@ var require_tmp = __commonJS({
50093
50096
  do {
50094
50097
  const name = _generateTmpName(opts);
50095
50098
  try {
50096
- fs50.statSync(name);
50099
+ fs51.statSync(name);
50097
50100
  } catch (e2) {
50098
50101
  return name;
50099
50102
  }
@@ -50105,13 +50108,13 @@ var require_tmp = __commonJS({
50105
50108
  opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
50106
50109
  tmpName(opts, function _tmpNameCreated(err, name) {
50107
50110
  if (err) return cb(err);
50108
- fs50.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
50111
+ fs51.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
50109
50112
  if (err2) return cb(err2);
50110
50113
  if (opts.discardDescriptor) {
50111
- return fs50.close(fd, function _discardCallback(err3) {
50114
+ return fs51.close(fd, function _discardCallback(err3) {
50112
50115
  if (err3) {
50113
50116
  try {
50114
- fs50.unlinkSync(name);
50117
+ fs51.unlinkSync(name);
50115
50118
  } catch (e2) {
50116
50119
  if (!isENOENT(e2)) {
50117
50120
  err3 = e2;
@@ -50134,9 +50137,9 @@ var require_tmp = __commonJS({
50134
50137
  opts.postfix = opts.postfix || ".tmp";
50135
50138
  const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
50136
50139
  const name = tmpNameSync(opts);
50137
- var fd = fs50.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
50140
+ var fd = fs51.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
50138
50141
  if (opts.discardDescriptor) {
50139
- fs50.closeSync(fd);
50142
+ fs51.closeSync(fd);
50140
50143
  fd = void 0;
50141
50144
  }
50142
50145
  return {
@@ -50148,9 +50151,9 @@ var require_tmp = __commonJS({
50148
50151
  function _rmdirRecursiveSync(root) {
50149
50152
  const dirs = [root];
50150
50153
  do {
50151
- var dir2 = dirs.pop(), deferred = false, files = fs50.readdirSync(dir2);
50154
+ var dir2 = dirs.pop(), deferred = false, files = fs51.readdirSync(dir2);
50152
50155
  for (var i2 = 0, length = files.length; i2 < length; i2++) {
50153
- var file2 = path63.join(dir2, files[i2]), stat = fs50.lstatSync(file2);
50156
+ var file2 = path64.join(dir2, files[i2]), stat = fs51.lstatSync(file2);
50154
50157
  if (stat.isDirectory()) {
50155
50158
  if (!deferred) {
50156
50159
  deferred = true;
@@ -50158,11 +50161,11 @@ var require_tmp = __commonJS({
50158
50161
  }
50159
50162
  dirs.push(file2);
50160
50163
  } else {
50161
- fs50.unlinkSync(file2);
50164
+ fs51.unlinkSync(file2);
50162
50165
  }
50163
50166
  }
50164
50167
  if (!deferred) {
50165
- fs50.rmdirSync(dir2);
50168
+ fs51.rmdirSync(dir2);
50166
50169
  }
50167
50170
  } while (dirs.length !== 0);
50168
50171
  }
@@ -50170,7 +50173,7 @@ var require_tmp = __commonJS({
50170
50173
  var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
50171
50174
  tmpName(opts, function _tmpNameCreated(err, name) {
50172
50175
  if (err) return cb(err);
50173
- fs50.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
50176
+ fs51.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
50174
50177
  if (err2) return cb(err2);
50175
50178
  cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
50176
50179
  });
@@ -50179,7 +50182,7 @@ var require_tmp = __commonJS({
50179
50182
  function dirSync(options) {
50180
50183
  var args = _parseArguments(options), opts = args[0];
50181
50184
  const name = tmpNameSync(opts);
50182
- fs50.mkdirSync(name, opts.mode || DIR_MODE);
50185
+ fs51.mkdirSync(name, opts.mode || DIR_MODE);
50183
50186
  return {
50184
50187
  name,
50185
50188
  removeCallback: _prepareTmpDirRemoveCallback(name, opts)
@@ -50189,7 +50192,7 @@ var require_tmp = __commonJS({
50189
50192
  const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
50190
50193
  try {
50191
50194
  if (0 <= fdPath[0]) {
50192
- fs50.closeSync(fdPath[0]);
50195
+ fs51.closeSync(fdPath[0]);
50193
50196
  }
50194
50197
  } catch (e2) {
50195
50198
  if (!isEBADF(e2) && !isENOENT(e2)) {
@@ -50197,7 +50200,7 @@ var require_tmp = __commonJS({
50197
50200
  }
50198
50201
  }
50199
50202
  try {
50200
- fs50.unlinkSync(fdPath[1]);
50203
+ fs51.unlinkSync(fdPath[1]);
50201
50204
  } catch (e2) {
50202
50205
  if (!isENOENT(e2)) {
50203
50206
  throw e2;
@@ -50210,7 +50213,7 @@ var require_tmp = __commonJS({
50210
50213
  return removeCallback;
50211
50214
  }
50212
50215
  function _prepareTmpDirRemoveCallback(name, opts) {
50213
- const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs50.rmdirSync.bind(fs50);
50216
+ const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs51.rmdirSync.bind(fs51);
50214
50217
  const removeCallback = _prepareRemoveCallback(removeFunction, name);
50215
50218
  if (!opts.keep) {
50216
50219
  _removeObjects.unshift(removeCallback);
@@ -63343,8 +63346,8 @@ var require_utils2 = __commonJS({
63343
63346
  }
63344
63347
  return ind;
63345
63348
  }
63346
- function removeDotSegments(path63) {
63347
- let input = path63;
63349
+ function removeDotSegments(path64) {
63350
+ let input = path64;
63348
63351
  const output = [];
63349
63352
  let nextSlash = -1;
63350
63353
  let len = 0;
@@ -63596,8 +63599,8 @@ var require_schemes = __commonJS({
63596
63599
  wsComponent.secure = void 0;
63597
63600
  }
63598
63601
  if (wsComponent.resourceName) {
63599
- const [path63, query] = wsComponent.resourceName.split("?");
63600
- wsComponent.path = path63 && path63 !== "/" ? path63 : void 0;
63602
+ const [path64, query] = wsComponent.resourceName.split("?");
63603
+ wsComponent.path = path64 && path64 !== "/" ? path64 : void 0;
63601
63604
  wsComponent.query = query;
63602
63605
  wsComponent.resourceName = void 0;
63603
63606
  }
@@ -66990,12 +66993,12 @@ var require_dist = __commonJS({
66990
66993
  throw new Error(`Unknown format "${name}"`);
66991
66994
  return f2;
66992
66995
  };
66993
- function addFormats(ajv, list, fs50, exportName) {
66996
+ function addFormats(ajv, list, fs51, exportName) {
66994
66997
  var _a3;
66995
66998
  var _b2;
66996
66999
  (_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
66997
67000
  for (const f2 of list)
66998
- ajv.addFormat(f2, fs50[f2]);
67001
+ ajv.addFormat(f2, fs51[f2]);
66999
67002
  }
67000
67003
  module2.exports = exports2 = formatsPlugin;
67001
67004
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -68279,11 +68282,11 @@ var parser = new YargsParser({
68279
68282
  resolve: import_path2.resolve,
68280
68283
  // TODO: figure out a way to combine ESM and CJS coverage, such that
68281
68284
  // we can exercise all the lines below:
68282
- require: (path63) => {
68285
+ require: (path64) => {
68283
68286
  if (typeof require !== "undefined") {
68284
- return require(path63);
68285
- } else if (path63.match(/\.json$/)) {
68286
- return JSON.parse((0, import_fs2.readFileSync)(path63, "utf8"));
68287
+ return require(path64);
68288
+ } else if (path64.match(/\.json$/)) {
68289
+ return JSON.parse((0, import_fs2.readFileSync)(path64, "utf8"));
68287
68290
  } else {
68288
68291
  throw Error("only .json config files are supported in ESM");
68289
68292
  }
@@ -72202,7 +72205,7 @@ function handleRemove(argv) {
72202
72205
  }
72203
72206
 
72204
72207
  // src/cli/commands/env.ts
72205
- var path52 = __toESM(require("path"));
72208
+ var path53 = __toESM(require("path"));
72206
72209
 
72207
72210
  // src/cli/finish-command.ts
72208
72211
  init_sync_context();
@@ -72212,8 +72215,8 @@ async function finishCommand(code) {
72212
72215
  }
72213
72216
 
72214
72217
  // src/core/harness.ts
72215
- var fs39 = __toESM(require("fs"));
72216
- var path43 = __toESM(require("path"));
72218
+ var fs40 = __toESM(require("fs"));
72219
+ var path44 = __toESM(require("path"));
72217
72220
 
72218
72221
  // src/harness/generator.ts
72219
72222
  var fs28 = __toESM(require("fs"));
@@ -72290,15 +72293,6 @@ function pruneCliProfile(harnessDir) {
72290
72293
  }
72291
72294
  }
72292
72295
  }
72293
- function scaffoldClaudeMd(repoPath, projectName, force) {
72294
- const templatePath = resolveTemplateFile("CLAUDE.md.template");
72295
- if (!templatePath) return;
72296
- const dest = path34.join(repoPath, "CLAUDE.md");
72297
- if (fs28.existsSync(dest) && !force) return;
72298
- const displayName = projectName.replace(/_/g, " ");
72299
- const content = fs28.readFileSync(templatePath, "utf8").replace(/__PROJECT_DISPLAY_NAME__/g, displayName);
72300
- fs28.writeFileSync(dest, content);
72301
- }
72302
72296
  function scaffoldHarnessBoilerplate(repoPath, options = {}) {
72303
72297
  const harnessDir = path34.join(repoPath, DEFAULT_HAR_DIR);
72304
72298
  const projectName = path34.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
@@ -72334,7 +72328,6 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
72334
72328
  profile
72335
72329
  );
72336
72330
  writeManifest(repoPath, manifest);
72337
- scaffoldClaudeMd(repoPath, projectName, options.force ?? false);
72338
72331
  ensureRootGitignorePatterns(repoPath);
72339
72332
  success(`Copied harness boilerplate to .har/ (profile: ${profile})`);
72340
72333
  info(`Project name: ${projectName}`);
@@ -72348,8 +72341,8 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
72348
72341
  }
72349
72342
 
72350
72343
  // src/llm/authoring-agent.ts
72351
- var fs32 = __toESM(require("fs"));
72352
- var path37 = __toESM(require("path"));
72344
+ var fs33 = __toESM(require("fs"));
72345
+ var path38 = __toESM(require("path"));
72353
72346
 
72354
72347
  // node_modules/@anthropic-ai/sdk/error.mjs
72355
72348
  var error_exports = {};
@@ -72748,13 +72741,13 @@ var MultipartBody = class {
72748
72741
  // node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
72749
72742
  var import_web = require("node:stream/web");
72750
72743
  var fileFromPathWarned = false;
72751
- async function fileFromPath3(path63, ...args) {
72744
+ async function fileFromPath3(path64, ...args) {
72752
72745
  const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
72753
72746
  if (!fileFromPathWarned) {
72754
- console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path63)}) instead`);
72747
+ console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path64)}) instead`);
72755
72748
  fileFromPathWarned = true;
72756
72749
  }
72757
- return await _fileFromPath(path63, ...args);
72750
+ return await _fileFromPath(path64, ...args);
72758
72751
  }
72759
72752
  var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
72760
72753
  var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
@@ -73351,29 +73344,29 @@ var APIClient = class {
73351
73344
  defaultIdempotencyKey() {
73352
73345
  return `stainless-node-retry-${uuid4()}`;
73353
73346
  }
73354
- get(path63, opts) {
73355
- return this.methodRequest("get", path63, opts);
73347
+ get(path64, opts) {
73348
+ return this.methodRequest("get", path64, opts);
73356
73349
  }
73357
- post(path63, opts) {
73358
- return this.methodRequest("post", path63, opts);
73350
+ post(path64, opts) {
73351
+ return this.methodRequest("post", path64, opts);
73359
73352
  }
73360
- patch(path63, opts) {
73361
- return this.methodRequest("patch", path63, opts);
73353
+ patch(path64, opts) {
73354
+ return this.methodRequest("patch", path64, opts);
73362
73355
  }
73363
- put(path63, opts) {
73364
- return this.methodRequest("put", path63, opts);
73356
+ put(path64, opts) {
73357
+ return this.methodRequest("put", path64, opts);
73365
73358
  }
73366
- delete(path63, opts) {
73367
- return this.methodRequest("delete", path63, opts);
73359
+ delete(path64, opts) {
73360
+ return this.methodRequest("delete", path64, opts);
73368
73361
  }
73369
- methodRequest(method, path63, opts) {
73362
+ methodRequest(method, path64, opts) {
73370
73363
  return this.request(Promise.resolve(opts).then(async (opts2) => {
73371
73364
  const body = opts2 && isBlobLike(opts2?.body) ? new DataView(await opts2.body.arrayBuffer()) : opts2?.body instanceof DataView ? opts2.body : opts2?.body instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2?.body) ? new DataView(opts2.body.buffer) : opts2?.body;
73372
- return { method, path: path63, ...opts2, body };
73365
+ return { method, path: path64, ...opts2, body };
73373
73366
  }));
73374
73367
  }
73375
- getAPIList(path63, Page, opts) {
73376
- return this.requestAPIList(Page, { method: "get", path: path63, ...opts });
73368
+ getAPIList(path64, Page, opts) {
73369
+ return this.requestAPIList(Page, { method: "get", path: path64, ...opts });
73377
73370
  }
73378
73371
  calculateContentLength(body) {
73379
73372
  if (typeof body === "string") {
@@ -73391,10 +73384,10 @@ var APIClient = class {
73391
73384
  return null;
73392
73385
  }
73393
73386
  buildRequest(options) {
73394
- const { method, path: path63, query, headers = {} } = options;
73387
+ const { method, path: path64, query, headers = {} } = options;
73395
73388
  const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
73396
73389
  const contentLength = this.calculateContentLength(body);
73397
- const url = this.buildURL(path63, query);
73390
+ const url = this.buildURL(path64, query);
73398
73391
  if ("timeout" in options)
73399
73392
  validatePositiveInteger("timeout", options.timeout);
73400
73393
  const timeout = options.timeout ?? this.timeout;
@@ -73503,8 +73496,8 @@ var APIClient = class {
73503
73496
  const request = this.makeRequest(options, null);
73504
73497
  return new PagePromise(this, request, Page);
73505
73498
  }
73506
- buildURL(path63, query) {
73507
- const url = isAbsoluteURL(path63) ? new URL(path63) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path63.startsWith("/") ? path63.slice(1) : path63));
73499
+ buildURL(path64, query) {
73500
+ const url = isAbsoluteURL(path64) ? new URL(path64) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path64.startsWith("/") ? path64.slice(1) : path64));
73508
73501
  const defaultQuery = this.defaultQuery();
73509
73502
  if (!isEmptyObj(defaultQuery)) {
73510
73503
  query = { ...defaultQuery, ...query };
@@ -75327,64 +75320,368 @@ var { AnthropicError: AnthropicError2, APIError: APIError2, APIConnectionError:
75327
75320
  var sdk_default = Anthropic;
75328
75321
 
75329
75322
  // src/llm/tools.ts
75323
+ var fs32 = __toESM(require("fs"));
75324
+ var path37 = __toESM(require("path"));
75325
+ var readline4 = __toESM(require("readline"));
75326
+ init_file_ops();
75327
+ init_logging();
75328
+
75329
+ // src/harness/agent-md.ts
75330
75330
  var fs31 = __toESM(require("fs"));
75331
75331
  var path36 = __toESM(require("path"));
75332
75332
  var readline3 = __toESM(require("readline"));
75333
75333
  init_file_ops();
75334
75334
  init_logging();
75335
+ init_manifest();
75335
75336
 
75336
- // src/harness/agent-md.ts
75337
+ // src/harness/instruction-files.ts
75337
75338
  var fs30 = __toESM(require("fs"));
75339
+ var os13 = __toESM(require("os"));
75338
75340
  var path35 = __toESM(require("path"));
75339
75341
  var readline2 = __toESM(require("readline"));
75340
75342
  init_file_ops();
75341
75343
  init_logging();
75342
- init_manifest();
75344
+ var AGENTS_MD = "AGENTS.md";
75345
+ var LEGACY_AGENT_MD = "AGENT.md";
75346
+ var CLAUDE_MD = "CLAUDE.md";
75347
+ var HAR_SECTION_START = "<!-- har:agent-environment:start -->";
75348
+ var HAR_SECTION_END = "<!-- har:agent-environment:end -->";
75349
+ var CLAUDE_HAR_SECTION_START = "<!-- har:claude-pointer:start -->";
75350
+ var CLAUDE_HAR_SECTION_END = "<!-- har:claude-pointer:end -->";
75351
+ function escapeRegExp(value) {
75352
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
75353
+ }
75354
+ function detectInstructionFiles(repoPath) {
75355
+ return {
75356
+ agentsMd: fs30.existsSync(path35.join(repoPath, AGENTS_MD)),
75357
+ agentMd: fs30.existsSync(path35.join(repoPath, LEGACY_AGENT_MD)),
75358
+ claudeMd: fs30.existsSync(path35.join(repoPath, CLAUDE_MD)),
75359
+ cursorDir: fs30.existsSync(path35.join(repoPath, ".cursor")),
75360
+ claudeDir: fs30.existsSync(path35.join(repoPath, ".claude")),
75361
+ codexHome: fs30.existsSync(path35.join(os13.homedir(), ".codex"))
75362
+ };
75363
+ }
75364
+ function formatDetectionReport(detection) {
75365
+ const lines2 = ["Detected:"];
75366
+ lines2.push(` - ${AGENTS_MD} (${detection.agentsMd ? "exists" : "missing"})`);
75367
+ if (detection.agentMd) {
75368
+ lines2.push(` - ${LEGACY_AGENT_MD} (legacy \u2014 will migrate into ${AGENTS_MD})`);
75369
+ }
75370
+ lines2.push(` - ${CLAUDE_MD} (${detection.claudeMd ? "exists" : "missing"})`);
75371
+ lines2.push(` - .cursor/ (${detection.cursorDir ? "exists" : "missing"})`);
75372
+ lines2.push(` - .claude/ (${detection.claudeDir ? "exists" : "missing"})`);
75373
+ lines2.push(` - ~/.codex (${detection.codexHome ? "exists" : "missing"})`);
75374
+ return lines2.join("\n");
75375
+ }
75376
+ function buildInstallPlan(detection, targets, options = {}) {
75377
+ const writeAgentsMd = options.writeAgentsMd !== false;
75378
+ const skillsEnabled = options.skillsEnabled !== false;
75379
+ const cursorExplicit = options.cursorRule;
75380
+ const wantsCursor = cursorExplicit === true || cursorExplicit !== false && (targets.includes("cursor") || detection.cursorDir);
75381
+ return {
75382
+ agentsMd: writeAgentsMd,
75383
+ migrateLegacyAgentMd: writeAgentsMd && detection.agentMd,
75384
+ claudeMd: skillsEnabled && targets.includes("claude"),
75385
+ cursorRule: wantsCursor,
75386
+ skills: skillsEnabled ? targets : []
75387
+ };
75388
+ }
75389
+ function formatInstallPlan(plan, detection) {
75390
+ const mark = (on) => on ? "[x]" : "[ ]";
75391
+ const lines2 = ["After you confirm, HAR will:"];
75392
+ const agentsAction = detection.agentsMd ? `Update ${AGENTS_MD} \u2014 refresh HAR / agent environment section` : `Create ${AGENTS_MD} \u2014 shared HAR workflow (Codex + cross-tool)`;
75393
+ lines2.push(` ${mark(plan.agentsMd)} ${agentsAction}`);
75394
+ if (plan.migrateLegacyAgentMd) {
75395
+ lines2.push(` ${mark(true)} Migrate ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD}, then remove legacy file`);
75396
+ }
75397
+ lines2.push(
75398
+ ` ${mark(plan.claudeMd)} Claude \u2014 ensure ${CLAUDE_MD} points at ${AGENTS_MD}; install .claude/skills if confirmed`
75399
+ );
75400
+ lines2.push(
75401
+ ` ${mark(plan.cursorRule)} Cursor \u2014 install/refresh .cursor/rules/har-workflow.mdc + commands if confirmed`
75402
+ );
75403
+ lines2.push(
75404
+ ` ${mark(plan.skills.includes("codex"))} Codex \u2014 global ~/.codex/prompts (skills); project contract is ${AGENTS_MD}`
75405
+ );
75406
+ return lines2.join("\n");
75407
+ }
75408
+ function loadHarAgentsSectionFromTemplate() {
75409
+ const templatePath = resolveTemplateFile("AGENTS.md.template");
75410
+ if (!templatePath) {
75411
+ throw new Error("AGENTS.md.template not found. Run npm run build.");
75412
+ }
75413
+ const content = fs30.readFileSync(templatePath, "utf8");
75414
+ const start = content.indexOf(HAR_SECTION_START);
75415
+ const end = content.indexOf(HAR_SECTION_END);
75416
+ if (start === -1 || end === -1 || end < start) {
75417
+ throw new Error("AGENTS.md.template is missing har:agent-environment markers.");
75418
+ }
75419
+ return content.slice(start, end + HAR_SECTION_END.length);
75420
+ }
75421
+ function loadAgentsMdTemplate() {
75422
+ const templatePath = resolveTemplateFile("AGENTS.md.template");
75423
+ if (!templatePath) {
75424
+ throw new Error("AGENTS.md.template not found. Run npm run build.");
75425
+ }
75426
+ return fs30.readFileSync(templatePath, "utf8");
75427
+ }
75428
+ function upsertMarkedBlock(content, block, startMarker, endMarker) {
75429
+ if (content.includes(startMarker)) {
75430
+ const pattern = new RegExp(
75431
+ `${escapeRegExp(startMarker)}[\\s\\S]*?${escapeRegExp(endMarker)}`
75432
+ );
75433
+ return { content: content.replace(pattern, block), action: "updated" };
75434
+ }
75435
+ const suffix = content.endsWith("\n") ? "" : "\n";
75436
+ return { content: `${content}${suffix}
75437
+ ${block}
75438
+ `, action: "appended" };
75439
+ }
75440
+ function upsertAgentsMdHarSection(repoPath) {
75441
+ const dest = path35.join(repoPath, AGENTS_MD);
75442
+ const section = loadHarAgentsSectionFromTemplate();
75443
+ if (!fs30.existsSync(dest)) {
75444
+ writeFileSafe(dest, loadAgentsMdTemplate());
75445
+ return "created";
75446
+ }
75447
+ const existing = fs30.readFileSync(dest, "utf8");
75448
+ const { content, action } = upsertMarkedBlock(
75449
+ existing,
75450
+ section,
75451
+ HAR_SECTION_START,
75452
+ HAR_SECTION_END
75453
+ );
75454
+ writeFileSafe(dest, content);
75455
+ return action;
75456
+ }
75457
+ function migrateLegacyAgentMd(repoPath) {
75458
+ const legacyPath = path35.join(repoPath, LEGACY_AGENT_MD);
75459
+ const agentsPath = path35.join(repoPath, AGENTS_MD);
75460
+ if (!fs30.existsSync(legacyPath)) return false;
75461
+ const legacy = fs30.readFileSync(legacyPath, "utf8");
75462
+ if (!fs30.existsSync(agentsPath)) {
75463
+ writeFileSafe(agentsPath, legacy);
75464
+ upsertAgentsMdHarSection(repoPath);
75465
+ } else {
75466
+ upsertAgentsMdHarSection(repoPath);
75467
+ }
75468
+ fs30.unlinkSync(legacyPath);
75469
+ info(`Migrated ${LEGACY_AGENT_MD} \u2192 ${AGENTS_MD} (removed legacy file)`);
75470
+ return true;
75471
+ }
75472
+ function loadClaudeMdTemplate(projectName) {
75473
+ const templatePath = resolveTemplateFile("CLAUDE.md.template");
75474
+ if (!templatePath) {
75475
+ throw new Error("CLAUDE.md.template not found. Run npm run build.");
75476
+ }
75477
+ const displayName = projectName.replace(/_/g, " ");
75478
+ return fs30.readFileSync(templatePath, "utf8").replace(/__PROJECT_DISPLAY_NAME__/g, displayName);
75479
+ }
75480
+ function isThinClaudePointer(content) {
75481
+ const trimmed = content.trim();
75482
+ if (trimmed.length > 600) return false;
75483
+ return /AGENTS\.md|AGENT\.md/.test(trimmed) && (trimmed.includes(".har/README.md") || trimmed.includes("har-workflow"));
75484
+ }
75485
+ var CLAUDE_POINTER_BLOCK = `${CLAUDE_HAR_SECTION_START}
75486
+ ## HAR
75487
+
75488
+ This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
75489
+ [\`.har/README.md\`](./.har/README.md) before making changes.
75490
+ ${CLAUDE_HAR_SECTION_END}`;
75491
+ function ensureClaudeMdPointer(repoPath, options = {}) {
75492
+ const dest = path35.join(repoPath, CLAUDE_MD);
75493
+ const projectName = path35.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
75494
+ const thin = loadClaudeMdTemplate(projectName);
75495
+ if (!fs30.existsSync(dest)) {
75496
+ writeFileSafe(dest, thin);
75497
+ return "created";
75498
+ }
75499
+ const existing = fs30.readFileSync(dest, "utf8");
75500
+ if (isThinClaudePointer(existing) || options.force) {
75501
+ writeFileSafe(dest, thin);
75502
+ return "updated";
75503
+ }
75504
+ if (existing.includes(CLAUDE_HAR_SECTION_START) || /\[AGENTS\.md\]/.test(existing)) {
75505
+ if (existing.includes(CLAUDE_HAR_SECTION_START)) {
75506
+ const { content: content2, action: action2 } = upsertMarkedBlock(
75507
+ existing,
75508
+ CLAUDE_POINTER_BLOCK,
75509
+ CLAUDE_HAR_SECTION_START,
75510
+ CLAUDE_HAR_SECTION_END
75511
+ );
75512
+ writeFileSafe(dest, content2);
75513
+ return action2;
75514
+ }
75515
+ return "skipped";
75516
+ }
75517
+ const { content, action } = upsertMarkedBlock(
75518
+ existing,
75519
+ CLAUDE_POINTER_BLOCK,
75520
+ CLAUDE_HAR_SECTION_START,
75521
+ CLAUDE_HAR_SECTION_END
75522
+ );
75523
+ writeFileSafe(dest, content);
75524
+ return action;
75525
+ }
75526
+ async function askYesNo2(question, defaultYes = true) {
75527
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
75528
+ return new Promise((resolve47) => {
75529
+ process.stderr.write(`${question} `);
75530
+ rl.once("line", (answer) => {
75531
+ rl.close();
75532
+ const trimmed = answer.trim();
75533
+ if (trimmed === "") {
75534
+ resolve47(defaultYes);
75535
+ return;
75536
+ }
75537
+ resolve47(/^y(es)?$/i.test(trimmed));
75538
+ });
75539
+ });
75540
+ }
75541
+ async function handleInstructionFiles(options) {
75542
+ const { repoPath, mode } = options;
75543
+ const writeAgentsMd = options.writeAgentsMd !== false;
75544
+ const skillsEnabled = options.enabled !== false;
75545
+ const detection = detectInstructionFiles(repoPath);
75546
+ let targets;
75547
+ if (!skillsEnabled) {
75548
+ targets = [];
75549
+ } else if (typeof options.agents === "string") {
75550
+ targets = parseAgentTargets(options.agents);
75551
+ } else {
75552
+ targets = detectAgentTargets(repoPath);
75553
+ }
75554
+ if (skillsEnabled && targets.length === 0 && mode === "init" && typeof options.agents !== "string" && !options.autoYes) {
75555
+ targets = [...AGENT_SKILL_TARGETS];
75556
+ }
75557
+ let plan = buildInstallPlan(detection, targets, {
75558
+ writeAgentsMd,
75559
+ cursorRule: options.cursorRule,
75560
+ skillsEnabled
75561
+ });
75562
+ divider();
75563
+ process.stderr.write(`${formatDetectionReport(detection)}
75564
+
75565
+ `);
75566
+ process.stderr.write(`${formatInstallPlan(plan, detection)}
75567
+ `);
75568
+ divider();
75569
+ const shouldPrompt = !options.autoYes && skillsEnabled && typeof options.agents !== "string" && !(mode === "maintain" && targets.length > 0 && !detection.agentMd);
75570
+ if (shouldPrompt && targets.length > 0) {
75571
+ const accepted = await askYesNo2(
75572
+ `Install HAR agent instructions for: ${targets.join(", ")}? [Y/n]`
75573
+ );
75574
+ if (!accepted) {
75575
+ info("Skipped agent instruction adapters (AGENTS.md will still be updated)");
75576
+ targets = [];
75577
+ plan = buildInstallPlan(detection, targets, {
75578
+ writeAgentsMd,
75579
+ cursorRule: options.cursorRule === true ? true : false,
75580
+ skillsEnabled: false
75581
+ });
75582
+ }
75583
+ }
75584
+ let migratedLegacy = false;
75585
+ let agentsMdAction = null;
75586
+ let claudeMdAction = null;
75587
+ if (writeAgentsMd) {
75588
+ if (detection.agentMd) {
75589
+ migratedLegacy = migrateLegacyAgentMd(repoPath);
75590
+ }
75591
+ agentsMdAction = upsertAgentsMdHarSection(repoPath);
75592
+ if (agentsMdAction === "created") {
75593
+ success(`Wrote ${AGENTS_MD}`);
75594
+ } else if (agentsMdAction === "updated" || agentsMdAction === "appended") {
75595
+ info(
75596
+ `${agentsMdAction === "updated" ? "Refreshed" : "Appended"} HAR section in ${AGENTS_MD}`
75597
+ );
75598
+ }
75599
+ } else {
75600
+ agentsMdAction = "skipped";
75601
+ }
75602
+ if (plan.claudeMd) {
75603
+ claudeMdAction = ensureClaudeMdPointer(repoPath);
75604
+ if (claudeMdAction === "created") {
75605
+ success(`Wrote ${CLAUDE_MD} (pointer \u2192 ${AGENTS_MD})`);
75606
+ } else if (claudeMdAction === "updated" || claudeMdAction === "appended") {
75607
+ info(
75608
+ `${claudeMdAction === "updated" ? "Updated" : "Appended"} ${CLAUDE_MD} pointer \u2192 ${AGENTS_MD}`
75609
+ );
75610
+ }
75611
+ } else {
75612
+ claudeMdAction = "skipped";
75613
+ }
75614
+ return {
75615
+ detection,
75616
+ plan,
75617
+ targets,
75618
+ agentsMdAction,
75619
+ migratedLegacy,
75620
+ claudeMdAction
75621
+ };
75622
+ }
75623
+
75624
+ // src/harness/agent-md.ts
75625
+ var AGENTS_MD_PROPOSAL = "AGENTS.md.proposed";
75626
+ var AGENTS_MD_PROPOSAL_META = "AGENTS.md.proposed.meta.json";
75343
75627
  var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
75344
75628
  var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
75345
75629
  function writeAgentMdProposal(repoPath, content, rationale) {
75346
75630
  const harnessDir = getHarnessDir(repoPath);
75347
- writeFileSafe(path35.join(harnessDir, AGENT_MD_PROPOSAL), content);
75631
+ writeFileSafe(path36.join(harnessDir, AGENTS_MD_PROPOSAL), content);
75348
75632
  writeFileSafe(
75349
- path35.join(harnessDir, AGENT_MD_PROPOSAL_META),
75633
+ path36.join(harnessDir, AGENTS_MD_PROPOSAL_META),
75350
75634
  JSON.stringify({ rationale, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
75351
75635
  );
75636
+ for (const file of [AGENT_MD_PROPOSAL, AGENT_MD_PROPOSAL_META]) {
75637
+ const p2 = path36.join(harnessDir, file);
75638
+ if (fs31.existsSync(p2)) fs31.unlinkSync(p2);
75639
+ }
75352
75640
  }
75353
75641
  function readAgentMdProposal(repoPath) {
75354
75642
  const harnessDir = getHarnessDir(repoPath);
75355
- const proposalPath = path35.join(harnessDir, AGENT_MD_PROPOSAL);
75356
- const metaPath = path35.join(harnessDir, AGENT_MD_PROPOSAL_META);
75357
- if (!fs30.existsSync(proposalPath)) return null;
75358
- const content = fs30.readFileSync(proposalPath, "utf8");
75643
+ const proposalPath = path36.join(harnessDir, AGENTS_MD_PROPOSAL);
75644
+ const metaPath = path36.join(harnessDir, AGENTS_MD_PROPOSAL_META);
75645
+ const legacyProposalPath = path36.join(harnessDir, AGENT_MD_PROPOSAL);
75646
+ const legacyMetaPath = path36.join(harnessDir, AGENT_MD_PROPOSAL_META);
75647
+ const resolvedProposal = fs31.existsSync(proposalPath) ? proposalPath : fs31.existsSync(legacyProposalPath) ? legacyProposalPath : null;
75648
+ if (!resolvedProposal) return null;
75649
+ const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
75650
+ const content = fs31.readFileSync(resolvedProposal, "utf8");
75359
75651
  let rationale = "";
75360
- if (fs30.existsSync(metaPath)) {
75652
+ let createdAt = (/* @__PURE__ */ new Date()).toISOString();
75653
+ if (fs31.existsSync(resolvedMeta)) {
75361
75654
  try {
75362
- rationale = JSON.parse(fs30.readFileSync(metaPath, "utf8")).rationale ?? "";
75655
+ const meta = JSON.parse(fs31.readFileSync(resolvedMeta, "utf8"));
75656
+ rationale = meta.rationale ?? "";
75657
+ createdAt = meta.createdAt ?? createdAt;
75363
75658
  } catch {
75364
75659
  rationale = "";
75365
75660
  }
75366
75661
  }
75367
- return {
75368
- content,
75369
- rationale,
75370
- createdAt: fs30.existsSync(metaPath) ? JSON.parse(fs30.readFileSync(metaPath, "utf8")).createdAt : (/* @__PURE__ */ new Date()).toISOString()
75371
- };
75662
+ return { content, rationale, createdAt };
75372
75663
  }
75373
75664
  function clearAgentMdProposal(repoPath) {
75374
75665
  const harnessDir = getHarnessDir(repoPath);
75375
- for (const file of [AGENT_MD_PROPOSAL, AGENT_MD_PROPOSAL_META]) {
75376
- const p2 = path35.join(harnessDir, file);
75377
- if (fs30.existsSync(p2)) fs30.unlinkSync(p2);
75666
+ for (const file of [
75667
+ AGENTS_MD_PROPOSAL,
75668
+ AGENTS_MD_PROPOSAL_META,
75669
+ AGENT_MD_PROPOSAL,
75670
+ AGENT_MD_PROPOSAL_META
75671
+ ]) {
75672
+ const p2 = path36.join(harnessDir, file);
75673
+ if (fs31.existsSync(p2)) fs31.unlinkSync(p2);
75378
75674
  }
75379
75675
  }
75380
75676
  async function promptApplyAgentMdProposal(repoPath) {
75381
75677
  const proposal = readAgentMdProposal(repoPath);
75382
75678
  if (!proposal) return false;
75383
- const agentMdPath = path35.join(repoPath, "AGENT.md");
75384
- const exists = fs30.existsSync(agentMdPath);
75679
+ const agentsMdPath = path36.join(repoPath, AGENTS_MD);
75680
+ const exists = fs31.existsSync(agentsMdPath);
75385
75681
  process.stderr.write("\n");
75386
75682
  process.stderr.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
75387
- process.stderr.write("Proposed AGENT.md (repo root)\n");
75683
+ process.stderr.write(`Proposed ${AGENTS_MD} (repo root)
75684
+ `);
75388
75685
  process.stderr.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
75389
75686
  if (proposal.rationale) {
75390
75687
  process.stderr.write(`Why: ${proposal.rationale}
@@ -75400,29 +75697,29 @@ async function promptApplyAgentMdProposal(repoPath) {
75400
75697
  process.stderr.write(" ...\n");
75401
75698
  }
75402
75699
  process.stderr.write("\n");
75403
- process.stderr.write(`Full proposal: .har/${AGENT_MD_PROPOSAL}
75700
+ process.stderr.write(`Full proposal: .har/${AGENTS_MD_PROPOSAL}
75404
75701
  `);
75405
75702
  if (exists) {
75406
- warn("AGENT.md already exists at repo root.");
75407
- const answer = await askYesNo2("Replace AGENT.md with this proposal? (y/n)");
75703
+ warn(`${AGENTS_MD} already exists at repo root.`);
75704
+ const answer = await askYesNo3(`Replace ${AGENTS_MD} with this proposal? (y/n)`);
75408
75705
  if (!answer) {
75409
- info("Skipped \u2014 proposal kept at .har/AGENT.md.proposed");
75706
+ info(`Skipped \u2014 proposal kept at .har/${AGENTS_MD_PROPOSAL}`);
75410
75707
  return false;
75411
75708
  }
75412
75709
  } else {
75413
- const answer = await askYesNo2("Create AGENT.md at repo root? (y/n)");
75710
+ const answer = await askYesNo3(`Create ${AGENTS_MD} at repo root? (y/n)`);
75414
75711
  if (!answer) {
75415
- info("Skipped \u2014 proposal kept at .har/AGENT.md.proposed");
75712
+ info(`Skipped \u2014 proposal kept at .har/${AGENTS_MD_PROPOSAL}`);
75416
75713
  return false;
75417
75714
  }
75418
75715
  }
75419
- writeFileSafe(agentMdPath, proposal.content);
75716
+ writeFileSafe(agentsMdPath, proposal.content);
75420
75717
  clearAgentMdProposal(repoPath);
75421
- info("Wrote AGENT.md");
75718
+ info(`Wrote ${AGENTS_MD}`);
75422
75719
  return true;
75423
75720
  }
75424
- async function askYesNo2(question) {
75425
- const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
75721
+ async function askYesNo3(question) {
75722
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
75426
75723
  return new Promise((resolve47) => {
75427
75724
  process.stderr.write(`${question} `);
75428
75725
  rl.once("line", (answer) => {
@@ -75519,12 +75816,12 @@ function buildAuthoringTools() {
75519
75816
  }
75520
75817
  },
75521
75818
  {
75522
- name: "proposeAgentMd",
75523
- description: "Propose content for AGENT.md at the repo root. Does NOT write the file \u2014 the user approves after init/maintain. Include project-specific notes and pointer to .har/.",
75819
+ name: "proposeAgentsMd",
75820
+ description: "Propose content for AGENTS.md at the repo root. Does NOT write the file \u2014 the user approves after init/maintain. Include project-specific notes and pointer to .har/.",
75524
75821
  input_schema: {
75525
75822
  type: "object",
75526
75823
  properties: {
75527
- content: { type: "string", description: "Full proposed AGENT.md content" },
75824
+ content: { type: "string", description: "Full proposed AGENTS.md content" },
75528
75825
  rationale: { type: "string", description: "Why these changes (shown to user)" }
75529
75826
  },
75530
75827
  required: ["content", "rationale"]
@@ -75569,13 +75866,13 @@ async function handleAuthoringToolCall(toolName, input, repoPath, harnessDir, ca
75569
75866
  async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, callbacks) {
75570
75867
  switch (toolName) {
75571
75868
  case "readRepoFile": {
75572
- const filePath = path36.join(repoPath, input.path);
75869
+ const filePath = path37.join(repoPath, input.path);
75573
75870
  const content = readFile(filePath, input.maxChars ?? 8e3);
75574
75871
  info(`Read repo: ${input.path}`);
75575
75872
  return content;
75576
75873
  }
75577
75874
  case "listRepoDir": {
75578
- const dirPath = path36.join(repoPath, input.path ?? ".");
75875
+ const dirPath = path37.join(repoPath, input.path ?? ".");
75579
75876
  const entries = listDir(dirPath, input.maxFiles ?? 60);
75580
75877
  info(`List repo: ${input.path} \u2192 ${entries.length} entries`);
75581
75878
  return entries.length > 0 ? entries.join("\n") : "(empty directory)";
@@ -75600,17 +75897,17 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
75600
75897
  const filePath = resolveSafePath(harnessDir, relPath);
75601
75898
  writeFileSafe(filePath, input.content);
75602
75899
  if (relPath.endsWith(".sh")) {
75603
- fs31.chmodSync(filePath, 493);
75900
+ fs32.chmodSync(filePath, 493);
75604
75901
  }
75605
75902
  info(`Wrote harness: ${relPath}`);
75606
75903
  return `Written ${relPath} (${input.content.length} bytes)`;
75607
75904
  }
75608
75905
  case "editHarnessFile": {
75609
75906
  const filePath = resolveSafePath(harnessDir, input.path);
75610
- if (!fs31.existsSync(filePath)) {
75907
+ if (!fs32.existsSync(filePath)) {
75611
75908
  return `Error: file not found: ${input.path}`;
75612
75909
  }
75613
- const content = fs31.readFileSync(filePath, "utf8");
75910
+ const content = fs32.readFileSync(filePath, "utf8");
75614
75911
  const oldStr = input.old_string;
75615
75912
  const newStr = input.new_string;
75616
75913
  const count = content.split(oldStr).length - 1;
@@ -75627,17 +75924,17 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
75627
75924
  }
75628
75925
  case "deleteHarnessFile": {
75629
75926
  const filePath = resolveSafePath(harnessDir, input.path);
75630
- if (!fs31.existsSync(filePath)) {
75927
+ if (!fs32.existsSync(filePath)) {
75631
75928
  return `File not found (already deleted): ${input.path}`;
75632
75929
  }
75633
- fs31.unlinkSync(filePath);
75930
+ fs32.unlinkSync(filePath);
75634
75931
  info(`Deleted harness: ${input.path}`);
75635
75932
  return `Deleted ${input.path}`;
75636
75933
  }
75637
- case "proposeAgentMd": {
75934
+ case "proposeAgentsMd": {
75638
75935
  writeAgentMdProposal(repoPath, input.content, input.rationale);
75639
- info("Proposed AGENT.md (awaiting user approval)");
75640
- return "AGENT.md proposal saved to .har/AGENT.md.proposed \u2014 user will be prompted to apply.";
75936
+ info("Proposed AGENTS.md (awaiting user approval)");
75937
+ return "AGENTS.md proposal saved to .har/AGENTS.md.proposed \u2014 user will be prompted to apply.";
75641
75938
  }
75642
75939
  case "ask": {
75643
75940
  return askUser(input.question, input.options ?? []);
@@ -75656,7 +75953,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
75656
75953
  }
75657
75954
  }
75658
75955
  async function askUser(question, options) {
75659
- const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
75956
+ const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
75660
75957
  return new Promise((resolve47) => {
75661
75958
  process.stderr.write("\n");
75662
75959
  process.stderr.write(`\u2753 ${question}
@@ -75682,30 +75979,30 @@ async function authorHarness(repoPath, apiKey, options = {}) {
75682
75979
  const harnessDir = getHarnessDir(repoPath);
75683
75980
  const mode = options.mode ?? "init";
75684
75981
  const systemPromptPath = resolvePromptPath("system-authoring.md");
75685
- const agentMdTemplatePath = resolveTemplateFile("AGENT.md.template");
75686
- let systemPrompt = fs32.existsSync(systemPromptPath) ? fs32.readFileSync(systemPromptPath, "utf8") : "Adapt the .har/ boilerplate to match the repository. Edit files directly. Call finishAuthoring when done.";
75982
+ const agentMdTemplatePath = resolveTemplateFile("AGENTS.md.template");
75983
+ let systemPrompt = fs33.existsSync(systemPromptPath) ? fs33.readFileSync(systemPromptPath, "utf8") : "Adapt the .har/ boilerplate to match the repository. Edit files directly. Call finishAuthoring when done.";
75687
75984
  if (agentMdTemplatePath) {
75688
75985
  systemPrompt += `
75689
75986
 
75690
- ## AGENT.md template (starting point for proposeAgentMd)
75987
+ ## AGENTS.md template (starting point for proposeAgentsMd)
75691
75988
 
75692
- ${fs32.readFileSync(agentMdTemplatePath, "utf8")}`;
75989
+ ${fs33.readFileSync(agentMdTemplatePath, "utf8")}`;
75693
75990
  }
75694
75991
  const tools = buildAuthoringTools();
75695
75992
  const messages = [];
75696
75993
  let rootListing;
75697
75994
  try {
75698
- rootListing = fs32.readdirSync(repoPath).slice(0, 50).join("\n");
75995
+ rootListing = fs33.readdirSync(repoPath).slice(0, 50).join("\n");
75699
75996
  } catch {
75700
75997
  throw new Error(`Cannot read repo at path: ${repoPath}`);
75701
75998
  }
75702
75999
  let harnessListing;
75703
76000
  try {
75704
- harnessListing = fs32.readdirSync(harnessDir).join("\n");
76001
+ harnessListing = fs33.readdirSync(harnessDir).join("\n");
75705
76002
  } catch {
75706
76003
  throw new Error(`Cannot read harness dir at: ${harnessDir}`);
75707
76004
  }
75708
- const existingAgentMd = fs32.existsSync(path37.join(repoPath, "AGENT.md")) ? "AGENT.md exists at repo root \u2014 read it before proposing changes via proposeAgentMd." : "No AGENT.md at repo root yet \u2014 propose one via proposeAgentMd.";
76005
+ const existingAgentMd = fs33.existsSync(path38.join(repoPath, "AGENTS.md")) ? "AGENTS.md exists at repo root \u2014 read it before proposing changes via proposeAgentsMd." : "No AGENTS.md at repo root yet \u2014 propose one via proposeAgentsMd.";
75709
76006
  const modeInstructions = mode === "maintain" ? `This is a MAINTENANCE run. .har/ already exists and may have been edited by humans.
75710
76007
  Update it to reflect current repo changes. Prefer editHarnessFile over writeHarnessFile.
75711
76008
  Keep README.md accurate \u2014 it is the index of the harness. ${existingAgentMd}` : `This is an INITIAL setup. A fresh boilerplate has been copied to .har/.
@@ -75785,8 +76082,8 @@ Try running with --verbose to see what the agent is doing.`
75785
76082
  }
75786
76083
 
75787
76084
  // src/harness/validator.ts
75788
- var fs33 = __toESM(require("fs"));
75789
- var path38 = __toESM(require("path"));
76085
+ var fs34 = __toESM(require("fs"));
76086
+ var path39 = __toESM(require("path"));
75790
76087
  init_shell();
75791
76088
  init_manifest();
75792
76089
  init_stages();
@@ -75841,22 +76138,22 @@ var SHELL_SCRIPTS = [
75841
76138
  function validateHarness(repoPath) {
75842
76139
  const harnessDir = getHarnessDir(repoPath);
75843
76140
  const issues = [];
75844
- if (!fs33.existsSync(harnessDir)) {
76141
+ if (!fs34.existsSync(harnessDir)) {
75845
76142
  return {
75846
76143
  pass: false,
75847
76144
  issues: [{ file: ".har", message: "Harness directory not found", severity: "error" }]
75848
76145
  };
75849
76146
  }
75850
76147
  for (const file of getRequiredFiles(repoPath)) {
75851
- const filePath = path38.join(harnessDir, file);
75852
- if (!fs33.existsSync(filePath)) {
76148
+ const filePath = path39.join(harnessDir, file);
76149
+ if (!fs34.existsSync(filePath)) {
75853
76150
  issues.push({ file, message: "Required file missing", severity: "error" });
75854
76151
  }
75855
76152
  }
75856
76153
  for (const script of SHELL_SCRIPTS) {
75857
- const scriptPath = path38.join(harnessDir, script);
75858
- if (!fs33.existsSync(scriptPath)) continue;
75859
- const stat = fs33.statSync(scriptPath);
76154
+ const scriptPath = path39.join(harnessDir, script);
76155
+ if (!fs34.existsSync(scriptPath)) continue;
76156
+ const stat = fs34.statSync(scriptPath);
75860
76157
  if (!(stat.mode & 73)) {
75861
76158
  issues.push({ file: script, message: "Script is not executable", severity: "warning" });
75862
76159
  }
@@ -75871,9 +76168,9 @@ function validateHarness(repoPath) {
75871
76168
  }
75872
76169
  const manifest = readManifest(repoPath);
75873
76170
  const profile = manifest?.profile ?? "default";
75874
- const ecosystemPath = path38.join(harnessDir, "ecosystem.agent.template.cjs");
75875
- if (profile !== "cli" && fs33.existsSync(ecosystemPath)) {
75876
- const content = fs33.readFileSync(ecosystemPath, "utf8");
76171
+ const ecosystemPath = path39.join(harnessDir, "ecosystem.agent.template.cjs");
76172
+ if (profile !== "cli" && fs34.existsSync(ecosystemPath)) {
76173
+ const content = fs34.readFileSync(ecosystemPath, "utf8");
75877
76174
  if (!content.includes("module.exports")) {
75878
76175
  issues.push({
75879
76176
  file: "ecosystem.agent.template.cjs",
@@ -75882,9 +76179,9 @@ function validateHarness(repoPath) {
75882
76179
  });
75883
76180
  }
75884
76181
  }
75885
- const harnessEnvPath = path38.join(harnessDir, "harness.env");
75886
- if (fs33.existsSync(harnessEnvPath)) {
75887
- const content = fs33.readFileSync(harnessEnvPath, "utf8");
76182
+ const harnessEnvPath = path39.join(harnessDir, "harness.env");
76183
+ if (fs34.existsSync(harnessEnvPath)) {
76184
+ const content = fs34.readFileSync(harnessEnvPath, "utf8");
75888
76185
  if (content.includes("TODO: set migrate command")) {
75889
76186
  issues.push({ file: "harness.env", message: "Migrate command still has TODO", severity: "warning" });
75890
76187
  }
@@ -75892,17 +76189,17 @@ function validateHarness(repoPath) {
75892
76189
  issues.push({ file: "harness.env", message: "Seed command still has TODO", severity: "warning" });
75893
76190
  }
75894
76191
  }
75895
- const verifyPath = path38.join(harnessDir, "verify.sh");
75896
- if (fs33.existsSync(verifyPath)) {
75897
- const content = fs33.readFileSync(verifyPath, "utf8");
76192
+ const verifyPath = path39.join(harnessDir, "verify.sh");
76193
+ if (fs34.existsSync(verifyPath)) {
76194
+ const content = fs34.readFileSync(verifyPath, "utf8");
75898
76195
  if (content.includes("echo 'TODO:")) {
75899
76196
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
75900
76197
  }
75901
76198
  }
75902
- const stagesPath = path38.join(harnessDir, "stages.json");
75903
- if (fs33.existsSync(stagesPath)) {
76199
+ const stagesPath = path39.join(harnessDir, "stages.json");
76200
+ if (fs34.existsSync(stagesPath)) {
75904
76201
  try {
75905
- JSON.parse(fs33.readFileSync(stagesPath, "utf8"));
76202
+ JSON.parse(fs34.readFileSync(stagesPath, "utf8"));
75906
76203
  const registry2 = readStageRegistry(repoPath);
75907
76204
  if (registry2.stages.length === 0) {
75908
76205
  issues.push({ file: "stages.json", message: "No harness stages declared", severity: "warning" });
@@ -75917,9 +76214,9 @@ function validateHarness(repoPath) {
75917
76214
  } else {
75918
76215
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
75919
76216
  }
75920
- const readmePath = path38.join(harnessDir, "README.md");
75921
- if (fs33.existsSync(readmePath)) {
75922
- const content = fs33.readFileSync(readmePath, "utf8");
76217
+ const readmePath = path39.join(harnessDir, "README.md");
76218
+ if (fs34.existsSync(readmePath)) {
76219
+ const content = fs34.readFileSync(readmePath, "utf8");
75923
76220
  if (!content.includes(".har")) {
75924
76221
  issues.push({ file: "README.md", message: "README should document .har/ paths", severity: "warning" });
75925
76222
  }
@@ -75933,8 +76230,8 @@ function validateHarness(repoPath) {
75933
76230
  async function smokeTestHarness(repoPath) {
75934
76231
  const harnessDir = getHarnessDir(repoPath);
75935
76232
  const issues = [];
75936
- const setupScript = path38.join(harnessDir, "setup-infra.sh");
75937
- if (fs33.existsSync(setupScript)) {
76233
+ const setupScript = path39.join(harnessDir, "setup-infra.sh");
76234
+ if (fs34.existsSync(setupScript)) {
75938
76235
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
75939
76236
  if (result.code !== 0) {
75940
76237
  issues.push({
@@ -75949,8 +76246,8 @@ async function smokeTestHarness(repoPath) {
75949
76246
  }
75950
76247
 
75951
76248
  // src/harness/drift.ts
75952
- var fs34 = __toESM(require("fs"));
75953
- var path39 = __toESM(require("path"));
76249
+ var fs35 = __toESM(require("fs"));
76250
+ var path40 = __toESM(require("path"));
75954
76251
  init_env();
75955
76252
  init_manifest();
75956
76253
  init_stages();
@@ -76021,16 +76318,16 @@ function substituteProjectName(content, projectName) {
76021
76318
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
76022
76319
  }
76023
76320
  function listBoilerplateFiles(boilerplateDir) {
76024
- if (!fs34.existsSync(boilerplateDir)) return [];
76025
- return fs34.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
76321
+ if (!fs35.existsSync(boilerplateDir)) return [];
76322
+ return fs35.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
76026
76323
  }
76027
76324
  function compareHarnessToTemplate(repoPath) {
76028
- const resolved = path39.resolve(repoPath);
76325
+ const resolved = path40.resolve(repoPath);
76029
76326
  const manifest = readManifest(resolved);
76030
76327
  const profile = manifest?.profile ?? "default";
76031
76328
  const harnessDir = getHarnessDir(resolved);
76032
- const projectName = path39.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
76033
- const boilerplateDir = path39.join(resolveTemplatesDir(), PROFILE_DIRS2[profile]);
76329
+ const projectName = path40.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
76330
+ const boilerplateDir = path40.join(resolveTemplatesDir(), PROFILE_DIRS2[profile]);
76034
76331
  const templateFiles = listBoilerplateFiles(boilerplateDir);
76035
76332
  const missing = [];
76036
76333
  const checksumMismatch = [];
@@ -76038,17 +76335,17 @@ function compareHarnessToTemplate(repoPath) {
76038
76335
  const unchanged = [];
76039
76336
  for (const file of templateFiles) {
76040
76337
  const harnessFile = harnessFileForTemplate(file);
76041
- const templatePath = path39.join(boilerplateDir, file);
76042
- const harnessPath = path39.join(harnessDir, harnessFile);
76043
- let templateContent = fs34.readFileSync(templatePath, "utf8");
76338
+ const templatePath = path40.join(boilerplateDir, file);
76339
+ const harnessPath = path40.join(harnessDir, harnessFile);
76340
+ let templateContent = fs35.readFileSync(templatePath, "utf8");
76044
76341
  if (file === "harness.env") {
76045
76342
  templateContent = substituteProjectName(templateContent, projectName);
76046
76343
  }
76047
- if (!fs34.existsSync(harnessPath)) {
76344
+ if (!fs35.existsSync(harnessPath)) {
76048
76345
  missing.push(harnessFile);
76049
76346
  continue;
76050
76347
  }
76051
- const harnessChecksum = computeFileChecksum(fs34.readFileSync(harnessPath, "utf8"));
76348
+ const harnessChecksum = computeFileChecksum(fs35.readFileSync(harnessPath, "utf8"));
76052
76349
  const templateChecksum = computeFileChecksum(templateContent);
76053
76350
  if (harnessChecksum === templateChecksum) {
76054
76351
  unchanged.push(harnessFile);
@@ -76056,10 +76353,10 @@ function compareHarnessToTemplate(repoPath) {
76056
76353
  checksumMismatch.push(harnessFile);
76057
76354
  }
76058
76355
  }
76059
- if (fs34.existsSync(harnessDir)) {
76060
- for (const file of fs34.readdirSync(harnessDir)) {
76061
- const full = path39.join(harnessDir, file);
76062
- if (!fs34.statSync(full).isFile()) continue;
76356
+ if (fs35.existsSync(harnessDir)) {
76357
+ for (const file of fs35.readdirSync(harnessDir)) {
76358
+ const full = path40.join(harnessDir, file);
76359
+ if (!fs35.statSync(full).isFile()) continue;
76063
76360
  if (file === "manifest.json" || file.startsWith("ADAPT-PROMPT")) continue;
76064
76361
  if (profile === "cli" && CLI_EXPECTED_ABSENT.has(file)) {
76065
76362
  extra.push(file);
@@ -76090,29 +76387,29 @@ function compareHarnessToTemplate(repoPath) {
76090
76387
  }
76091
76388
 
76092
76389
  // src/harness/maintain-bundle.ts
76093
- var fs38 = __toESM(require("fs"));
76094
- var os13 = __toESM(require("os"));
76095
- var path42 = __toESM(require("path"));
76390
+ var fs39 = __toESM(require("fs"));
76391
+ var os14 = __toESM(require("os"));
76392
+ var path43 = __toESM(require("path"));
76096
76393
  init_file_ops();
76097
76394
  init_shell();
76098
76395
  init_manifest();
76099
76396
 
76100
76397
  // src/harness/plugin-drift.ts
76101
- var fs37 = __toESM(require("fs"));
76102
- var path41 = __toESM(require("path"));
76398
+ var fs38 = __toESM(require("fs"));
76399
+ var path42 = __toESM(require("path"));
76103
76400
  init_manifest();
76104
76401
 
76105
76402
  // src/harness/plugins.ts
76106
- var fs36 = __toESM(require("fs"));
76107
- var path40 = __toESM(require("path"));
76403
+ var fs37 = __toESM(require("fs"));
76404
+ var path41 = __toESM(require("path"));
76108
76405
  init_zod();
76109
76406
  init_logging();
76110
76407
 
76111
76408
  // src/harness/parser.ts
76112
- var fs35 = __toESM(require("fs"));
76409
+ var fs36 = __toESM(require("fs"));
76113
76410
  init_manifest();
76114
76411
  function harnessExists(repoPath) {
76115
- return fs35.existsSync(`${repoPath}/.har/setup-infra.sh`);
76412
+ return fs36.existsSync(`${repoPath}/.har/setup-infra.sh`);
76116
76413
  }
76117
76414
 
76118
76415
  // src/harness/plugins.ts
@@ -76137,16 +76434,16 @@ var PluginManifestSchema = external_exports.object({
76137
76434
  docsPath: external_exports.string().min(1)
76138
76435
  });
76139
76436
  function resolvePluginDir(pluginId) {
76140
- const dir = path40.join(resolveTemplatesDir(), "plugins", pluginId);
76141
- if (!fs36.existsSync(dir)) {
76437
+ const dir = path41.join(resolveTemplatesDir(), "plugins", pluginId);
76438
+ if (!fs37.existsSync(dir)) {
76142
76439
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
76143
76440
  }
76144
76441
  return dir;
76145
76442
  }
76146
76443
  function readPluginManifest(pluginId) {
76147
- const manifestPath = path40.join(resolvePluginDir(pluginId), "template.manifest.json");
76444
+ const manifestPath = path41.join(resolvePluginDir(pluginId), "template.manifest.json");
76148
76445
  const parsed = PluginManifestSchema.safeParse(
76149
- JSON.parse(fs36.readFileSync(manifestPath, "utf8"))
76446
+ JSON.parse(fs37.readFileSync(manifestPath, "utf8"))
76150
76447
  );
76151
76448
  if (!parsed.success) {
76152
76449
  throw new Error(`Invalid plugin manifest for ${pluginId}: ${parsed.error.message}`);
@@ -76157,40 +76454,40 @@ function readPluginManifest(pluginId) {
76157
76454
  return parsed.data;
76158
76455
  }
76159
76456
  function ensureParentDir(filePath) {
76160
- const parent = path40.dirname(filePath);
76161
- if (!fs36.existsSync(parent)) {
76162
- fs36.mkdirSync(parent, { recursive: true });
76457
+ const parent = path41.dirname(filePath);
76458
+ if (!fs37.existsSync(parent)) {
76459
+ fs37.mkdirSync(parent, { recursive: true });
76163
76460
  }
76164
76461
  }
76165
76462
  function copyPluginFile(pluginDir, file, repoPath, force) {
76166
- const srcPath = path40.join(pluginDir, file.src);
76167
- const destPath = path40.join(repoPath, file.dest);
76168
- if (!fs36.existsSync(srcPath)) {
76463
+ const srcPath = path41.join(pluginDir, file.src);
76464
+ const destPath = path41.join(repoPath, file.dest);
76465
+ if (!fs37.existsSync(srcPath)) {
76169
76466
  throw new Error(`Plugin file missing: ${file.src}`);
76170
76467
  }
76171
- if (fs36.existsSync(destPath) && !force) {
76468
+ if (fs37.existsSync(destPath) && !force) {
76172
76469
  throw new Error(
76173
76470
  `File already exists: ${file.dest}. Use --force to overwrite or remove it first.`
76174
76471
  );
76175
76472
  }
76176
76473
  ensureParentDir(destPath);
76177
- fs36.copyFileSync(srcPath, destPath);
76474
+ fs37.copyFileSync(srcPath, destPath);
76178
76475
  if (file.executable) {
76179
- fs36.chmodSync(destPath, 493);
76476
+ fs37.chmodSync(destPath, 493);
76180
76477
  }
76181
76478
  return { written: true, path: file.dest };
76182
76479
  }
76183
76480
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
76184
- const packagePath = path40.join(repoPath, "package.json");
76185
- if (!fs36.existsSync(packagePath)) {
76481
+ const packagePath = path41.join(repoPath, "package.json");
76482
+ if (!fs37.existsSync(packagePath)) {
76186
76483
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
76187
76484
  }
76188
- const fragmentPath = path40.join(pluginDir, fragmentRelPath);
76189
- if (!fs36.existsSync(fragmentPath)) {
76485
+ const fragmentPath = path41.join(pluginDir, fragmentRelPath);
76486
+ if (!fs37.existsSync(fragmentPath)) {
76190
76487
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
76191
76488
  }
76192
- const pkg = JSON.parse(fs36.readFileSync(packagePath, "utf8"));
76193
- const fragment = JSON.parse(fs36.readFileSync(fragmentPath, "utf8"));
76489
+ const pkg = JSON.parse(fs37.readFileSync(packagePath, "utf8"));
76490
+ const fragment = JSON.parse(fs37.readFileSync(fragmentPath, "utf8"));
76194
76491
  for (const section of ["scripts", "devDependencies"]) {
76195
76492
  const existing = pkg[section] ?? {};
76196
76493
  const incoming = fragment[section] ?? {};
@@ -76203,7 +76500,7 @@ function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
76203
76500
  }
76204
76501
  pkg[section] = existing;
76205
76502
  }
76206
- fs36.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
76503
+ fs37.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + "\n");
76207
76504
  }
76208
76505
  function patchStageRegistry(repoPath, manifest, force) {
76209
76506
  const registry2 = readStageRegistry(repoPath);
@@ -76243,8 +76540,8 @@ function assertHarnessPresent(repoPath) {
76243
76540
  }
76244
76541
  function assertStageNotPresent(repoPath, stageId, force) {
76245
76542
  if (force) return;
76246
- const scriptPath = path40.join(repoPath, ".har", "stages", `${stageId}.sh`);
76247
- if (fs36.existsSync(scriptPath)) {
76543
+ const scriptPath = path41.join(repoPath, ".har", "stages", `${stageId}.sh`);
76544
+ if (fs37.existsSync(scriptPath)) {
76248
76545
  throw new Error(
76249
76546
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
76250
76547
  );
@@ -76257,7 +76554,7 @@ function assertStageNotPresent(repoPath, stageId, force) {
76257
76554
  }
76258
76555
  }
76259
76556
  function applyPlugin(repoPath, pluginId, options = {}) {
76260
- const resolved = path40.resolve(repoPath);
76557
+ const resolved = path41.resolve(repoPath);
76261
76558
  const force = options.force ?? false;
76262
76559
  const warnings = [];
76263
76560
  const filesWritten = [];
@@ -76276,7 +76573,7 @@ function applyPlugin(repoPath, pluginId, options = {}) {
76276
76573
  if (file.skipFlag === "skipCi" && options.skipCi) {
76277
76574
  continue;
76278
76575
  }
76279
- if (fs36.existsSync(path40.join(resolved, file.dest)) && !force) {
76576
+ if (fs37.existsSync(path41.join(resolved, file.dest)) && !force) {
76280
76577
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
76281
76578
  continue;
76282
76579
  }
@@ -76311,18 +76608,18 @@ function applyPlugin(repoPath, pluginId, options = {}) {
76311
76608
  };
76312
76609
  }
76313
76610
  function listPluginIds() {
76314
- const root = path40.join(resolveTemplatesDir(), "plugins");
76315
- if (!fs36.existsSync(root)) return [...PLUGIN_IDS];
76316
- return fs36.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
76611
+ const root = path41.join(resolveTemplatesDir(), "plugins");
76612
+ if (!fs37.existsSync(root)) return [...PLUGIN_IDS];
76613
+ return fs37.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => PLUGIN_IDS.includes(name));
76317
76614
  }
76318
76615
 
76319
76616
  // src/harness/plugin-drift.ts
76320
76617
  init_stages();
76321
76618
  var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
76322
76619
  function detectInstalledPlugins(repoPath) {
76323
- const resolved = path41.resolve(repoPath);
76324
- const registryPath = path41.join(resolved, ".har", "stages.json");
76325
- if (!fs37.existsSync(registryPath)) return [];
76620
+ const resolved = path42.resolve(repoPath);
76621
+ const registryPath = path42.join(resolved, ".har", "stages.json");
76622
+ if (!fs38.existsSync(registryPath)) return [];
76326
76623
  const registry2 = readStageRegistry(resolved);
76327
76624
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
76328
76625
  const installed = [];
@@ -76335,17 +76632,17 @@ function detectInstalledPlugins(repoPath) {
76335
76632
  return installed;
76336
76633
  }
76337
76634
  function pluginTemplatePath(pluginId, srcRel) {
76338
- return path41.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
76635
+ return path42.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
76339
76636
  }
76340
76637
  function readBundledPluginFile(pluginId, srcRel) {
76341
- return fs37.readFileSync(pluginTemplatePath(pluginId, srcRel), "utf8");
76638
+ return fs38.readFileSync(pluginTemplatePath(pluginId, srcRel), "utf8");
76342
76639
  }
76343
76640
  function listPluginDestPaths(pluginId, repoPath) {
76344
76641
  const manifest = readPluginManifest(pluginId);
76345
76642
  const paths = manifest.files.map((file) => file.dest);
76346
76643
  if (manifest.optionalFiles) {
76347
76644
  for (const file of manifest.optionalFiles) {
76348
- if (fs37.existsSync(path41.join(repoPath, file.dest))) {
76645
+ if (fs38.existsSync(path42.join(repoPath, file.dest))) {
76349
76646
  paths.push(file.dest);
76350
76647
  }
76351
76648
  }
@@ -76404,9 +76701,9 @@ function readTemplatePluginFile(pluginId, dest) {
76404
76701
  return null;
76405
76702
  }
76406
76703
  function readInstalledPluginFile(repoPath, pluginId, dest) {
76407
- const installedPath = path41.join(path41.resolve(repoPath), dest);
76408
- if (!fs37.existsSync(installedPath)) return null;
76409
- const content = fs37.readFileSync(installedPath, "utf8");
76704
+ const installedPath = path42.join(path42.resolve(repoPath), dest);
76705
+ if (!fs38.existsSync(installedPath)) return null;
76706
+ const content = fs38.readFileSync(installedPath, "utf8");
76410
76707
  const manifest = readPluginManifest(pluginId);
76411
76708
  const fragmentRel = manifest.merge?.[dest];
76412
76709
  if (fragmentRel) {
@@ -76425,7 +76722,7 @@ function pluginActionHint(pluginId, dest, kind2) {
76425
76722
  }
76426
76723
  function comparePluginToTemplate(repoPath, pluginId) {
76427
76724
  const manifest = readPluginManifest(pluginId);
76428
- const resolved = path41.resolve(repoPath);
76725
+ const resolved = path42.resolve(repoPath);
76429
76726
  const destPaths = listPluginDestPaths(pluginId, resolved);
76430
76727
  const missing = [];
76431
76728
  const checksumMismatch = [];
@@ -76440,8 +76737,8 @@ function comparePluginToTemplate(repoPath, pluginId) {
76440
76737
  }
76441
76738
  if (dest === "package.json") {
76442
76739
  const fragmentRel = manifest.merge?.[dest];
76443
- const installedPath = path41.join(resolved, dest);
76444
- const installedRaw = fs37.readFileSync(installedPath, "utf8");
76740
+ const installedPath = path42.join(resolved, dest);
76741
+ const installedRaw = fs38.readFileSync(installedPath, "utf8");
76445
76742
  if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
76446
76743
  unchanged.push(dest);
76447
76744
  } else if (computeFileChecksum(installedContent) === computeFileChecksum(templateContent)) {
@@ -76510,14 +76807,14 @@ function substituteProjectName2(content, projectName) {
76510
76807
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
76511
76808
  }
76512
76809
  function projectNameFromRepo(repoPath) {
76513
- return path42.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
76810
+ return path43.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
76514
76811
  }
76515
76812
  function boilerplateDirForProfile(profile) {
76516
- return path42.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
76813
+ return path43.join(resolveTemplatesDir(), PROFILE_DIRS3[profile]);
76517
76814
  }
76518
76815
  function readBundledTemplateContent(repoPath, profile, file) {
76519
- const templatePath = path42.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
76520
- let content = fs38.readFileSync(templatePath, "utf8");
76816
+ const templatePath = path43.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
76817
+ let content = fs39.readFileSync(templatePath, "utf8");
76521
76818
  if (file === "harness.env") {
76522
76819
  content = substituteProjectName2(content, projectNameFromRepo(repoPath));
76523
76820
  }
@@ -76548,12 +76845,12 @@ function actionHint(file, kind2) {
76548
76845
  return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
76549
76846
  }
76550
76847
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
76551
- const tmpDir = fs38.mkdtempSync(path42.join(os13.tmpdir(), "har-maintain-diff-"));
76848
+ const tmpDir = fs39.mkdtempSync(path43.join(os14.tmpdir(), "har-maintain-diff-"));
76552
76849
  try {
76553
- const installedPath = path42.join(tmpDir, "installed");
76554
- const templatePath = path42.join(tmpDir, "template");
76555
- fs38.writeFileSync(installedPath, installedContent);
76556
- fs38.writeFileSync(templatePath, templateContent);
76850
+ const installedPath = path43.join(tmpDir, "installed");
76851
+ const templatePath = path43.join(tmpDir, "template");
76852
+ fs39.writeFileSync(installedPath, installedContent);
76853
+ fs39.writeFileSync(templatePath, templateContent);
76557
76854
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
76558
76855
  const body = result.stdout.trim();
76559
76856
  if (!body) return "";
@@ -76562,7 +76859,7 @@ function createUnifiedDiff(installedContent, templateContent, installedLabel, te
76562
76859
  ${body.split("\n").slice(2).join("\n")}
76563
76860
  `;
76564
76861
  } finally {
76565
- fs38.rmSync(tmpDir, { recursive: true, force: true });
76862
+ fs39.rmSync(tmpDir, { recursive: true, force: true });
76566
76863
  }
76567
76864
  }
76568
76865
  function buildActions(repoPath, profile, drift) {
@@ -76577,7 +76874,7 @@ function buildActions(repoPath, profile, drift) {
76577
76874
  });
76578
76875
  }
76579
76876
  for (const file of drift.checksumMismatch) {
76580
- const installedPath = path42.join(harnessDir, file);
76877
+ const installedPath = path43.join(harnessDir, file);
76581
76878
  const installedRel = `maintain/installed/${file}`;
76582
76879
  const templateRel = `maintain/templates/${file}`;
76583
76880
  const diffRel = `maintain/diffs/${file}.diff`;
@@ -76585,7 +76882,7 @@ function buildActions(repoPath, profile, drift) {
76585
76882
  file,
76586
76883
  kind: "drift",
76587
76884
  template: templateRel,
76588
- installed: fs38.existsSync(installedPath) ? installedRel : void 0,
76885
+ installed: fs39.existsSync(installedPath) ? installedRel : void 0,
76589
76886
  diff: diffRel,
76590
76887
  hint: actionHint(file, "drift")
76591
76888
  });
@@ -76595,6 +76892,44 @@ function buildActions(repoPath, profile, drift) {
76595
76892
  function buildStale(drift) {
76596
76893
  return drift.extra.map((file) => ({ file, hint: staleFileHint(file) })).sort((a2, b3) => a2.file.localeCompare(b3.file));
76597
76894
  }
76895
+ function buildInstructionFileNotes(repoPath) {
76896
+ const detection = detectInstructionFiles(repoPath);
76897
+ const notes = [];
76898
+ if (detection.agentMd) {
76899
+ notes.push({
76900
+ kind: "migrate_legacy_agent_md",
76901
+ path: "AGENT.md",
76902
+ message: "Legacy AGENT.md (singular) found \u2014 merge unique notes into AGENTS.md, then delete AGENT.md. Codex auto-loads AGENTS.md only."
76903
+ });
76904
+ }
76905
+ if (!detection.agentsMd) {
76906
+ notes.push({
76907
+ kind: "create_agents_md",
76908
+ path: "AGENTS.md",
76909
+ message: "AGENTS.md missing \u2014 create it with a HAR / agent environment section (or let maintain\u2019s instruction-files step scaffold it, then fill project-specific notes)."
76910
+ });
76911
+ } else {
76912
+ notes.push({
76913
+ kind: "refresh_agents_md_har_section",
76914
+ path: "AGENTS.md",
76915
+ message: "Refresh the managed HAR / agent environment section in AGENTS.md if workflow/commands changed \u2014 do not wipe unrelated project guidance."
76916
+ });
76917
+ }
76918
+ if (detection.claudeMd) {
76919
+ notes.push({
76920
+ kind: "claude_md_pointer",
76921
+ path: "CLAUDE.md",
76922
+ message: "Keep CLAUDE.md as a thin pointer to AGENTS.md (do not duplicate the full HAR workflow)."
76923
+ });
76924
+ } else {
76925
+ notes.push({
76926
+ kind: "claude_md_pointer",
76927
+ path: "CLAUDE.md",
76928
+ message: "Optional: add a thin CLAUDE.md pointer \u2192 AGENTS.md when Claude Code is used on this repo."
76929
+ });
76930
+ }
76931
+ return notes;
76932
+ }
76598
76933
  function buildReadme(report) {
76599
76934
  const lines2 = [
76600
76935
  "# Harness maintenance bundle",
@@ -76662,6 +76997,16 @@ function buildReadme(report) {
76662
76997
  ""
76663
76998
  );
76664
76999
  }
77000
+ if (report.instructionFiles.length > 0) {
77001
+ lines2.push("", "## Agent instruction files (generator 0.5.0)", "");
77002
+ lines2.push(
77003
+ "Repo-root agent docs are **outside** `.har/` checksum drift. Apply while adapting:",
77004
+ ""
77005
+ );
77006
+ for (const note of report.instructionFiles) {
77007
+ lines2.push(`- **\`${note.path}\`** (${note.kind}): ${note.message}`);
77008
+ }
77009
+ }
76665
77010
  lines2.push("", "## Stale files (review)", "");
76666
77011
  if (report.stale.length === 0) {
76667
77012
  lines2.push("None detected.");
@@ -76685,28 +77030,28 @@ function buildReadme(report) {
76685
77030
  }
76686
77031
  function writeBundleArtifacts(repoPath, profile, drift, report) {
76687
77032
  const harnessDir = getHarnessDir(repoPath);
76688
- const bundleDir = path42.join(harnessDir, MAINTAIN_DIR);
76689
- if (fs38.existsSync(bundleDir)) {
76690
- fs38.rmSync(bundleDir, { recursive: true, force: true });
77033
+ const bundleDir = path43.join(harnessDir, MAINTAIN_DIR);
77034
+ if (fs39.existsSync(bundleDir)) {
77035
+ fs39.rmSync(bundleDir, { recursive: true, force: true });
76691
77036
  }
76692
77037
  const dirs = [
76693
77038
  bundleDir,
76694
- path42.join(bundleDir, "templates"),
76695
- path42.join(bundleDir, "installed"),
76696
- path42.join(bundleDir, "diffs"),
76697
- path42.join(bundleDir, "stale")
77039
+ path43.join(bundleDir, "templates"),
77040
+ path43.join(bundleDir, "installed"),
77041
+ path43.join(bundleDir, "diffs"),
77042
+ path43.join(bundleDir, "stale")
76698
77043
  ];
76699
77044
  for (const dir of dirs) {
76700
- fs38.mkdirSync(dir, { recursive: true });
77045
+ fs39.mkdirSync(dir, { recursive: true });
76701
77046
  }
76702
77047
  const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
76703
77048
  for (const file of affectedFiles) {
76704
77049
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
76705
- writeFileSafe(path42.join(bundleDir, "templates", file), templateContent);
76706
- const harnessPath = path42.join(harnessDir, file);
76707
- if (fs38.existsSync(harnessPath)) {
76708
- const installedContent = fs38.readFileSync(harnessPath, "utf8");
76709
- writeFileSafe(path42.join(bundleDir, "installed", file), installedContent);
77050
+ writeFileSafe(path43.join(bundleDir, "templates", file), templateContent);
77051
+ const harnessPath = path43.join(harnessDir, file);
77052
+ if (fs39.existsSync(harnessPath)) {
77053
+ const installedContent = fs39.readFileSync(harnessPath, "utf8");
77054
+ writeFileSafe(path43.join(bundleDir, "installed", file), installedContent);
76710
77055
  const diff = createUnifiedDiff(
76711
77056
  installedContent,
76712
77057
  templateContent,
@@ -76714,14 +77059,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
76714
77059
  `templates/${file}`
76715
77060
  );
76716
77061
  if (diff) {
76717
- writeFileSafe(path42.join(bundleDir, "diffs", `${file}.diff`), diff);
77062
+ writeFileSafe(path43.join(bundleDir, "diffs", `${file}.diff`), diff);
76718
77063
  }
76719
77064
  }
76720
77065
  }
76721
- writeFileSafe(path42.join(bundleDir, "README.md"), buildReadme(report));
76722
- writeFileSafe(path42.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
77066
+ writeFileSafe(path43.join(bundleDir, "README.md"), buildReadme(report));
77067
+ writeFileSafe(path43.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
76723
77068
  writeFileSafe(
76724
- path42.join(bundleDir, "validation.json"),
77069
+ path43.join(bundleDir, "validation.json"),
76725
77070
  JSON.stringify(report.validation, null, 2) + "\n"
76726
77071
  );
76727
77072
  if (report.stale.length > 0) {
@@ -76733,34 +77078,34 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
76733
77078
  ...report.stale.map((s2) => `- **${s2.file}** \u2014 ${s2.hint}`),
76734
77079
  ""
76735
77080
  ];
76736
- writeFileSafe(path42.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
77081
+ writeFileSafe(path43.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
76737
77082
  }
76738
77083
  return bundleDir;
76739
77084
  }
76740
77085
  function ensureParentDir2(filePath) {
76741
- const parent = path42.dirname(filePath);
76742
- if (!fs38.existsSync(parent)) {
76743
- fs38.mkdirSync(parent, { recursive: true });
77086
+ const parent = path43.dirname(filePath);
77087
+ if (!fs39.existsSync(parent)) {
77088
+ fs39.mkdirSync(parent, { recursive: true });
76744
77089
  }
76745
77090
  }
76746
77091
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
76747
77092
  if (report.pluginActions.length === 0) return;
76748
77093
  for (const action of report.pluginActions) {
76749
- const pluginRoot = path42.join(bundleDir, "plugins", action.pluginId);
76750
- const templatesDir = path42.join(pluginRoot, "templates");
76751
- const installedDir = path42.join(pluginRoot, "installed");
76752
- const diffsDir = path42.join(pluginRoot, "diffs");
77094
+ const pluginRoot = path43.join(bundleDir, "plugins", action.pluginId);
77095
+ const templatesDir = path43.join(pluginRoot, "templates");
77096
+ const installedDir = path43.join(pluginRoot, "installed");
77097
+ const diffsDir = path43.join(pluginRoot, "diffs");
76753
77098
  for (const dir of [templatesDir, installedDir, diffsDir]) {
76754
- fs38.mkdirSync(dir, { recursive: true });
77099
+ fs39.mkdirSync(dir, { recursive: true });
76755
77100
  }
76756
77101
  const templateContent = readTemplatePluginFile(action.pluginId, action.file);
76757
77102
  if (templateContent === null) continue;
76758
- const templatePath = path42.join(templatesDir, action.file);
77103
+ const templatePath = path43.join(templatesDir, action.file);
76759
77104
  ensureParentDir2(templatePath);
76760
77105
  writeFileSafe(templatePath, templateContent);
76761
77106
  const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
76762
77107
  if (installedContent !== null) {
76763
- const installedPath = path42.join(installedDir, action.file);
77108
+ const installedPath = path43.join(installedDir, action.file);
76764
77109
  ensureParentDir2(installedPath);
76765
77110
  writeFileSafe(installedPath, installedContent);
76766
77111
  const diff = createUnifiedDiff(
@@ -76770,7 +77115,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
76770
77115
  `templates/${action.file}`
76771
77116
  );
76772
77117
  if (diff) {
76773
- const diffPath = path42.join(diffsDir, `${action.file}.diff`);
77118
+ const diffPath = path43.join(diffsDir, `${action.file}.diff`);
76774
77119
  ensureParentDir2(diffPath);
76775
77120
  writeFileSafe(diffPath, diff);
76776
77121
  }
@@ -76794,6 +77139,7 @@ function buildMaintainBundle(repoPath, validation2, drift) {
76794
77139
  stale: buildStale(drift),
76795
77140
  missingPortVars: drift.missingPortVars,
76796
77141
  agentSlotMismatch: drift.agentSlotMismatch,
77142
+ instructionFiles: buildInstructionFileNotes(repoPath),
76797
77143
  validation: {
76798
77144
  pass: validation2.pass,
76799
77145
  errors,
@@ -76805,9 +77151,9 @@ function buildMaintainBundle(repoPath, validation2, drift) {
76805
77151
  return { bundleDir, report };
76806
77152
  }
76807
77153
  function removeMaintainBundle(repoPath) {
76808
- const bundleDir = path42.join(getHarnessDir(repoPath), MAINTAIN_DIR);
76809
- if (fs38.existsSync(bundleDir)) {
76810
- fs38.rmSync(bundleDir, { recursive: true, force: true });
77154
+ const bundleDir = path43.join(getHarnessDir(repoPath), MAINTAIN_DIR);
77155
+ if (fs39.existsSync(bundleDir)) {
77156
+ fs39.rmSync(bundleDir, { recursive: true, force: true });
76811
77157
  }
76812
77158
  }
76813
77159
  function formatMaintainBundlePromptSection(report) {
@@ -76873,7 +77219,19 @@ function formatMaintainBundlePromptSection(report) {
76873
77219
  ""
76874
77220
  );
76875
77221
  }
76876
- if (report.actions.length === 0 && report.pluginActions.length === 0 && report.stale.length === 0 && report.missingPortVars.length === 0 && !report.agentSlotMismatch && report.validation.errors.length === 0) {
77222
+ if (report.instructionFiles.length > 0) {
77223
+ lines2.push(
77224
+ "### Agent instruction files (generator 0.5.0 \u2014 outside `.har/` drift)",
77225
+ "",
77226
+ "These are **not** checksum drift rows. Apply them while adapting (HAR also migrates/scaffolds on maintain):",
77227
+ ""
77228
+ );
77229
+ for (const note of report.instructionFiles) {
77230
+ lines2.push(`- **\`${note.path}\`** (${note.kind}): ${note.message}`);
77231
+ }
77232
+ lines2.push("");
77233
+ }
77234
+ if (report.actions.length === 0 && report.pluginActions.length === 0 && report.stale.length === 0 && report.missingPortVars.length === 0 && !report.agentSlotMismatch && report.validation.errors.length === 0 && report.instructionFiles.length === 0) {
76877
77235
  lines2.push("No template drift detected. Review repo stack changes manually if needed.", "");
76878
77236
  }
76879
77237
  return lines2.join("\n");
@@ -76885,11 +77243,11 @@ init_stages();
76885
77243
  init_validation();
76886
77244
  function listHarnessScripts(repoPath) {
76887
77245
  const harnessDir = getHarnessDir(repoPath);
76888
- if (!fs39.existsSync(harnessDir)) return [];
76889
- return fs39.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
77246
+ if (!fs40.existsSync(harnessDir)) return [];
77247
+ return fs40.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
76890
77248
  }
76891
77249
  function describeProject(repoPath) {
76892
- const resolved = path43.resolve(repoPath);
77250
+ const resolved = path44.resolve(repoPath);
76893
77251
  const manifest = readManifest(resolved);
76894
77252
  const present = harnessExists(resolved);
76895
77253
  return {
@@ -76909,8 +77267,8 @@ function describeProject(repoPath) {
76909
77267
  };
76910
77268
  }
76911
77269
  async function initHarness(options) {
76912
- const repoPath = path43.resolve(options.repoPath);
76913
- if (!fs39.existsSync(repoPath)) {
77270
+ const repoPath = path44.resolve(options.repoPath);
77271
+ if (!fs40.existsSync(repoPath)) {
76914
77272
  throw new Error(`Path not found: ${repoPath}`);
76915
77273
  }
76916
77274
  const scaffold = scaffoldHarnessBoilerplate(repoPath, {
@@ -76942,9 +77300,9 @@ async function initHarness(options) {
76942
77300
  };
76943
77301
  }
76944
77302
  async function maintainHarness(options) {
76945
- const repoPath = path43.resolve(options.repoPath);
77303
+ const repoPath = path44.resolve(options.repoPath);
76946
77304
  const harnessDir = getHarnessDir(repoPath);
76947
- if (!fs39.existsSync(harnessDir)) {
77305
+ if (!fs40.existsSync(harnessDir)) {
76948
77306
  throw new Error('No .har/ found. Run "har env init" first.');
76949
77307
  }
76950
77308
  if (options.auto) {
@@ -76996,13 +77354,13 @@ function addPlugin(repoPath, pluginId, options = {}) {
76996
77354
  }
76997
77355
 
76998
77356
  // src/harness/custom-stage.ts
76999
- var fs40 = __toESM(require("fs"));
77000
- var path44 = __toESM(require("path"));
77357
+ var fs41 = __toESM(require("fs"));
77358
+ var path45 = __toESM(require("path"));
77001
77359
  init_schema2();
77002
77360
  init_stages();
77003
77361
  var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
77004
77362
  function addCustomStage(repoPath, options) {
77005
- const resolved = path44.resolve(repoPath);
77363
+ const resolved = path45.resolve(repoPath);
77006
77364
  if (!harnessExists(resolved)) {
77007
77365
  throw new Error('No .har/ harness found. Run "har env init" first.');
77008
77366
  }
@@ -77039,20 +77397,20 @@ function addCustomStage(repoPath, options) {
77039
77397
  if (options.command) {
77040
77398
  stage.command = options.command;
77041
77399
  } else {
77042
- const scriptRel = path44.join("stages", `${id}.sh`);
77043
- const scriptAbs = path44.join(resolved, ".har", scriptRel);
77044
- if (fs40.existsSync(scriptAbs) && !options.force) {
77400
+ const scriptRel = path45.join("stages", `${id}.sh`);
77401
+ const scriptAbs = path45.join(resolved, ".har", scriptRel);
77402
+ if (fs41.existsSync(scriptAbs) && !options.force) {
77045
77403
  throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
77046
77404
  }
77047
- const skeletonPath = path44.join(
77405
+ const skeletonPath = path45.join(
77048
77406
  resolveTemplatesDir(),
77049
77407
  "plugins",
77050
77408
  "custom-stage-skeleton.sh"
77051
77409
  );
77052
- const skeleton = fs40.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind2).replace(/__STAGE_DESCRIPTION__/g, stage.description);
77053
- fs40.mkdirSync(path44.dirname(scriptAbs), { recursive: true });
77054
- fs40.writeFileSync(scriptAbs, skeleton);
77055
- fs40.chmodSync(scriptAbs, 493);
77410
+ const skeleton = fs41.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind2).replace(/__STAGE_DESCRIPTION__/g, stage.description);
77411
+ fs41.mkdirSync(path45.dirname(scriptAbs), { recursive: true });
77412
+ fs41.writeFileSync(scriptAbs, skeleton);
77413
+ fs41.chmodSync(scriptAbs, 493);
77056
77414
  filesWritten.push(`.har/${scriptRel}`);
77057
77415
  stage.script = scriptRel;
77058
77416
  stage.artifacts = [
@@ -77100,9 +77458,9 @@ function addCustomStage(repoPath, options) {
77100
77458
  }
77101
77459
 
77102
77460
  // src/harness/adaptation-prompt.ts
77103
- var fs41 = __toESM(require("fs"));
77104
- var path45 = __toESM(require("path"));
77105
- var readline4 = __toESM(require("readline"));
77461
+ var fs42 = __toESM(require("fs"));
77462
+ var path46 = __toESM(require("path"));
77463
+ var readline5 = __toESM(require("readline"));
77106
77464
 
77107
77465
  // src/utils/clipboard.ts
77108
77466
  var import_child_process8 = require("child_process");
@@ -77191,7 +77549,7 @@ function loadTemplate(name) {
77191
77549
  if (!filePath) {
77192
77550
  throw new Error(`Adaptation prompt template not found: ${name}. Run npm run build.`);
77193
77551
  }
77194
- return fs41.readFileSync(filePath, "utf8");
77552
+ return fs42.readFileSync(filePath, "utf8");
77195
77553
  }
77196
77554
  function applyProfilePlaceholders(content, profile) {
77197
77555
  return content.replace(/\{\{PROFILE\}\}/g, profile).replace(/\{\{PROFILE_HINT\}\}/g, PROFILE_HINTS[profile]);
@@ -77213,7 +77571,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
77213
77571
  }
77214
77572
  function writeAdaptationPrompt(repoPath, content) {
77215
77573
  const harnessDir = getHarnessDir(repoPath);
77216
- const filePath = path45.join(harnessDir, ADAPTATION_PROMPT_FILE);
77574
+ const filePath = path46.join(harnessDir, ADAPTATION_PROMPT_FILE);
77217
77575
  writeFileSafe(filePath, content);
77218
77576
  return filePath;
77219
77577
  }
@@ -77230,8 +77588,8 @@ function printAdaptationPrompt(content) {
77230
77588
  `);
77231
77589
  process.stderr.write("\n");
77232
77590
  }
77233
- function askYesNo3(question) {
77234
- const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
77591
+ function askYesNo4(question) {
77592
+ const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
77235
77593
  return new Promise((resolve47) => {
77236
77594
  process.stderr.write(`${question} `);
77237
77595
  rl.once("line", (answer) => {
@@ -77249,7 +77607,7 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
77249
77607
  }
77250
77608
  let shouldCopy = options.autoYes === true;
77251
77609
  if (!shouldCopy && interactive) {
77252
- shouldCopy = await askYesNo3("Copy adaptation prompt to clipboard for your coding agent? [Y/n]");
77610
+ shouldCopy = await askYesNo4("Copy adaptation prompt to clipboard for your coding agent? [Y/n]");
77253
77611
  }
77254
77612
  if (!shouldCopy) {
77255
77613
  info("Skipped clipboard copy \u2014 prompt is in .har/ADAPT-PROMPT.md");
@@ -77268,27 +77626,27 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
77268
77626
  }
77269
77627
 
77270
77628
  // src/harness/cursor-rule.ts
77271
- var fs42 = __toESM(require("fs"));
77272
- var path46 = __toESM(require("path"));
77273
- var readline5 = __toESM(require("readline"));
77629
+ var fs43 = __toESM(require("fs"));
77630
+ var path47 = __toESM(require("path"));
77631
+ var readline6 = __toESM(require("readline"));
77274
77632
  init_file_ops();
77275
77633
  init_logging();
77276
77634
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
77277
77635
  function getCursorRulePath(repoPath) {
77278
- return path46.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
77636
+ return path47.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
77279
77637
  }
77280
77638
  function isCursorWorkspace(repoPath) {
77281
- return fs42.existsSync(path46.join(repoPath, ".cursor"));
77639
+ return fs43.existsSync(path47.join(repoPath, ".cursor"));
77282
77640
  }
77283
77641
  function cursorRuleExists(repoPath) {
77284
- return fs42.existsSync(getCursorRulePath(repoPath));
77642
+ return fs43.existsSync(getCursorRulePath(repoPath));
77285
77643
  }
77286
77644
  function scaffoldCursorRule(repoPath) {
77287
77645
  const templatePath = resolveTemplateFile("cursor-rule.mdc.template");
77288
77646
  if (!templatePath) {
77289
77647
  throw new Error("Cursor rule template not found (cursor-rule.mdc.template). Run npm run build.");
77290
77648
  }
77291
- const content = fs42.readFileSync(templatePath, "utf8");
77649
+ const content = fs43.readFileSync(templatePath, "utf8");
77292
77650
  writeFileSafe(getCursorRulePath(repoPath), content);
77293
77651
  }
77294
77652
  async function handleCursorRule(options) {
@@ -77322,10 +77680,10 @@ async function handleCursorRule(options) {
77322
77680
  }
77323
77681
  async function promptScaffoldCursorRule(exists) {
77324
77682
  const action = exists ? "Update" : "Create";
77325
- return askYesNo4(`${action} ${CURSOR_RULE_RELATIVE_PATH}? [Y/n]`);
77683
+ return askYesNo5(`${action} ${CURSOR_RULE_RELATIVE_PATH}? [Y/n]`);
77326
77684
  }
77327
- async function askYesNo4(question) {
77328
- const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
77685
+ async function askYesNo5(question) {
77686
+ const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
77329
77687
  return new Promise((resolve47) => {
77330
77688
  process.stderr.write(`${question} `);
77331
77689
  rl.once("line", (answer) => {
@@ -77378,7 +77736,7 @@ init_control_config();
77378
77736
 
77379
77737
  // src/core/control-lifecycle.ts
77380
77738
  var import_child_process9 = require("child_process");
77381
- var path47 = __toESM(require("path"));
77739
+ var path48 = __toESM(require("path"));
77382
77740
 
77383
77741
  // src/core/control-image.ts
77384
77742
  var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
@@ -77404,10 +77762,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
77404
77762
  var CONTROL_CONTAINER_PORT = 3847;
77405
77763
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
77406
77764
  function resolveControlDir() {
77407
- return path47.resolve(__dirname, "..", "control");
77765
+ return path48.resolve(__dirname, "..", "control");
77408
77766
  }
77409
77767
  function resolveControlBuildContext() {
77410
- return path47.resolve(resolveControlDir(), "..");
77768
+ return path48.resolve(resolveControlDir(), "..");
77411
77769
  }
77412
77770
  function buildDockerRunArgs(options) {
77413
77771
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -77463,7 +77821,7 @@ async function startMissionControl(options) {
77463
77821
  "-t",
77464
77822
  imageRef,
77465
77823
  "-f",
77466
- path47.join(resolveControlDir(), "Dockerfile"),
77824
+ path48.join(resolveControlDir(), "Dockerfile"),
77467
77825
  resolveControlBuildContext()
77468
77826
  ]);
77469
77827
  if (buildCode !== 0) {
@@ -77610,7 +77968,7 @@ async function ensureTelemetryInfrastructure(options) {
77610
77968
  // src/core/run-service.ts
77611
77969
  init_telemetry_config();
77612
77970
  init_telemetry_env();
77613
- var path49 = __toESM(require("path"));
77971
+ var path50 = __toESM(require("path"));
77614
77972
  init_local_executor();
77615
77973
  function extractShellOutput(result) {
77616
77974
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
@@ -77813,12 +78171,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
77813
78171
  suffix: session.suffix,
77814
78172
  createdAt: session.createdAt
77815
78173
  });
77816
- const envFile = path49.join(session.workDir, `.env.agent.${options.agentId}`);
78174
+ const envFile = path50.join(session.workDir, `.env.agent.${options.agentId}`);
77817
78175
  try {
77818
78176
  appendTelemetryEnvToFile(envFile, {
77819
78177
  sessionKey,
77820
78178
  agentId: options.agentId,
77821
- repoPath: path49.resolve(options.repoPath),
78179
+ repoPath: path50.resolve(options.repoPath),
77822
78180
  workDir: session.workDir,
77823
78181
  branch: session.branch,
77824
78182
  suffix: session.suffix,
@@ -78053,12 +78411,12 @@ init_runs();
78053
78411
  init_slot_status();
78054
78412
 
78055
78413
  // src/core/commit-gate-onboarding.ts
78056
- var readline6 = __toESM(require("readline"));
78414
+ var readline7 = __toESM(require("readline"));
78057
78415
 
78058
78416
  // src/core/hooks.ts
78059
- var fs44 = __toESM(require("fs"));
78060
- var os15 = __toESM(require("os"));
78061
- var path50 = __toESM(require("path"));
78417
+ var fs45 = __toESM(require("fs"));
78418
+ var os16 = __toESM(require("os"));
78419
+ var path51 = __toESM(require("path"));
78062
78420
  init_shell();
78063
78421
  init_schema2();
78064
78422
  init_stages();
@@ -78089,7 +78447,7 @@ function resolveCheckoutRoot(cwd) {
78089
78447
  function resolveHooksDir(checkoutDir) {
78090
78448
  const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
78091
78449
  if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
78092
- return path50.resolve(checkoutDir, hooksPath);
78450
+ return path51.resolve(checkoutDir, hooksPath);
78093
78451
  }
78094
78452
  function getConfiguredHooksPath(checkoutDir) {
78095
78453
  return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
@@ -78097,9 +78455,9 @@ function getConfiguredHooksPath(checkoutDir) {
78097
78455
  function defaultHarInvocation() {
78098
78456
  const entry = process.argv[1];
78099
78457
  if (entry && entry.endsWith(".js")) {
78100
- return `"${process.execPath}" "${path50.resolve(entry)}"`;
78458
+ return `"${process.execPath}" "${path51.resolve(entry)}"`;
78101
78459
  }
78102
- if (entry) return `"${path50.resolve(entry)}"`;
78460
+ if (entry) return `"${path51.resolve(entry)}"`;
78103
78461
  return "har";
78104
78462
  }
78105
78463
  function buildHookScript(harInvocation, subcommand, failOpenNotice) {
@@ -78119,45 +78477,45 @@ echo "${failOpenNotice}" >&2
78119
78477
  exit 0
78120
78478
  `;
78121
78479
  }
78122
- function upsertMarkedBlock(filePath, block) {
78123
- if (!fs44.existsSync(filePath)) {
78124
- fs44.writeFileSync(filePath, `#!/bin/sh
78480
+ function upsertMarkedBlock2(filePath, block) {
78481
+ if (!fs45.existsSync(filePath)) {
78482
+ fs45.writeFileSync(filePath, `#!/bin/sh
78125
78483
  ${block}
78126
78484
  `, { mode: 493 });
78127
78485
  return "created";
78128
78486
  }
78129
- const content = fs44.readFileSync(filePath, "utf8");
78487
+ const content = fs45.readFileSync(filePath, "utf8");
78130
78488
  if (content.includes(MARKER_START)) {
78131
78489
  const pattern = new RegExp(
78132
- `${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
78490
+ `${escapeRegExp2(MARKER_START)}[\\s\\S]*?${escapeRegExp2(MARKER_END)}`
78133
78491
  );
78134
- fs44.writeFileSync(filePath, content.replace(pattern, block));
78135
- fs44.chmodSync(filePath, 493);
78492
+ fs45.writeFileSync(filePath, content.replace(pattern, block));
78493
+ fs45.chmodSync(filePath, 493);
78136
78494
  return "updated";
78137
78495
  }
78138
78496
  const suffix = content.endsWith("\n") ? "" : "\n";
78139
- fs44.writeFileSync(filePath, `${content}${suffix}
78497
+ fs45.writeFileSync(filePath, `${content}${suffix}
78140
78498
  ${block}
78141
78499
  `);
78142
- fs44.chmodSync(filePath, 493);
78500
+ fs45.chmodSync(filePath, 493);
78143
78501
  return "appended";
78144
78502
  }
78145
78503
  function removeMarkedBlock(filePath) {
78146
- if (!fs44.existsSync(filePath)) return false;
78147
- const content = fs44.readFileSync(filePath, "utf8");
78504
+ if (!fs45.existsSync(filePath)) return false;
78505
+ const content = fs45.readFileSync(filePath, "utf8");
78148
78506
  if (!content.includes(MARKER_START)) return false;
78149
78507
  const pattern = new RegExp(
78150
- `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
78508
+ `\\n?${escapeRegExp2(MARKER_START)}[\\s\\S]*?${escapeRegExp2(MARKER_END)}\\n?`
78151
78509
  );
78152
78510
  const stripped = content.replace(pattern, "\n");
78153
78511
  if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
78154
- fs44.rmSync(filePath);
78512
+ fs45.rmSync(filePath);
78155
78513
  } else {
78156
- fs44.writeFileSync(filePath, stripped);
78514
+ fs45.writeFileSync(filePath, stripped);
78157
78515
  }
78158
78516
  return true;
78159
78517
  }
78160
- function escapeRegExp(value) {
78518
+ function escapeRegExp2(value) {
78161
78519
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
78162
78520
  }
78163
78521
  function installHooks(options) {
@@ -78175,20 +78533,20 @@ Or re-run with --force to write into that directory anyway.`
78175
78533
  );
78176
78534
  }
78177
78535
  const hooksDir = resolveHooksDir(checkout);
78178
- fs44.mkdirSync(hooksDir, { recursive: true });
78536
+ fs45.mkdirSync(hooksDir, { recursive: true });
78179
78537
  const invocation = options.harInvocation ?? defaultHarInvocation();
78180
- fs44.writeFileSync(
78181
- path50.join(hooksDir, "har-pre-commit"),
78538
+ fs45.writeFileSync(
78539
+ path51.join(hooksDir, "har-pre-commit"),
78182
78540
  buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
78183
78541
  { mode: 493 }
78184
78542
  );
78185
- fs44.writeFileSync(
78186
- path50.join(hooksDir, "har-post-commit"),
78543
+ fs45.writeFileSync(
78544
+ path51.join(hooksDir, "har-post-commit"),
78187
78545
  buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
78188
78546
  { mode: 493 }
78189
78547
  );
78190
- const preCommit = upsertMarkedBlock(path50.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
78191
- const postCommit = upsertMarkedBlock(path50.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
78548
+ const preCommit = upsertMarkedBlock2(path51.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
78549
+ const postCommit = upsertMarkedBlock2(path51.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
78192
78550
  ensureValidationsIgnored(checkout);
78193
78551
  return { hooksDir, preCommit, postCommit };
78194
78552
  }
@@ -78197,12 +78555,12 @@ function uninstallHooks(repoPath) {
78197
78555
  if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
78198
78556
  const hooksDir = resolveHooksDir(checkout);
78199
78557
  let removed = false;
78200
- removed = removeMarkedBlock(path50.join(hooksDir, "pre-commit")) || removed;
78201
- removed = removeMarkedBlock(path50.join(hooksDir, "post-commit")) || removed;
78558
+ removed = removeMarkedBlock(path51.join(hooksDir, "pre-commit")) || removed;
78559
+ removed = removeMarkedBlock(path51.join(hooksDir, "post-commit")) || removed;
78202
78560
  for (const file of ["har-pre-commit", "har-post-commit"]) {
78203
- const full = path50.join(hooksDir, file);
78204
- if (fs44.existsSync(full)) {
78205
- fs44.rmSync(full);
78561
+ const full = path51.join(hooksDir, file);
78562
+ if (fs45.existsSync(full)) {
78563
+ fs45.rmSync(full);
78206
78564
  removed = true;
78207
78565
  }
78208
78566
  }
@@ -78221,10 +78579,10 @@ function isAgentWorktree(checkoutDir) {
78221
78579
  if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
78222
78580
  return true;
78223
78581
  }
78224
- const worktreesRoot = path50.join(os15.homedir(), "worktrees");
78225
- const resolved = path50.resolve(checkoutDir);
78226
- const name = path50.basename(resolved);
78227
- return resolved.startsWith(`${worktreesRoot}${path50.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
78582
+ const worktreesRoot = path51.join(os16.homedir(), "worktrees");
78583
+ const resolved = path51.resolve(checkoutDir);
78584
+ const name = path51.basename(resolved);
78585
+ return resolved.startsWith(`${worktreesRoot}${path51.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
78228
78586
  }
78229
78587
  function resolveEffectiveMode(checkoutDir, gate) {
78230
78588
  if (!gate.enabled) return "off";
@@ -78237,15 +78595,15 @@ function getHooksStatus(repoPath) {
78237
78595
  const hooksDir = resolveHooksDir(checkout);
78238
78596
  const gate = getCommitGateConfig(checkout);
78239
78597
  const hasBlock = (name) => {
78240
- const file = path50.join(hooksDir, name);
78241
- return fs44.existsSync(file) && fs44.readFileSync(file, "utf8").includes(MARKER_START);
78598
+ const file = path51.join(hooksDir, name);
78599
+ return fs45.existsSync(file) && fs45.readFileSync(file, "utf8").includes(MARKER_START);
78242
78600
  };
78243
78601
  return {
78244
78602
  checkout,
78245
78603
  hooksDir,
78246
78604
  configuredHooksPath: getConfiguredHooksPath(checkout),
78247
- preCommitInstalled: hasBlock("pre-commit") && fs44.existsSync(path50.join(hooksDir, "har-pre-commit")),
78248
- postCommitInstalled: hasBlock("post-commit") && fs44.existsSync(path50.join(hooksDir, "har-post-commit")),
78605
+ preCommitInstalled: hasBlock("pre-commit") && fs45.existsSync(path51.join(hooksDir, "har-pre-commit")),
78606
+ postCommitInstalled: hasBlock("post-commit") && fs45.existsSync(path51.join(hooksDir, "har-post-commit")),
78249
78607
  gate,
78250
78608
  effectiveMode: resolveEffectiveMode(checkout, gate)
78251
78609
  };
@@ -78256,7 +78614,7 @@ function checkCommitGate(cwd) {
78256
78614
  }
78257
78615
  const checkout = resolveCheckoutRoot(cwd);
78258
78616
  if (!checkout) return { exitCode: 0, messages: [] };
78259
- if (!fs44.existsSync(path50.join(checkout, ".har", "stages.json"))) {
78617
+ if (!fs45.existsSync(path51.join(checkout, ".har", "stages.json"))) {
78260
78618
  return { exitCode: 0, messages: [] };
78261
78619
  }
78262
78620
  const gate = getCommitGateConfig(checkout);
@@ -78329,8 +78687,8 @@ async function recordCommitAssociation(cwd) {
78329
78687
  // src/core/commit-gate-onboarding.ts
78330
78688
  init_stages();
78331
78689
  init_logging();
78332
- function askYesNo5(question) {
78333
- const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
78690
+ function askYesNo6(question) {
78691
+ const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
78334
78692
  return new Promise((resolve47) => {
78335
78693
  process.stderr.write(`${question} `);
78336
78694
  rl.once("line", (answer) => {
@@ -78361,7 +78719,7 @@ async function handleCommitGateOnboarding(options) {
78361
78719
  const status = getHooksStatus(options.repoPath);
78362
78720
  let shouldInstall = status.preCommitInstalled || status.postCommitInstalled || options.install === "always" || options.autoYes === true;
78363
78721
  if (!shouldInstall && options.install === "prompt" && process.stdin.isTTY && process.stdout.isTTY) {
78364
- shouldInstall = await askYesNo5("Install the HAR commit gate for this repository? [Y/n]");
78722
+ shouldInstall = await askYesNo6("Install the HAR commit gate for this repository? [Y/n]");
78365
78723
  }
78366
78724
  if (!shouldInstall) {
78367
78725
  info("Commit gate is not installed; run `har hooks install` when ready.");
@@ -78378,21 +78736,21 @@ async function handleCommitGateOnboarding(options) {
78378
78736
  }
78379
78737
 
78380
78738
  // src/core/onboarding-preferences.ts
78381
- var fs45 = __toESM(require("fs"));
78382
- var os16 = __toESM(require("os"));
78383
- var path51 = __toESM(require("path"));
78739
+ var fs46 = __toESM(require("fs"));
78740
+ var os17 = __toESM(require("os"));
78741
+ var path52 = __toESM(require("path"));
78384
78742
  init_schema2();
78385
78743
  function getOnboardingPreferencesPath() {
78386
78744
  if (process.env.HAR_PREFERENCES_PATH) {
78387
- return path51.resolve(process.env.HAR_PREFERENCES_PATH);
78745
+ return path52.resolve(process.env.HAR_PREFERENCES_PATH);
78388
78746
  }
78389
- return path51.join(os16.homedir(), ".har", "preferences.json");
78747
+ return path52.join(os17.homedir(), ".har", "preferences.json");
78390
78748
  }
78391
78749
  function readOnboardingPreferences() {
78392
78750
  const preferencePath = getOnboardingPreferencesPath();
78393
78751
  try {
78394
- if (!fs45.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
78395
- return OnboardingPreferencesSchema.parse(JSON.parse(fs45.readFileSync(preferencePath, "utf8")));
78752
+ if (!fs46.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
78753
+ return OnboardingPreferencesSchema.parse(JSON.parse(fs46.readFileSync(preferencePath, "utf8")));
78396
78754
  } catch {
78397
78755
  return OnboardingPreferencesSchema.parse({});
78398
78756
  }
@@ -78417,8 +78775,8 @@ function writeOnboardingPreferences(overrides) {
78417
78775
  };
78418
78776
  const parsed = OnboardingPreferencesSchema.parse(preference);
78419
78777
  const preferencePath = getOnboardingPreferencesPath();
78420
- fs45.mkdirSync(path51.dirname(preferencePath), { recursive: true });
78421
- fs45.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
78778
+ fs46.mkdirSync(path52.dirname(preferencePath), { recursive: true });
78779
+ fs46.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
78422
78780
  `);
78423
78781
  return parsed;
78424
78782
  }
@@ -78712,7 +79070,7 @@ var envCommand = {
78712
79070
  }
78713
79071
  };
78714
79072
  async function handleInit(argv) {
78715
- const repoPath = path52.resolve(argv.repo);
79073
+ const repoPath = path53.resolve(argv.repo);
78716
79074
  const onboarding = resolveOnboardingOptions(argv);
78717
79075
  header("har env init");
78718
79076
  info(`Repository: ${repoPath}`);
@@ -78755,18 +79113,13 @@ async function handleInit(argv) {
78755
79113
  ...onboarding.commitGate,
78756
79114
  autoYes: argv.yes
78757
79115
  });
78758
- await handleCursorRule({
79116
+ await applyAgentIntegrations({
78759
79117
  repoPath,
78760
- cursorRule: onboarding.cursorRule,
78761
- autoYes: argv.yes,
78762
- mode: "init"
78763
- });
78764
- await handleAgentSkills({
78765
- repoPath,
78766
- ...onboarding.agentSkills,
79118
+ mode: "init",
78767
79119
  autoYes: argv.yes,
78768
79120
  force: argv.force,
78769
- mode: "init"
79121
+ cursorRule: onboarding.cursorRule,
79122
+ ...onboarding.agentSkills
78770
79123
  });
78771
79124
  printNextSteps(argv.auto);
78772
79125
  } catch (err) {
@@ -78775,7 +79128,7 @@ async function handleInit(argv) {
78775
79128
  }
78776
79129
  }
78777
79130
  async function handleMaintain(argv) {
78778
- const repoPath = path52.resolve(argv.repo);
79131
+ const repoPath = path53.resolve(argv.repo);
78779
79132
  const onboarding = resolveOnboardingOptions(argv);
78780
79133
  header("har env maintain");
78781
79134
  info(`Repository: ${repoPath}`);
@@ -78839,17 +79192,12 @@ async function handleMaintain(argv) {
78839
79192
  ...onboarding.commitGate,
78840
79193
  autoYes: argv.yes
78841
79194
  });
78842
- await handleCursorRule({
79195
+ await applyAgentIntegrations({
78843
79196
  repoPath,
78844
- cursorRule: onboarding.cursorRule,
79197
+ mode: "maintain",
78845
79198
  autoYes: argv.yes,
78846
- mode: "maintain"
78847
- });
78848
- await handleAgentSkills({
78849
- repoPath,
78850
- ...onboarding.agentSkills,
78851
- autoYes: argv.yes,
78852
- mode: "maintain"
79199
+ cursorRule: onboarding.cursorRule,
79200
+ ...onboarding.agentSkills
78853
79201
  });
78854
79202
  } catch (err) {
78855
79203
  error(err.message);
@@ -78897,16 +79245,43 @@ async function handleAgentMdProposal(repoPath, autoYes) {
78897
79245
  if (autoYes) {
78898
79246
  const proposal = readAgentMdProposal(repoPath);
78899
79247
  if (proposal) {
78900
- writeFileSafe(path52.join(repoPath, "AGENT.md"), proposal.content);
79248
+ writeFileSafe(path53.join(repoPath, AGENTS_MD), proposal.content);
78901
79249
  clearAgentMdProposal(repoPath);
78902
- info("Applied AGENT.md proposal (--yes)");
79250
+ info(`Applied ${AGENTS_MD} proposal (--yes)`);
78903
79251
  }
78904
79252
  return;
78905
79253
  }
78906
79254
  await promptApplyAgentMdProposal(repoPath);
78907
79255
  }
79256
+ async function applyAgentIntegrations(options) {
79257
+ const instruction = await handleInstructionFiles({
79258
+ repoPath: options.repoPath,
79259
+ agents: options.agents,
79260
+ enabled: options.enabled,
79261
+ cursorRule: options.cursorRule,
79262
+ autoYes: options.autoYes,
79263
+ mode: options.mode
79264
+ });
79265
+ const cursorRuleFlag = options.cursorRule === false ? false : options.cursorRule === true || instruction.plan.cursorRule ? true : false;
79266
+ await handleCursorRule({
79267
+ repoPath: options.repoPath,
79268
+ cursorRule: cursorRuleFlag,
79269
+ autoYes: options.autoYes,
79270
+ mode: options.mode
79271
+ });
79272
+ if (instruction.plan.skills.length > 0) {
79273
+ await handleAgentSkills({
79274
+ repoPath: options.repoPath,
79275
+ agents: instruction.plan.skills.join(","),
79276
+ autoYes: options.autoYes,
79277
+ force: options.force,
79278
+ mode: options.mode
79279
+ });
79280
+ } else if (options.enabled === false) {
79281
+ }
79282
+ }
78908
79283
  async function handleAddPlugin(argv) {
78909
- const repoPath = path52.resolve(argv.repo);
79284
+ const repoPath = path53.resolve(argv.repo);
78910
79285
  const available = listPluginIds();
78911
79286
  if (argv.list) {
78912
79287
  for (const id of available) {
@@ -78944,7 +79319,7 @@ async function handleAddPlugin(argv) {
78944
79319
  }
78945
79320
  }
78946
79321
  async function handleAddStage(argv) {
78947
- const repoPath = path52.resolve(argv.repo);
79322
+ const repoPath = path53.resolve(argv.repo);
78948
79323
  const available = listPluginIds();
78949
79324
  if (argv.list) {
78950
79325
  warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
@@ -79010,7 +79385,7 @@ async function handleAddStage(argv) {
79010
79385
  });
79011
79386
  }
79012
79387
  async function handlePreflight(argv) {
79013
- const repo = path52.resolve(argv.repo);
79388
+ const repo = path53.resolve(argv.repo);
79014
79389
  const agentId = validateAgentId(argv.id, repo);
79015
79390
  const result = await preflightEnvironment({
79016
79391
  repoPath: repo,
@@ -79026,7 +79401,7 @@ async function handlePreflight(argv) {
79026
79401
  return finishCommand(result.code);
79027
79402
  }
79028
79403
  async function handleLaunch(argv) {
79029
- const repo = path52.resolve(argv.repo);
79404
+ const repo = path53.resolve(argv.repo);
79030
79405
  const agentId = validateAgentId(argv.id, repo);
79031
79406
  if (!argv.resume) {
79032
79407
  const guard = checkLaunchGuard2(repo, agentId, {});
@@ -79081,7 +79456,7 @@ async function handleRecover(argv) {
79081
79456
  });
79082
79457
  }
79083
79458
  async function handleVerify(argv) {
79084
- const repo = path52.resolve(argv.repo);
79459
+ const repo = path53.resolve(argv.repo);
79085
79460
  const agentId = validateAgentId(argv.id, repo);
79086
79461
  const result = await runVerification({
79087
79462
  repoPath: repo,
@@ -79093,7 +79468,7 @@ async function handleVerify(argv) {
79093
79468
  return finishCommand(result.code);
79094
79469
  }
79095
79470
  async function handleTeardown(argv) {
79096
- const repo = path52.resolve(argv.repo);
79471
+ const repo = path53.resolve(argv.repo);
79097
79472
  const agentId = validateAgentId(argv.id, repo);
79098
79473
  const result = await teardownEnvironment({
79099
79474
  repoPath: repo,
@@ -79104,7 +79479,7 @@ async function handleTeardown(argv) {
79104
79479
  return finishCommand(result.code);
79105
79480
  }
79106
79481
  async function handleComplete(argv) {
79107
- const repo = path52.resolve(argv.repo);
79482
+ const repo = path53.resolve(argv.repo);
79108
79483
  const agentId = validateAgentId(argv.id, repo);
79109
79484
  const result = await completeEnvironment({
79110
79485
  repoPath: repo,
@@ -79125,7 +79500,7 @@ async function handleComplete(argv) {
79125
79500
  return finishCommand(result.code);
79126
79501
  }
79127
79502
  async function handleStatus(argv) {
79128
- const repoPath = path52.resolve(argv.repo);
79503
+ const repoPath = path53.resolve(argv.repo);
79129
79504
  if (argv.json) {
79130
79505
  const status = collectEnvironmentStatus(repoPath);
79131
79506
  const output = EnvironmentStatusSchema.parse(status);
@@ -79138,7 +79513,7 @@ async function handleStatus(argv) {
79138
79513
  });
79139
79514
  }
79140
79515
  async function handleRunsList(argv) {
79141
- const repoPath = path52.resolve(argv.repo);
79516
+ const repoPath = path53.resolve(argv.repo);
79142
79517
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
79143
79518
  if (argv.json) {
79144
79519
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -79155,7 +79530,7 @@ async function handleRunsList(argv) {
79155
79530
  }
79156
79531
  }
79157
79532
  async function handleRunsGet(argv) {
79158
- const run2 = getRun(path52.resolve(argv.repo), argv.runId);
79533
+ const run2 = getRun(path53.resolve(argv.repo), argv.runId);
79159
79534
  if (!run2) {
79160
79535
  error(`Run not found: ${argv.runId}`);
79161
79536
  return finishCommand(1);
@@ -79230,7 +79605,7 @@ function printNextSteps(auto2) {
79230
79605
  console.error(" Adapt: paste clipboard / prompt above into your coding agent");
79231
79606
  console.error(" Prompt file: .har/ADAPT-PROMPT.md");
79232
79607
  } else {
79233
- console.error(" Agent guide: AGENT.md (repo root, if applied)");
79608
+ console.error(" Agent guide: AGENTS.md (repo root, if applied)");
79234
79609
  }
79235
79610
  console.error(" Setup infra: ./.har/setup-infra.sh # when Docker infra is enabled");
79236
79611
  console.error(" Launch: har env launch 1 # preferred; or ./.har/launch.sh 1");
@@ -79241,7 +79616,7 @@ function printNextSteps(auto2) {
79241
79616
  }
79242
79617
 
79243
79618
  // src/cli/commands/control.ts
79244
- var path56 = __toESM(require("path"));
79619
+ var path57 = __toESM(require("path"));
79245
79620
 
79246
79621
  // node_modules/@inquirer/core/dist/esm/lib/key.mjs
79247
79622
  var isUpKey = (key) => (
@@ -79322,7 +79697,7 @@ function getStore() {
79322
79697
  }
79323
79698
  return store;
79324
79699
  }
79325
- function readline7() {
79700
+ function readline8() {
79326
79701
  return getStore().rl;
79327
79702
  }
79328
79703
  function withUpdates(fn) {
@@ -79367,7 +79742,7 @@ var effectScheduler = {
79367
79742
  const { index } = store;
79368
79743
  store.hooksEffect.push(() => {
79369
79744
  store.hooksCleanup[index]?.();
79370
- const cleanFn = cb(readline7());
79745
+ const cleanFn = cb(readline8());
79371
79746
  if (cleanFn != null && typeof cleanFn !== "function") {
79372
79747
  throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
79373
79748
  }
@@ -79843,7 +80218,7 @@ function breakLines(content, width) {
79843
80218
  return content.split("\n").flatMap((line) => (0, import_wrap_ansi.default)(line, width, { trim: false, hard: true }).split("\n").map((str) => str.trimEnd())).join("\n");
79844
80219
  }
79845
80220
  function readlineWidth() {
79846
- return (0, import_cli_width.default)({ defaultWidth: 80, output: readline7().output });
80221
+ return (0, import_cli_width.default)({ defaultWidth: 80, output: readline8().output });
79847
80222
  }
79848
80223
 
79849
80224
  // node_modules/@inquirer/core/dist/esm/lib/pagination/lines.mjs
@@ -79935,7 +80310,7 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
79935
80310
  }
79936
80311
 
79937
80312
  // node_modules/@inquirer/core/dist/esm/lib/create-prompt.mjs
79938
- var readline8 = __toESM(require("node:readline"), 1);
80313
+ var readline9 = __toESM(require("node:readline"), 1);
79939
80314
  var import_node_async_hooks3 = require("node:async_hooks");
79940
80315
  var import_mute_stream = __toESM(require_lib3(), 1);
79941
80316
 
@@ -80278,7 +80653,7 @@ function createPrompt(view) {
80278
80653
  const cleanups = /* @__PURE__ */ new Set();
80279
80654
  const output = new import_mute_stream.default();
80280
80655
  output.pipe(context.output ?? process.stdout);
80281
- const rl = readline8.createInterface({
80656
+ const rl = readline9.createInterface({
80282
80657
  terminal: true,
80283
80658
  input,
80284
80659
  output
@@ -81295,9 +81670,9 @@ var import_run_async = __toESM(require_run_async(), 1);
81295
81670
  var import_mute_stream2 = __toESM(require_lib3(), 1);
81296
81671
  var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
81297
81672
  var _2 = {
81298
- set: (obj, path63 = "", value) => {
81673
+ set: (obj, path64 = "", value) => {
81299
81674
  let pointer = obj;
81300
- path63.split(".").forEach((key, index, arr) => {
81675
+ path64.split(".").forEach((key, index, arr) => {
81301
81676
  if (key === "__proto__" || key === "constructor")
81302
81677
  return;
81303
81678
  if (index === arr.length - 1) {
@@ -81308,8 +81683,8 @@ var _2 = {
81308
81683
  pointer = pointer[key];
81309
81684
  });
81310
81685
  },
81311
- get: (obj, path63 = "", defaultValue) => {
81312
- const travel = (regexp) => String.prototype.split.call(path63, regexp).filter(Boolean).reduce(
81686
+ get: (obj, path64 = "", defaultValue) => {
81687
+ const travel = (regexp) => String.prototype.split.call(path64, regexp).filter(Boolean).reduce(
81313
81688
  // @ts-expect-error implicit any on res[key]
81314
81689
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
81315
81690
  obj
@@ -81563,21 +81938,21 @@ init_control_port();
81563
81938
  init_control_sync();
81564
81939
 
81565
81940
  // src/core/control-sync-selection.ts
81566
- var fs46 = __toESM(require("fs"));
81567
- var os17 = __toESM(require("os"));
81568
- var path53 = __toESM(require("path"));
81941
+ var fs47 = __toESM(require("fs"));
81942
+ var os18 = __toESM(require("os"));
81943
+ var path54 = __toESM(require("path"));
81569
81944
  init_control_repo_path();
81570
81945
  function getSelectionPath() {
81571
81946
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
81572
- return path53.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
81947
+ return path54.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
81573
81948
  }
81574
- return path53.join(os17.homedir(), ".har", "sync-selection.json");
81949
+ return path54.join(os18.homedir(), ".har", "sync-selection.json");
81575
81950
  }
81576
81951
  function readSyncSelection() {
81577
81952
  const selectionPath = getSelectionPath();
81578
81953
  try {
81579
- if (!fs46.existsSync(selectionPath)) return null;
81580
- const parsed = JSON.parse(fs46.readFileSync(selectionPath, "utf8"));
81954
+ if (!fs47.existsSync(selectionPath)) return null;
81955
+ const parsed = JSON.parse(fs47.readFileSync(selectionPath, "utf8"));
81581
81956
  if (!Array.isArray(parsed.repos)) return null;
81582
81957
  return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
81583
81958
  } catch {
@@ -81587,8 +81962,8 @@ function readSyncSelection() {
81587
81962
  function writeSyncSelection(repos) {
81588
81963
  const selectionPath = getSelectionPath();
81589
81964
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
81590
- fs46.mkdirSync(path53.dirname(selectionPath), { recursive: true });
81591
- fs46.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
81965
+ fs47.mkdirSync(path54.dirname(selectionPath), { recursive: true });
81966
+ fs47.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
81592
81967
  }
81593
81968
  function resolveSyncSelection(input) {
81594
81969
  const { discovered, stored, forceSelect, isTTY } = input;
@@ -81695,8 +82070,8 @@ If your browser did not open, paste that URL.
81695
82070
  }
81696
82071
 
81697
82072
  // src/core/control-unregister.ts
81698
- var fs47 = __toESM(require("fs"));
81699
- var path54 = __toESM(require("path"));
82073
+ var fs48 = __toESM(require("fs"));
82074
+ var path55 = __toESM(require("path"));
81700
82075
  init_control_repo_path();
81701
82076
  init_control_registry();
81702
82077
  init_control_config();
@@ -81706,9 +82081,9 @@ function listUnregisterWorktreeCandidates(repoPath) {
81706
82081
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
81707
82082
  const byPath = /* @__PURE__ */ new Map();
81708
82083
  const add = (partial2) => {
81709
- const resolved = path54.resolve(partial2.worktreePath);
82084
+ const resolved = path55.resolve(partial2.worktreePath);
81710
82085
  if (!resolved || resolved === harnessRoot) return;
81711
- const exists = partial2.exists ?? fs47.existsSync(resolved);
82086
+ const exists = partial2.exists ?? fs48.existsSync(resolved);
81712
82087
  const prev = byPath.get(resolved);
81713
82088
  if (prev) {
81714
82089
  byPath.set(resolved, {
@@ -81755,10 +82130,10 @@ function listUnregisterWorktreeCandidates(repoPath) {
81755
82130
  }
81756
82131
  return [...byPath.values()].sort((a2, b3) => a2.agentId - b3.agentId);
81757
82132
  }
81758
- async function askYesNo6(question) {
82133
+ async function askYesNo7(question) {
81759
82134
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
81760
- const readline10 = await import("readline");
81761
- const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
82135
+ const readline11 = await import("readline");
82136
+ const rl = readline11.createInterface({ input: process.stdin, output: process.stderr });
81762
82137
  const answer = await new Promise((resolve47) => {
81763
82138
  rl.question(question, resolve47);
81764
82139
  });
@@ -81772,7 +82147,7 @@ async function confirmUnregister(options) {
81772
82147
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
81773
82148
  throw new Error("Non-interactive terminal \u2014 pass --yes (and optionally --delete-worktrees)");
81774
82149
  }
81775
- const proceed = await askYesNo6("Unregister this repository from Mission Control? [y/N] ");
82150
+ const proceed = await askYesNo7("Unregister this repository from Mission Control? [y/N] ");
81776
82151
  if (!proceed) return { proceed: false, deleteWorktrees: false };
81777
82152
  const existing = options.worktrees.filter((w3) => w3.exists);
81778
82153
  if (existing.length === 0) {
@@ -81784,7 +82159,7 @@ async function confirmUnregister(options) {
81784
82159
  process.stderr.write(` agent-${wt2.agentId}: ${wt2.worktreePath}${dirty}
81785
82160
  `);
81786
82161
  }
81787
- const deleteWorktrees = await askYesNo6(
82162
+ const deleteWorktrees = await askYesNo7(
81788
82163
  `Also delete ${existing.length} session worktree(s) on disk? [y/N] `
81789
82164
  );
81790
82165
  return { proceed: true, deleteWorktrees };
@@ -81822,28 +82197,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
81822
82197
  trigger: "cli"
81823
82198
  });
81824
82199
  if (result.code !== 0) {
81825
- if (fs47.existsSync(candidate.worktreePath)) {
81826
- fs47.rmSync(candidate.worktreePath, { recursive: true, force: true });
82200
+ if (fs48.existsSync(candidate.worktreePath)) {
82201
+ fs48.rmSync(candidate.worktreePath, { recursive: true, force: true });
81827
82202
  }
81828
82203
  }
81829
82204
  outcomes.push({
81830
82205
  path: candidate.worktreePath,
81831
82206
  agentId: candidate.agentId,
81832
- deleted: !fs47.existsSync(candidate.worktreePath),
81833
- error: result.code !== 0 && fs47.existsSync(candidate.worktreePath) ? result.stderr : void 0
82207
+ deleted: !fs48.existsSync(candidate.worktreePath),
82208
+ error: result.code !== 0 && fs48.existsSync(candidate.worktreePath) ? result.stderr : void 0
81834
82209
  });
81835
82210
  } catch (err) {
81836
82211
  const message = err instanceof Error ? err.message : String(err);
81837
82212
  try {
81838
- if (fs47.existsSync(candidate.worktreePath)) {
81839
- fs47.rmSync(candidate.worktreePath, { recursive: true, force: true });
82213
+ if (fs48.existsSync(candidate.worktreePath)) {
82214
+ fs48.rmSync(candidate.worktreePath, { recursive: true, force: true });
81840
82215
  }
81841
82216
  } catch {
81842
82217
  }
81843
82218
  outcomes.push({
81844
82219
  path: candidate.worktreePath,
81845
82220
  agentId: candidate.agentId,
81846
- deleted: !fs47.existsSync(candidate.worktreePath),
82221
+ deleted: !fs48.existsSync(candidate.worktreePath),
81847
82222
  error: message
81848
82223
  });
81849
82224
  }
@@ -81906,16 +82281,16 @@ init_control_config();
81906
82281
  init_control_registry();
81907
82282
 
81908
82283
  // src/core/harness-scrub.ts
81909
- var fs48 = __toESM(require("fs"));
81910
- var path55 = __toESM(require("path"));
82284
+ var fs49 = __toESM(require("fs"));
82285
+ var path56 = __toESM(require("path"));
81911
82286
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
81912
82287
  function scrubLocalHarnessDirs(repoPath) {
81913
82288
  const results = [];
81914
- const resolved = path55.resolve(repoPath);
81915
- if (!fs48.existsSync(resolved)) {
82289
+ const resolved = path56.resolve(repoPath);
82290
+ if (!fs49.existsSync(resolved)) {
81916
82291
  for (const directory of HARNESS_SCRUB_DIRS) {
81917
82292
  results.push({
81918
- path: path55.join(resolved, ".har", directory),
82293
+ path: path56.join(resolved, ".har", directory),
81919
82294
  directory,
81920
82295
  deleted: false,
81921
82296
  error: "repository path does not exist"
@@ -81924,24 +82299,24 @@ function scrubLocalHarnessDirs(repoPath) {
81924
82299
  return results;
81925
82300
  }
81926
82301
  for (const directory of HARNESS_SCRUB_DIRS) {
81927
- const target = path55.join(resolved, ".har", directory);
81928
- if (!fs48.existsSync(target)) {
82302
+ const target = path56.join(resolved, ".har", directory);
82303
+ if (!fs49.existsSync(target)) {
81929
82304
  results.push({ path: target, directory, deleted: true });
81930
82305
  continue;
81931
82306
  }
81932
82307
  try {
81933
- fs48.rmSync(target, { recursive: true, force: true });
82308
+ fs49.rmSync(target, { recursive: true, force: true });
81934
82309
  results.push({
81935
82310
  path: target,
81936
82311
  directory,
81937
- deleted: !fs48.existsSync(target),
81938
- error: fs48.existsSync(target) ? "failed to remove directory" : void 0
82312
+ deleted: !fs49.existsSync(target),
82313
+ error: fs49.existsSync(target) ? "failed to remove directory" : void 0
81939
82314
  });
81940
82315
  } catch (err) {
81941
82316
  results.push({
81942
82317
  path: target,
81943
82318
  directory,
81944
- deleted: !fs48.existsSync(target),
82319
+ deleted: !fs49.existsSync(target),
81945
82320
  error: err instanceof Error ? err.message : String(err)
81946
82321
  });
81947
82322
  }
@@ -81952,7 +82327,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
81952
82327
  const results = [];
81953
82328
  const seen = /* @__PURE__ */ new Set();
81954
82329
  for (const repoPath of repoPaths) {
81955
- const key = path55.resolve(repoPath);
82330
+ const key = path56.resolve(repoPath);
81956
82331
  if (seen.has(key)) continue;
81957
82332
  seen.add(key);
81958
82333
  results.push(...scrubLocalHarnessDirs(key));
@@ -81961,10 +82336,10 @@ function scrubLocalHarnessForRepos(repoPaths) {
81961
82336
  }
81962
82337
 
81963
82338
  // src/core/control-reset.ts
81964
- async function askYesNo7(question) {
82339
+ async function askYesNo8(question) {
81965
82340
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
81966
- const readline10 = await import("readline");
81967
- const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
82341
+ const readline11 = await import("readline");
82342
+ const rl = readline11.createInterface({ input: process.stdin, output: process.stderr });
81968
82343
  const answer = await new Promise((resolve47) => {
81969
82344
  rl.question(question, resolve47);
81970
82345
  });
@@ -81976,7 +82351,7 @@ async function confirmControlReset(options) {
81976
82351
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
81977
82352
  throw new Error("Non-interactive terminal \u2014 pass --yes");
81978
82353
  }
81979
- return askYesNo7(
82354
+ return askYesNo8(
81980
82355
  `Clear Mission Control data for ${options.repoCount} registered repositor${options.repoCount === 1 ? "y" : "ies"} (and scrub local .har history)? [y/N] `
81981
82356
  );
81982
82357
  }
@@ -82208,7 +82583,7 @@ async function handleDown() {
82208
82583
  return finishCommand(code);
82209
82584
  }
82210
82585
  async function handleRegister(argv) {
82211
- const repoPath = path56.resolve(argv.repo);
82586
+ const repoPath = path57.resolve(argv.repo);
82212
82587
  header("har control register");
82213
82588
  info(`Repository: ${repoPath}`);
82214
82589
  try {
@@ -82300,7 +82675,7 @@ async function handleReset(argv) {
82300
82675
  }
82301
82676
  }
82302
82677
  async function handleUnregister(argv) {
82303
- const repoPath = path56.resolve(argv.repo);
82678
+ const repoPath = path57.resolve(argv.repo);
82304
82679
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
82305
82680
  try {
82306
82681
  let deleteWorktrees = argv.deleteWorktrees;
@@ -82479,11 +82854,11 @@ async function handleLogin(argv) {
82479
82854
  }
82480
82855
 
82481
82856
  // src/cli/commands/hooks.ts
82482
- var path58 = __toESM(require("path"));
82857
+ var path59 = __toESM(require("path"));
82483
82858
 
82484
82859
  // src/core/claude-hooks.ts
82485
- var fs49 = __toESM(require("fs"));
82486
- var path57 = __toESM(require("path"));
82860
+ var fs50 = __toESM(require("fs"));
82861
+ var path58 = __toESM(require("path"));
82487
82862
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
82488
82863
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
82489
82864
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -82494,8 +82869,8 @@ function isHarGuardEntry(entry) {
82494
82869
  );
82495
82870
  }
82496
82871
  function readSettings(settingsPath) {
82497
- if (!fs49.existsSync(settingsPath)) return {};
82498
- const raw = fs49.readFileSync(settingsPath, "utf8").trim();
82872
+ if (!fs50.existsSync(settingsPath)) return {};
82873
+ const raw = fs50.readFileSync(settingsPath, "utf8").trim();
82499
82874
  if (raw === "") return {};
82500
82875
  const parsed = JSON.parse(raw);
82501
82876
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -82504,19 +82879,19 @@ function readSettings(settingsPath) {
82504
82879
  return parsed;
82505
82880
  }
82506
82881
  function writeSettings(settingsPath, settings) {
82507
- fs49.mkdirSync(path57.dirname(settingsPath), { recursive: true });
82508
- fs49.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
82882
+ fs50.mkdirSync(path58.dirname(settingsPath), { recursive: true });
82883
+ fs50.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
82509
82884
  }
82510
82885
  function installClaudeGuard(repoPath) {
82511
82886
  const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
82512
82887
  if (!templatePath) {
82513
82888
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
82514
82889
  }
82515
- const guardScript = path57.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82516
- fs49.mkdirSync(path57.dirname(guardScript), { recursive: true });
82517
- fs49.copyFileSync(templatePath, guardScript);
82518
- fs49.chmodSync(guardScript, 493);
82519
- const settingsPath = path57.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82890
+ const guardScript = path58.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82891
+ fs50.mkdirSync(path58.dirname(guardScript), { recursive: true });
82892
+ fs50.copyFileSync(templatePath, guardScript);
82893
+ fs50.chmodSync(guardScript, 493);
82894
+ const settingsPath = path58.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82520
82895
  const settings = readSettings(settingsPath);
82521
82896
  const hooks = settings.hooks ?? {};
82522
82897
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -82530,15 +82905,15 @@ function installClaudeGuard(repoPath) {
82530
82905
  }
82531
82906
  function uninstallClaudeGuard(repoPath) {
82532
82907
  let removed = false;
82533
- const guardScript = path57.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82534
- if (fs49.existsSync(guardScript)) {
82535
- fs49.rmSync(guardScript);
82908
+ const guardScript = path58.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
82909
+ if (fs50.existsSync(guardScript)) {
82910
+ fs50.rmSync(guardScript);
82536
82911
  removed = true;
82537
- const parent = path57.dirname(guardScript);
82538
- if (fs49.existsSync(parent) && fs49.readdirSync(parent).length === 0) fs49.rmdirSync(parent);
82912
+ const parent = path58.dirname(guardScript);
82913
+ if (fs50.existsSync(parent) && fs50.readdirSync(parent).length === 0) fs50.rmdirSync(parent);
82539
82914
  }
82540
- const settingsPath = path57.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82541
- if (fs49.existsSync(settingsPath)) {
82915
+ const settingsPath = path58.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82916
+ if (fs50.existsSync(settingsPath)) {
82542
82917
  const settings = readSettings(settingsPath);
82543
82918
  const preToolUse = settings.hooks?.PreToolUse;
82544
82919
  if (preToolUse) {
@@ -82563,8 +82938,8 @@ function uninstallClaudeGuard(repoPath) {
82563
82938
  return { removed };
82564
82939
  }
82565
82940
  function claudeGuardInstalled(repoPath) {
82566
- const settingsPath = path57.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82567
- if (!fs49.existsSync(settingsPath)) return false;
82941
+ const settingsPath = path58.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
82942
+ if (!fs50.existsSync(settingsPath)) return false;
82568
82943
  try {
82569
82944
  const settings = readSettings(settingsPath);
82570
82945
  return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
@@ -82581,7 +82956,7 @@ function repoOption(y2) {
82581
82956
  function handleInstall2(argv) {
82582
82957
  try {
82583
82958
  if (argv.claude) {
82584
- const result2 = installClaudeGuard(path58.resolve(argv.repo));
82959
+ const result2 = installClaudeGuard(path59.resolve(argv.repo));
82585
82960
  success("Claude Code worktree guard installed.");
82586
82961
  info(`Guard script: ${result2.guardScript}`);
82587
82962
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -82589,7 +82964,7 @@ function handleInstall2(argv) {
82589
82964
  info("Commit both files so the guard travels with the repo.");
82590
82965
  return;
82591
82966
  }
82592
- const result = installHooks({ repoPath: path58.resolve(argv.repo), force: argv.force });
82967
+ const result = installHooks({ repoPath: path59.resolve(argv.repo), force: argv.force });
82593
82968
  success(`Commit gate installed in ${result.hooksDir}`);
82594
82969
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
82595
82970
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -82602,7 +82977,7 @@ function handleInstall2(argv) {
82602
82977
  function handleUninstall(argv) {
82603
82978
  try {
82604
82979
  if (argv.claude) {
82605
- const result2 = uninstallClaudeGuard(path58.resolve(argv.repo));
82980
+ const result2 = uninstallClaudeGuard(path59.resolve(argv.repo));
82606
82981
  if (result2.removed) {
82607
82982
  success("Claude Code worktree guard removed.");
82608
82983
  } else {
@@ -82610,7 +82985,7 @@ function handleUninstall(argv) {
82610
82985
  }
82611
82986
  return;
82612
82987
  }
82613
- const result = uninstallHooks(path58.resolve(argv.repo));
82988
+ const result = uninstallHooks(path59.resolve(argv.repo));
82614
82989
  if (result.removed) {
82615
82990
  success(`Commit gate removed from ${result.hooksDir}`);
82616
82991
  } else {
@@ -82623,7 +82998,7 @@ function handleUninstall(argv) {
82623
82998
  }
82624
82999
  function handleStatus2(argv) {
82625
83000
  try {
82626
- const status = getHooksStatus(path58.resolve(argv.repo));
83001
+ const status = getHooksStatus(path59.resolve(argv.repo));
82627
83002
  if (argv.json) {
82628
83003
  process.stdout.write(`${JSON.stringify(status, null, 2)}
82629
83004
  `);
@@ -82641,7 +83016,7 @@ function handleStatus2(argv) {
82641
83016
  );
82642
83017
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
82643
83018
  info(
82644
- `Claude guard: ${claudeGuardInstalled(path58.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
83019
+ `Claude guard: ${claudeGuardInstalled(path59.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
82645
83020
  );
82646
83021
  } catch (err) {
82647
83022
  error(err instanceof Error ? err.message : String(err));
@@ -82902,10 +83277,10 @@ function assignProp(target, prop, value) {
82902
83277
  configurable: true
82903
83278
  });
82904
83279
  }
82905
- function getElementAtPath(obj, path63) {
82906
- if (!path63)
83280
+ function getElementAtPath(obj, path64) {
83281
+ if (!path64)
82907
83282
  return obj;
82908
- return path63.reduce((acc, key) => acc?.[key], obj);
83283
+ return path64.reduce((acc, key) => acc?.[key], obj);
82909
83284
  }
82910
83285
  function promiseAllObject(promisesObj) {
82911
83286
  const keys = Object.keys(promisesObj);
@@ -83225,11 +83600,11 @@ function aborted(x2, startIndex = 0) {
83225
83600
  }
83226
83601
  return false;
83227
83602
  }
83228
- function prefixIssues(path63, issues) {
83603
+ function prefixIssues(path64, issues) {
83229
83604
  return issues.map((iss) => {
83230
83605
  var _a3;
83231
83606
  (_a3 = iss).path ?? (_a3.path = []);
83232
- iss.path.unshift(path63);
83607
+ iss.path.unshift(path64);
83233
83608
  return iss;
83234
83609
  });
83235
83610
  }
@@ -89703,7 +90078,7 @@ var Server = class extends Protocol {
89703
90078
  };
89704
90079
 
89705
90080
  // src/mcp/server.ts
89706
- var path59 = __toESM(require("path"));
90081
+ var path60 = __toESM(require("path"));
89707
90082
 
89708
90083
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
89709
90084
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -90344,7 +90719,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
90344
90719
  const input = ControlUpInputSchema.parse({ ...args, repo });
90345
90720
  const result = await startControlAndSync({
90346
90721
  detach: input.detach,
90347
- cwd: path59.resolve(input.repo)
90722
+ cwd: path60.resolve(input.repo)
90348
90723
  });
90349
90724
  if (result.code !== 0) {
90350
90725
  return {
@@ -90408,11 +90783,11 @@ var mcpCommand = {
90408
90783
  };
90409
90784
 
90410
90785
  // src/cli/commands/onboard.ts
90411
- var path61 = __toESM(require("path"));
90786
+ var path62 = __toESM(require("path"));
90412
90787
  init_stages();
90413
90788
 
90414
90789
  // src/core/onboarding.ts
90415
- var path60 = __toESM(require("path"));
90790
+ var path61 = __toESM(require("path"));
90416
90791
  init_control_config();
90417
90792
  init_control_sync();
90418
90793
  init_otel_hooks();
@@ -90547,7 +90922,7 @@ async function defaultEnsureControl(options) {
90547
90922
  return { started: true, apiUrl: result.apiUrl };
90548
90923
  }
90549
90924
  async function runOnboarding(options, deps = {}) {
90550
- const repoPath = path60.resolve(options.repoPath);
90925
+ const repoPath = path61.resolve(options.repoPath);
90551
90926
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
90552
90927
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
90553
90928
  const init = deps.initHarness ?? initHarness;
@@ -90736,7 +91111,7 @@ async function promptChoices(args) {
90736
91111
  };
90737
91112
  }
90738
91113
  const pluginChoices = listPluginChoices();
90739
- const repoPath = path61.resolve(args.repo);
91114
+ const repoPath = path62.resolve(args.repo);
90740
91115
  const alreadyPresent = harnessExists(repoPath);
90741
91116
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
90742
91117
  const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
@@ -90853,7 +91228,7 @@ function printSummary(result) {
90853
91228
  console.error("");
90854
91229
  }
90855
91230
  async function handleOnboard(argv) {
90856
- const repoPath = path61.resolve(argv.repo);
91231
+ const repoPath = path62.resolve(argv.repo);
90857
91232
  header("har onboard");
90858
91233
  info(`Repository: ${repoPath}`);
90859
91234
  try {
@@ -90883,18 +91258,13 @@ async function handleOnboard(argv) {
90883
91258
  ...onboarding.commitGate,
90884
91259
  autoYes: argv.yes
90885
91260
  });
90886
- await handleCursorRule({
91261
+ await applyAgentIntegrations({
90887
91262
  repoPath,
90888
- cursorRule: onboarding.cursorRule,
90889
- autoYes: argv.yes,
90890
- mode: result.harnessInitialized ? "init" : "maintain"
90891
- });
90892
- await handleAgentSkills({
90893
- repoPath,
90894
- ...onboarding.agentSkills,
91263
+ mode: result.harnessInitialized ? "init" : "maintain",
90895
91264
  autoYes: argv.yes,
90896
91265
  force: argv.force,
90897
- mode: result.harnessInitialized ? "init" : "maintain"
91266
+ cursorRule: onboarding.cursorRule,
91267
+ ...onboarding.agentSkills
90898
91268
  });
90899
91269
  }
90900
91270
  if (harnessExists(repoPath)) {
@@ -91089,7 +91459,7 @@ var preferencesCommand = {
91089
91459
  };
91090
91460
 
91091
91461
  // src/cli/commands/telemetry.ts
91092
- var path62 = __toESM(require("path"));
91462
+ var path63 = __toESM(require("path"));
91093
91463
  init_control_config();
91094
91464
  init_control_sync();
91095
91465
  init_manifest();
@@ -91182,7 +91552,7 @@ async function handleOff() {
91182
91552
  info("Mission Control will not auto-start. Existing usage rows are kept.");
91183
91553
  }
91184
91554
  async function handleWriteEnv(argv) {
91185
- const repoPath = path62.resolve(argv.repo);
91555
+ const repoPath = path63.resolve(argv.repo);
91186
91556
  const harnessRoot = resolveHarnessRoot(repoPath);
91187
91557
  const session = readSlotRegistry(harnessRoot, argv.agentId);
91188
91558
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -91194,7 +91564,7 @@ async function handleWriteEnv(argv) {
91194
91564
  suffix,
91195
91565
  createdAt: session?.createdAt
91196
91566
  });
91197
- const envFile = argv.envFile ?? path62.join(workDir, `.env.agent.${argv.agentId}`);
91567
+ const envFile = argv.envFile ?? path63.join(workDir, `.env.agent.${argv.agentId}`);
91198
91568
  const attrs = {
91199
91569
  sessionKey,
91200
91570
  agentId: argv.agentId,
@@ -91210,7 +91580,7 @@ async function handleWriteEnv(argv) {
91210
91580
  success(`Wrote session attribution to ${envFile}`);
91211
91581
  }
91212
91582
  function handlePrintEnv(argv) {
91213
- const repoPath = path62.resolve(argv.repo);
91583
+ const repoPath = path63.resolve(argv.repo);
91214
91584
  const workDir = argv.workDir ?? repoPath;
91215
91585
  const sessionKey = buildSessionKey({
91216
91586
  branch: argv.branch,