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