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