@osfactory/har 0.57.0 → 0.59.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 +854 -247
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -553,8 +553,8 @@ var init_parseUtil = __esm({
|
|
|
553
553
|
init_errors();
|
|
554
554
|
init_en();
|
|
555
555
|
makeIssue = (params) => {
|
|
556
|
-
const { data, path:
|
|
557
|
-
const fullPath = [...
|
|
556
|
+
const { data, path: path66, errorMaps, issueData } = params;
|
|
557
|
+
const fullPath = [...path66, ...issueData.path || []];
|
|
558
558
|
const fullIssue = {
|
|
559
559
|
...issueData,
|
|
560
560
|
path: fullPath
|
|
@@ -862,11 +862,11 @@ var init_types = __esm({
|
|
|
862
862
|
init_parseUtil();
|
|
863
863
|
init_util();
|
|
864
864
|
ParseInputLazyPath = class {
|
|
865
|
-
constructor(parent, value,
|
|
865
|
+
constructor(parent, value, path66, key) {
|
|
866
866
|
this._cachedPath = [];
|
|
867
867
|
this.parent = parent;
|
|
868
868
|
this.data = value;
|
|
869
|
-
this._path =
|
|
869
|
+
this._path = path66;
|
|
870
870
|
this._key = key;
|
|
871
871
|
}
|
|
872
872
|
get path() {
|
|
@@ -4248,7 +4248,7 @@ var init_zod = __esm({
|
|
|
4248
4248
|
});
|
|
4249
4249
|
|
|
4250
4250
|
// packages/schemas/src/schema.ts
|
|
4251
|
-
var HAR_STAGE_KINDS, HAR_AGENT_SLOT_MIN, AgentSkillTargetSchema, ScaffoldedAgentFileSchema, HarnessManifestSchema, HarnessStageKindSchema, HarnessArtifactKindSchema, HarnessArtifactSchema, HarnessStageIdSchema, HarnessStageSchema, HarnessAgentSlotsSchema, CommitGateConfigSchema, OnboardingPreferencesSchema, HarnessStageRegistrySchema, HarnessVerificationStepSchema, ShellRunOutputSchema, HarnessVerificationResultSchema, HarnessStageRunStatusSchema, HarnessStageLogSchema, HarnessStageUrlSchema, HarnessStageRunResultSchema, StageKindSchema, VerificationResultSchema, StageResultSchema, RunRecordTriggerSchema, WorkUnitIdSchema, WorkAttemptIdSchema, WorkUnitMetadataSchema, WorkUnitOutcomeSchema, WorkUnitRecordSchema, WorkAttemptRecordSchema, RunRecordSchema, SlotRegistryEntrySchema, AgentSlotHarnessUsageSchema, PreflightBlockerSchema, SlotReadinessSchema, AgentSlotStatusSchema, EnvironmentStatusSchema, RegisterRepoInputSchema, UnregisterRepoInputSchema, UnregisterWorktreeResultSchema, UnregisterRepoResultSchema, ResetMissionControlInputSchema, HarnessScrubResultSchema, ResetMissionControlResultSchema, DeleteWorktreesInputSchema, DeleteWorktreeResultSchema, DeleteWorktreesResultSchema, SyncRunsInputSchema, SyncSlotsInputSchema, SyncWorkUnitsInputSchema, ChangedFileStatusSchema, ChangedFileSchema, ValidationRecordSchema, SyncValidationsInputSchema, ValidationBindingRecordSchema, SyncValidationBindingsInputSchema, AgentToolSchema, UsageSourceSchema, AgentTrajectorySourceSchema, AgentTrajectoryContentDisclosureSchema, AgentTrajectoryRecordV1Schema, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
|
|
4251
|
+
var HAR_STAGE_KINDS, HAR_AGENT_SLOT_MIN, AgentSkillTargetSchema, ScaffoldedAgentFileSchema, HarnessManifestSchema, HarnessStageKindSchema, HarnessArtifactKindSchema, HarnessArtifactSchema, HarnessStageIdSchema, HarnessStageSchema, HarnessAgentSlotsSchema, CommitGateConfigSchema, OnboardingPreferencesSchema, HarnessStageRegistrySchema, HarnessVerificationStepSchema, ShellRunOutputSchema, HarnessVerificationResultSchema, HarnessStageRunStatusSchema, HarnessStageLogSchema, HarnessStageUrlSchema, HarnessStageRunResultSchema, StageKindSchema, VerificationResultSchema, StageResultSchema, RunRecordTriggerSchema, WorkUnitIdSchema, WorkAttemptIdSchema, WorkUnitRelatedLinkSchema, WorkUnitMetadataSchema, WorkUnitOutcomeSchema, WorkUnitRecordSchema, WorkAttemptRecordSchema, RunRecordSchema, SlotRegistryEntrySchema, AgentSlotHarnessUsageSchema, PreflightBlockerSchema, SlotReadinessSchema, AgentSlotStatusSchema, EnvironmentStatusSchema, RegisterRepoInputSchema, UnregisterRepoInputSchema, UnregisterWorktreeResultSchema, UnregisterRepoResultSchema, ResetMissionControlInputSchema, HarnessScrubResultSchema, ResetMissionControlResultSchema, DeleteWorktreesInputSchema, DeleteWorktreeResultSchema, DeleteWorktreesResultSchema, SyncRunsInputSchema, SyncSlotsInputSchema, SyncWorkUnitsInputSchema, ChangedFileStatusSchema, ChangedFileSchema, ValidationRecordSchema, SyncValidationsInputSchema, ValidationBindingRecordSchema, SyncValidationBindingsInputSchema, AgentToolSchema, UsageSourceSchema, AgentTrajectorySourceSchema, AgentTrajectoryContentDisclosureSchema, AgentTrajectoryRecordV1Schema, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
|
|
4252
4252
|
var init_schema = __esm({
|
|
4253
4253
|
"packages/schemas/src/schema.ts"() {
|
|
4254
4254
|
"use strict";
|
|
@@ -4413,12 +4413,18 @@ var init_schema = __esm({
|
|
|
4413
4413
|
"work unit id must start with an alphanumeric character and contain only stable identifier characters"
|
|
4414
4414
|
);
|
|
4415
4415
|
WorkAttemptIdSchema = external_exports.string().uuid();
|
|
4416
|
+
WorkUnitRelatedLinkSchema = external_exports.object({
|
|
4417
|
+
source: external_exports.string().min(1).max(64),
|
|
4418
|
+
url: external_exports.string().url(),
|
|
4419
|
+
label: external_exports.string().min(1).max(128).optional()
|
|
4420
|
+
});
|
|
4416
4421
|
WorkUnitMetadataSchema = external_exports.object({
|
|
4417
4422
|
workUnitId: WorkUnitIdSchema,
|
|
4418
4423
|
source: external_exports.string().min(1).max(64).optional(),
|
|
4419
4424
|
sourceUrl: external_exports.string().url().optional(),
|
|
4420
4425
|
title: external_exports.string().min(1).max(256).optional(),
|
|
4421
|
-
parentWorkUnitId: WorkUnitIdSchema.optional()
|
|
4426
|
+
parentWorkUnitId: WorkUnitIdSchema.optional(),
|
|
4427
|
+
relatedLinks: external_exports.array(WorkUnitRelatedLinkSchema).optional()
|
|
4422
4428
|
});
|
|
4423
4429
|
WorkUnitOutcomeSchema = external_exports.object({
|
|
4424
4430
|
decision: external_exports.enum(["completed", "abandoned"]),
|
|
@@ -28758,7 +28764,7 @@ function runScript(scriptPath, args = [], options = {}) {
|
|
|
28758
28764
|
function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
28759
28765
|
const stream = options.stream ?? false;
|
|
28760
28766
|
const { stream: _stream, ...spawnOptions } = options;
|
|
28761
|
-
return new Promise((
|
|
28767
|
+
return new Promise((resolve50) => {
|
|
28762
28768
|
const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
|
|
28763
28769
|
...spawnOptions,
|
|
28764
28770
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -28773,13 +28779,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
|
28773
28779
|
stderr += d;
|
|
28774
28780
|
if (stream) process.stderr.write(d);
|
|
28775
28781
|
});
|
|
28776
|
-
proc.on("close", (code) =>
|
|
28782
|
+
proc.on("close", (code) => resolve50({ stdout, stderr, code: code ?? 0 }));
|
|
28777
28783
|
});
|
|
28778
28784
|
}
|
|
28779
28785
|
function runShellCommand(command2, options = {}) {
|
|
28780
28786
|
const stream = options.stream ?? false;
|
|
28781
28787
|
const { stream: _stream, ...spawnOptions } = options;
|
|
28782
|
-
return new Promise((
|
|
28788
|
+
return new Promise((resolve50) => {
|
|
28783
28789
|
const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
|
|
28784
28790
|
...spawnOptions,
|
|
28785
28791
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -28794,7 +28800,7 @@ function runShellCommand(command2, options = {}) {
|
|
|
28794
28800
|
stderr += d;
|
|
28795
28801
|
if (stream) process.stderr.write(d);
|
|
28796
28802
|
});
|
|
28797
|
-
proc.on("close", (code) =>
|
|
28803
|
+
proc.on("close", (code) => resolve50({ stdout, stderr, code: code ?? 0 }));
|
|
28798
28804
|
});
|
|
28799
28805
|
}
|
|
28800
28806
|
var import_child_process;
|
|
@@ -28863,11 +28869,16 @@ function getRegistryPath() {
|
|
|
28863
28869
|
}
|
|
28864
28870
|
return path9.join(os3.homedir(), ".har", "repos.json");
|
|
28865
28871
|
}
|
|
28872
|
+
function normalizeRegistry(raw) {
|
|
28873
|
+
const repos = Array.isArray(raw?.repos) ? raw.repos.filter((p) => typeof p === "string") : [];
|
|
28874
|
+
const portalOptOut = Array.isArray(raw?.portalOptOut) ? raw.portalOptOut.filter((p) => typeof p === "string") : void 0;
|
|
28875
|
+
return portalOptOut && portalOptOut.length > 0 ? { repos, portalOptOut } : { repos };
|
|
28876
|
+
}
|
|
28866
28877
|
function readRegistry() {
|
|
28867
28878
|
const registryPath = getRegistryPath();
|
|
28868
28879
|
try {
|
|
28869
28880
|
if (!fs9.existsSync(registryPath)) return { repos: [] };
|
|
28870
|
-
return JSON.parse(fs9.readFileSync(registryPath, "utf8"));
|
|
28881
|
+
return normalizeRegistry(JSON.parse(fs9.readFileSync(registryPath, "utf8")));
|
|
28871
28882
|
} catch {
|
|
28872
28883
|
return { repos: [] };
|
|
28873
28884
|
}
|
|
@@ -28875,12 +28886,37 @@ function readRegistry() {
|
|
|
28875
28886
|
function writeRegistry(registry2) {
|
|
28876
28887
|
const registryPath = getRegistryPath();
|
|
28877
28888
|
fs9.mkdirSync(path9.dirname(registryPath), { recursive: true });
|
|
28878
|
-
|
|
28889
|
+
const normalized = normalizeRegistry(registry2);
|
|
28890
|
+
fs9.writeFileSync(registryPath, JSON.stringify(normalized, null, 2) + "\n");
|
|
28879
28891
|
}
|
|
28880
28892
|
function registryChanged(before, after) {
|
|
28881
28893
|
if (before.length !== after.length) return true;
|
|
28882
28894
|
return before.some((repoPath, index) => repoPath !== after[index]);
|
|
28883
28895
|
}
|
|
28896
|
+
function pathEqualsCanonical(entry, resolved) {
|
|
28897
|
+
try {
|
|
28898
|
+
return canonicalizeControlRepoPath(entry) === resolved;
|
|
28899
|
+
} catch {
|
|
28900
|
+
return path9.resolve(entry) === resolved;
|
|
28901
|
+
}
|
|
28902
|
+
}
|
|
28903
|
+
function prunePortalOptOut(registry2, keptRepos) {
|
|
28904
|
+
const kept = new Set(keptRepos);
|
|
28905
|
+
const next = [];
|
|
28906
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28907
|
+
for (const entry of registry2.portalOptOut ?? []) {
|
|
28908
|
+
let canonical;
|
|
28909
|
+
try {
|
|
28910
|
+
canonical = canonicalizeControlRepoPath(entry);
|
|
28911
|
+
} catch {
|
|
28912
|
+
canonical = path9.resolve(entry);
|
|
28913
|
+
}
|
|
28914
|
+
if (!kept.has(canonical) || seen.has(canonical)) continue;
|
|
28915
|
+
seen.add(canonical);
|
|
28916
|
+
next.push(canonical);
|
|
28917
|
+
}
|
|
28918
|
+
return next.length > 0 ? next : void 0;
|
|
28919
|
+
}
|
|
28884
28920
|
function recordRepoForControlSync(repoPath) {
|
|
28885
28921
|
if (process.env.HAR_CONTROL_DISABLED === "true") return;
|
|
28886
28922
|
const resolved = canonicalizeControlRepoPath(repoPath);
|
|
@@ -28891,18 +28927,40 @@ function recordRepoForControlSync(repoPath) {
|
|
|
28891
28927
|
registry2.repos.push(resolved);
|
|
28892
28928
|
writeRegistry(registry2);
|
|
28893
28929
|
}
|
|
28894
|
-
function
|
|
28930
|
+
function isRepoPortalSyncEnabled(repoPath) {
|
|
28895
28931
|
const resolved = canonicalizeControlRepoPath(repoPath);
|
|
28896
28932
|
const registry2 = readRegistry();
|
|
28897
|
-
|
|
28898
|
-
|
|
28899
|
-
|
|
28900
|
-
|
|
28901
|
-
|
|
28902
|
-
|
|
28933
|
+
return !(registry2.portalOptOut ?? []).some((entry) => pathEqualsCanonical(entry, resolved));
|
|
28934
|
+
}
|
|
28935
|
+
function setRepoPortalSync(repoPath, enabled) {
|
|
28936
|
+
const resolved = canonicalizeControlRepoPath(repoPath);
|
|
28937
|
+
const registry2 = readRegistry();
|
|
28938
|
+
const current = registry2.portalOptOut ?? [];
|
|
28939
|
+
const without = current.filter((entry) => !pathEqualsCanonical(entry, resolved));
|
|
28940
|
+
if (enabled) {
|
|
28941
|
+
if (without.length === current.length) return;
|
|
28942
|
+
writeRegistry({
|
|
28943
|
+
repos: registry2.repos,
|
|
28944
|
+
...without.length > 0 ? { portalOptOut: without } : {}
|
|
28945
|
+
});
|
|
28946
|
+
return;
|
|
28947
|
+
}
|
|
28948
|
+
if (without.length !== current.length) return;
|
|
28949
|
+
writeRegistry({
|
|
28950
|
+
repos: registry2.repos,
|
|
28951
|
+
portalOptOut: [...without, resolved]
|
|
28903
28952
|
});
|
|
28953
|
+
}
|
|
28954
|
+
function removeRegisteredRepo(repoPath) {
|
|
28955
|
+
const resolved = canonicalizeControlRepoPath(repoPath);
|
|
28956
|
+
const registry2 = readRegistry();
|
|
28957
|
+
const next = registry2.repos.filter((entry) => !pathEqualsCanonical(entry, resolved));
|
|
28904
28958
|
if (next.length === registry2.repos.length) return false;
|
|
28905
|
-
|
|
28959
|
+
const portalOptOut = prunePortalOptOut(registry2, next);
|
|
28960
|
+
writeRegistry({
|
|
28961
|
+
repos: next,
|
|
28962
|
+
...portalOptOut ? { portalOptOut } : {}
|
|
28963
|
+
});
|
|
28906
28964
|
return true;
|
|
28907
28965
|
}
|
|
28908
28966
|
function listRegisteredRepos() {
|
|
@@ -28917,15 +28975,21 @@ function listRegisteredRepos() {
|
|
|
28917
28975
|
seen.add(canonical);
|
|
28918
28976
|
kept.push(canonical);
|
|
28919
28977
|
}
|
|
28920
|
-
|
|
28921
|
-
|
|
28978
|
+
const prunedOptOut = prunePortalOptOut(registry2, kept);
|
|
28979
|
+
const optOutBefore = registry2.portalOptOut ?? [];
|
|
28980
|
+
const optOutChanged = (prunedOptOut?.length ?? 0) !== optOutBefore.length || (prunedOptOut ?? []).some((p, i) => p !== optOutBefore[i]);
|
|
28981
|
+
if (registryChanged(registry2.repos, kept) || optOutChanged) {
|
|
28982
|
+
writeRegistry({
|
|
28983
|
+
repos: kept,
|
|
28984
|
+
...prunedOptOut ? { portalOptOut: prunedOptOut } : {}
|
|
28985
|
+
});
|
|
28922
28986
|
}
|
|
28923
28987
|
return kept;
|
|
28924
28988
|
}
|
|
28925
28989
|
function clearRegisteredRepos() {
|
|
28926
28990
|
const registry2 = readRegistry();
|
|
28927
28991
|
const count = registry2.repos.length;
|
|
28928
|
-
if (count === 0) return 0;
|
|
28992
|
+
if (count === 0 && !registry2.portalOptOut?.length) return 0;
|
|
28929
28993
|
writeRegistry({ repos: [] });
|
|
28930
28994
|
return count;
|
|
28931
28995
|
}
|
|
@@ -30904,6 +30968,29 @@ function listRecords(harnessRoot, dir, parse4) {
|
|
|
30904
30968
|
}
|
|
30905
30969
|
return records;
|
|
30906
30970
|
}
|
|
30971
|
+
function parseWorkLinkSpec(spec) {
|
|
30972
|
+
const parts = spec.split("|");
|
|
30973
|
+
if (parts.length < 2) {
|
|
30974
|
+
throw new Error(
|
|
30975
|
+
`Invalid work link "${spec}" \u2014 use source|url or source|url|label (example: github|https://github.com/org/repo/pull/42|PR #42)`
|
|
30976
|
+
);
|
|
30977
|
+
}
|
|
30978
|
+
const [source, url, ...labelParts] = parts;
|
|
30979
|
+
const label = labelParts.length > 0 ? labelParts.join("|") : void 0;
|
|
30980
|
+
return WorkUnitRelatedLinkSchema.parse({ source, url, label });
|
|
30981
|
+
}
|
|
30982
|
+
function mergeRelatedLinks(existing, incoming, primaryUrl) {
|
|
30983
|
+
if (!incoming?.length) return existing?.length ? existing : void 0;
|
|
30984
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30985
|
+
const merged = [];
|
|
30986
|
+
for (const link of [...existing ?? [], ...incoming]) {
|
|
30987
|
+
if (primaryUrl && link.url === primaryUrl) continue;
|
|
30988
|
+
if (seen.has(link.url)) continue;
|
|
30989
|
+
seen.add(link.url);
|
|
30990
|
+
merged.push(link);
|
|
30991
|
+
}
|
|
30992
|
+
return merged.length > 0 ? merged : void 0;
|
|
30993
|
+
}
|
|
30907
30994
|
function findWorkUnit(harnessRoot, workUnitId) {
|
|
30908
30995
|
const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
|
|
30909
30996
|
const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
|
|
@@ -30933,13 +31020,19 @@ function upsertWorkUnit(harnessRoot, input) {
|
|
|
30933
31020
|
}
|
|
30934
31021
|
}
|
|
30935
31022
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
31023
|
+
const sourceUrl = existing?.sourceUrl ?? metadata.sourceUrl;
|
|
30936
31024
|
const record2 = WorkUnitRecordSchema.parse({
|
|
30937
31025
|
...existing,
|
|
30938
31026
|
workUnitId: metadata.workUnitId,
|
|
30939
31027
|
source: existing?.source ?? metadata.source,
|
|
30940
|
-
sourceUrl
|
|
31028
|
+
sourceUrl,
|
|
30941
31029
|
title: existing?.title ?? metadata.title,
|
|
30942
31030
|
parentWorkUnitId: existing?.parentWorkUnitId ?? metadata.parentWorkUnitId,
|
|
31031
|
+
relatedLinks: mergeRelatedLinks(
|
|
31032
|
+
existing?.relatedLinks,
|
|
31033
|
+
metadata.relatedLinks,
|
|
31034
|
+
sourceUrl
|
|
31035
|
+
),
|
|
30943
31036
|
version: 1,
|
|
30944
31037
|
createdAt: existing?.createdAt ?? now,
|
|
30945
31038
|
updatedAt: now,
|
|
@@ -30952,6 +31045,23 @@ function upsertWorkUnit(harnessRoot, input) {
|
|
|
30952
31045
|
markDirty(harnessRoot);
|
|
30953
31046
|
return record2;
|
|
30954
31047
|
}
|
|
31048
|
+
function addWorkUnitLinks(harnessRoot, workUnitId, links) {
|
|
31049
|
+
const existing = findWorkUnit(harnessRoot, workUnitId);
|
|
31050
|
+
if (!existing) throw new Error(`Unknown work unit: ${workUnitId}`);
|
|
31051
|
+
const parsed = links.map((link) => WorkUnitRelatedLinkSchema.parse(link));
|
|
31052
|
+
const relatedLinks = mergeRelatedLinks(existing.relatedLinks, parsed, existing.sourceUrl);
|
|
31053
|
+
const record2 = WorkUnitRecordSchema.parse({
|
|
31054
|
+
...existing,
|
|
31055
|
+
relatedLinks,
|
|
31056
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
31057
|
+
});
|
|
31058
|
+
writeRecord2(
|
|
31059
|
+
hashedRecordPath(harnessRoot, WORK_UNITS_DIR, workUnitId),
|
|
31060
|
+
record2
|
|
31061
|
+
);
|
|
31062
|
+
markDirty(harnessRoot);
|
|
31063
|
+
return record2;
|
|
31064
|
+
}
|
|
30955
31065
|
function listWorkUnits(harnessRoot) {
|
|
30956
31066
|
return listRecords(
|
|
30957
31067
|
harnessRoot,
|
|
@@ -32431,7 +32541,7 @@ async function postForResponse(url, headers, payload) {
|
|
|
32431
32541
|
} catch (err) {
|
|
32432
32542
|
lastErr = err;
|
|
32433
32543
|
if (attempt < MAX_FETCH_ATTEMPTS) {
|
|
32434
|
-
await new Promise((
|
|
32544
|
+
await new Promise((resolve50) => setTimeout(resolve50, attempt * 100));
|
|
32435
32545
|
}
|
|
32436
32546
|
}
|
|
32437
32547
|
}
|
|
@@ -32631,7 +32741,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
|
|
|
32631
32741
|
const deadline = Date.now() + timeoutMs;
|
|
32632
32742
|
while (Date.now() < deadline) {
|
|
32633
32743
|
if (await isControlApiReachable(apiUrl)) return true;
|
|
32634
|
-
await new Promise((
|
|
32744
|
+
await new Promise((resolve50) => setTimeout(resolve50, intervalMs));
|
|
32635
32745
|
}
|
|
32636
32746
|
return false;
|
|
32637
32747
|
}
|
|
@@ -32734,6 +32844,7 @@ async function syncRepoWithLocalControl(options) {
|
|
|
32734
32844
|
}
|
|
32735
32845
|
}
|
|
32736
32846
|
async function syncRepoWithPortal(options, controlApiUrl) {
|
|
32847
|
+
if (!isRepoPortalSyncEnabled(options.repoPath)) return;
|
|
32737
32848
|
const portal = getPortalTarget();
|
|
32738
32849
|
if (!portal) return;
|
|
32739
32850
|
const { repoPath, dryRun, full } = options;
|
|
@@ -32956,6 +33067,7 @@ async function syncRunWithControlAsync(repoPath, run2) {
|
|
|
32956
33067
|
}
|
|
32957
33068
|
const portal = getPortalTarget();
|
|
32958
33069
|
if (!portal) return;
|
|
33070
|
+
if (!isRepoPortalSyncEnabled(canonical)) return;
|
|
32959
33071
|
try {
|
|
32960
33072
|
if (!await isControlApiReachable(portal.url)) return;
|
|
32961
33073
|
await postPortal(portal, "/api/sync", { path: canonical, runs: [run2] });
|
|
@@ -34128,15 +34240,15 @@ var require_route = __commonJS({
|
|
|
34128
34240
|
};
|
|
34129
34241
|
}
|
|
34130
34242
|
function wrapConversion(toModel, graph) {
|
|
34131
|
-
const
|
|
34243
|
+
const path66 = [graph[toModel].parent, toModel];
|
|
34132
34244
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
34133
34245
|
let cur = graph[toModel].parent;
|
|
34134
34246
|
while (graph[cur].parent) {
|
|
34135
|
-
|
|
34247
|
+
path66.unshift(graph[cur].parent);
|
|
34136
34248
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
34137
34249
|
cur = graph[cur].parent;
|
|
34138
34250
|
}
|
|
34139
|
-
fn.conversion =
|
|
34251
|
+
fn.conversion = path66;
|
|
34140
34252
|
return fn;
|
|
34141
34253
|
}
|
|
34142
34254
|
module2.exports = function(fromModel) {
|
|
@@ -40066,7 +40178,7 @@ var require_iso2022 = __commonJS({
|
|
|
40066
40178
|
// node_modules/chardet/index.js
|
|
40067
40179
|
var require_chardet = __commonJS({
|
|
40068
40180
|
"node_modules/chardet/index.js"(exports2, module2) {
|
|
40069
|
-
var
|
|
40181
|
+
var fs52 = require("fs");
|
|
40070
40182
|
var utf8 = require_utf8();
|
|
40071
40183
|
var unicode = require_unicode();
|
|
40072
40184
|
var mbcs = require_mbcs();
|
|
@@ -40140,28 +40252,28 @@ var require_chardet = __commonJS({
|
|
|
40140
40252
|
var fd;
|
|
40141
40253
|
var handler = function(err, buffer) {
|
|
40142
40254
|
if (fd) {
|
|
40143
|
-
|
|
40255
|
+
fs52.closeSync(fd);
|
|
40144
40256
|
}
|
|
40145
40257
|
if (err) return cb(err, null);
|
|
40146
40258
|
cb(null, self.detect(buffer, opts));
|
|
40147
40259
|
};
|
|
40148
40260
|
if (opts && opts.sampleSize) {
|
|
40149
|
-
fd =
|
|
40150
|
-
|
|
40261
|
+
fd = fs52.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
40262
|
+
fs52.read(fd, sample, 0, opts.sampleSize, null, function(err) {
|
|
40151
40263
|
handler(err, sample);
|
|
40152
40264
|
});
|
|
40153
40265
|
return;
|
|
40154
40266
|
}
|
|
40155
|
-
|
|
40267
|
+
fs52.readFile(filepath, handler);
|
|
40156
40268
|
};
|
|
40157
40269
|
module2.exports.detectFileSync = function(filepath, opts) {
|
|
40158
40270
|
if (opts && opts.sampleSize) {
|
|
40159
|
-
var fd =
|
|
40160
|
-
|
|
40161
|
-
|
|
40271
|
+
var fd = fs52.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
|
|
40272
|
+
fs52.readSync(fd, sample2, 0, opts.sampleSize);
|
|
40273
|
+
fs52.closeSync(fd);
|
|
40162
40274
|
return self.detect(sample2, opts);
|
|
40163
40275
|
}
|
|
40164
|
-
return self.detect(
|
|
40276
|
+
return self.detect(fs52.readFileSync(filepath), opts);
|
|
40165
40277
|
};
|
|
40166
40278
|
module2.exports.detectAll = function(buffer, opts) {
|
|
40167
40279
|
if (typeof opts !== "object") {
|
|
@@ -43626,16 +43738,16 @@ var require_os_tmpdir = __commonJS({
|
|
|
43626
43738
|
var isWindows = process.platform === "win32";
|
|
43627
43739
|
var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
|
|
43628
43740
|
module2.exports = function() {
|
|
43629
|
-
var
|
|
43741
|
+
var path66;
|
|
43630
43742
|
if (isWindows) {
|
|
43631
|
-
|
|
43743
|
+
path66 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
|
|
43632
43744
|
} else {
|
|
43633
|
-
|
|
43745
|
+
path66 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
|
|
43634
43746
|
}
|
|
43635
|
-
if (trailingSlashRe.test(
|
|
43636
|
-
|
|
43747
|
+
if (trailingSlashRe.test(path66)) {
|
|
43748
|
+
path66 = path66.slice(0, -1);
|
|
43637
43749
|
}
|
|
43638
|
-
return
|
|
43750
|
+
return path66;
|
|
43639
43751
|
};
|
|
43640
43752
|
}
|
|
43641
43753
|
});
|
|
@@ -43643,8 +43755,8 @@ var require_os_tmpdir = __commonJS({
|
|
|
43643
43755
|
// node_modules/tmp/lib/tmp.js
|
|
43644
43756
|
var require_tmp = __commonJS({
|
|
43645
43757
|
"node_modules/tmp/lib/tmp.js"(exports2, module2) {
|
|
43646
|
-
var
|
|
43647
|
-
var
|
|
43758
|
+
var fs52 = require("fs");
|
|
43759
|
+
var path66 = require("path");
|
|
43648
43760
|
var crypto6 = require("crypto");
|
|
43649
43761
|
var osTmpDir = require_os_tmpdir();
|
|
43650
43762
|
var _c2 = process.binding("constants");
|
|
@@ -43686,7 +43798,7 @@ var require_tmp = __commonJS({
|
|
|
43686
43798
|
}
|
|
43687
43799
|
function _generateTmpName(opts) {
|
|
43688
43800
|
if (opts.name) {
|
|
43689
|
-
return
|
|
43801
|
+
return path66.join(opts.dir || tmpDir, opts.name);
|
|
43690
43802
|
}
|
|
43691
43803
|
if (opts.template) {
|
|
43692
43804
|
return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
|
|
@@ -43697,7 +43809,7 @@ var require_tmp = __commonJS({
|
|
|
43697
43809
|
_randomChars(12),
|
|
43698
43810
|
opts.postfix || ""
|
|
43699
43811
|
].join("");
|
|
43700
|
-
return
|
|
43812
|
+
return path66.join(opts.dir || tmpDir, name);
|
|
43701
43813
|
}
|
|
43702
43814
|
function tmpName(options, callback) {
|
|
43703
43815
|
var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
|
|
@@ -43707,7 +43819,7 @@ var require_tmp = __commonJS({
|
|
|
43707
43819
|
return cb(new Error("Invalid template provided"));
|
|
43708
43820
|
(function _getUniqueName() {
|
|
43709
43821
|
const name = _generateTmpName(opts);
|
|
43710
|
-
|
|
43822
|
+
fs52.stat(name, function(err) {
|
|
43711
43823
|
if (!err) {
|
|
43712
43824
|
if (tries-- > 0) return _getUniqueName();
|
|
43713
43825
|
return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
|
|
@@ -43725,7 +43837,7 @@ var require_tmp = __commonJS({
|
|
|
43725
43837
|
do {
|
|
43726
43838
|
const name = _generateTmpName(opts);
|
|
43727
43839
|
try {
|
|
43728
|
-
|
|
43840
|
+
fs52.statSync(name);
|
|
43729
43841
|
} catch (e) {
|
|
43730
43842
|
return name;
|
|
43731
43843
|
}
|
|
@@ -43737,13 +43849,13 @@ var require_tmp = __commonJS({
|
|
|
43737
43849
|
opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
|
|
43738
43850
|
tmpName(opts, function _tmpNameCreated(err, name) {
|
|
43739
43851
|
if (err) return cb(err);
|
|
43740
|
-
|
|
43852
|
+
fs52.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
|
|
43741
43853
|
if (err2) return cb(err2);
|
|
43742
43854
|
if (opts.discardDescriptor) {
|
|
43743
|
-
return
|
|
43855
|
+
return fs52.close(fd, function _discardCallback(err3) {
|
|
43744
43856
|
if (err3) {
|
|
43745
43857
|
try {
|
|
43746
|
-
|
|
43858
|
+
fs52.unlinkSync(name);
|
|
43747
43859
|
} catch (e) {
|
|
43748
43860
|
if (!isENOENT(e)) {
|
|
43749
43861
|
err3 = e;
|
|
@@ -43766,9 +43878,9 @@ var require_tmp = __commonJS({
|
|
|
43766
43878
|
opts.postfix = opts.postfix || ".tmp";
|
|
43767
43879
|
const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
|
|
43768
43880
|
const name = tmpNameSync(opts);
|
|
43769
|
-
var fd =
|
|
43881
|
+
var fd = fs52.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
|
|
43770
43882
|
if (opts.discardDescriptor) {
|
|
43771
|
-
|
|
43883
|
+
fs52.closeSync(fd);
|
|
43772
43884
|
fd = void 0;
|
|
43773
43885
|
}
|
|
43774
43886
|
return {
|
|
@@ -43780,9 +43892,9 @@ var require_tmp = __commonJS({
|
|
|
43780
43892
|
function _rmdirRecursiveSync(root) {
|
|
43781
43893
|
const dirs = [root];
|
|
43782
43894
|
do {
|
|
43783
|
-
var dir2 = dirs.pop(), deferred = false, files =
|
|
43895
|
+
var dir2 = dirs.pop(), deferred = false, files = fs52.readdirSync(dir2);
|
|
43784
43896
|
for (var i = 0, length = files.length; i < length; i++) {
|
|
43785
|
-
var file2 =
|
|
43897
|
+
var file2 = path66.join(dir2, files[i]), stat = fs52.lstatSync(file2);
|
|
43786
43898
|
if (stat.isDirectory()) {
|
|
43787
43899
|
if (!deferred) {
|
|
43788
43900
|
deferred = true;
|
|
@@ -43790,11 +43902,11 @@ var require_tmp = __commonJS({
|
|
|
43790
43902
|
}
|
|
43791
43903
|
dirs.push(file2);
|
|
43792
43904
|
} else {
|
|
43793
|
-
|
|
43905
|
+
fs52.unlinkSync(file2);
|
|
43794
43906
|
}
|
|
43795
43907
|
}
|
|
43796
43908
|
if (!deferred) {
|
|
43797
|
-
|
|
43909
|
+
fs52.rmdirSync(dir2);
|
|
43798
43910
|
}
|
|
43799
43911
|
} while (dirs.length !== 0);
|
|
43800
43912
|
}
|
|
@@ -43802,7 +43914,7 @@ var require_tmp = __commonJS({
|
|
|
43802
43914
|
var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
|
|
43803
43915
|
tmpName(opts, function _tmpNameCreated(err, name) {
|
|
43804
43916
|
if (err) return cb(err);
|
|
43805
|
-
|
|
43917
|
+
fs52.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
|
|
43806
43918
|
if (err2) return cb(err2);
|
|
43807
43919
|
cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
|
|
43808
43920
|
});
|
|
@@ -43811,7 +43923,7 @@ var require_tmp = __commonJS({
|
|
|
43811
43923
|
function dirSync(options) {
|
|
43812
43924
|
var args = _parseArguments(options), opts = args[0];
|
|
43813
43925
|
const name = tmpNameSync(opts);
|
|
43814
|
-
|
|
43926
|
+
fs52.mkdirSync(name, opts.mode || DIR_MODE);
|
|
43815
43927
|
return {
|
|
43816
43928
|
name,
|
|
43817
43929
|
removeCallback: _prepareTmpDirRemoveCallback(name, opts)
|
|
@@ -43821,7 +43933,7 @@ var require_tmp = __commonJS({
|
|
|
43821
43933
|
const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
|
|
43822
43934
|
try {
|
|
43823
43935
|
if (0 <= fdPath[0]) {
|
|
43824
|
-
|
|
43936
|
+
fs52.closeSync(fdPath[0]);
|
|
43825
43937
|
}
|
|
43826
43938
|
} catch (e) {
|
|
43827
43939
|
if (!isEBADF(e) && !isENOENT(e)) {
|
|
@@ -43829,7 +43941,7 @@ var require_tmp = __commonJS({
|
|
|
43829
43941
|
}
|
|
43830
43942
|
}
|
|
43831
43943
|
try {
|
|
43832
|
-
|
|
43944
|
+
fs52.unlinkSync(fdPath[1]);
|
|
43833
43945
|
} catch (e) {
|
|
43834
43946
|
if (!isENOENT(e)) {
|
|
43835
43947
|
throw e;
|
|
@@ -43842,7 +43954,7 @@ var require_tmp = __commonJS({
|
|
|
43842
43954
|
return removeCallback;
|
|
43843
43955
|
}
|
|
43844
43956
|
function _prepareTmpDirRemoveCallback(name, opts) {
|
|
43845
|
-
const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync :
|
|
43957
|
+
const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs52.rmdirSync.bind(fs52);
|
|
43846
43958
|
const removeCallback = _prepareRemoveCallback(removeFunction, name);
|
|
43847
43959
|
if (!opts.keep) {
|
|
43848
43960
|
_removeObjects.unshift(removeCallback);
|
|
@@ -44993,7 +45105,7 @@ var require_Observable = __commonJS({
|
|
|
44993
45105
|
Observable2.prototype.forEach = function(next, promiseCtor) {
|
|
44994
45106
|
var _this = this;
|
|
44995
45107
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
44996
|
-
return new promiseCtor(function(
|
|
45108
|
+
return new promiseCtor(function(resolve50, reject) {
|
|
44997
45109
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
44998
45110
|
next: function(value) {
|
|
44999
45111
|
try {
|
|
@@ -45004,7 +45116,7 @@ var require_Observable = __commonJS({
|
|
|
45004
45116
|
}
|
|
45005
45117
|
},
|
|
45006
45118
|
error: reject,
|
|
45007
|
-
complete:
|
|
45119
|
+
complete: resolve50
|
|
45008
45120
|
});
|
|
45009
45121
|
_this.subscribe(subscriber);
|
|
45010
45122
|
});
|
|
@@ -45026,14 +45138,14 @@ var require_Observable = __commonJS({
|
|
|
45026
45138
|
Observable2.prototype.toPromise = function(promiseCtor) {
|
|
45027
45139
|
var _this = this;
|
|
45028
45140
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
45029
|
-
return new promiseCtor(function(
|
|
45141
|
+
return new promiseCtor(function(resolve50, reject) {
|
|
45030
45142
|
var value;
|
|
45031
45143
|
_this.subscribe(function(x) {
|
|
45032
45144
|
return value = x;
|
|
45033
45145
|
}, function(err) {
|
|
45034
45146
|
return reject(err);
|
|
45035
45147
|
}, function() {
|
|
45036
|
-
return
|
|
45148
|
+
return resolve50(value);
|
|
45037
45149
|
});
|
|
45038
45150
|
});
|
|
45039
45151
|
};
|
|
@@ -47129,11 +47241,11 @@ var require_innerFrom = __commonJS({
|
|
|
47129
47241
|
"use strict";
|
|
47130
47242
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
|
|
47131
47243
|
function adopt(value) {
|
|
47132
|
-
return value instanceof P2 ? value : new P2(function(
|
|
47133
|
-
|
|
47244
|
+
return value instanceof P2 ? value : new P2(function(resolve50) {
|
|
47245
|
+
resolve50(value);
|
|
47134
47246
|
});
|
|
47135
47247
|
}
|
|
47136
|
-
return new (P2 || (P2 = Promise))(function(
|
|
47248
|
+
return new (P2 || (P2 = Promise))(function(resolve50, reject) {
|
|
47137
47249
|
function fulfilled(value) {
|
|
47138
47250
|
try {
|
|
47139
47251
|
step(generator.next(value));
|
|
@@ -47149,7 +47261,7 @@ var require_innerFrom = __commonJS({
|
|
|
47149
47261
|
}
|
|
47150
47262
|
}
|
|
47151
47263
|
function step(result) {
|
|
47152
|
-
result.done ?
|
|
47264
|
+
result.done ? resolve50(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
47153
47265
|
}
|
|
47154
47266
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
47155
47267
|
});
|
|
@@ -47231,14 +47343,14 @@ var require_innerFrom = __commonJS({
|
|
|
47231
47343
|
}, i);
|
|
47232
47344
|
function verb(n) {
|
|
47233
47345
|
i[n] = o[n] && function(v2) {
|
|
47234
|
-
return new Promise(function(
|
|
47235
|
-
v2 = o[n](v2), settle(
|
|
47346
|
+
return new Promise(function(resolve50, reject) {
|
|
47347
|
+
v2 = o[n](v2), settle(resolve50, reject, v2.done, v2.value);
|
|
47236
47348
|
});
|
|
47237
47349
|
};
|
|
47238
47350
|
}
|
|
47239
|
-
function settle(
|
|
47351
|
+
function settle(resolve50, reject, d, v2) {
|
|
47240
47352
|
Promise.resolve(v2).then(function(v3) {
|
|
47241
|
-
|
|
47353
|
+
resolve50({ value: v3, done: d });
|
|
47242
47354
|
}, reject);
|
|
47243
47355
|
}
|
|
47244
47356
|
};
|
|
@@ -47857,7 +47969,7 @@ var require_lastValueFrom = __commonJS({
|
|
|
47857
47969
|
var EmptyError_1 = require_EmptyError();
|
|
47858
47970
|
function lastValueFrom2(source, config2) {
|
|
47859
47971
|
var hasConfig = typeof config2 === "object";
|
|
47860
|
-
return new Promise(function(
|
|
47972
|
+
return new Promise(function(resolve50, reject) {
|
|
47861
47973
|
var _hasValue = false;
|
|
47862
47974
|
var _value;
|
|
47863
47975
|
source.subscribe({
|
|
@@ -47868,9 +47980,9 @@ var require_lastValueFrom = __commonJS({
|
|
|
47868
47980
|
error: reject,
|
|
47869
47981
|
complete: function() {
|
|
47870
47982
|
if (_hasValue) {
|
|
47871
|
-
|
|
47983
|
+
resolve50(_value);
|
|
47872
47984
|
} else if (hasConfig) {
|
|
47873
|
-
|
|
47985
|
+
resolve50(config2.defaultValue);
|
|
47874
47986
|
} else {
|
|
47875
47987
|
reject(new EmptyError_1.EmptyError());
|
|
47876
47988
|
}
|
|
@@ -47892,16 +48004,16 @@ var require_firstValueFrom = __commonJS({
|
|
|
47892
48004
|
var Subscriber_1 = require_Subscriber();
|
|
47893
48005
|
function firstValueFrom(source, config2) {
|
|
47894
48006
|
var hasConfig = typeof config2 === "object";
|
|
47895
|
-
return new Promise(function(
|
|
48007
|
+
return new Promise(function(resolve50, reject) {
|
|
47896
48008
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
47897
48009
|
next: function(value) {
|
|
47898
|
-
|
|
48010
|
+
resolve50(value);
|
|
47899
48011
|
subscriber.unsubscribe();
|
|
47900
48012
|
},
|
|
47901
48013
|
error: reject,
|
|
47902
48014
|
complete: function() {
|
|
47903
48015
|
if (hasConfig) {
|
|
47904
|
-
|
|
48016
|
+
resolve50(config2.defaultValue);
|
|
47905
48017
|
} else {
|
|
47906
48018
|
reject(new EmptyError_1.EmptyError());
|
|
47907
48019
|
}
|
|
@@ -53694,14 +53806,14 @@ var require_run_async = __commonJS({
|
|
|
53694
53806
|
return function() {
|
|
53695
53807
|
var args = arguments;
|
|
53696
53808
|
var originalThis = this;
|
|
53697
|
-
var promise = new Promise(function(
|
|
53809
|
+
var promise = new Promise(function(resolve50, reject) {
|
|
53698
53810
|
var resolved = false;
|
|
53699
53811
|
const wrappedResolve = function(value) {
|
|
53700
53812
|
if (resolved) {
|
|
53701
53813
|
console.warn("Run-async promise already resolved.");
|
|
53702
53814
|
}
|
|
53703
53815
|
resolved = true;
|
|
53704
|
-
|
|
53816
|
+
resolve50(value);
|
|
53705
53817
|
};
|
|
53706
53818
|
var rejected = false;
|
|
53707
53819
|
const wrappedReject = function(value) {
|
|
@@ -57213,7 +57325,7 @@ var require_compile = __commonJS({
|
|
|
57213
57325
|
const schOrFunc = root.refs[ref];
|
|
57214
57326
|
if (schOrFunc)
|
|
57215
57327
|
return schOrFunc;
|
|
57216
|
-
let _sch =
|
|
57328
|
+
let _sch = resolve50.call(this, root, ref);
|
|
57217
57329
|
if (_sch === void 0) {
|
|
57218
57330
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
57219
57331
|
const { schemaId } = this.opts;
|
|
@@ -57240,7 +57352,7 @@ var require_compile = __commonJS({
|
|
|
57240
57352
|
function sameSchemaEnv(s1, s2) {
|
|
57241
57353
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
57242
57354
|
}
|
|
57243
|
-
function
|
|
57355
|
+
function resolve50(root, ref) {
|
|
57244
57356
|
let sch;
|
|
57245
57357
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
57246
57358
|
ref = sch;
|
|
@@ -57458,8 +57570,8 @@ var require_utils = __commonJS({
|
|
|
57458
57570
|
}
|
|
57459
57571
|
return ind;
|
|
57460
57572
|
}
|
|
57461
|
-
function removeDotSegments(
|
|
57462
|
-
let input =
|
|
57573
|
+
function removeDotSegments(path66) {
|
|
57574
|
+
let input = path66;
|
|
57463
57575
|
const output = [];
|
|
57464
57576
|
let nextSlash = -1;
|
|
57465
57577
|
let len = 0;
|
|
@@ -57711,8 +57823,8 @@ var require_schemes = __commonJS({
|
|
|
57711
57823
|
wsComponent.secure = void 0;
|
|
57712
57824
|
}
|
|
57713
57825
|
if (wsComponent.resourceName) {
|
|
57714
|
-
const [
|
|
57715
|
-
wsComponent.path =
|
|
57826
|
+
const [path66, query] = wsComponent.resourceName.split("?");
|
|
57827
|
+
wsComponent.path = path66 && path66 !== "/" ? path66 : void 0;
|
|
57716
57828
|
wsComponent.query = query;
|
|
57717
57829
|
wsComponent.resourceName = void 0;
|
|
57718
57830
|
}
|
|
@@ -57871,7 +57983,7 @@ var require_fast_uri = __commonJS({
|
|
|
57871
57983
|
}
|
|
57872
57984
|
return uri;
|
|
57873
57985
|
}
|
|
57874
|
-
function
|
|
57986
|
+
function resolve50(baseURI, relativeURI, options) {
|
|
57875
57987
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
57876
57988
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
57877
57989
|
schemelessOptions.skipEscape = true;
|
|
@@ -58129,7 +58241,7 @@ var require_fast_uri = __commonJS({
|
|
|
58129
58241
|
var fastUri = {
|
|
58130
58242
|
SCHEMES,
|
|
58131
58243
|
normalize: normalize3,
|
|
58132
|
-
resolve:
|
|
58244
|
+
resolve: resolve50,
|
|
58133
58245
|
resolveComponent,
|
|
58134
58246
|
equal,
|
|
58135
58247
|
serialize,
|
|
@@ -61105,12 +61217,12 @@ var require_dist = __commonJS({
|
|
|
61105
61217
|
throw new Error(`Unknown format "${name}"`);
|
|
61106
61218
|
return f;
|
|
61107
61219
|
};
|
|
61108
|
-
function addFormats(ajv, list,
|
|
61220
|
+
function addFormats(ajv, list, fs52, exportName) {
|
|
61109
61221
|
var _a2;
|
|
61110
61222
|
var _b2;
|
|
61111
61223
|
(_a2 = (_b2 = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
61112
61224
|
for (const f of list)
|
|
61113
|
-
ajv.addFormat(f,
|
|
61225
|
+
ajv.addFormat(f, fs52[f]);
|
|
61114
61226
|
}
|
|
61115
61227
|
module2.exports = exports2 = formatsPlugin;
|
|
61116
61228
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -62394,11 +62506,11 @@ var parser = new YargsParser({
|
|
|
62394
62506
|
resolve: import_path2.resolve,
|
|
62395
62507
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
62396
62508
|
// we can exercise all the lines below:
|
|
62397
|
-
require: (
|
|
62509
|
+
require: (path66) => {
|
|
62398
62510
|
if (typeof require !== "undefined") {
|
|
62399
|
-
return require(
|
|
62400
|
-
} else if (
|
|
62401
|
-
return JSON.parse((0, import_fs2.readFileSync)(
|
|
62511
|
+
return require(path66);
|
|
62512
|
+
} else if (path66.match(/\.json$/)) {
|
|
62513
|
+
return JSON.parse((0, import_fs2.readFileSync)(path66, "utf8"));
|
|
62402
62514
|
} else {
|
|
62403
62515
|
throw Error("only .json config files are supported in ESM");
|
|
62404
62516
|
}
|
|
@@ -64924,12 +65036,12 @@ var YargsInstance = class {
|
|
|
64924
65036
|
async getCompletion(args, done) {
|
|
64925
65037
|
argsert("<array> [function]", [args, done], arguments.length);
|
|
64926
65038
|
if (!done) {
|
|
64927
|
-
return new Promise((
|
|
65039
|
+
return new Promise((resolve50, reject) => {
|
|
64928
65040
|
__classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
|
|
64929
65041
|
if (err)
|
|
64930
65042
|
reject(err);
|
|
64931
65043
|
else
|
|
64932
|
-
|
|
65044
|
+
resolve50(completions);
|
|
64933
65045
|
});
|
|
64934
65046
|
});
|
|
64935
65047
|
} else {
|
|
@@ -66218,16 +66330,16 @@ async function handleAgentSkills(options) {
|
|
|
66218
66330
|
}
|
|
66219
66331
|
async function askYesNo(question) {
|
|
66220
66332
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
66221
|
-
return new Promise((
|
|
66333
|
+
return new Promise((resolve50) => {
|
|
66222
66334
|
process.stderr.write(`${question} `);
|
|
66223
66335
|
rl.once("line", (answer) => {
|
|
66224
66336
|
rl.close();
|
|
66225
66337
|
const trimmed = answer.trim();
|
|
66226
66338
|
if (trimmed === "") {
|
|
66227
|
-
|
|
66339
|
+
resolve50(true);
|
|
66228
66340
|
return;
|
|
66229
66341
|
}
|
|
66230
|
-
|
|
66342
|
+
resolve50(/^y(es)?$/i.test(trimmed));
|
|
66231
66343
|
});
|
|
66232
66344
|
});
|
|
66233
66345
|
}
|
|
@@ -66307,7 +66419,7 @@ function handleRemove(argv) {
|
|
|
66307
66419
|
}
|
|
66308
66420
|
|
|
66309
66421
|
// src/cli/commands/env.ts
|
|
66310
|
-
var
|
|
66422
|
+
var path55 = __toESM(require("path"));
|
|
66311
66423
|
|
|
66312
66424
|
// src/cli/finish-command.ts
|
|
66313
66425
|
init_sync_context();
|
|
@@ -67632,13 +67744,13 @@ var PromisePolyfill = class extends Promise {
|
|
|
67632
67744
|
// Available starting from Node 22
|
|
67633
67745
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
67634
67746
|
static withResolver() {
|
|
67635
|
-
let
|
|
67747
|
+
let resolve50;
|
|
67636
67748
|
let reject;
|
|
67637
67749
|
const promise = new Promise((res, rej) => {
|
|
67638
|
-
|
|
67750
|
+
resolve50 = res;
|
|
67639
67751
|
reject = rej;
|
|
67640
67752
|
});
|
|
67641
|
-
return { promise, resolve:
|
|
67753
|
+
return { promise, resolve: resolve50, reject };
|
|
67642
67754
|
}
|
|
67643
67755
|
};
|
|
67644
67756
|
|
|
@@ -67655,7 +67767,7 @@ function createPrompt(view) {
|
|
|
67655
67767
|
output
|
|
67656
67768
|
});
|
|
67657
67769
|
const screen = new ScreenManager(rl);
|
|
67658
|
-
const { promise, resolve:
|
|
67770
|
+
const { promise, resolve: resolve50, reject } = PromisePolyfill.withResolver();
|
|
67659
67771
|
const cancel = () => reject(new CancelPromptError());
|
|
67660
67772
|
if (signal) {
|
|
67661
67773
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -67679,7 +67791,7 @@ function createPrompt(view) {
|
|
|
67679
67791
|
cycle(() => {
|
|
67680
67792
|
try {
|
|
67681
67793
|
const nextView = view(config2, (value) => {
|
|
67682
|
-
setImmediate(() =>
|
|
67794
|
+
setImmediate(() => resolve50(value));
|
|
67683
67795
|
});
|
|
67684
67796
|
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
67685
67797
|
screen.render(content, bottomContent);
|
|
@@ -68666,9 +68778,9 @@ var import_run_async = __toESM(require_run_async(), 1);
|
|
|
68666
68778
|
var import_mute_stream2 = __toESM(require_lib(), 1);
|
|
68667
68779
|
var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
|
|
68668
68780
|
var _ = {
|
|
68669
|
-
set: (obj,
|
|
68781
|
+
set: (obj, path66 = "", value) => {
|
|
68670
68782
|
let pointer = obj;
|
|
68671
|
-
|
|
68783
|
+
path66.split(".").forEach((key, index, arr) => {
|
|
68672
68784
|
if (key === "__proto__" || key === "constructor")
|
|
68673
68785
|
return;
|
|
68674
68786
|
if (index === arr.length - 1) {
|
|
@@ -68679,8 +68791,8 @@ var _ = {
|
|
|
68679
68791
|
pointer = pointer[key];
|
|
68680
68792
|
});
|
|
68681
68793
|
},
|
|
68682
|
-
get: (obj,
|
|
68683
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
68794
|
+
get: (obj, path66 = "", defaultValue) => {
|
|
68795
|
+
const travel = (regexp) => String.prototype.split.call(path66, regexp).filter(Boolean).reduce(
|
|
68684
68796
|
// @ts-expect-error implicit any on res[key]
|
|
68685
68797
|
(res, key) => res !== null && res !== void 0 ? res[key] : res,
|
|
68686
68798
|
obj
|
|
@@ -68794,7 +68906,7 @@ var PromptsRunner = class {
|
|
|
68794
68906
|
throw new Error(`Prompt for type ${question.type} not found`);
|
|
68795
68907
|
}
|
|
68796
68908
|
let cleanupSignal;
|
|
68797
|
-
const promptFn = isPromptConstructor(prompt2) ? (q, { signal: signal2 } = {}) => new Promise((
|
|
68909
|
+
const promptFn = isPromptConstructor(prompt2) ? (q, { signal: signal2 } = {}) => new Promise((resolve50, reject) => {
|
|
68798
68910
|
const rl = import_node_readline.default.createInterface(setupReadlineOptions(this.opt));
|
|
68799
68911
|
rl.resume();
|
|
68800
68912
|
const onClose = () => {
|
|
@@ -68830,7 +68942,7 @@ var PromptsRunner = class {
|
|
|
68830
68942
|
cleanupSignal = void 0;
|
|
68831
68943
|
};
|
|
68832
68944
|
}
|
|
68833
|
-
activePrompt.run().then(
|
|
68945
|
+
activePrompt.run().then(resolve50, reject).finally(cleanup);
|
|
68834
68946
|
}) : prompt2;
|
|
68835
68947
|
const { signal: moduleSignal } = this.opt;
|
|
68836
68948
|
if (moduleSignal?.aborted) {
|
|
@@ -71185,12 +71297,12 @@ function printAdaptationPrompt(content) {
|
|
|
71185
71297
|
}
|
|
71186
71298
|
function askYesNo2(question) {
|
|
71187
71299
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
71188
|
-
return new Promise((
|
|
71300
|
+
return new Promise((resolve50) => {
|
|
71189
71301
|
process.stderr.write(`${question} `);
|
|
71190
71302
|
rl.once("line", (answer) => {
|
|
71191
71303
|
rl.close();
|
|
71192
71304
|
const trimmed = answer.trim();
|
|
71193
|
-
|
|
71305
|
+
resolve50(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
71194
71306
|
});
|
|
71195
71307
|
});
|
|
71196
71308
|
}
|
|
@@ -71279,16 +71391,16 @@ async function promptScaffoldCursorRule(exists) {
|
|
|
71279
71391
|
}
|
|
71280
71392
|
async function askYesNo3(question) {
|
|
71281
71393
|
const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
|
|
71282
|
-
return new Promise((
|
|
71394
|
+
return new Promise((resolve50) => {
|
|
71283
71395
|
process.stderr.write(`${question} `);
|
|
71284
71396
|
rl.once("line", (answer) => {
|
|
71285
71397
|
rl.close();
|
|
71286
71398
|
const trimmed = answer.trim();
|
|
71287
71399
|
if (trimmed === "") {
|
|
71288
|
-
|
|
71400
|
+
resolve50(true);
|
|
71289
71401
|
return;
|
|
71290
71402
|
}
|
|
71291
|
-
|
|
71403
|
+
resolve50(/^y(es)?$/i.test(trimmed));
|
|
71292
71404
|
});
|
|
71293
71405
|
});
|
|
71294
71406
|
}
|
|
@@ -71728,7 +71840,8 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
71728
71840
|
source: options.source,
|
|
71729
71841
|
sourceUrl: options.sourceUrl,
|
|
71730
71842
|
title: options.title,
|
|
71731
|
-
parentWorkUnitId: options.parentWorkUnitId
|
|
71843
|
+
parentWorkUnitId: options.parentWorkUnitId,
|
|
71844
|
+
relatedLinks: options.relatedLinks
|
|
71732
71845
|
});
|
|
71733
71846
|
createWorkAttempt(harnessRoot, {
|
|
71734
71847
|
attemptId,
|
|
@@ -72005,21 +72118,319 @@ var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunSer
|
|
|
72005
72118
|
|
|
72006
72119
|
// src/cli/commands/env.ts
|
|
72007
72120
|
init_runs();
|
|
72121
|
+
init_work_units();
|
|
72122
|
+
init_manifest();
|
|
72123
|
+
init_slot_status();
|
|
72124
|
+
|
|
72125
|
+
// src/core/cleanup-service.ts
|
|
72126
|
+
var fs46 = __toESM(require("fs"));
|
|
72127
|
+
var os18 = __toESM(require("os"));
|
|
72128
|
+
var path53 = __toESM(require("path"));
|
|
72129
|
+
var import_child_process14 = require("child_process");
|
|
72130
|
+
init_control_sync();
|
|
72131
|
+
init_control_repo_path();
|
|
72008
72132
|
init_slot_status();
|
|
72133
|
+
init_manifest();
|
|
72134
|
+
var DEFAULT_STALE_DAYS = 7;
|
|
72135
|
+
function getWorktreesRoot() {
|
|
72136
|
+
if (process.env.HAR_WORKTREES_ROOT) {
|
|
72137
|
+
return path53.resolve(process.env.HAR_WORKTREES_ROOT);
|
|
72138
|
+
}
|
|
72139
|
+
return path53.join(process.env.HOME || os18.homedir(), "worktrees");
|
|
72140
|
+
}
|
|
72141
|
+
function runGit3(cwd, args) {
|
|
72142
|
+
try {
|
|
72143
|
+
return (0, import_child_process14.execSync)(`git ${args}`, {
|
|
72144
|
+
cwd,
|
|
72145
|
+
encoding: "utf8",
|
|
72146
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
72147
|
+
}).trim();
|
|
72148
|
+
} catch {
|
|
72149
|
+
return void 0;
|
|
72150
|
+
}
|
|
72151
|
+
}
|
|
72152
|
+
function basenameRepo(repoPath) {
|
|
72153
|
+
return path53.basename(canonicalizeControlRepoPath(repoPath));
|
|
72154
|
+
}
|
|
72155
|
+
function ageDaysFrom(iso) {
|
|
72156
|
+
if (!iso) return void 0;
|
|
72157
|
+
const created = Date.parse(iso);
|
|
72158
|
+
if (Number.isNaN(created)) return void 0;
|
|
72159
|
+
return Math.floor((Date.now() - created) / (24 * 60 * 60 * 1e3));
|
|
72160
|
+
}
|
|
72161
|
+
function matchesKeep(candidate, keep) {
|
|
72162
|
+
if (!keep?.length) return false;
|
|
72163
|
+
for (const pin of keep) {
|
|
72164
|
+
if (pin.worktreePath && candidate.worktreePath) {
|
|
72165
|
+
if (path53.resolve(pin.worktreePath) === path53.resolve(candidate.worktreePath)) return true;
|
|
72166
|
+
}
|
|
72167
|
+
if (pin.repoPath && pin.agentId !== void 0 && candidate.agentId !== void 0) {
|
|
72168
|
+
const repo = canonicalizeControlRepoPath(pin.repoPath);
|
|
72169
|
+
const candidateRepo = path53.resolve(candidate.repoPath);
|
|
72170
|
+
if ((repo === candidateRepo || path53.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
|
|
72171
|
+
return true;
|
|
72172
|
+
}
|
|
72173
|
+
}
|
|
72174
|
+
if (pin.repoPath && pin.agentId === void 0 && !pin.worktreePath) {
|
|
72175
|
+
if (canonicalizeControlRepoPath(pin.repoPath) === candidate.repoPath) return true;
|
|
72176
|
+
}
|
|
72177
|
+
}
|
|
72178
|
+
return false;
|
|
72179
|
+
}
|
|
72180
|
+
function classifySlotCandidate(repoPath, projectName, slot, options) {
|
|
72181
|
+
if (!slot.active && !slot.worktreePath) return void 0;
|
|
72182
|
+
const candidate = {
|
|
72183
|
+
kind: "active_slot",
|
|
72184
|
+
repoPath,
|
|
72185
|
+
projectName,
|
|
72186
|
+
agentId: slot.agentId,
|
|
72187
|
+
worktreePath: slot.worktreePath ?? slot.workDir,
|
|
72188
|
+
branch: slot.branch,
|
|
72189
|
+
active: slot.active,
|
|
72190
|
+
dirty: slot.dirty,
|
|
72191
|
+
ageDays: ageDaysFrom(slot.sessionCreatedAt),
|
|
72192
|
+
sessionCreatedAt: slot.sessionCreatedAt,
|
|
72193
|
+
recommendation: "review",
|
|
72194
|
+
reason: "active session"
|
|
72195
|
+
};
|
|
72196
|
+
if (matchesKeep(candidate, options?.keep)) {
|
|
72197
|
+
candidate.recommendation = "keep";
|
|
72198
|
+
candidate.reason = "pinned with --keep";
|
|
72199
|
+
return candidate;
|
|
72200
|
+
}
|
|
72201
|
+
if (slot.dirty) {
|
|
72202
|
+
candidate.recommendation = "review";
|
|
72203
|
+
candidate.reason = "uncommitted changes \u2014 review before teardown";
|
|
72204
|
+
return candidate;
|
|
72205
|
+
}
|
|
72206
|
+
if (slot.sessionStatus === "failed" || slot.sessionStatus === "starting") {
|
|
72207
|
+
candidate.recommendation = "review";
|
|
72208
|
+
candidate.reason = "failed or resumable session \u2014 recover or teardown manually";
|
|
72209
|
+
return candidate;
|
|
72210
|
+
}
|
|
72211
|
+
const staleDays = options?.staleDays ?? DEFAULT_STALE_DAYS;
|
|
72212
|
+
const age = candidate.ageDays;
|
|
72213
|
+
if (age !== void 0 && age >= staleDays) {
|
|
72214
|
+
candidate.recommendation = "teardown";
|
|
72215
|
+
candidate.reason = `idle ${age}d, clean`;
|
|
72216
|
+
return candidate;
|
|
72217
|
+
}
|
|
72218
|
+
if (slot.active) {
|
|
72219
|
+
candidate.recommendation = "review";
|
|
72220
|
+
candidate.reason = age !== void 0 ? `active session (${age}d) \u2014 keep unless finished` : "active session \u2014 keep unless finished";
|
|
72221
|
+
}
|
|
72222
|
+
return candidate;
|
|
72223
|
+
}
|
|
72224
|
+
function resolveRepoForWorktree(worktreePath) {
|
|
72225
|
+
if (!fs46.existsSync(worktreePath)) return void 0;
|
|
72226
|
+
const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
|
|
72227
|
+
if (!commonDir) return void 0;
|
|
72228
|
+
const gitRoot = path53.resolve(worktreePath, commonDir, "..");
|
|
72229
|
+
if (!readManifest(gitRoot)) return void 0;
|
|
72230
|
+
return canonicalizeControlRepoPath(gitRoot);
|
|
72231
|
+
}
|
|
72232
|
+
function discoverOrphanWorktrees(knownPaths) {
|
|
72233
|
+
const worktreesRoot = getWorktreesRoot();
|
|
72234
|
+
if (!fs46.existsSync(worktreesRoot)) return [];
|
|
72235
|
+
const orphans = [];
|
|
72236
|
+
for (const entry of fs46.readdirSync(worktreesRoot, { withFileTypes: true })) {
|
|
72237
|
+
if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
|
|
72238
|
+
const worktreePath = path53.resolve(path53.join(worktreesRoot, entry.name));
|
|
72239
|
+
if (knownPaths.has(worktreePath)) continue;
|
|
72240
|
+
const repoPath = resolveRepoForWorktree(worktreePath) ?? worktreesRoot;
|
|
72241
|
+
const porcelain = runGit3(worktreePath, "status --porcelain");
|
|
72242
|
+
const dirty = porcelain !== void 0 ? porcelain.length > 0 : void 0;
|
|
72243
|
+
const branch = runGit3(worktreePath, "rev-parse --abbrev-ref HEAD");
|
|
72244
|
+
orphans.push({
|
|
72245
|
+
kind: "orphan_worktree",
|
|
72246
|
+
repoPath,
|
|
72247
|
+
projectName: basenameRepo(repoPath),
|
|
72248
|
+
worktreePath,
|
|
72249
|
+
branch: branch && branch !== "HEAD" ? branch : void 0,
|
|
72250
|
+
active: false,
|
|
72251
|
+
dirty,
|
|
72252
|
+
recommendation: dirty ? "review" : "remove_orphan",
|
|
72253
|
+
reason: dirty ? "orphan worktree with uncommitted changes" : "orphan worktree \u2014 no slot registry"
|
|
72254
|
+
});
|
|
72255
|
+
}
|
|
72256
|
+
return orphans.sort((a, b2) => (a.worktreePath ?? "").localeCompare(b2.worktreePath ?? ""));
|
|
72257
|
+
}
|
|
72258
|
+
async function discoverCleanupCandidates(options = {}) {
|
|
72259
|
+
const repoPaths = options.repoPaths ?? await discoverHarRepos({ cwd: options.cwd ?? process.cwd() });
|
|
72260
|
+
const candidates = [];
|
|
72261
|
+
const knownWorktreePaths = /* @__PURE__ */ new Set();
|
|
72262
|
+
for (const repoPath of repoPaths) {
|
|
72263
|
+
if (!fs46.existsSync(repoPath) || !readManifest(repoPath)) continue;
|
|
72264
|
+
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
72265
|
+
const canonicalRepo = canonicalizeControlRepoPath(harnessRoot);
|
|
72266
|
+
const status = collectEnvironmentStatus(harnessRoot);
|
|
72267
|
+
const projectName = basenameRepo(harnessRoot);
|
|
72268
|
+
for (const slot of status.slots) {
|
|
72269
|
+
if (slot.worktreePath) knownWorktreePaths.add(path53.resolve(slot.worktreePath));
|
|
72270
|
+
if (slot.workDir) knownWorktreePaths.add(path53.resolve(slot.workDir));
|
|
72271
|
+
const candidate = classifySlotCandidate(canonicalRepo, projectName, slot, {
|
|
72272
|
+
staleDays: options.staleDays,
|
|
72273
|
+
keep: options.keep
|
|
72274
|
+
});
|
|
72275
|
+
if (!candidate) continue;
|
|
72276
|
+
if (candidate.recommendation === "review" && !options.includeReview) {
|
|
72277
|
+
}
|
|
72278
|
+
candidates.push(candidate);
|
|
72279
|
+
}
|
|
72280
|
+
}
|
|
72281
|
+
if (options.orphans !== false) {
|
|
72282
|
+
for (const orphan of discoverOrphanWorktrees(knownWorktreePaths)) {
|
|
72283
|
+
if (matchesKeep(orphan, options.keep)) {
|
|
72284
|
+
orphan.recommendation = "keep";
|
|
72285
|
+
orphan.reason = "pinned with --keep";
|
|
72286
|
+
}
|
|
72287
|
+
candidates.push(orphan);
|
|
72288
|
+
}
|
|
72289
|
+
}
|
|
72290
|
+
return {
|
|
72291
|
+
candidates: candidates.sort((a, b2) => {
|
|
72292
|
+
const repo = a.repoPath.localeCompare(b2.repoPath);
|
|
72293
|
+
if (repo !== 0) return repo;
|
|
72294
|
+
return (a.agentId ?? 0) - (b2.agentId ?? 0);
|
|
72295
|
+
}),
|
|
72296
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
72297
|
+
};
|
|
72298
|
+
}
|
|
72299
|
+
function selectAutoApprovedCandidates(plan, options) {
|
|
72300
|
+
return plan.candidates.filter((candidate) => {
|
|
72301
|
+
if (candidate.recommendation === "keep") return false;
|
|
72302
|
+
if (candidate.recommendation === "review") return options?.includeReview === true;
|
|
72303
|
+
return candidate.recommendation === "teardown" || candidate.recommendation === "remove_orphan";
|
|
72304
|
+
});
|
|
72305
|
+
}
|
|
72306
|
+
function formatCleanupPlan(plan) {
|
|
72307
|
+
if (plan.candidates.length === 0) {
|
|
72308
|
+
return "No session worktrees or orphans found.";
|
|
72309
|
+
}
|
|
72310
|
+
const lines2 = [];
|
|
72311
|
+
lines2.push(
|
|
72312
|
+
`${"REC".padEnd(8)} ${"REPO".padEnd(18)} ${"SLOT".padEnd(6)} ${"AGE".padEnd(5)} WORKTREE / REASON`
|
|
72313
|
+
);
|
|
72314
|
+
lines2.push("-".repeat(100));
|
|
72315
|
+
for (const candidate of plan.candidates) {
|
|
72316
|
+
const slot = candidate.agentId !== void 0 ? String(candidate.agentId) : "-";
|
|
72317
|
+
const age = candidate.ageDays !== void 0 ? `${candidate.ageDays}d` : "-";
|
|
72318
|
+
const target = candidate.worktreePath ?? candidate.repoPath;
|
|
72319
|
+
lines2.push(
|
|
72320
|
+
`${candidate.recommendation.padEnd(8)} ${candidate.projectName.padEnd(18)} ${slot.padEnd(6)} ${age.padEnd(5)} ${target}`
|
|
72321
|
+
);
|
|
72322
|
+
lines2.push(` ${candidate.reason}`);
|
|
72323
|
+
}
|
|
72324
|
+
return lines2.join("\n");
|
|
72325
|
+
}
|
|
72326
|
+
async function askYesNo4(question) {
|
|
72327
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
72328
|
+
const readline8 = await import("readline");
|
|
72329
|
+
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
72330
|
+
const answer = await new Promise((resolve50) => {
|
|
72331
|
+
rl.question(question, resolve50);
|
|
72332
|
+
});
|
|
72333
|
+
rl.close();
|
|
72334
|
+
return /^[Yy]$/.test(answer.trim());
|
|
72335
|
+
}
|
|
72336
|
+
async function confirmCleanupSelection(candidates) {
|
|
72337
|
+
if (candidates.length === 0) return [];
|
|
72338
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
72339
|
+
throw new Error("Non-interactive terminal \u2014 pass --yes (and optionally --include-review)");
|
|
72340
|
+
}
|
|
72341
|
+
const approved = [];
|
|
72342
|
+
for (const candidate of candidates) {
|
|
72343
|
+
if (candidate.recommendation === "keep") continue;
|
|
72344
|
+
const label = candidate.kind === "orphan_worktree" ? `orphan ${candidate.worktreePath}` : `${candidate.projectName} agent ${candidate.agentId}`;
|
|
72345
|
+
const action = candidate.recommendation === "remove_orphan" ? "remove" : "teardown";
|
|
72346
|
+
const ok = await askYesNo4(`${action} ${label}? [${candidate.recommendation === "teardown" || candidate.recommendation === "remove_orphan" ? "Y" : "y"}/n] `);
|
|
72347
|
+
if (ok) approved.push(candidate);
|
|
72348
|
+
}
|
|
72349
|
+
return approved;
|
|
72350
|
+
}
|
|
72351
|
+
async function executeCleanupCandidates(candidates, options = {}) {
|
|
72352
|
+
const service = createRunService();
|
|
72353
|
+
const outcomes = [];
|
|
72354
|
+
for (const candidate of candidates) {
|
|
72355
|
+
if (candidate.recommendation === "keep") continue;
|
|
72356
|
+
if (options.dryRun) {
|
|
72357
|
+
outcomes.push({ candidate, ok: true });
|
|
72358
|
+
continue;
|
|
72359
|
+
}
|
|
72360
|
+
try {
|
|
72361
|
+
if (candidate.kind === "active_slot" && candidate.agentId !== void 0) {
|
|
72362
|
+
const result = await service.teardownEnvironment({
|
|
72363
|
+
repoPath: candidate.repoPath,
|
|
72364
|
+
agentId: candidate.agentId,
|
|
72365
|
+
capture: false,
|
|
72366
|
+
trigger: "cli"
|
|
72367
|
+
});
|
|
72368
|
+
outcomes.push({
|
|
72369
|
+
candidate,
|
|
72370
|
+
ok: result.code === 0,
|
|
72371
|
+
error: result.code === 0 ? void 0 : result.stderr?.trim() || `exit ${result.code}`
|
|
72372
|
+
});
|
|
72373
|
+
continue;
|
|
72374
|
+
}
|
|
72375
|
+
if (candidate.kind === "orphan_worktree" && candidate.worktreePath) {
|
|
72376
|
+
if (fs46.existsSync(candidate.worktreePath)) {
|
|
72377
|
+
const repoRoot = candidate.repoPath !== getWorktreesRoot() ? candidate.repoPath : resolveRepoForWorktree(candidate.worktreePath);
|
|
72378
|
+
if (repoRoot) {
|
|
72379
|
+
try {
|
|
72380
|
+
(0, import_child_process14.execSync)(`git worktree remove --force ${JSON.stringify(candidate.worktreePath)}`, {
|
|
72381
|
+
cwd: repoRoot,
|
|
72382
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
72383
|
+
});
|
|
72384
|
+
} catch {
|
|
72385
|
+
}
|
|
72386
|
+
}
|
|
72387
|
+
if (fs46.existsSync(candidate.worktreePath)) {
|
|
72388
|
+
fs46.rmSync(candidate.worktreePath, { recursive: true, force: true });
|
|
72389
|
+
}
|
|
72390
|
+
}
|
|
72391
|
+
outcomes.push({ candidate, ok: true });
|
|
72392
|
+
continue;
|
|
72393
|
+
}
|
|
72394
|
+
outcomes.push({ candidate, ok: false, error: "unsupported candidate" });
|
|
72395
|
+
} catch (err) {
|
|
72396
|
+
outcomes.push({
|
|
72397
|
+
candidate,
|
|
72398
|
+
ok: false,
|
|
72399
|
+
error: err instanceof Error ? err.message : String(err)
|
|
72400
|
+
});
|
|
72401
|
+
}
|
|
72402
|
+
}
|
|
72403
|
+
return outcomes;
|
|
72404
|
+
}
|
|
72405
|
+
function parseCleanupKeepPins(values) {
|
|
72406
|
+
if (!values?.length) return [];
|
|
72407
|
+
return values.map((raw) => {
|
|
72408
|
+
const agentMatch = raw.match(/^(.+):(\d+)$/);
|
|
72409
|
+
if (agentMatch) {
|
|
72410
|
+
return { repoPath: agentMatch[1], agentId: Number(agentMatch[2]) };
|
|
72411
|
+
}
|
|
72412
|
+
if (raw.startsWith("/") || raw.startsWith("~")) {
|
|
72413
|
+
return {
|
|
72414
|
+
worktreePath: raw.startsWith("~") ? path53.join(process.env.HOME || os18.homedir(), raw.slice(2)) : path53.resolve(raw)
|
|
72415
|
+
};
|
|
72416
|
+
}
|
|
72417
|
+
return { repoPath: raw };
|
|
72418
|
+
});
|
|
72419
|
+
}
|
|
72009
72420
|
|
|
72010
72421
|
// src/core/commit-gate-onboarding.ts
|
|
72011
72422
|
var readline7 = __toESM(require("readline"));
|
|
72012
72423
|
init_hooks();
|
|
72013
72424
|
init_stages();
|
|
72014
72425
|
init_logging();
|
|
72015
|
-
function
|
|
72426
|
+
function askYesNo5(question) {
|
|
72016
72427
|
const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
|
|
72017
|
-
return new Promise((
|
|
72428
|
+
return new Promise((resolve50) => {
|
|
72018
72429
|
process.stderr.write(`${question} `);
|
|
72019
72430
|
rl.once("line", (answer) => {
|
|
72020
72431
|
rl.close();
|
|
72021
72432
|
const trimmed = answer.trim();
|
|
72022
|
-
|
|
72433
|
+
resolve50(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
72023
72434
|
});
|
|
72024
72435
|
});
|
|
72025
72436
|
}
|
|
@@ -72044,7 +72455,7 @@ async function handleCommitGateOnboarding(options) {
|
|
|
72044
72455
|
const status = getHooksStatus(options.repoPath);
|
|
72045
72456
|
let shouldInstall = status.preCommitInstalled || status.postCommitInstalled || options.install === "always" || options.autoYes === true;
|
|
72046
72457
|
if (!shouldInstall && options.install === "prompt" && process.stdin.isTTY && process.stdout.isTTY) {
|
|
72047
|
-
shouldInstall = await
|
|
72458
|
+
shouldInstall = await askYesNo5("Install the HAR commit gate for this repository? [Y/n]");
|
|
72048
72459
|
}
|
|
72049
72460
|
if (!shouldInstall) {
|
|
72050
72461
|
info("Commit gate is not installed; run `har hooks install` when ready.");
|
|
@@ -72061,21 +72472,21 @@ async function handleCommitGateOnboarding(options) {
|
|
|
72061
72472
|
}
|
|
72062
72473
|
|
|
72063
72474
|
// src/core/onboarding-preferences.ts
|
|
72064
|
-
var
|
|
72065
|
-
var
|
|
72066
|
-
var
|
|
72475
|
+
var fs47 = __toESM(require("fs"));
|
|
72476
|
+
var os19 = __toESM(require("os"));
|
|
72477
|
+
var path54 = __toESM(require("path"));
|
|
72067
72478
|
init_schema2();
|
|
72068
72479
|
function getOnboardingPreferencesPath() {
|
|
72069
72480
|
if (process.env.HAR_PREFERENCES_PATH) {
|
|
72070
|
-
return
|
|
72481
|
+
return path54.resolve(process.env.HAR_PREFERENCES_PATH);
|
|
72071
72482
|
}
|
|
72072
|
-
return
|
|
72483
|
+
return path54.join(os19.homedir(), ".har", "preferences.json");
|
|
72073
72484
|
}
|
|
72074
72485
|
function readOnboardingPreferences() {
|
|
72075
72486
|
const preferencePath = getOnboardingPreferencesPath();
|
|
72076
72487
|
try {
|
|
72077
|
-
if (!
|
|
72078
|
-
return OnboardingPreferencesSchema.parse(JSON.parse(
|
|
72488
|
+
if (!fs47.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
|
|
72489
|
+
return OnboardingPreferencesSchema.parse(JSON.parse(fs47.readFileSync(preferencePath, "utf8")));
|
|
72079
72490
|
} catch {
|
|
72080
72491
|
return OnboardingPreferencesSchema.parse({});
|
|
72081
72492
|
}
|
|
@@ -72100,8 +72511,8 @@ function writeOnboardingPreferences(overrides) {
|
|
|
72100
72511
|
};
|
|
72101
72512
|
const parsed = OnboardingPreferencesSchema.parse(preference);
|
|
72102
72513
|
const preferencePath = getOnboardingPreferencesPath();
|
|
72103
|
-
|
|
72104
|
-
|
|
72514
|
+
fs47.mkdirSync(path54.dirname(preferencePath), { recursive: true });
|
|
72515
|
+
fs47.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
|
|
72105
72516
|
`);
|
|
72106
72517
|
return parsed;
|
|
72107
72518
|
}
|
|
@@ -72165,6 +72576,14 @@ feature branch.
|
|
|
72165
72576
|
Failed launch: har env recover 1 # or: har env launch 1 --resume`;
|
|
72166
72577
|
|
|
72167
72578
|
// src/cli/commands/env.ts
|
|
72579
|
+
var workLinkOptions = (y) => y.option("repo", { type: "string", default: ".", describe: "Path to the repository" }).option("work-id", {
|
|
72580
|
+
type: "string",
|
|
72581
|
+
demandOption: true,
|
|
72582
|
+
describe: "Repo-scoped work unit id (same as --work-id at launch)"
|
|
72583
|
+
}).option("link", {
|
|
72584
|
+
type: "string",
|
|
72585
|
+
describe: "Link as source|url or source|url|label"
|
|
72586
|
+
}).option("source", { type: "string", describe: "Tracker provider (e.g. github, jira)" }).option("url", { type: "string", describe: "Canonical URL for the link" }).option("label", { type: "string", describe: "Optional display label" });
|
|
72168
72587
|
var envCommand = {
|
|
72169
72588
|
command: "env <subcommand>",
|
|
72170
72589
|
describe: "Manage agent environments (launch \u2192 verify \u2192 complete)",
|
|
@@ -72324,8 +72743,17 @@ var envCommand = {
|
|
|
72324
72743
|
}).option("parent-work-id", {
|
|
72325
72744
|
type: "string",
|
|
72326
72745
|
describe: "Optional parent work unit identifier"
|
|
72746
|
+
}).option("work-link", {
|
|
72747
|
+
type: "array",
|
|
72748
|
+
string: true,
|
|
72749
|
+
describe: "Additional tracker link: source|url or source|url|label (repeatable)"
|
|
72327
72750
|
}).epilog(LAUNCH_EPILOG),
|
|
72328
72751
|
handleLaunch
|
|
72752
|
+
).command(
|
|
72753
|
+
"work-link",
|
|
72754
|
+
"Append a related external link to an existing work unit",
|
|
72755
|
+
workLinkOptions,
|
|
72756
|
+
handleWorkLink
|
|
72329
72757
|
).command(
|
|
72330
72758
|
"recover <id>",
|
|
72331
72759
|
"Resume a failed or partial launch (alias for launch --resume)",
|
|
@@ -72364,6 +72792,38 @@ var envCommand = {
|
|
|
72364
72792
|
"Show status of all running agents",
|
|
72365
72793
|
(y) => y.option("repo", { type: "string", default: "." }).option("json", { type: "boolean", default: false, describe: "Structured JSON output" }),
|
|
72366
72794
|
handleStatus
|
|
72795
|
+
).command(
|
|
72796
|
+
"cleanup",
|
|
72797
|
+
"Discover stale session worktrees across registered repos and tear them down",
|
|
72798
|
+
(y) => y.option("repo", {
|
|
72799
|
+
type: "string",
|
|
72800
|
+
describe: "Limit cleanup scan to one repository path"
|
|
72801
|
+
}).option("dry-run", {
|
|
72802
|
+
type: "boolean",
|
|
72803
|
+
default: false,
|
|
72804
|
+
describe: "Show the cleanup plan without executing"
|
|
72805
|
+
}).option("yes", {
|
|
72806
|
+
alias: "y",
|
|
72807
|
+
type: "boolean",
|
|
72808
|
+
default: false,
|
|
72809
|
+
describe: "Approve teardown/remove for recommended rows without prompting"
|
|
72810
|
+
}).option("keep", {
|
|
72811
|
+
type: "string",
|
|
72812
|
+
describe: "Pin sessions to keep (comma-separated repoPath:agentId or worktree paths)"
|
|
72813
|
+
}).option("stale", {
|
|
72814
|
+
type: "number",
|
|
72815
|
+
default: 7,
|
|
72816
|
+
describe: "Age in days before a clean idle session is recommended for teardown"
|
|
72817
|
+
}).option("orphans", {
|
|
72818
|
+
type: "boolean",
|
|
72819
|
+
default: true,
|
|
72820
|
+
describe: "Include orphan worktree directories under ~/worktrees"
|
|
72821
|
+
}).option("include-review", {
|
|
72822
|
+
type: "boolean",
|
|
72823
|
+
default: false,
|
|
72824
|
+
describe: "With --yes, also teardown/remove rows marked review (dirty or recent active)"
|
|
72825
|
+
}).option("json", { type: "boolean", default: false, describe: "Structured JSON output" }),
|
|
72826
|
+
handleCleanup
|
|
72367
72827
|
).command(
|
|
72368
72828
|
"runs",
|
|
72369
72829
|
"Inspect harness run history",
|
|
@@ -72386,13 +72846,13 @@ var envCommand = {
|
|
|
72386
72846
|
}
|
|
72387
72847
|
).demandCommand(
|
|
72388
72848
|
1,
|
|
72389
|
-
"Please specify a subcommand: init, maintain, add-stage, launch, recover, verify, complete, teardown, status, runs"
|
|
72849
|
+
"Please specify a subcommand: init, maintain, add-stage, launch, recover, verify, complete, teardown, status, cleanup, runs"
|
|
72390
72850
|
).epilog(HAR_ENV_EPILOG),
|
|
72391
72851
|
handler: () => {
|
|
72392
72852
|
}
|
|
72393
72853
|
};
|
|
72394
72854
|
async function handleInit(argv) {
|
|
72395
|
-
const repoPath =
|
|
72855
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72396
72856
|
const onboarding = resolveOnboardingOptions(argv);
|
|
72397
72857
|
header("har env init");
|
|
72398
72858
|
info(`Repository: ${repoPath}`);
|
|
@@ -72438,7 +72898,7 @@ async function handleInit(argv) {
|
|
|
72438
72898
|
}
|
|
72439
72899
|
}
|
|
72440
72900
|
async function handleMaintain(argv) {
|
|
72441
|
-
const repoPath =
|
|
72901
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72442
72902
|
const onboarding = resolveOnboardingOptions(argv);
|
|
72443
72903
|
header("har env maintain");
|
|
72444
72904
|
info(`Repository: ${repoPath}`);
|
|
@@ -72569,7 +73029,7 @@ async function applyAgentIntegrations(options) {
|
|
|
72569
73029
|
}
|
|
72570
73030
|
}
|
|
72571
73031
|
async function handleAddPlugin(argv) {
|
|
72572
|
-
const repoPath =
|
|
73032
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72573
73033
|
const available = listPluginIds();
|
|
72574
73034
|
if (argv.list) {
|
|
72575
73035
|
for (const id of available) {
|
|
@@ -72609,7 +73069,7 @@ async function handleAddPlugin(argv) {
|
|
|
72609
73069
|
}
|
|
72610
73070
|
}
|
|
72611
73071
|
async function handleAddStage(argv) {
|
|
72612
|
-
const repoPath =
|
|
73072
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72613
73073
|
const available = listPluginIds();
|
|
72614
73074
|
if (argv.list) {
|
|
72615
73075
|
warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
|
|
@@ -72675,7 +73135,7 @@ async function handleAddStage(argv) {
|
|
|
72675
73135
|
});
|
|
72676
73136
|
}
|
|
72677
73137
|
async function handlePreflight(argv) {
|
|
72678
|
-
const repo =
|
|
73138
|
+
const repo = path55.resolve(argv.repo);
|
|
72679
73139
|
const agentId = validateAgentId(argv.id, repo);
|
|
72680
73140
|
const result = await preflightEnvironment({
|
|
72681
73141
|
repoPath: repo,
|
|
@@ -72691,7 +73151,7 @@ async function handlePreflight(argv) {
|
|
|
72691
73151
|
return finishCommand(result.code);
|
|
72692
73152
|
}
|
|
72693
73153
|
async function handleLaunch(argv) {
|
|
72694
|
-
const repo =
|
|
73154
|
+
const repo = path55.resolve(argv.repo);
|
|
72695
73155
|
const agentId = validateAgentId(argv.id, repo);
|
|
72696
73156
|
if (!argv.resume) {
|
|
72697
73157
|
const guard = checkLaunchGuard2(repo, agentId, { worktree: argv.worktree });
|
|
@@ -72714,6 +73174,7 @@ async function handleLaunch(argv) {
|
|
|
72714
73174
|
sourceUrl: argv.workUrl,
|
|
72715
73175
|
title: argv.workTitle,
|
|
72716
73176
|
parentWorkUnitId: argv.parentWorkId,
|
|
73177
|
+
relatedLinks: argv.workLink?.map(parseWorkLinkSpec),
|
|
72717
73178
|
capture: false
|
|
72718
73179
|
});
|
|
72719
73180
|
if (result.blocked) {
|
|
@@ -72734,6 +73195,22 @@ async function handleLaunch(argv) {
|
|
|
72734
73195
|
}
|
|
72735
73196
|
return finishCommand(result.code);
|
|
72736
73197
|
}
|
|
73198
|
+
async function handleWorkLink(argv) {
|
|
73199
|
+
if (!argv.link && !(argv.source && argv.url)) {
|
|
73200
|
+
error("Provide --link or both --source and --url");
|
|
73201
|
+
return finishCommand(1);
|
|
73202
|
+
}
|
|
73203
|
+
const harnessRoot = resolveHarnessRoot(path55.resolve(argv.repo));
|
|
73204
|
+
const links = argv.link ? [parseWorkLinkSpec(argv.link)] : [{ source: argv.source, url: argv.url, label: argv.label }];
|
|
73205
|
+
try {
|
|
73206
|
+
const record2 = addWorkUnitLinks(harnessRoot, argv.workId, links);
|
|
73207
|
+
success(`Added link to work unit ${record2.workUnitId}`);
|
|
73208
|
+
return finishCommand(0);
|
|
73209
|
+
} catch (err) {
|
|
73210
|
+
error(err instanceof Error ? err.message : String(err));
|
|
73211
|
+
return finishCommand(1);
|
|
73212
|
+
}
|
|
73213
|
+
}
|
|
72737
73214
|
async function handleRecover(argv) {
|
|
72738
73215
|
return handleLaunch({
|
|
72739
73216
|
id: argv.id,
|
|
@@ -72749,7 +73226,7 @@ async function handleRecover(argv) {
|
|
|
72749
73226
|
});
|
|
72750
73227
|
}
|
|
72751
73228
|
async function handleVerify(argv) {
|
|
72752
|
-
const repo =
|
|
73229
|
+
const repo = path55.resolve(argv.repo);
|
|
72753
73230
|
const agentId = validateAgentId(argv.id, repo);
|
|
72754
73231
|
const result = await runVerification({
|
|
72755
73232
|
repoPath: repo,
|
|
@@ -72761,7 +73238,7 @@ async function handleVerify(argv) {
|
|
|
72761
73238
|
return finishCommand(result.code);
|
|
72762
73239
|
}
|
|
72763
73240
|
async function handleTeardown(argv) {
|
|
72764
|
-
const repo =
|
|
73241
|
+
const repo = path55.resolve(argv.repo);
|
|
72765
73242
|
const agentId = validateAgentId(argv.id, repo);
|
|
72766
73243
|
const result = await teardownEnvironment({
|
|
72767
73244
|
repoPath: repo,
|
|
@@ -72772,7 +73249,7 @@ async function handleTeardown(argv) {
|
|
|
72772
73249
|
return finishCommand(result.code);
|
|
72773
73250
|
}
|
|
72774
73251
|
async function handleComplete(argv) {
|
|
72775
|
-
const repo =
|
|
73252
|
+
const repo = path55.resolve(argv.repo);
|
|
72776
73253
|
const agentId = validateAgentId(argv.id, repo);
|
|
72777
73254
|
const result = await completeEnvironment({
|
|
72778
73255
|
repoPath: repo,
|
|
@@ -72793,7 +73270,7 @@ async function handleComplete(argv) {
|
|
|
72793
73270
|
return finishCommand(result.code);
|
|
72794
73271
|
}
|
|
72795
73272
|
async function handleStatus(argv) {
|
|
72796
|
-
const repoPath =
|
|
73273
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72797
73274
|
if (argv.json) {
|
|
72798
73275
|
const status = collectEnvironmentStatus(repoPath);
|
|
72799
73276
|
const output = EnvironmentStatusSchema.parse(status);
|
|
@@ -72805,8 +73282,59 @@ async function handleStatus(argv) {
|
|
|
72805
73282
|
capture: false
|
|
72806
73283
|
});
|
|
72807
73284
|
}
|
|
73285
|
+
async function handleCleanup(argv) {
|
|
73286
|
+
const keepValues = argv.keep?.split(",").map((value) => value.trim()).filter(Boolean);
|
|
73287
|
+
const keep = parseCleanupKeepPins(keepValues);
|
|
73288
|
+
const repoPaths = argv.repo ? [path55.resolve(argv.repo)] : void 0;
|
|
73289
|
+
const plan = await discoverCleanupCandidates({
|
|
73290
|
+
cwd: process.cwd(),
|
|
73291
|
+
repoPaths,
|
|
73292
|
+
keep,
|
|
73293
|
+
staleDays: argv.stale,
|
|
73294
|
+
orphans: argv.orphans
|
|
73295
|
+
});
|
|
73296
|
+
if (argv.json) {
|
|
73297
|
+
process.stdout.write(JSON.stringify(plan, null, 2) + "\n");
|
|
73298
|
+
if (argv.dryRun) return;
|
|
73299
|
+
} else {
|
|
73300
|
+
header("har env cleanup");
|
|
73301
|
+
process.stdout.write(`${formatCleanupPlan(plan)}
|
|
73302
|
+
|
|
73303
|
+
`);
|
|
73304
|
+
if (argv.dryRun) {
|
|
73305
|
+
info("Dry run \u2014 no changes made.");
|
|
73306
|
+
return;
|
|
73307
|
+
}
|
|
73308
|
+
}
|
|
73309
|
+
let selected = selectAutoApprovedCandidates(plan, { includeReview: argv.includeReview });
|
|
73310
|
+
if (!argv.yes) {
|
|
73311
|
+
try {
|
|
73312
|
+
const interactive = await confirmCleanupSelection(plan.candidates);
|
|
73313
|
+
selected = interactive;
|
|
73314
|
+
} catch (err) {
|
|
73315
|
+
error(err instanceof Error ? err.message : String(err));
|
|
73316
|
+
return finishCommand(1);
|
|
73317
|
+
}
|
|
73318
|
+
}
|
|
73319
|
+
if (selected.length === 0) {
|
|
73320
|
+
info("Nothing selected for cleanup.");
|
|
73321
|
+
return;
|
|
73322
|
+
}
|
|
73323
|
+
const outcomes = await executeCleanupCandidates(selected, { dryRun: false });
|
|
73324
|
+
let failed = 0;
|
|
73325
|
+
for (const outcome of outcomes) {
|
|
73326
|
+
const label = outcome.candidate.kind === "orphan_worktree" ? outcome.candidate.worktreePath : `${outcome.candidate.projectName} agent ${outcome.candidate.agentId}`;
|
|
73327
|
+
if (outcome.ok) {
|
|
73328
|
+
success(`Cleaned ${label}`);
|
|
73329
|
+
} else {
|
|
73330
|
+
failed++;
|
|
73331
|
+
error(`${label}: ${outcome.error ?? "failed"}`);
|
|
73332
|
+
}
|
|
73333
|
+
}
|
|
73334
|
+
return finishCommand(failed > 0 ? 1 : 0);
|
|
73335
|
+
}
|
|
72808
73336
|
async function handleRunsList(argv) {
|
|
72809
|
-
const repoPath =
|
|
73337
|
+
const repoPath = path55.resolve(argv.repo);
|
|
72810
73338
|
const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
|
|
72811
73339
|
if (argv.json) {
|
|
72812
73340
|
process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
|
|
@@ -72823,7 +73351,7 @@ async function handleRunsList(argv) {
|
|
|
72823
73351
|
}
|
|
72824
73352
|
}
|
|
72825
73353
|
async function handleRunsGet(argv) {
|
|
72826
|
-
const run2 = getRun(
|
|
73354
|
+
const run2 = getRun(path55.resolve(argv.repo), argv.runId);
|
|
72827
73355
|
if (!run2) {
|
|
72828
73356
|
error(`Run not found: ${argv.runId}`);
|
|
72829
73357
|
return finishCommand(1);
|
|
@@ -72905,27 +73433,27 @@ function printNextSteps() {
|
|
|
72905
73433
|
}
|
|
72906
73434
|
|
|
72907
73435
|
// src/cli/commands/control.ts
|
|
72908
|
-
var
|
|
73436
|
+
var path59 = __toESM(require("path"));
|
|
72909
73437
|
init_control_config();
|
|
72910
73438
|
init_control_port();
|
|
72911
73439
|
init_control_sync();
|
|
72912
73440
|
|
|
72913
73441
|
// src/core/control-sync-selection.ts
|
|
72914
|
-
var
|
|
72915
|
-
var
|
|
72916
|
-
var
|
|
73442
|
+
var fs48 = __toESM(require("fs"));
|
|
73443
|
+
var os20 = __toESM(require("os"));
|
|
73444
|
+
var path56 = __toESM(require("path"));
|
|
72917
73445
|
init_control_repo_path();
|
|
72918
73446
|
function getSelectionPath() {
|
|
72919
73447
|
if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
|
|
72920
|
-
return
|
|
73448
|
+
return path56.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
|
|
72921
73449
|
}
|
|
72922
|
-
return
|
|
73450
|
+
return path56.join(os20.homedir(), ".har", "sync-selection.json");
|
|
72923
73451
|
}
|
|
72924
73452
|
function readSyncSelection() {
|
|
72925
73453
|
const selectionPath = getSelectionPath();
|
|
72926
73454
|
try {
|
|
72927
|
-
if (!
|
|
72928
|
-
const parsed = JSON.parse(
|
|
73455
|
+
if (!fs48.existsSync(selectionPath)) return null;
|
|
73456
|
+
const parsed = JSON.parse(fs48.readFileSync(selectionPath, "utf8"));
|
|
72929
73457
|
if (!Array.isArray(parsed.repos)) return null;
|
|
72930
73458
|
return parsed.repos.map((repoPath) => canonicalizeControlRepoPath(repoPath));
|
|
72931
73459
|
} catch {
|
|
@@ -72935,8 +73463,8 @@ function readSyncSelection() {
|
|
|
72935
73463
|
function writeSyncSelection(repos) {
|
|
72936
73464
|
const selectionPath = getSelectionPath();
|
|
72937
73465
|
const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
|
|
72938
|
-
|
|
72939
|
-
|
|
73466
|
+
fs48.mkdirSync(path56.dirname(selectionPath), { recursive: true });
|
|
73467
|
+
fs48.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
|
|
72940
73468
|
}
|
|
72941
73469
|
function resolveSyncSelection(input) {
|
|
72942
73470
|
const { discovered, stored, forceSelect, isTTY } = input;
|
|
@@ -72968,13 +73496,13 @@ init_portal_credentials();
|
|
|
72968
73496
|
// src/core/portal-login.ts
|
|
72969
73497
|
var http = __toESM(require("http"));
|
|
72970
73498
|
var import_crypto = require("crypto");
|
|
72971
|
-
var
|
|
73499
|
+
var import_child_process15 = require("child_process");
|
|
72972
73500
|
var CALLBACK_PATH = "/callback";
|
|
72973
73501
|
var LOGIN_TIMEOUT_MS = 3 * 6e4;
|
|
72974
73502
|
function openBrowser(url) {
|
|
72975
73503
|
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
72976
73504
|
try {
|
|
72977
|
-
const child = (0,
|
|
73505
|
+
const child = (0, import_child_process15.spawn)(cmd, args, { stdio: "ignore", detached: true });
|
|
72978
73506
|
child.on("error", () => {
|
|
72979
73507
|
});
|
|
72980
73508
|
child.unref();
|
|
@@ -72983,7 +73511,7 @@ function openBrowser(url) {
|
|
|
72983
73511
|
}
|
|
72984
73512
|
async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
72985
73513
|
const state = (0, import_crypto.randomUUID)();
|
|
72986
|
-
return new Promise((
|
|
73514
|
+
return new Promise((resolve50, reject) => {
|
|
72987
73515
|
let timer;
|
|
72988
73516
|
const server = http.createServer((req, res) => {
|
|
72989
73517
|
const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
|
|
@@ -73008,7 +73536,7 @@ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
|
73008
73536
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
73009
73537
|
res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
|
|
73010
73538
|
cleanup();
|
|
73011
|
-
|
|
73539
|
+
resolve50({
|
|
73012
73540
|
portalUrl,
|
|
73013
73541
|
token,
|
|
73014
73542
|
workspace,
|
|
@@ -73043,8 +73571,8 @@ If your browser did not open, paste that URL.
|
|
|
73043
73571
|
}
|
|
73044
73572
|
|
|
73045
73573
|
// src/core/control-unregister.ts
|
|
73046
|
-
var
|
|
73047
|
-
var
|
|
73574
|
+
var fs49 = __toESM(require("fs"));
|
|
73575
|
+
var path57 = __toESM(require("path"));
|
|
73048
73576
|
init_control_repo_path();
|
|
73049
73577
|
init_control_registry();
|
|
73050
73578
|
init_control_config();
|
|
@@ -73054,9 +73582,9 @@ function listUnregisterWorktreeCandidates(repoPath) {
|
|
|
73054
73582
|
const harnessRoot = canonicalizeControlRepoPath(repoPath);
|
|
73055
73583
|
const byPath = /* @__PURE__ */ new Map();
|
|
73056
73584
|
const add = (partial2) => {
|
|
73057
|
-
const resolved =
|
|
73585
|
+
const resolved = path57.resolve(partial2.worktreePath);
|
|
73058
73586
|
if (!resolved || resolved === harnessRoot) return;
|
|
73059
|
-
const exists = partial2.exists ??
|
|
73587
|
+
const exists = partial2.exists ?? fs49.existsSync(resolved);
|
|
73060
73588
|
const prev = byPath.get(resolved);
|
|
73061
73589
|
if (prev) {
|
|
73062
73590
|
byPath.set(resolved, {
|
|
@@ -73103,12 +73631,12 @@ function listUnregisterWorktreeCandidates(repoPath) {
|
|
|
73103
73631
|
}
|
|
73104
73632
|
return [...byPath.values()].sort((a, b2) => a.agentId - b2.agentId);
|
|
73105
73633
|
}
|
|
73106
|
-
async function
|
|
73634
|
+
async function askYesNo6(question) {
|
|
73107
73635
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
73108
73636
|
const readline8 = await import("readline");
|
|
73109
73637
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
73110
|
-
const answer = await new Promise((
|
|
73111
|
-
rl.question(question,
|
|
73638
|
+
const answer = await new Promise((resolve50) => {
|
|
73639
|
+
rl.question(question, resolve50);
|
|
73112
73640
|
});
|
|
73113
73641
|
rl.close();
|
|
73114
73642
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -73120,7 +73648,7 @@ async function confirmUnregister(options) {
|
|
|
73120
73648
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
73121
73649
|
throw new Error("Non-interactive terminal \u2014 pass --yes (and optionally --delete-worktrees)");
|
|
73122
73650
|
}
|
|
73123
|
-
const proceed = await
|
|
73651
|
+
const proceed = await askYesNo6("Unregister this repository from Mission Control? [y/N] ");
|
|
73124
73652
|
if (!proceed) return { proceed: false, deleteWorktrees: false };
|
|
73125
73653
|
const existing = options.worktrees.filter((w2) => w2.exists);
|
|
73126
73654
|
if (existing.length === 0) {
|
|
@@ -73132,7 +73660,7 @@ async function confirmUnregister(options) {
|
|
|
73132
73660
|
process.stderr.write(` agent-${wt.agentId}: ${wt.worktreePath}${dirty}
|
|
73133
73661
|
`);
|
|
73134
73662
|
}
|
|
73135
|
-
const deleteWorktrees = await
|
|
73663
|
+
const deleteWorktrees = await askYesNo6(
|
|
73136
73664
|
`Also delete ${existing.length} session worktree(s) on disk? [y/N] `
|
|
73137
73665
|
);
|
|
73138
73666
|
return { proceed: true, deleteWorktrees };
|
|
@@ -73170,28 +73698,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
|
|
|
73170
73698
|
trigger: "cli"
|
|
73171
73699
|
});
|
|
73172
73700
|
if (result.code !== 0) {
|
|
73173
|
-
if (
|
|
73174
|
-
|
|
73701
|
+
if (fs49.existsSync(candidate.worktreePath)) {
|
|
73702
|
+
fs49.rmSync(candidate.worktreePath, { recursive: true, force: true });
|
|
73175
73703
|
}
|
|
73176
73704
|
}
|
|
73177
73705
|
outcomes.push({
|
|
73178
73706
|
path: candidate.worktreePath,
|
|
73179
73707
|
agentId: candidate.agentId,
|
|
73180
|
-
deleted: !
|
|
73181
|
-
error: result.code !== 0 &&
|
|
73708
|
+
deleted: !fs49.existsSync(candidate.worktreePath),
|
|
73709
|
+
error: result.code !== 0 && fs49.existsSync(candidate.worktreePath) ? result.stderr : void 0
|
|
73182
73710
|
});
|
|
73183
73711
|
} catch (err) {
|
|
73184
73712
|
const message = err instanceof Error ? err.message : String(err);
|
|
73185
73713
|
try {
|
|
73186
|
-
if (
|
|
73187
|
-
|
|
73714
|
+
if (fs49.existsSync(candidate.worktreePath)) {
|
|
73715
|
+
fs49.rmSync(candidate.worktreePath, { recursive: true, force: true });
|
|
73188
73716
|
}
|
|
73189
73717
|
} catch {
|
|
73190
73718
|
}
|
|
73191
73719
|
outcomes.push({
|
|
73192
73720
|
path: candidate.worktreePath,
|
|
73193
73721
|
agentId: candidate.agentId,
|
|
73194
|
-
deleted: !
|
|
73722
|
+
deleted: !fs49.existsSync(candidate.worktreePath),
|
|
73195
73723
|
error: message
|
|
73196
73724
|
});
|
|
73197
73725
|
}
|
|
@@ -73254,16 +73782,16 @@ init_control_config();
|
|
|
73254
73782
|
init_control_registry();
|
|
73255
73783
|
|
|
73256
73784
|
// src/core/harness-scrub.ts
|
|
73257
|
-
var
|
|
73258
|
-
var
|
|
73785
|
+
var fs50 = __toESM(require("fs"));
|
|
73786
|
+
var path58 = __toESM(require("path"));
|
|
73259
73787
|
var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
|
|
73260
73788
|
function scrubLocalHarnessDirs(repoPath) {
|
|
73261
73789
|
const results = [];
|
|
73262
|
-
const resolved =
|
|
73263
|
-
if (!
|
|
73790
|
+
const resolved = path58.resolve(repoPath);
|
|
73791
|
+
if (!fs50.existsSync(resolved)) {
|
|
73264
73792
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
73265
73793
|
results.push({
|
|
73266
|
-
path:
|
|
73794
|
+
path: path58.join(resolved, ".har", directory),
|
|
73267
73795
|
directory,
|
|
73268
73796
|
deleted: false,
|
|
73269
73797
|
error: "repository path does not exist"
|
|
@@ -73272,24 +73800,24 @@ function scrubLocalHarnessDirs(repoPath) {
|
|
|
73272
73800
|
return results;
|
|
73273
73801
|
}
|
|
73274
73802
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
73275
|
-
const target =
|
|
73276
|
-
if (!
|
|
73803
|
+
const target = path58.join(resolved, ".har", directory);
|
|
73804
|
+
if (!fs50.existsSync(target)) {
|
|
73277
73805
|
results.push({ path: target, directory, deleted: true });
|
|
73278
73806
|
continue;
|
|
73279
73807
|
}
|
|
73280
73808
|
try {
|
|
73281
|
-
|
|
73809
|
+
fs50.rmSync(target, { recursive: true, force: true });
|
|
73282
73810
|
results.push({
|
|
73283
73811
|
path: target,
|
|
73284
73812
|
directory,
|
|
73285
|
-
deleted: !
|
|
73286
|
-
error:
|
|
73813
|
+
deleted: !fs50.existsSync(target),
|
|
73814
|
+
error: fs50.existsSync(target) ? "failed to remove directory" : void 0
|
|
73287
73815
|
});
|
|
73288
73816
|
} catch (err) {
|
|
73289
73817
|
results.push({
|
|
73290
73818
|
path: target,
|
|
73291
73819
|
directory,
|
|
73292
|
-
deleted: !
|
|
73820
|
+
deleted: !fs50.existsSync(target),
|
|
73293
73821
|
error: err instanceof Error ? err.message : String(err)
|
|
73294
73822
|
});
|
|
73295
73823
|
}
|
|
@@ -73300,7 +73828,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
|
|
|
73300
73828
|
const results = [];
|
|
73301
73829
|
const seen = /* @__PURE__ */ new Set();
|
|
73302
73830
|
for (const repoPath of repoPaths) {
|
|
73303
|
-
const key =
|
|
73831
|
+
const key = path58.resolve(repoPath);
|
|
73304
73832
|
if (seen.has(key)) continue;
|
|
73305
73833
|
seen.add(key);
|
|
73306
73834
|
results.push(...scrubLocalHarnessDirs(key));
|
|
@@ -73309,12 +73837,12 @@ function scrubLocalHarnessForRepos(repoPaths) {
|
|
|
73309
73837
|
}
|
|
73310
73838
|
|
|
73311
73839
|
// src/core/control-reset.ts
|
|
73312
|
-
async function
|
|
73840
|
+
async function askYesNo7(question) {
|
|
73313
73841
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
73314
73842
|
const readline8 = await import("readline");
|
|
73315
73843
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
73316
|
-
const answer = await new Promise((
|
|
73317
|
-
rl.question(question,
|
|
73844
|
+
const answer = await new Promise((resolve50) => {
|
|
73845
|
+
rl.question(question, resolve50);
|
|
73318
73846
|
});
|
|
73319
73847
|
rl.close();
|
|
73320
73848
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -73324,7 +73852,7 @@ async function confirmControlReset(options) {
|
|
|
73324
73852
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
73325
73853
|
throw new Error("Non-interactive terminal \u2014 pass --yes");
|
|
73326
73854
|
}
|
|
73327
|
-
return
|
|
73855
|
+
return askYesNo7(
|
|
73328
73856
|
`Clear Mission Control data for ${options.repoCount} registered repositor${options.repoCount === 1 ? "y" : "ies"} (and scrub local .har history)? [y/N] `
|
|
73329
73857
|
);
|
|
73330
73858
|
}
|
|
@@ -73434,6 +73962,9 @@ var controlCommand = {
|
|
|
73434
73962
|
type: "boolean",
|
|
73435
73963
|
default: false,
|
|
73436
73964
|
describe: "Re-register even if previously unregistered"
|
|
73965
|
+
}).option("portal", {
|
|
73966
|
+
type: "boolean",
|
|
73967
|
+
describe: "Sync this repo to the hosted portal when logged in. Use --no-portal to keep it local-only."
|
|
73437
73968
|
}),
|
|
73438
73969
|
handleRegister
|
|
73439
73970
|
).command(
|
|
@@ -73559,12 +74090,15 @@ async function handleDown() {
|
|
|
73559
74090
|
return finishCommand(code);
|
|
73560
74091
|
}
|
|
73561
74092
|
async function handleRegister(argv) {
|
|
73562
|
-
const repoPath =
|
|
74093
|
+
const repoPath = path59.resolve(argv.repo);
|
|
73563
74094
|
header("har control register");
|
|
73564
74095
|
info(`Repository: ${repoPath}`);
|
|
73565
74096
|
try {
|
|
73566
74097
|
if (!argv.dryRun) {
|
|
73567
74098
|
recordRepoForControlSync(repoPath);
|
|
74099
|
+
if (argv.portal !== void 0) {
|
|
74100
|
+
setRepoPortalSync(repoPath, argv.portal);
|
|
74101
|
+
}
|
|
73568
74102
|
}
|
|
73569
74103
|
await syncRepoWithControl({
|
|
73570
74104
|
repoPath,
|
|
@@ -73576,6 +74110,9 @@ async function handleRegister(argv) {
|
|
|
73576
74110
|
info("Dry run \u2014 no API call made");
|
|
73577
74111
|
} else {
|
|
73578
74112
|
success("Registered and synced with Mission Control");
|
|
74113
|
+
if (!isRepoPortalSyncEnabled(repoPath)) {
|
|
74114
|
+
info("Local-only \u2014 skipped hosted portal sync");
|
|
74115
|
+
}
|
|
73579
74116
|
}
|
|
73580
74117
|
} catch (err) {
|
|
73581
74118
|
error(err.message);
|
|
@@ -73651,7 +74188,7 @@ async function handleReset(argv) {
|
|
|
73651
74188
|
}
|
|
73652
74189
|
}
|
|
73653
74190
|
async function handleUnregister(argv) {
|
|
73654
|
-
const repoPath =
|
|
74191
|
+
const repoPath = path59.resolve(argv.repo);
|
|
73655
74192
|
const worktrees = listUnregisterWorktreeCandidates(repoPath);
|
|
73656
74193
|
try {
|
|
73657
74194
|
let deleteWorktrees = argv.deleteWorktrees;
|
|
@@ -73833,12 +74370,12 @@ async function handleLogin(argv) {
|
|
|
73833
74370
|
}
|
|
73834
74371
|
|
|
73835
74372
|
// src/cli/commands/hooks.ts
|
|
73836
|
-
var
|
|
74373
|
+
var path61 = __toESM(require("path"));
|
|
73837
74374
|
init_hooks();
|
|
73838
74375
|
|
|
73839
74376
|
// src/core/claude-hooks.ts
|
|
73840
|
-
var
|
|
73841
|
-
var
|
|
74377
|
+
var fs51 = __toESM(require("fs"));
|
|
74378
|
+
var path60 = __toESM(require("path"));
|
|
73842
74379
|
var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
|
|
73843
74380
|
var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
|
|
73844
74381
|
var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
@@ -73849,8 +74386,8 @@ function isHarGuardEntry(entry) {
|
|
|
73849
74386
|
);
|
|
73850
74387
|
}
|
|
73851
74388
|
function readSettings(settingsPath) {
|
|
73852
|
-
if (!
|
|
73853
|
-
const raw =
|
|
74389
|
+
if (!fs51.existsSync(settingsPath)) return {};
|
|
74390
|
+
const raw = fs51.readFileSync(settingsPath, "utf8").trim();
|
|
73854
74391
|
if (raw === "") return {};
|
|
73855
74392
|
const parsed = JSON.parse(raw);
|
|
73856
74393
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -73859,19 +74396,19 @@ function readSettings(settingsPath) {
|
|
|
73859
74396
|
return parsed;
|
|
73860
74397
|
}
|
|
73861
74398
|
function writeSettings(settingsPath, settings) {
|
|
73862
|
-
|
|
73863
|
-
|
|
74399
|
+
fs51.mkdirSync(path60.dirname(settingsPath), { recursive: true });
|
|
74400
|
+
fs51.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
73864
74401
|
}
|
|
73865
74402
|
function installClaudeGuard(repoPath) {
|
|
73866
74403
|
const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
|
|
73867
74404
|
if (!templatePath) {
|
|
73868
74405
|
throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
|
|
73869
74406
|
}
|
|
73870
|
-
const guardScript =
|
|
73871
|
-
|
|
73872
|
-
|
|
73873
|
-
|
|
73874
|
-
const settingsPath =
|
|
74407
|
+
const guardScript = path60.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
74408
|
+
fs51.mkdirSync(path60.dirname(guardScript), { recursive: true });
|
|
74409
|
+
fs51.copyFileSync(templatePath, guardScript);
|
|
74410
|
+
fs51.chmodSync(guardScript, 493);
|
|
74411
|
+
const settingsPath = path60.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
73875
74412
|
const settings = readSettings(settingsPath);
|
|
73876
74413
|
const hooks = settings.hooks ?? {};
|
|
73877
74414
|
const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
|
|
@@ -73885,15 +74422,15 @@ function installClaudeGuard(repoPath) {
|
|
|
73885
74422
|
}
|
|
73886
74423
|
function uninstallClaudeGuard(repoPath) {
|
|
73887
74424
|
let removed = false;
|
|
73888
|
-
const guardScript =
|
|
73889
|
-
if (
|
|
73890
|
-
|
|
74425
|
+
const guardScript = path60.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
74426
|
+
if (fs51.existsSync(guardScript)) {
|
|
74427
|
+
fs51.rmSync(guardScript);
|
|
73891
74428
|
removed = true;
|
|
73892
|
-
const parent =
|
|
73893
|
-
if (
|
|
74429
|
+
const parent = path60.dirname(guardScript);
|
|
74430
|
+
if (fs51.existsSync(parent) && fs51.readdirSync(parent).length === 0) fs51.rmdirSync(parent);
|
|
73894
74431
|
}
|
|
73895
|
-
const settingsPath =
|
|
73896
|
-
if (
|
|
74432
|
+
const settingsPath = path60.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
74433
|
+
if (fs51.existsSync(settingsPath)) {
|
|
73897
74434
|
const settings = readSettings(settingsPath);
|
|
73898
74435
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
73899
74436
|
if (preToolUse) {
|
|
@@ -73918,8 +74455,8 @@ function uninstallClaudeGuard(repoPath) {
|
|
|
73918
74455
|
return { removed };
|
|
73919
74456
|
}
|
|
73920
74457
|
function claudeGuardInstalled(repoPath) {
|
|
73921
|
-
const settingsPath =
|
|
73922
|
-
if (!
|
|
74458
|
+
const settingsPath = path60.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
74459
|
+
if (!fs51.existsSync(settingsPath)) return false;
|
|
73923
74460
|
try {
|
|
73924
74461
|
const settings = readSettings(settingsPath);
|
|
73925
74462
|
return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
|
|
@@ -73936,7 +74473,7 @@ function repoOption(y) {
|
|
|
73936
74473
|
function handleInstall2(argv) {
|
|
73937
74474
|
try {
|
|
73938
74475
|
if (argv.claude) {
|
|
73939
|
-
const result2 = installClaudeGuard(
|
|
74476
|
+
const result2 = installClaudeGuard(path61.resolve(argv.repo));
|
|
73940
74477
|
success("Claude Code worktree guard installed.");
|
|
73941
74478
|
info(`Guard script: ${result2.guardScript}`);
|
|
73942
74479
|
info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
|
|
@@ -73944,7 +74481,7 @@ function handleInstall2(argv) {
|
|
|
73944
74481
|
info("Commit both files so the guard travels with the repo.");
|
|
73945
74482
|
return;
|
|
73946
74483
|
}
|
|
73947
|
-
const result = installHooks({ repoPath:
|
|
74484
|
+
const result = installHooks({ repoPath: path61.resolve(argv.repo), force: argv.force });
|
|
73948
74485
|
success(`Commit gate installed in ${result.hooksDir}`);
|
|
73949
74486
|
info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
|
|
73950
74487
|
info("Commits of unverified change batches will be blocked in agent worktrees.");
|
|
@@ -73957,7 +74494,7 @@ function handleInstall2(argv) {
|
|
|
73957
74494
|
function handleUninstall(argv) {
|
|
73958
74495
|
try {
|
|
73959
74496
|
if (argv.claude) {
|
|
73960
|
-
const result2 = uninstallClaudeGuard(
|
|
74497
|
+
const result2 = uninstallClaudeGuard(path61.resolve(argv.repo));
|
|
73961
74498
|
if (result2.removed) {
|
|
73962
74499
|
success("Claude Code worktree guard removed.");
|
|
73963
74500
|
} else {
|
|
@@ -73965,7 +74502,7 @@ function handleUninstall(argv) {
|
|
|
73965
74502
|
}
|
|
73966
74503
|
return;
|
|
73967
74504
|
}
|
|
73968
|
-
const result = uninstallHooks(
|
|
74505
|
+
const result = uninstallHooks(path61.resolve(argv.repo));
|
|
73969
74506
|
if (result.removed) {
|
|
73970
74507
|
success(`Commit gate removed from ${result.hooksDir}`);
|
|
73971
74508
|
} else {
|
|
@@ -73978,7 +74515,7 @@ function handleUninstall(argv) {
|
|
|
73978
74515
|
}
|
|
73979
74516
|
function handleStatus2(argv) {
|
|
73980
74517
|
try {
|
|
73981
|
-
const status = getHooksStatus(
|
|
74518
|
+
const status = getHooksStatus(path61.resolve(argv.repo));
|
|
73982
74519
|
if (argv.json) {
|
|
73983
74520
|
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
73984
74521
|
`);
|
|
@@ -73996,7 +74533,7 @@ function handleStatus2(argv) {
|
|
|
73996
74533
|
);
|
|
73997
74534
|
info(`Effective: ${status.effectiveMode} (in this checkout)`);
|
|
73998
74535
|
info(
|
|
73999
|
-
`Claude guard: ${claudeGuardInstalled(
|
|
74536
|
+
`Claude guard: ${claudeGuardInstalled(path61.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
|
|
74000
74537
|
);
|
|
74001
74538
|
} catch (err) {
|
|
74002
74539
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -74257,10 +74794,10 @@ function assignProp(target, prop, value) {
|
|
|
74257
74794
|
configurable: true
|
|
74258
74795
|
});
|
|
74259
74796
|
}
|
|
74260
|
-
function getElementAtPath(obj,
|
|
74261
|
-
if (!
|
|
74797
|
+
function getElementAtPath(obj, path66) {
|
|
74798
|
+
if (!path66)
|
|
74262
74799
|
return obj;
|
|
74263
|
-
return
|
|
74800
|
+
return path66.reduce((acc, key) => acc?.[key], obj);
|
|
74264
74801
|
}
|
|
74265
74802
|
function promiseAllObject(promisesObj) {
|
|
74266
74803
|
const keys = Object.keys(promisesObj);
|
|
@@ -74580,11 +75117,11 @@ function aborted(x, startIndex = 0) {
|
|
|
74580
75117
|
}
|
|
74581
75118
|
return false;
|
|
74582
75119
|
}
|
|
74583
|
-
function prefixIssues(
|
|
75120
|
+
function prefixIssues(path66, issues) {
|
|
74584
75121
|
return issues.map((iss) => {
|
|
74585
75122
|
var _a2;
|
|
74586
75123
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
74587
|
-
iss.path.unshift(
|
|
75124
|
+
iss.path.unshift(path66);
|
|
74588
75125
|
return iss;
|
|
74589
75126
|
});
|
|
74590
75127
|
}
|
|
@@ -79907,7 +80444,7 @@ var Protocol = class {
|
|
|
79907
80444
|
return;
|
|
79908
80445
|
}
|
|
79909
80446
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
79910
|
-
await new Promise((
|
|
80447
|
+
await new Promise((resolve50) => setTimeout(resolve50, pollInterval));
|
|
79911
80448
|
options?.signal?.throwIfAborted();
|
|
79912
80449
|
}
|
|
79913
80450
|
} catch (error3) {
|
|
@@ -79924,7 +80461,7 @@ var Protocol = class {
|
|
|
79924
80461
|
*/
|
|
79925
80462
|
request(request, resultSchema, options) {
|
|
79926
80463
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
79927
|
-
return new Promise((
|
|
80464
|
+
return new Promise((resolve50, reject) => {
|
|
79928
80465
|
const earlyReject = (error3) => {
|
|
79929
80466
|
reject(error3);
|
|
79930
80467
|
};
|
|
@@ -80002,7 +80539,7 @@ var Protocol = class {
|
|
|
80002
80539
|
if (!parseResult.success) {
|
|
80003
80540
|
reject(parseResult.error);
|
|
80004
80541
|
} else {
|
|
80005
|
-
|
|
80542
|
+
resolve50(parseResult.data);
|
|
80006
80543
|
}
|
|
80007
80544
|
} catch (error3) {
|
|
80008
80545
|
reject(error3);
|
|
@@ -80263,12 +80800,12 @@ var Protocol = class {
|
|
|
80263
80800
|
}
|
|
80264
80801
|
} catch {
|
|
80265
80802
|
}
|
|
80266
|
-
return new Promise((
|
|
80803
|
+
return new Promise((resolve50, reject) => {
|
|
80267
80804
|
if (signal.aborted) {
|
|
80268
80805
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
80269
80806
|
return;
|
|
80270
80807
|
}
|
|
80271
|
-
const timeoutId = setTimeout(
|
|
80808
|
+
const timeoutId = setTimeout(resolve50, interval);
|
|
80272
80809
|
signal.addEventListener("abort", () => {
|
|
80273
80810
|
clearTimeout(timeoutId);
|
|
80274
80811
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -81058,7 +81595,7 @@ var Server = class extends Protocol {
|
|
|
81058
81595
|
};
|
|
81059
81596
|
|
|
81060
81597
|
// src/mcp/server.ts
|
|
81061
|
-
var
|
|
81598
|
+
var path62 = __toESM(require("path"));
|
|
81062
81599
|
|
|
81063
81600
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
81064
81601
|
var import_node_process3 = __toESM(require("node:process"), 1);
|
|
@@ -81141,12 +81678,12 @@ var StdioServerTransport = class {
|
|
|
81141
81678
|
this.onclose?.();
|
|
81142
81679
|
}
|
|
81143
81680
|
send(message) {
|
|
81144
|
-
return new Promise((
|
|
81681
|
+
return new Promise((resolve50) => {
|
|
81145
81682
|
const json = serializeMessage(message);
|
|
81146
81683
|
if (this._stdout.write(json)) {
|
|
81147
|
-
|
|
81684
|
+
resolve50();
|
|
81148
81685
|
} else {
|
|
81149
|
-
this._stdout.once("drain",
|
|
81686
|
+
this._stdout.once("drain", resolve50);
|
|
81150
81687
|
}
|
|
81151
81688
|
});
|
|
81152
81689
|
}
|
|
@@ -81155,6 +81692,8 @@ var StdioServerTransport = class {
|
|
|
81155
81692
|
// src/mcp/server.ts
|
|
81156
81693
|
init_telemetry_config();
|
|
81157
81694
|
init_runs();
|
|
81695
|
+
init_work_units();
|
|
81696
|
+
init_manifest();
|
|
81158
81697
|
|
|
81159
81698
|
// src/mcp/schema-tools.ts
|
|
81160
81699
|
init_schema2();
|
|
@@ -81239,7 +81778,21 @@ var LaunchEnvironmentInputSchema = external_exports.object({
|
|
|
81239
81778
|
source: external_exports.string().min(1).max(64).optional(),
|
|
81240
81779
|
sourceUrl: external_exports.string().url().optional(),
|
|
81241
81780
|
title: external_exports.string().min(1).max(256).optional(),
|
|
81242
|
-
parentWorkUnitId: external_exports.string().min(1).max(128).optional()
|
|
81781
|
+
parentWorkUnitId: external_exports.string().min(1).max(128).optional(),
|
|
81782
|
+
relatedLinks: external_exports.array(
|
|
81783
|
+
external_exports.object({
|
|
81784
|
+
source: external_exports.string().min(1).max(64),
|
|
81785
|
+
url: external_exports.string().url(),
|
|
81786
|
+
label: external_exports.string().min(1).max(128).optional()
|
|
81787
|
+
})
|
|
81788
|
+
).optional()
|
|
81789
|
+
});
|
|
81790
|
+
var AddWorkUnitLinkInputSchema = external_exports.object({
|
|
81791
|
+
repo: external_exports.string().default("."),
|
|
81792
|
+
workUnitId: external_exports.string().min(1).max(128),
|
|
81793
|
+
source: external_exports.string().min(1).max(64),
|
|
81794
|
+
url: external_exports.string().url(),
|
|
81795
|
+
label: external_exports.string().min(1).max(128).optional()
|
|
81243
81796
|
});
|
|
81244
81797
|
var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
81245
81798
|
previewUrls: external_exports.record(external_exports.string()).optional(),
|
|
@@ -81386,11 +81939,41 @@ var HAR_MCP_TOOLS = [
|
|
|
81386
81939
|
parentWorkUnitId: {
|
|
81387
81940
|
type: "string",
|
|
81388
81941
|
description: "Optional parent work unit identifier."
|
|
81942
|
+
},
|
|
81943
|
+
relatedLinks: {
|
|
81944
|
+
type: "array",
|
|
81945
|
+
description: "Additional tracker links (append-only). Each item: source, url, optional label.",
|
|
81946
|
+
items: {
|
|
81947
|
+
type: "object",
|
|
81948
|
+
properties: {
|
|
81949
|
+
source: { type: "string" },
|
|
81950
|
+
url: { type: "string" },
|
|
81951
|
+
label: { type: "string" }
|
|
81952
|
+
},
|
|
81953
|
+
required: ["source", "url"]
|
|
81954
|
+
}
|
|
81389
81955
|
}
|
|
81390
81956
|
},
|
|
81391
81957
|
["agentId"]
|
|
81392
81958
|
)
|
|
81393
81959
|
},
|
|
81960
|
+
{
|
|
81961
|
+
name: "har_add_work_unit_link",
|
|
81962
|
+
description: "Append a related external link (PR, mirrored issue, alternate tracker) to an existing work unit.",
|
|
81963
|
+
inputSchema: objectJsonSchema(
|
|
81964
|
+
{
|
|
81965
|
+
repo: repoJsonProperty,
|
|
81966
|
+
workUnitId: {
|
|
81967
|
+
type: "string",
|
|
81968
|
+
description: "Repo-scoped work unit id bound at launch."
|
|
81969
|
+
},
|
|
81970
|
+
source: { type: "string", description: "Tracker provider (e.g. github, jira)." },
|
|
81971
|
+
url: { type: "string", description: "Canonical URL for the link." },
|
|
81972
|
+
label: { type: "string", description: "Optional display label." }
|
|
81973
|
+
},
|
|
81974
|
+
["workUnitId", "source", "url"]
|
|
81975
|
+
)
|
|
81976
|
+
},
|
|
81394
81977
|
{
|
|
81395
81978
|
name: "har_recover_environment",
|
|
81396
81979
|
description: "Resume a failed or partial agent launch without replacing the worktree. Alias for har_launch_environment with resume=true.",
|
|
@@ -81561,6 +82144,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
81561
82144
|
sourceUrl: input.sourceUrl,
|
|
81562
82145
|
title: input.title,
|
|
81563
82146
|
parentWorkUnitId: input.parentWorkUnitId,
|
|
82147
|
+
relatedLinks: input.relatedLinks,
|
|
81564
82148
|
capture: true
|
|
81565
82149
|
});
|
|
81566
82150
|
const parsed = LaunchEnvironmentOutputSchema.parse(result);
|
|
@@ -81583,6 +82167,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
81583
82167
|
sourceUrl: input.sourceUrl,
|
|
81584
82168
|
title: input.title,
|
|
81585
82169
|
parentWorkUnitId: input.parentWorkUnitId,
|
|
82170
|
+
relatedLinks: input.relatedLinks,
|
|
81586
82171
|
capture: true
|
|
81587
82172
|
});
|
|
81588
82173
|
const parsed = LaunchEnvironmentOutputSchema.parse(result);
|
|
@@ -81591,6 +82176,28 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
81591
82176
|
...result.blocked ? { isError: true } : {}
|
|
81592
82177
|
};
|
|
81593
82178
|
}
|
|
82179
|
+
case "har_add_work_unit_link": {
|
|
82180
|
+
const input = AddWorkUnitLinkInputSchema.parse({ ...args, repo });
|
|
82181
|
+
const harnessRoot = resolveHarnessRoot(repo);
|
|
82182
|
+
try {
|
|
82183
|
+
const record2 = addWorkUnitLinks(harnessRoot, input.workUnitId, [
|
|
82184
|
+
{ source: input.source, url: input.url, label: input.label }
|
|
82185
|
+
]);
|
|
82186
|
+
return jsonContent({
|
|
82187
|
+
ok: true,
|
|
82188
|
+
workUnitId: record2.workUnitId,
|
|
82189
|
+
relatedLinks: record2.relatedLinks
|
|
82190
|
+
});
|
|
82191
|
+
} catch (err) {
|
|
82192
|
+
return {
|
|
82193
|
+
...jsonContent({
|
|
82194
|
+
ok: false,
|
|
82195
|
+
error: err instanceof Error ? err.message : String(err)
|
|
82196
|
+
}),
|
|
82197
|
+
isError: true
|
|
82198
|
+
};
|
|
82199
|
+
}
|
|
82200
|
+
}
|
|
81594
82201
|
case "har_preflight_environment": {
|
|
81595
82202
|
const input = PreflightEnvironmentInputSchema.parse({ ...args, repo });
|
|
81596
82203
|
const agentId = validateAgentId(input.agentId, repo);
|
|
@@ -81701,7 +82308,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
81701
82308
|
const input = ControlUpInputSchema.parse({ ...args, repo });
|
|
81702
82309
|
const result = await startControlAndSync({
|
|
81703
82310
|
detach: input.detach,
|
|
81704
|
-
cwd:
|
|
82311
|
+
cwd: path62.resolve(input.repo)
|
|
81705
82312
|
});
|
|
81706
82313
|
if (result.code !== 0) {
|
|
81707
82314
|
return {
|
|
@@ -81765,11 +82372,11 @@ var mcpCommand = {
|
|
|
81765
82372
|
};
|
|
81766
82373
|
|
|
81767
82374
|
// src/cli/commands/onboard.ts
|
|
81768
|
-
var
|
|
82375
|
+
var path64 = __toESM(require("path"));
|
|
81769
82376
|
init_stages();
|
|
81770
82377
|
|
|
81771
82378
|
// src/core/onboarding.ts
|
|
81772
|
-
var
|
|
82379
|
+
var path63 = __toESM(require("path"));
|
|
81773
82380
|
init_control_config();
|
|
81774
82381
|
init_control_sync();
|
|
81775
82382
|
init_otel_hooks();
|
|
@@ -81905,7 +82512,7 @@ async function defaultEnsureControl(options) {
|
|
|
81905
82512
|
return { started: true, apiUrl: result.apiUrl };
|
|
81906
82513
|
}
|
|
81907
82514
|
async function runOnboarding(options, deps = {}) {
|
|
81908
|
-
const repoPath =
|
|
82515
|
+
const repoPath = path63.resolve(options.repoPath);
|
|
81909
82516
|
const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
|
|
81910
82517
|
const ensureControl = deps.ensureControl ?? defaultEnsureControl;
|
|
81911
82518
|
const init = deps.initHarness ?? initHarness;
|
|
@@ -82093,7 +82700,7 @@ async function promptChoices(args) {
|
|
|
82093
82700
|
};
|
|
82094
82701
|
}
|
|
82095
82702
|
const pluginChoices = listPluginChoices();
|
|
82096
|
-
const repoPath =
|
|
82703
|
+
const repoPath = path64.resolve(args.repo);
|
|
82097
82704
|
const alreadyPresent = harnessExists(repoPath);
|
|
82098
82705
|
const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
|
|
82099
82706
|
const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
|
|
@@ -82210,7 +82817,7 @@ function printSummary(result) {
|
|
|
82210
82817
|
console.error("");
|
|
82211
82818
|
}
|
|
82212
82819
|
async function handleOnboard(argv) {
|
|
82213
|
-
const repoPath =
|
|
82820
|
+
const repoPath = path64.resolve(argv.repo);
|
|
82214
82821
|
header("har onboard");
|
|
82215
82822
|
info(`Repository: ${repoPath}`);
|
|
82216
82823
|
try {
|
|
@@ -82441,7 +83048,7 @@ var preferencesCommand = {
|
|
|
82441
83048
|
};
|
|
82442
83049
|
|
|
82443
83050
|
// src/cli/commands/telemetry.ts
|
|
82444
|
-
var
|
|
83051
|
+
var path65 = __toESM(require("path"));
|
|
82445
83052
|
init_control_config();
|
|
82446
83053
|
init_control_sync();
|
|
82447
83054
|
init_manifest();
|
|
@@ -82534,7 +83141,7 @@ async function handleOff() {
|
|
|
82534
83141
|
info("Mission Control will not auto-start. Existing usage rows are kept.");
|
|
82535
83142
|
}
|
|
82536
83143
|
async function handleWriteEnv(argv) {
|
|
82537
|
-
const repoPath =
|
|
83144
|
+
const repoPath = path65.resolve(argv.repo);
|
|
82538
83145
|
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
82539
83146
|
const session = readSlotRegistry(harnessRoot, argv.agentId);
|
|
82540
83147
|
const workDir = argv.workDir ?? session?.workDir ?? repoPath;
|
|
@@ -82546,7 +83153,7 @@ async function handleWriteEnv(argv) {
|
|
|
82546
83153
|
suffix,
|
|
82547
83154
|
createdAt: session?.createdAt
|
|
82548
83155
|
});
|
|
82549
|
-
const envFile = argv.envFile ??
|
|
83156
|
+
const envFile = argv.envFile ?? path65.join(workDir, `.env.agent.${argv.agentId}`);
|
|
82550
83157
|
const attrs = {
|
|
82551
83158
|
sessionKey,
|
|
82552
83159
|
agentId: argv.agentId,
|
|
@@ -82562,7 +83169,7 @@ async function handleWriteEnv(argv) {
|
|
|
82562
83169
|
success(`Wrote session attribution to ${envFile}`);
|
|
82563
83170
|
}
|
|
82564
83171
|
function handlePrintEnv(argv) {
|
|
82565
|
-
const repoPath =
|
|
83172
|
+
const repoPath = path65.resolve(argv.repo);
|
|
82566
83173
|
const workDir = argv.workDir ?? repoPath;
|
|
82567
83174
|
const sessionKey = buildSessionKey({
|
|
82568
83175
|
branch: argv.branch,
|