@osfactory/har 0.64.1 → 0.64.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +660 -464
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -593,8 +593,8 @@ var init_parseUtil = __esm({
593
593
  init_errors();
594
594
  init_en();
595
595
  makeIssue = (params) => {
596
- const { data, path: path70, errorMaps, issueData } = params;
597
- const fullPath = [...path70, ...issueData.path || []];
596
+ const { data, path: path69, errorMaps, issueData } = params;
597
+ const fullPath = [...path69, ...issueData.path || []];
598
598
  const fullIssue = {
599
599
  ...issueData,
600
600
  path: fullPath
@@ -902,11 +902,11 @@ var init_types = __esm({
902
902
  init_parseUtil();
903
903
  init_util();
904
904
  ParseInputLazyPath = class {
905
- constructor(parent, value, path70, key) {
905
+ constructor(parent, value, path69, key) {
906
906
  this._cachedPath = [];
907
907
  this.parent = parent;
908
908
  this.data = value;
909
- this._path = path70;
909
+ this._path = path69;
910
910
  this._key = key;
911
911
  }
912
912
  get path() {
@@ -4288,7 +4288,7 @@ var init_zod = __esm({
4288
4288
  });
4289
4289
 
4290
4290
  // packages/schemas/src/schema.ts
4291
- 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, AgentTrajectoryRecordSchema, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
4291
+ 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, AgentTrajectoryRecordSchema, USAGE_HARVEST_VERSION, PRE_DEDUPE_HARVEST_VERSION, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
4292
4292
  var init_schema = __esm({
4293
4293
  "packages/schemas/src/schema.ts"() {
4294
4294
  "use strict";
@@ -4774,6 +4774,8 @@ var init_schema = __esm({
4774
4774
  attemptId: WorkAttemptIdSchema.optional()
4775
4775
  }).passthrough();
4776
4776
  AgentTrajectoryRecordSchema = AgentTrajectoryRecordV1Schema;
4777
+ USAGE_HARVEST_VERSION = 1;
4778
+ PRE_DEDUPE_HARVEST_VERSION = 0;
4777
4779
  AgentSessionUsageSchema = external_exports.object({
4778
4780
  sessionKey: external_exports.string().min(1),
4779
4781
  agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
@@ -4792,6 +4794,7 @@ var init_schema = __esm({
4792
4794
  costUsd: external_exports.number().nonnegative().nullable().optional(),
4793
4795
  modelBreakdown: external_exports.record(external_exports.unknown()).optional(),
4794
4796
  sources: external_exports.array(UsageSourceSchema).default([]),
4797
+ harvestVersion: external_exports.number().int().nonnegative().default(PRE_DEDUPE_HARVEST_VERSION),
4795
4798
  firstSeenAt: external_exports.string(),
4796
4799
  lastSeenAt: external_exports.string()
4797
4800
  });
@@ -4819,6 +4822,31 @@ var init_schema = __esm({
4819
4822
  }
4820
4823
  });
4821
4824
 
4825
+ // packages/schemas/src/usage-authority.ts
4826
+ function usageHarvestVersion(row) {
4827
+ const version2 = Number(row?.harvestVersion ?? PRE_DEDUPE_HARVEST_VERSION);
4828
+ return Number.isFinite(version2) && version2 > 0 ? Math.floor(version2) : PRE_DEDUPE_HARVEST_VERSION;
4829
+ }
4830
+ function includesSource(row, source) {
4831
+ return (row?.sources ?? []).includes(source);
4832
+ }
4833
+ function harvestSupersedes(existing, incoming) {
4834
+ if (!existing || !incoming) return false;
4835
+ if (includesSource(existing, "otel") || includesSource(incoming, "otel")) return false;
4836
+ return usageHarvestVersion(incoming) > usageHarvestVersion(existing);
4837
+ }
4838
+ function mergedHarvestVersion(existing, incoming) {
4839
+ if (!includesSource(existing, "harvest")) return usageHarvestVersion(incoming);
4840
+ if (!includesSource(incoming, "harvest")) return usageHarvestVersion(existing);
4841
+ return Math.min(usageHarvestVersion(existing), usageHarvestVersion(incoming));
4842
+ }
4843
+ var init_usage_authority = __esm({
4844
+ "packages/schemas/src/usage-authority.ts"() {
4845
+ "use strict";
4846
+ init_schema();
4847
+ }
4848
+ });
4849
+
4822
4850
  // node_modules/@pydantic/genai-prices/dist/index.js
4823
4851
  function h() {
4824
4852
  return U;
@@ -28294,6 +28322,7 @@ var init_schema2 = __esm({
28294
28322
  "src/harness/schema.ts"() {
28295
28323
  "use strict";
28296
28324
  init_schema();
28325
+ init_usage_authority();
28297
28326
  init_usage_pricing();
28298
28327
  }
28299
28328
  });
@@ -28704,7 +28733,7 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
28704
28733
  const stream = options.stream ?? false;
28705
28734
  const echoStdout = stream && (options.streamStdout ?? true);
28706
28735
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
28707
- return new Promise((resolve53) => {
28736
+ return new Promise((resolve52) => {
28708
28737
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
28709
28738
  ...spawnOptions,
28710
28739
  stdio: ["inherit", "pipe", "pipe"]
@@ -28719,14 +28748,14 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
28719
28748
  stderr += d;
28720
28749
  if (stream) process.stderr.write(d);
28721
28750
  });
28722
- proc.on("close", (code) => resolve53({ stdout, stderr, code: code ?? 0 }));
28751
+ proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
28723
28752
  });
28724
28753
  }
28725
28754
  function runShellCommand(command2, options = {}) {
28726
28755
  const stream = options.stream ?? false;
28727
28756
  const echoStdout = stream && (options.streamStdout ?? true);
28728
28757
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
28729
- return new Promise((resolve53) => {
28758
+ return new Promise((resolve52) => {
28730
28759
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
28731
28760
  ...spawnOptions,
28732
28761
  stdio: ["inherit", "pipe", "pipe"]
@@ -28741,7 +28770,7 @@ function runShellCommand(command2, options = {}) {
28741
28770
  stderr += d;
28742
28771
  if (stream) process.stderr.write(d);
28743
28772
  });
28744
- proc.on("close", (code) => resolve53({ stdout, stderr, code: code ?? 0 }));
28773
+ proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
28745
28774
  });
28746
28775
  }
28747
28776
  var import_child_process;
@@ -31541,17 +31570,17 @@ function listWorkUnits(harnessRoot) {
31541
31570
  ).sort((a, b2) => b2.updatedAt.localeCompare(a.updatedAt));
31542
31571
  }
31543
31572
  function createWorkAttempt(harnessRoot, input) {
31544
- const attempt = WorkAttemptRecordSchema.parse({
31573
+ const attempt2 = WorkAttemptRecordSchema.parse({
31545
31574
  ...input,
31546
31575
  version: 1,
31547
31576
  createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
31548
31577
  });
31549
31578
  ensureWorkEvidenceIgnored(harnessRoot);
31550
31579
  writeRecord2(
31551
- hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt.attemptId),
31552
- attempt
31580
+ hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt2.attemptId),
31581
+ attempt2
31553
31582
  );
31554
- return attempt;
31583
+ return attempt2;
31555
31584
  }
31556
31585
  function listWorkAttempts(harnessRoot) {
31557
31586
  return listRecords(
@@ -32477,6 +32506,7 @@ function harvestClaudeUsage(slot) {
32477
32506
  costUsd: usage2.costUsd,
32478
32507
  ...Object.keys(usage2.modelBreakdown).length > 0 ? { modelBreakdown: usage2.modelBreakdown } : {},
32479
32508
  sources: ["harvest"],
32509
+ harvestVersion: USAGE_HARVEST_VERSION,
32480
32510
  firstSeenAt: slot.sessionCreatedAt ?? now,
32481
32511
  lastSeenAt: now
32482
32512
  };
@@ -32500,6 +32530,7 @@ var init_claude = __esm({
32500
32530
  fs23 = __toESM(require("fs"));
32501
32531
  os11 = __toESM(require("os"));
32502
32532
  path25 = __toESM(require("path"));
32533
+ init_schema2();
32503
32534
  init_telemetry_config();
32504
32535
  init_telemetry_env();
32505
32536
  init_workspace_path_match();
@@ -32618,6 +32649,7 @@ function harvestCodexUsage(slot) {
32618
32649
  tokensTotal,
32619
32650
  costUsd: null,
32620
32651
  sources: ["harvest"],
32652
+ harvestVersion: USAGE_HARVEST_VERSION,
32621
32653
  firstSeenAt: slot.sessionCreatedAt ?? now,
32622
32654
  lastSeenAt: now
32623
32655
  };
@@ -32629,6 +32661,7 @@ var init_codex = __esm({
32629
32661
  fs24 = __toESM(require("fs"));
32630
32662
  os12 = __toESM(require("os"));
32631
32663
  path26 = __toESM(require("path"));
32664
+ init_schema2();
32632
32665
  init_telemetry_env();
32633
32666
  init_workspace_path_match();
32634
32667
  }
@@ -32758,25 +32791,85 @@ var init_portal_watermark = __esm({
32758
32791
  }
32759
32792
  });
32760
32793
 
32761
- // src/core/control-persisted-usage.ts
32762
- async function getJson(url) {
32794
+ // src/core/control-api-read.ts
32795
+ function numberFromEnv(name, fallback) {
32796
+ const raw = Number(process.env[name]);
32797
+ return Number.isFinite(raw) && raw > 0 ? raw : fallback;
32798
+ }
32799
+ async function attempt(url) {
32763
32800
  try {
32764
32801
  const response = await fetch(url, {
32765
32802
  method: "GET",
32766
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
32803
+ signal: AbortSignal.timeout(numberFromEnv("HAR_CONTROL_READ_TIMEOUT_MS", DEFAULT_TIMEOUT_MS))
32767
32804
  });
32768
- if (!response.ok) return null;
32769
- return await response.json();
32770
- } catch {
32771
- return null;
32772
- }
32805
+ if (!response.ok) {
32806
+ return {
32807
+ read: { ok: false, error: `HTTP ${response.status}` },
32808
+ retryable: response.status >= 500
32809
+ };
32810
+ }
32811
+ return { read: { ok: true, data: await response.json() }, retryable: false };
32812
+ } catch (err) {
32813
+ return {
32814
+ read: { ok: false, error: err instanceof Error ? err.message : String(err) },
32815
+ retryable: true
32816
+ };
32817
+ }
32818
+ }
32819
+ async function readControlJson(url) {
32820
+ const first = await attempt(url);
32821
+ if (first.read.ok || !first.retryable) return first.read;
32822
+ await new Promise((resolve52) => setTimeout(resolve52, RETRY_DELAY_MS));
32823
+ return (await attempt(url)).read;
32824
+ }
32825
+ async function readControlPages(options) {
32826
+ const limit = numberFromEnv("HAR_CONTROL_READ_PAGE_SIZE", DEFAULT_PAGE_SIZE);
32827
+ const collected = [];
32828
+ let since = options.since;
32829
+ let sinceId = null;
32830
+ for (let page = 0; page < MAX_PAGES; page++) {
32831
+ const query = new URLSearchParams({ limit: String(limit) });
32832
+ if (since) query.set("since", since);
32833
+ if (sinceId) query.set("sinceId", sinceId);
32834
+ const read = await readControlJson(`${options.url}?${query.toString()}`);
32835
+ if (!read.ok) return { ok: false, error: read.error };
32836
+ const rows = options.rows(read.data);
32837
+ collected.push(...rows);
32838
+ if (rows.length < limit) return { ok: true, rows: collected, truncated: false };
32839
+ const last = options.cursor(rows[rows.length - 1]);
32840
+ const nextSince = last.createdAt ?? null;
32841
+ const nextSinceId = last.id ?? null;
32842
+ if (!nextSince || nextSince === since && nextSinceId === sinceId) {
32843
+ return { ok: true, rows: collected, truncated: false };
32844
+ }
32845
+ since = nextSince;
32846
+ sinceId = nextSinceId;
32847
+ }
32848
+ return { ok: true, rows: collected, truncated: true };
32773
32849
  }
32774
32850
  async function resolveControlRepoId(apiUrl, repoPath) {
32775
- const repos = await getJson(`${apiUrl}/api/repos`);
32776
- if (!Array.isArray(repos)) return null;
32851
+ const repos = await readControlJson(`${apiUrl}/api/repos`);
32852
+ if (!repos.ok) return repos;
32853
+ if (!Array.isArray(repos.data)) return { ok: false, error: "unexpected /api/repos payload" };
32777
32854
  const target = path28.resolve(repoPath);
32778
- return repos.find((repo) => path28.resolve(repo.path) === target)?.id ?? null;
32855
+ return {
32856
+ ok: true,
32857
+ data: repos.data.find((repo) => path28.resolve(repo.path) === target)?.id ?? null
32858
+ };
32779
32859
  }
32860
+ var path28, DEFAULT_TIMEOUT_MS, RETRY_DELAY_MS, DEFAULT_PAGE_SIZE, MAX_PAGES;
32861
+ var init_control_api_read = __esm({
32862
+ "src/core/control-api-read.ts"() {
32863
+ "use strict";
32864
+ path28 = __toESM(require("path"));
32865
+ DEFAULT_TIMEOUT_MS = 1e4;
32866
+ RETRY_DELAY_MS = 250;
32867
+ DEFAULT_PAGE_SIZE = 1e3;
32868
+ MAX_PAGES = 20;
32869
+ }
32870
+ });
32871
+
32872
+ // src/core/control-persisted-usage.ts
32780
32873
  function optionalString(value) {
32781
32874
  return value == null ? void 0 : value;
32782
32875
  }
@@ -32802,6 +32895,7 @@ function normalizeUsage(row) {
32802
32895
  costUsd: row.costUsd == null ? null : Number(row.costUsd),
32803
32896
  ...row.modelBreakdown ? { modelBreakdown: row.modelBreakdown } : {},
32804
32897
  sources: toSources(row.sources),
32898
+ harvestVersion: Number(row.harvestVersion ?? 0),
32805
32899
  firstSeenAt: row.firstSeenAt,
32806
32900
  lastSeenAt: row.lastSeenAt
32807
32901
  };
@@ -32829,50 +32923,54 @@ function maxTimestamp(a, b2) {
32829
32923
  return a > b2 ? a : b2;
32830
32924
  }
32831
32925
  async function fetchPersistedPortalTelemetry(repoPath, apiUrl, options) {
32832
- const repoId = await resolveControlRepoId(apiUrl, repoPath);
32833
- if (!repoId) return { usage: [], events: [], maxSyncedAt: null };
32926
+ const empty = { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
32927
+ const repo = await resolveControlRepoId(apiUrl, repoPath);
32928
+ if (!repo.ok) {
32929
+ return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
32930
+ }
32931
+ if (!repo.data) return empty;
32834
32932
  const since = options?.since ?? null;
32835
- const [usageResponse, eventsResponse] = await Promise.all([
32836
- getJson(`${apiUrl}/api/repos/${repoId}/usage`),
32837
- getJson(`${apiUrl}/api/repos/${repoId}/events`)
32933
+ const [usageRead, eventsRead] = await Promise.all([
32934
+ readControlJson(`${apiUrl}/api/repos/${repo.data}/usage`),
32935
+ readControlPages({
32936
+ url: `${apiUrl}/api/repos/${repo.data}/events`,
32937
+ since,
32938
+ rows: (data) => data?.events ?? [],
32939
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
32940
+ })
32838
32941
  ]);
32839
- const usage2 = selectSince(usageResponse?.usage ?? [], since, (row) => row.updatedAt ?? row.lastSeenAt);
32840
- const events = selectSince(eventsResponse?.events ?? [], since, (row) => row.createdAt ?? row.timestamp);
32942
+ const failures = [];
32943
+ const truncated = [];
32944
+ if (!usageRead.ok) failures.push({ channel: "usage", reason: usageRead.error });
32945
+ if (!eventsRead.ok) failures.push({ channel: "events", reason: eventsRead.error });
32946
+ else if (eventsRead.truncated) truncated.push("events");
32947
+ const usage2 = selectSince(
32948
+ usageRead.ok ? usageRead.data?.usage ?? [] : [],
32949
+ since,
32950
+ (row) => row.updatedAt ?? row.lastSeenAt
32951
+ );
32952
+ const events = selectSince(
32953
+ eventsRead.ok ? eventsRead.rows : [],
32954
+ since,
32955
+ (row) => row.createdAt ?? row.timestamp
32956
+ );
32841
32957
  return {
32842
32958
  usage: usage2.selected.map(normalizeUsage),
32843
32959
  events: events.selected.map(normalizeEvent),
32844
- maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt)
32960
+ maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt),
32961
+ failures,
32962
+ truncated
32845
32963
  };
32846
32964
  }
32847
- var path28, FETCH_TIMEOUT_MS;
32848
32965
  var init_control_persisted_usage = __esm({
32849
32966
  "src/core/control-persisted-usage.ts"() {
32850
32967
  "use strict";
32851
- path28 = __toESM(require("path"));
32852
32968
  init_portal_watermark();
32853
- FETCH_TIMEOUT_MS = 3e3;
32969
+ init_control_api_read();
32854
32970
  }
32855
32971
  });
32856
32972
 
32857
32973
  // src/core/control-persisted-trajectory.ts
32858
- async function getJson2(url) {
32859
- try {
32860
- const response = await fetch(url, {
32861
- method: "GET",
32862
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
32863
- });
32864
- if (!response.ok) return null;
32865
- return await response.json();
32866
- } catch {
32867
- return null;
32868
- }
32869
- }
32870
- async function resolveControlRepoId2(apiUrl, repoPath) {
32871
- const repos = await getJson2(`${apiUrl}/api/repos`);
32872
- if (!Array.isArray(repos)) return null;
32873
- const target = path29.resolve(repoPath);
32874
- return repos.find((repo) => path29.resolve(repo.path) === target)?.id ?? null;
32875
- }
32876
32974
  function optional(value) {
32877
32975
  return value == null ? void 0 : value;
32878
32976
  }
@@ -32928,24 +33026,44 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
32928
33026
  records: [],
32929
33027
  spans: [],
32930
33028
  recordsMaxSyncedAt: null,
32931
- spansMaxSyncedAt: null
33029
+ spansMaxSyncedAt: null,
33030
+ failures: [],
33031
+ truncated: []
32932
33032
  };
32933
33033
  if (!request.records && !request.spans) return empty;
32934
- const repoId = await resolveControlRepoId2(apiUrl, repoPath);
32935
- if (!repoId) return empty;
32936
- const [trajectoryResponse, spansResponse] = await Promise.all([
32937
- request.records ? getJson2(
32938
- `${apiUrl}/api/repos/${repoId}/trajectory`
32939
- ) : null,
32940
- request.spans ? getJson2(`${apiUrl}/api/repos/${repoId}/spans`) : null
33034
+ const repo = await resolveControlRepoId(apiUrl, repoPath);
33035
+ if (!repo.ok) return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
33036
+ if (!repo.data) return empty;
33037
+ const [trajectoryRead, spansRead] = await Promise.all([
33038
+ request.records ? readControlPages({
33039
+ url: `${apiUrl}/api/repos/${repo.data}/trajectory`,
33040
+ since: request.records.since,
33041
+ rows: (data) => data?.records ?? [],
33042
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
33043
+ }) : null,
33044
+ request.spans ? readControlPages({
33045
+ url: `${apiUrl}/api/repos/${repo.data}/spans`,
33046
+ since: request.spans.since,
33047
+ rows: (data) => data?.spans ?? [],
33048
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
33049
+ }) : null
32941
33050
  ]);
33051
+ const failures = [];
33052
+ const truncated = [];
33053
+ if (trajectoryRead && !trajectoryRead.ok) {
33054
+ failures.push({ channel: "trajectory", reason: trajectoryRead.error });
33055
+ } else if (trajectoryRead?.ok && trajectoryRead.truncated) {
33056
+ truncated.push("trajectory");
33057
+ }
33058
+ if (spansRead && !spansRead.ok) failures.push({ channel: "spans", reason: spansRead.error });
33059
+ else if (spansRead?.ok && spansRead.truncated) truncated.push("spans");
32942
33060
  const trajectory = selectSince(
32943
- trajectoryResponse?.records ?? [],
33061
+ trajectoryRead?.ok ? trajectoryRead.rows : [],
32944
33062
  request.records ? request.records.since : null,
32945
33063
  (row) => row.createdAt ?? null
32946
33064
  );
32947
33065
  const spans = selectSince(
32948
- spansResponse?.spans ?? [],
33066
+ spansRead?.ok ? spansRead.rows : [],
32949
33067
  request.spans ? request.spans.since : null,
32950
33068
  (row) => row.createdAt ?? null
32951
33069
  );
@@ -32956,17 +33074,17 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
32956
33074
  }),
32957
33075
  spans: spans.selected.map(toPortalSpan),
32958
33076
  recordsMaxSyncedAt: trajectory.maxSyncedAt,
32959
- spansMaxSyncedAt: spans.maxSyncedAt
33077
+ spansMaxSyncedAt: spans.maxSyncedAt,
33078
+ failures,
33079
+ truncated
32960
33080
  };
32961
33081
  }
32962
- var path29, FETCH_TIMEOUT_MS2;
32963
33082
  var init_control_persisted_trajectory = __esm({
32964
33083
  "src/core/control-persisted-trajectory.ts"() {
32965
33084
  "use strict";
32966
- path29 = __toESM(require("path"));
32967
33085
  init_schema2();
32968
33086
  init_portal_watermark();
32969
- FETCH_TIMEOUT_MS2 = 5e3;
33087
+ init_control_api_read();
32970
33088
  }
32971
33089
  });
32972
33090
 
@@ -33007,10 +33125,34 @@ function mergeModelBreakdown(a, b2) {
33007
33125
  }
33008
33126
  return out;
33009
33127
  }
33010
- function mergeUsageRow(a, b2) {
33128
+ function replaceCounters(row) {
33129
+ return {
33130
+ tokensInput: num2(row.tokensInput),
33131
+ tokensOutput: num2(row.tokensOutput),
33132
+ tokensCacheRead: num2(row.tokensCacheRead),
33133
+ tokensCacheCreation: num2(row.tokensCacheCreation),
33134
+ tokensTotal: num2(row.tokensTotal),
33135
+ costUsd: row.costUsd ?? null,
33136
+ modelBreakdown: row.modelBreakdown,
33137
+ harvestVersion: usageHarvestVersion(row)
33138
+ };
33139
+ }
33140
+ function maxCounters(a, b2) {
33011
33141
  const costA = a.costUsd ?? null;
33012
33142
  const costB = b2.costUsd ?? null;
33013
- const costUsd = costA != null || costB != null ? Math.max(num2(costA), num2(costB)) : a.costUsd ?? b2.costUsd;
33143
+ return {
33144
+ tokensInput: Math.max(num2(a.tokensInput), num2(b2.tokensInput)),
33145
+ tokensOutput: Math.max(num2(a.tokensOutput), num2(b2.tokensOutput)),
33146
+ tokensCacheRead: Math.max(num2(a.tokensCacheRead), num2(b2.tokensCacheRead)),
33147
+ tokensCacheCreation: Math.max(num2(a.tokensCacheCreation), num2(b2.tokensCacheCreation)),
33148
+ tokensTotal: Math.max(num2(a.tokensTotal), num2(b2.tokensTotal)),
33149
+ costUsd: costA != null || costB != null ? Math.max(num2(costA), num2(costB)) : a.costUsd ?? b2.costUsd,
33150
+ modelBreakdown: mergeModelBreakdown(a.modelBreakdown, b2.modelBreakdown),
33151
+ harvestVersion: mergedHarvestVersion(a, b2)
33152
+ };
33153
+ }
33154
+ function mergeUsageRow(a, b2) {
33155
+ const counters = harvestSupersedes(a, b2) ? replaceCounters(b2) : harvestSupersedes(b2, a) ? replaceCounters(a) : maxCounters(a, b2);
33014
33156
  return {
33015
33157
  ...a,
33016
33158
  ...b2,
@@ -33019,13 +33161,7 @@ function mergeUsageRow(a, b2) {
33019
33161
  suffix: b2.suffix ?? a.suffix,
33020
33162
  workUnitId: b2.workUnitId ?? a.workUnitId,
33021
33163
  attemptId: b2.attemptId ?? a.attemptId,
33022
- tokensInput: Math.max(num2(a.tokensInput), num2(b2.tokensInput)),
33023
- tokensOutput: Math.max(num2(a.tokensOutput), num2(b2.tokensOutput)),
33024
- tokensCacheRead: Math.max(num2(a.tokensCacheRead), num2(b2.tokensCacheRead)),
33025
- tokensCacheCreation: Math.max(num2(a.tokensCacheCreation), num2(b2.tokensCacheCreation)),
33026
- tokensTotal: Math.max(num2(a.tokensTotal), num2(b2.tokensTotal)),
33027
- costUsd,
33028
- modelBreakdown: mergeModelBreakdown(a.modelBreakdown, b2.modelBreakdown),
33164
+ ...counters,
33029
33165
  sources: [.../* @__PURE__ */ new Set([...a.sources ?? [], ...b2.sources ?? []])],
33030
33166
  firstSeenAt: earlier(a.firstSeenAt, b2.firstSeenAt),
33031
33167
  lastSeenAt: later(a.lastSeenAt, b2.lastSeenAt)
@@ -33052,6 +33188,7 @@ var KEY_SEP;
33052
33188
  var init_portal_usage_merge = __esm({
33053
33189
  "src/core/portal-usage-merge.ts"() {
33054
33190
  "use strict";
33191
+ init_schema2();
33055
33192
  KEY_SEP = "\0";
33056
33193
  }
33057
33194
  });
@@ -33161,13 +33298,13 @@ function describeFetchFailure(url, bodyBytes, err) {
33161
33298
  }
33162
33299
  async function postForResponse(url, headers, payload) {
33163
33300
  let lastErr;
33164
- for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS; attempt++) {
33301
+ for (let attempt2 = 1; attempt2 <= MAX_FETCH_ATTEMPTS; attempt2++) {
33165
33302
  try {
33166
33303
  return await fetch(url, { method: "POST", headers, body: payload });
33167
33304
  } catch (err) {
33168
33305
  lastErr = err;
33169
- if (attempt < MAX_FETCH_ATTEMPTS) {
33170
- await new Promise((resolve53) => setTimeout(resolve53, attempt * 100));
33306
+ if (attempt2 < MAX_FETCH_ATTEMPTS) {
33307
+ await new Promise((resolve52) => setTimeout(resolve52, attempt2 * 100));
33171
33308
  }
33172
33309
  }
33173
33310
  }
@@ -33262,8 +33399,17 @@ function modelsFromBreakdown(breakdown) {
33262
33399
  ...totals && typeof totals === "object" ? totals : {}
33263
33400
  }));
33264
33401
  }
33402
+ function describeReadFailures(repoPath, failures) {
33403
+ const detail = failures.map((f) => `${f.channel} (${f.reason})`).join(", ");
33404
+ return `${path29.basename(repoPath)}: could not read ${detail} from Mission Control \u2014 that telemetry is missing from this sync and its watermark is held, so the next sync retries it.`;
33405
+ }
33406
+ function describeTruncatedReads(repoPath, channels) {
33407
+ return `${path29.basename(repoPath)}: ${channels.join(", ")} hit the read page cap \u2014 the remainder syncs on the next run.`;
33408
+ }
33265
33409
  async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, portal) {
33266
- if (!isTelemetryEnabled()) return { usage: [], events: [], maxSyncedAt: null };
33410
+ if (!isTelemetryEnabled()) {
33411
+ return { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
33412
+ }
33267
33413
  try {
33268
33414
  const userEmail = resolvePortalUserEmail(portal);
33269
33415
  const fallbackAgentId = slots.length > 0 ? Math.min(...slots.map((slot) => slot.agentId)) : null;
@@ -33322,9 +33468,23 @@ async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, por
33322
33468
  const events = dedupePortalEvents(harvestedEvents, persisted.events).map(
33323
33469
  (event) => dropNullFields({ ...event })
33324
33470
  );
33325
- return { usage: usage2, events, maxSyncedAt: persisted.maxSyncedAt };
33326
- } catch {
33327
- return { usage: [], events: [], maxSyncedAt: null };
33471
+ return {
33472
+ usage: usage2,
33473
+ events,
33474
+ maxSyncedAt: persisted.maxSyncedAt,
33475
+ failures: persisted.failures,
33476
+ truncated: persisted.truncated
33477
+ };
33478
+ } catch (err) {
33479
+ return {
33480
+ usage: [],
33481
+ events: [],
33482
+ maxSyncedAt: null,
33483
+ failures: [
33484
+ { channel: "telemetry", reason: err instanceof Error ? err.message : String(err) }
33485
+ ],
33486
+ truncated: []
33487
+ };
33328
33488
  }
33329
33489
  }
33330
33490
  async function buildPortalPayload(repoPath, controlApiUrl, since, full = false, portal) {
@@ -33338,16 +33498,16 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
33338
33498
  const attempts = listWorkAttempts(harnessRoot);
33339
33499
  const validationBindings = listValidationBindings(harnessRoot);
33340
33500
  const userEmail = resolvePortalUserEmail(portal);
33341
- const { usage: usage2, events, maxSyncedAt } = await collectPortalTelemetry(
33501
+ const { usage: usage2, events, maxSyncedAt, failures, truncated } = await collectPortalTelemetry(
33342
33502
  repoPath,
33343
33503
  status.slots,
33344
33504
  controlApiUrl,
33345
33505
  since,
33346
33506
  portal
33347
33507
  );
33348
- if (full && isTelemetryEnabled() && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
33508
+ if (full && isTelemetryEnabled() && failures.length === 0 && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
33349
33509
  warn(
33350
- `${path30.basename(repoPath)}: agent runs found but no usage harvested \u2014 attribution will be missing. This happens when agent sessions ran outside the har worktree slot (e.g. in the main checkout). Run agents inside \`har env launch\`.`
33510
+ `${path29.basename(repoPath)}: agent runs found but no usage harvested \u2014 attribution will be missing. This happens when agent sessions ran outside the har worktree slot (e.g. in the main checkout). Run agents inside \`har env launch\`.`
33351
33511
  );
33352
33512
  }
33353
33513
  const syncBody = {
@@ -33367,7 +33527,7 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
33367
33527
  ...usage2.length > 0 ? { usage: usage2 } : {}
33368
33528
  };
33369
33529
  const runsPayload = userEmail ? runs.map((run2) => ({ ...run2, userEmail })) : runs;
33370
- return { syncBody, runs: runsPayload, events, maxSyncedAt };
33530
+ return { syncBody, runs: runsPayload, events, maxSyncedAt, failures, truncated };
33371
33531
  }
33372
33532
  async function isControlApiReachable(apiUrl = getControlApiUrl()) {
33373
33533
  try {
@@ -33384,7 +33544,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
33384
33544
  const deadline = Date.now() + timeoutMs;
33385
33545
  while (Date.now() < deadline) {
33386
33546
  if (await isControlApiReachable(apiUrl)) return true;
33387
- await new Promise((resolve53) => setTimeout(resolve53, intervalMs));
33547
+ await new Promise((resolve52) => setTimeout(resolve52, intervalMs));
33388
33548
  }
33389
33549
  return false;
33390
33550
  }
@@ -33401,13 +33561,14 @@ async function syncReposWithControl(options) {
33401
33561
  const results = [];
33402
33562
  let synced = 0;
33403
33563
  let failed = 0;
33564
+ let incomplete = 0;
33404
33565
  for (const repoPath of options.repoPaths) {
33405
33566
  const destinationAliases = destinationAliasesForSync(repoPath, options.portalTargets);
33406
33567
  if (destinationAliases.length > 1) {
33407
33568
  const targetResults = [];
33408
33569
  for (const alias of destinationAliases) {
33409
33570
  try {
33410
- await withTimeout(
33571
+ const outcome = await withTimeout(
33411
33572
  syncRepoWithControl({
33412
33573
  repoPath,
33413
33574
  apiUrl,
@@ -33419,7 +33580,11 @@ async function syncReposWithControl(options) {
33419
33580
  EXPLICIT_SYNC_TIMEOUT_MS,
33420
33581
  "control sync"
33421
33582
  );
33422
- targetResults.push({ alias, ok: true });
33583
+ targetResults.push({
33584
+ alias,
33585
+ ok: true,
33586
+ ...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
33587
+ });
33423
33588
  } catch (err) {
33424
33589
  targetResults.push({
33425
33590
  alias,
@@ -33431,11 +33596,12 @@ async function syncReposWithControl(options) {
33431
33596
  const ok = targetResults.every((entry) => entry.ok);
33432
33597
  if (ok) synced++;
33433
33598
  else failed++;
33599
+ if (ok && targetResults.some((entry) => entry.warnings)) incomplete++;
33434
33600
  results.push({ repoPath, ok, targets: targetResults, error: ok ? void 0 : "one or more targets failed" });
33435
33601
  continue;
33436
33602
  }
33437
33603
  try {
33438
- await withTimeout(
33604
+ const outcome = await withTimeout(
33439
33605
  syncRepoWithControl({
33440
33606
  repoPath,
33441
33607
  apiUrl,
@@ -33448,13 +33614,18 @@ async function syncReposWithControl(options) {
33448
33614
  "control sync"
33449
33615
  );
33450
33616
  synced++;
33451
- results.push({ repoPath, ok: true });
33617
+ if (outcome.warnings.length > 0) incomplete++;
33618
+ results.push({
33619
+ repoPath,
33620
+ ok: true,
33621
+ ...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
33622
+ });
33452
33623
  } catch (err) {
33453
33624
  failed++;
33454
33625
  results.push({ repoPath, ok: false, error: err instanceof Error ? err.message : String(err) });
33455
33626
  }
33456
33627
  }
33457
- return { synced, failed, results };
33628
+ return { synced, failed, incomplete, results };
33458
33629
  }
33459
33630
  function destinationAliasesForSync(repoPath, explicit) {
33460
33631
  if (explicit && explicit.length > 0) return explicit;
@@ -33519,7 +33690,7 @@ async function syncRepoWithLocalControl(options) {
33519
33690
  const listResponse = await fetch(`${apiUrl}/api/repos`);
33520
33691
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
33521
33692
  const repos = await listResponse.json();
33522
- const existing = repos.find((r) => path30.resolve(r.path) === repoPath);
33693
+ const existing = repos.find((r) => path29.resolve(r.path) === repoPath);
33523
33694
  if (!existing) {
33524
33695
  return;
33525
33696
  }
@@ -33531,7 +33702,7 @@ async function syncRepoWithLocalControl(options) {
33531
33702
  }
33532
33703
  }
33533
33704
  async function syncRepoWithPortal(options, controlApiUrl, portal) {
33534
- if (!isRepoPortalSyncEnabled(options.repoPath)) return;
33705
+ if (!isRepoPortalSyncEnabled(options.repoPath)) return [];
33535
33706
  const { repoPath, dryRun, full } = options;
33536
33707
  const watermarkKey = watermarkKeyForTarget(portal);
33537
33708
  const since = full ? null : readPortalWatermarkForTarget(repoPath, portal);
@@ -33544,7 +33715,7 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
33544
33715
  }
33545
33716
  }
33546
33717
  const runsSince = rewindSince(stored?.lastSyncedAt ?? null);
33547
- const { syncBody, runs, events, maxSyncedAt } = await buildPortalPayload(
33718
+ const { syncBody, runs, events, maxSyncedAt, failures, truncated } = await buildPortalPayload(
33548
33719
  repoPath,
33549
33720
  controlApiUrl,
33550
33721
  since,
@@ -33567,18 +33738,25 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
33567
33738
  for (const batch of chunkBySerializedSize(events, maxSyncBatchBytes())) {
33568
33739
  await postPortal(portal, "/api/otel", { path: repoPath, events: batch }, dryRun);
33569
33740
  }
33570
- if (!dryRun && maxSyncedAt) {
33741
+ if (!dryRun && maxSyncedAt && failures.length === 0) {
33571
33742
  writePortalWatermark(repoPath, watermarkKey, maxSyncedAt);
33572
33743
  }
33573
- await syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full);
33744
+ const warnings = [];
33745
+ if (failures.length > 0) warnings.push(describeReadFailures(repoPath, failures));
33746
+ if (truncated.length > 0) warnings.push(describeTruncatedReads(repoPath, truncated));
33747
+ warnings.push(
33748
+ ...await syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full)
33749
+ );
33750
+ for (const message of warnings) warn(message);
33751
+ return warnings;
33574
33752
  }
33575
33753
  async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full) {
33576
33754
  const wantRecords = isPortalTrajectoryEnabledForTarget(portal);
33577
33755
  const wantSpans = isTelemetryEnabled();
33578
- if (!wantRecords && !wantSpans) return;
33756
+ if (!wantRecords && !wantSpans) return [];
33579
33757
  const recordsTarget = trajectoryWatermarkTarget(portal);
33580
33758
  const spansTarget = spansWatermarkTarget(portal);
33581
- const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
33759
+ const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt, failures, truncated } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
33582
33760
  records: wantRecords ? {
33583
33761
  since: full ? null : readScopedPortalWatermark(
33584
33762
  repoPath,
@@ -33594,10 +33772,11 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
33594
33772
  )
33595
33773
  } : false
33596
33774
  });
33775
+ const failedChannel = (channel) => failures.some((failure) => failure.channel === channel || failure.channel === "repos");
33597
33776
  for (const batch of chunkBySerializedSize(spans, maxSyncBatchBytes())) {
33598
33777
  await postPortal(portal, "/api/otel", { path: repoPath, spans: batch }, dryRun);
33599
33778
  }
33600
- if (!dryRun && spansMaxSyncedAt) {
33779
+ if (!dryRun && spansMaxSyncedAt && !failedChannel("spans")) {
33601
33780
  writePortalWatermark(repoPath, spansTarget, spansMaxSyncedAt);
33602
33781
  }
33603
33782
  let recordsLanded = true;
@@ -33611,14 +33790,18 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
33611
33790
  if (!supported) {
33612
33791
  recordsLanded = false;
33613
33792
  warn(
33614
- `${path30.basename(repoPath)}: this har-portal has no /api/trajectory endpoint \u2014 trajectory forwarding skipped (upgrade the portal; records are kept for the next sync).`
33793
+ `${path29.basename(repoPath)}: this har-portal has no /api/trajectory endpoint \u2014 trajectory forwarding skipped (upgrade the portal; records are kept for the next sync).`
33615
33794
  );
33616
33795
  break;
33617
33796
  }
33618
33797
  }
33619
- if (!dryRun && recordsLanded && recordsMaxSyncedAt) {
33798
+ if (!dryRun && recordsLanded && recordsMaxSyncedAt && !failedChannel("trajectory")) {
33620
33799
  writePortalWatermark(repoPath, recordsTarget, recordsMaxSyncedAt);
33621
33800
  }
33801
+ return [
33802
+ ...failures.length > 0 ? [describeReadFailures(repoPath, failures)] : [],
33803
+ ...truncated.length > 0 ? [describeTruncatedReads(repoPath, truncated)] : []
33804
+ ];
33622
33805
  }
33623
33806
  async function syncRepoWithControl(options) {
33624
33807
  const repoPath = canonicalizeControlRepoPath(options.repoPath);
@@ -33650,19 +33833,20 @@ async function syncRepoWithControl(options) {
33650
33833
  if (!response.ok) {
33651
33834
  throw new Error(`Cloud sync failed: ${response.status}`);
33652
33835
  }
33653
- return;
33836
+ return { warnings: [] };
33654
33837
  }
33655
33838
  await syncRepoWithLocalControl({ ...options, repoPath, apiUrl });
33656
- if (!isRepoPortalSyncEnabled(repoPath)) return;
33839
+ if (!isRepoPortalSyncEnabled(repoPath)) return { warnings: [] };
33657
33840
  const resolved = resolvePortalTargetsForRepo({
33658
33841
  repoPath,
33659
33842
  explicitTargets: options.portalTargets
33660
33843
  });
33661
- if (!resolved) return;
33844
+ if (!resolved) return { warnings: [] };
33845
+ const warnings = [];
33662
33846
  const failures = [];
33663
33847
  for (const portal of resolved.targets) {
33664
33848
  try {
33665
- await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal);
33849
+ warnings.push(...await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal));
33666
33850
  } catch (err) {
33667
33851
  failures.push({
33668
33852
  alias: portal.alias ?? portal.identityKey,
@@ -33670,7 +33854,7 @@ async function syncRepoWithControl(options) {
33670
33854
  });
33671
33855
  }
33672
33856
  }
33673
- if (failures.length === 0) return;
33857
+ if (failures.length === 0) return { warnings };
33674
33858
  if (failures.length === resolved.targets.length && failures.length === 1) {
33675
33859
  throw new Error(failures[0].error);
33676
33860
  }
@@ -33810,7 +33994,7 @@ async function syncRunWithLocalControl(repoPath, run2, apiUrl) {
33810
33994
  const listResponse = await fetch(`${apiUrl}/api/repos`);
33811
33995
  if (!listResponse.ok) return;
33812
33996
  const repos = await listResponse.json();
33813
- repoId = repos.find((r) => path30.resolve(r.path) === repoPath)?.id;
33997
+ repoId = repos.find((r) => path29.resolve(r.path) === repoPath)?.id;
33814
33998
  }
33815
33999
  if (!repoId) return;
33816
34000
  const runsBody = SyncRunsInputSchema.parse({ runs: [run2] });
@@ -33843,11 +34027,11 @@ async function syncRunWithControlAsync(repoPath, run2) {
33843
34027
  }
33844
34028
  }
33845
34029
  }
33846
- var path30, DEFAULT_MAX_BATCH_BYTES, DEFAULT_SYNC_OVERLAP_MS, MAX_FETCH_ATTEMPTS, SYNC_TIMEOUT_MS, EXPLICIT_SYNC_TIMEOUT_MS;
34030
+ var path29, DEFAULT_MAX_BATCH_BYTES, DEFAULT_SYNC_OVERLAP_MS, MAX_FETCH_ATTEMPTS, SYNC_TIMEOUT_MS, EXPLICIT_SYNC_TIMEOUT_MS;
33847
34031
  var init_control_sync = __esm({
33848
34032
  "src/core/control-sync.ts"() {
33849
34033
  "use strict";
33850
- path30 = __toESM(require("path"));
34034
+ path29 = __toESM(require("path"));
33851
34035
  init_manifest();
33852
34036
  init_stages();
33853
34037
  init_schema2();
@@ -33882,7 +34066,7 @@ var init_control_sync = __esm({
33882
34066
  // src/core/sync-context.ts
33883
34067
  function markDirty(repoPath) {
33884
34068
  if (!repoPath) return;
33885
- dirtyRepos.add(path31.resolve(repoPath));
34069
+ dirtyRepos.add(path30.resolve(repoPath));
33886
34070
  }
33887
34071
  function markAllRegisteredDirty() {
33888
34072
  syncAllRegistered = true;
@@ -33907,11 +34091,11 @@ async function syncDirtyRepos() {
33907
34091
  } catch {
33908
34092
  }
33909
34093
  }
33910
- var path31, dirtyRepos, syncAllRegistered;
34094
+ var path30, dirtyRepos, syncAllRegistered;
33911
34095
  var init_sync_context = __esm({
33912
34096
  "src/core/sync-context.ts"() {
33913
34097
  "use strict";
33914
- path31 = __toESM(require("path"));
34098
+ path30 = __toESM(require("path"));
33915
34099
  dirtyRepos = /* @__PURE__ */ new Set();
33916
34100
  syncAllRegistered = false;
33917
34101
  }
@@ -35009,15 +35193,15 @@ var require_route = __commonJS({
35009
35193
  };
35010
35194
  }
35011
35195
  function wrapConversion(toModel, graph) {
35012
- const path70 = [graph[toModel].parent, toModel];
35196
+ const path69 = [graph[toModel].parent, toModel];
35013
35197
  let fn = conversions[graph[toModel].parent][toModel];
35014
35198
  let cur = graph[toModel].parent;
35015
35199
  while (graph[cur].parent) {
35016
- path70.unshift(graph[cur].parent);
35200
+ path69.unshift(graph[cur].parent);
35017
35201
  fn = link(conversions[graph[cur].parent][cur], fn);
35018
35202
  cur = graph[cur].parent;
35019
35203
  }
35020
- fn.conversion = path70;
35204
+ fn.conversion = path69;
35021
35205
  return fn;
35022
35206
  }
35023
35207
  module2.exports = function(fromModel) {
@@ -41511,7 +41695,7 @@ var require_lib2 = __commonJS({
41511
41695
  return matches;
41512
41696
  };
41513
41697
  exports2.analyse = analyse;
41514
- var detectFile = (filepath, opts = {}) => new Promise((resolve53, reject) => {
41698
+ var detectFile = (filepath, opts = {}) => new Promise((resolve52, reject) => {
41515
41699
  let fd;
41516
41700
  const fs54 = (0, node_1.default)();
41517
41701
  const handler = (err, buffer) => {
@@ -41521,7 +41705,7 @@ var require_lib2 = __commonJS({
41521
41705
  if (err) {
41522
41706
  reject(err);
41523
41707
  } else if (buffer) {
41524
- resolve53((0, exports2.detect)(buffer));
41708
+ resolve52((0, exports2.detect)(buffer));
41525
41709
  } else {
41526
41710
  reject(new Error("No error and no buffer received"));
41527
41711
  }
@@ -46070,7 +46254,7 @@ var require_Observable = __commonJS({
46070
46254
  Observable2.prototype.forEach = function(next, promiseCtor) {
46071
46255
  var _this = this;
46072
46256
  promiseCtor = getPromiseCtor(promiseCtor);
46073
- return new promiseCtor(function(resolve53, reject) {
46257
+ return new promiseCtor(function(resolve52, reject) {
46074
46258
  var subscriber = new Subscriber_1.SafeSubscriber({
46075
46259
  next: function(value) {
46076
46260
  try {
@@ -46081,7 +46265,7 @@ var require_Observable = __commonJS({
46081
46265
  }
46082
46266
  },
46083
46267
  error: reject,
46084
- complete: resolve53
46268
+ complete: resolve52
46085
46269
  });
46086
46270
  _this.subscribe(subscriber);
46087
46271
  });
@@ -46103,14 +46287,14 @@ var require_Observable = __commonJS({
46103
46287
  Observable2.prototype.toPromise = function(promiseCtor) {
46104
46288
  var _this = this;
46105
46289
  promiseCtor = getPromiseCtor(promiseCtor);
46106
- return new promiseCtor(function(resolve53, reject) {
46290
+ return new promiseCtor(function(resolve52, reject) {
46107
46291
  var value;
46108
46292
  _this.subscribe(function(x) {
46109
46293
  return value = x;
46110
46294
  }, function(err) {
46111
46295
  return reject(err);
46112
46296
  }, function() {
46113
- return resolve53(value);
46297
+ return resolve52(value);
46114
46298
  });
46115
46299
  });
46116
46300
  };
@@ -48206,11 +48390,11 @@ var require_innerFrom = __commonJS({
48206
48390
  "use strict";
48207
48391
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
48208
48392
  function adopt(value) {
48209
- return value instanceof P2 ? value : new P2(function(resolve53) {
48210
- resolve53(value);
48393
+ return value instanceof P2 ? value : new P2(function(resolve52) {
48394
+ resolve52(value);
48211
48395
  });
48212
48396
  }
48213
- return new (P2 || (P2 = Promise))(function(resolve53, reject) {
48397
+ return new (P2 || (P2 = Promise))(function(resolve52, reject) {
48214
48398
  function fulfilled(value) {
48215
48399
  try {
48216
48400
  step(generator.next(value));
@@ -48226,7 +48410,7 @@ var require_innerFrom = __commonJS({
48226
48410
  }
48227
48411
  }
48228
48412
  function step(result) {
48229
- result.done ? resolve53(result.value) : adopt(result.value).then(fulfilled, rejected);
48413
+ result.done ? resolve52(result.value) : adopt(result.value).then(fulfilled, rejected);
48230
48414
  }
48231
48415
  step((generator = generator.apply(thisArg, _arguments || [])).next());
48232
48416
  });
@@ -48308,14 +48492,14 @@ var require_innerFrom = __commonJS({
48308
48492
  }, i);
48309
48493
  function verb(n) {
48310
48494
  i[n] = o[n] && function(v2) {
48311
- return new Promise(function(resolve53, reject) {
48312
- v2 = o[n](v2), settle(resolve53, reject, v2.done, v2.value);
48495
+ return new Promise(function(resolve52, reject) {
48496
+ v2 = o[n](v2), settle(resolve52, reject, v2.done, v2.value);
48313
48497
  });
48314
48498
  };
48315
48499
  }
48316
- function settle(resolve53, reject, d, v2) {
48500
+ function settle(resolve52, reject, d, v2) {
48317
48501
  Promise.resolve(v2).then(function(v3) {
48318
- resolve53({ value: v3, done: d });
48502
+ resolve52({ value: v3, done: d });
48319
48503
  }, reject);
48320
48504
  }
48321
48505
  };
@@ -48934,7 +49118,7 @@ var require_lastValueFrom = __commonJS({
48934
49118
  var EmptyError_1 = require_EmptyError();
48935
49119
  function lastValueFrom2(source, config2) {
48936
49120
  var hasConfig = typeof config2 === "object";
48937
- return new Promise(function(resolve53, reject) {
49121
+ return new Promise(function(resolve52, reject) {
48938
49122
  var _hasValue = false;
48939
49123
  var _value;
48940
49124
  source.subscribe({
@@ -48945,9 +49129,9 @@ var require_lastValueFrom = __commonJS({
48945
49129
  error: reject,
48946
49130
  complete: function() {
48947
49131
  if (_hasValue) {
48948
- resolve53(_value);
49132
+ resolve52(_value);
48949
49133
  } else if (hasConfig) {
48950
- resolve53(config2.defaultValue);
49134
+ resolve52(config2.defaultValue);
48951
49135
  } else {
48952
49136
  reject(new EmptyError_1.EmptyError());
48953
49137
  }
@@ -48969,16 +49153,16 @@ var require_firstValueFrom = __commonJS({
48969
49153
  var Subscriber_1 = require_Subscriber();
48970
49154
  function firstValueFrom(source, config2) {
48971
49155
  var hasConfig = typeof config2 === "object";
48972
- return new Promise(function(resolve53, reject) {
49156
+ return new Promise(function(resolve52, reject) {
48973
49157
  var subscriber = new Subscriber_1.SafeSubscriber({
48974
49158
  next: function(value) {
48975
- resolve53(value);
49159
+ resolve52(value);
48976
49160
  subscriber.unsubscribe();
48977
49161
  },
48978
49162
  error: reject,
48979
49163
  complete: function() {
48980
49164
  if (hasConfig) {
48981
- resolve53(config2.defaultValue);
49165
+ resolve52(config2.defaultValue);
48982
49166
  } else {
48983
49167
  reject(new EmptyError_1.EmptyError());
48984
49168
  }
@@ -54770,14 +54954,14 @@ var require_run_async = __commonJS({
54770
54954
  return function() {
54771
54955
  var args = arguments;
54772
54956
  var originalThis = this;
54773
- var promise = new Promise(function(resolve53, reject) {
54957
+ var promise = new Promise(function(resolve52, reject) {
54774
54958
  var resolved = false;
54775
54959
  const wrappedResolve = function(value) {
54776
54960
  if (resolved) {
54777
54961
  console.warn("Run-async promise already resolved.");
54778
54962
  }
54779
54963
  resolved = true;
54780
- resolve53(value);
54964
+ resolve52(value);
54781
54965
  };
54782
54966
  var rejected = false;
54783
54967
  const wrappedReject = function(value) {
@@ -54885,25 +55069,25 @@ __export(otel_hooks_exports, {
54885
55069
  });
54886
55070
  function getOtelHooksHome() {
54887
55071
  if (process.env.HAR_OTEL_HOOKS_HOME) {
54888
- return path54.resolve(process.env.HAR_OTEL_HOOKS_HOME);
55072
+ return path53.resolve(process.env.HAR_OTEL_HOOKS_HOME);
54889
55073
  }
54890
- return path54.join(os19.homedir(), ".har", "otel-hooks");
55074
+ return path53.join(os19.homedir(), ".har", "otel-hooks");
54891
55075
  }
54892
55076
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
54893
- return path54.join(hooksHome, "otel_config.json");
55077
+ return path53.join(hooksHome, "otel_config.json");
54894
55078
  }
54895
55079
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
54896
- return path54.join(hooksHome, "run-otel-hook.sh");
55080
+ return path53.join(hooksHome, "run-otel-hook.sh");
54897
55081
  }
54898
55082
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
54899
- return path54.join(hooksHome, "state");
55083
+ return path53.join(hooksHome, "state");
54900
55084
  }
54901
55085
  function localOtelHookBin(hooksHome) {
54902
- return path54.join(hooksHome, "node_modules", ".bin", "otel-hook");
55086
+ return path53.join(hooksHome, "node_modules", ".bin", "otel-hook");
54903
55087
  }
54904
55088
  function installedPackageVersion(hooksHome) {
54905
55089
  try {
54906
- const pkgPath = path54.join(
55090
+ const pkgPath = path53.join(
54907
55091
  hooksHome,
54908
55092
  "node_modules",
54909
55093
  "@osfactory",
@@ -55050,9 +55234,9 @@ function uninstallLegacyPythonHooks(hooksHome) {
55050
55234
  }
55051
55235
  function removeLegacyPythonArtifacts(hooksHome) {
55052
55236
  const legacyPaths = [
55053
- path54.join(hooksHome, ".venv"),
55054
- path54.join(hooksHome, "otel_config.yaml"),
55055
- path54.join(hooksHome, "venv")
55237
+ path53.join(hooksHome, ".venv"),
55238
+ path53.join(hooksHome, "otel_config.yaml"),
55239
+ path53.join(hooksHome, "venv")
55056
55240
  ];
55057
55241
  for (const target of legacyPaths) {
55058
55242
  try {
@@ -55198,14 +55382,14 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
55198
55382
  function rewriteKnownHookRegistrations(wrapperPath) {
55199
55383
  const home = os19.homedir();
55200
55384
  const candidates = [
55201
- path54.join(home, ".cursor", "hooks.json"),
55202
- path54.join(home, ".claude", "settings.json"),
55203
- path54.join(home, ".codex", "hooks.json")
55385
+ path53.join(home, ".cursor", "hooks.json"),
55386
+ path53.join(home, ".claude", "settings.json"),
55387
+ path53.join(home, ".codex", "hooks.json")
55204
55388
  ];
55205
55389
  for (const filePath of candidates) {
55206
55390
  try {
55207
55391
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
55208
- if (filePath.endsWith(`${path54.sep}.cursor${path54.sep}hooks.json`)) {
55392
+ if (filePath.endsWith(`${path53.sep}.cursor${path53.sep}hooks.json`)) {
55209
55393
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
55210
55394
  }
55211
55395
  } catch {
@@ -55315,14 +55499,14 @@ function ensureOtelHooks(options) {
55315
55499
  function disableOtelHooksExport() {
55316
55500
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
55317
55501
  }
55318
- var import_child_process14, fs46, os19, path54, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
55502
+ var import_child_process14, fs46, os19, path53, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
55319
55503
  var init_otel_hooks = __esm({
55320
55504
  "src/core/otel-hooks.ts"() {
55321
55505
  "use strict";
55322
55506
  import_child_process14 = require("child_process");
55323
55507
  fs46 = __toESM(require("fs"));
55324
55508
  os19 = __toESM(require("os"));
55325
- path54 = __toESM(require("path"));
55509
+ path53 = __toESM(require("path"));
55326
55510
  init_control_config();
55327
55511
  init_telemetry_config();
55328
55512
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.2.0";
@@ -58297,7 +58481,7 @@ var require_compile = __commonJS({
58297
58481
  const schOrFunc = root.refs[ref];
58298
58482
  if (schOrFunc)
58299
58483
  return schOrFunc;
58300
- let _sch = resolve53.call(this, root, ref);
58484
+ let _sch = resolve52.call(this, root, ref);
58301
58485
  if (_sch === void 0) {
58302
58486
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
58303
58487
  const { schemaId } = this.opts;
@@ -58324,7 +58508,7 @@ var require_compile = __commonJS({
58324
58508
  function sameSchemaEnv(s1, s2) {
58325
58509
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
58326
58510
  }
58327
- function resolve53(root, ref) {
58511
+ function resolve52(root, ref) {
58328
58512
  let sch;
58329
58513
  while (typeof (sch = this.refs[ref]) == "string")
58330
58514
  ref = sch;
@@ -58542,8 +58726,8 @@ var require_utils2 = __commonJS({
58542
58726
  }
58543
58727
  return ind;
58544
58728
  }
58545
- function removeDotSegments(path70) {
58546
- let input = path70;
58729
+ function removeDotSegments(path69) {
58730
+ let input = path69;
58547
58731
  const output = [];
58548
58732
  let nextSlash = -1;
58549
58733
  let len = 0;
@@ -58795,8 +58979,8 @@ var require_schemes = __commonJS({
58795
58979
  wsComponent.secure = void 0;
58796
58980
  }
58797
58981
  if (wsComponent.resourceName) {
58798
- const [path70, query] = wsComponent.resourceName.split("?");
58799
- wsComponent.path = path70 && path70 !== "/" ? path70 : void 0;
58982
+ const [path69, query] = wsComponent.resourceName.split("?");
58983
+ wsComponent.path = path69 && path69 !== "/" ? path69 : void 0;
58800
58984
  wsComponent.query = query;
58801
58985
  wsComponent.resourceName = void 0;
58802
58986
  }
@@ -58955,7 +59139,7 @@ var require_fast_uri = __commonJS({
58955
59139
  }
58956
59140
  return uri;
58957
59141
  }
58958
- function resolve53(baseURI, relativeURI, options) {
59142
+ function resolve52(baseURI, relativeURI, options) {
58959
59143
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
58960
59144
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
58961
59145
  schemelessOptions.skipEscape = true;
@@ -59213,7 +59397,7 @@ var require_fast_uri = __commonJS({
59213
59397
  var fastUri = {
59214
59398
  SCHEMES,
59215
59399
  normalize: normalize3,
59216
- resolve: resolve53,
59400
+ resolve: resolve52,
59217
59401
  resolveComponent,
59218
59402
  equal,
59219
59403
  serialize,
@@ -63478,11 +63662,11 @@ var parser = new YargsParser({
63478
63662
  resolve: import_path2.resolve,
63479
63663
  // TODO: figure out a way to combine ESM and CJS coverage, such that
63480
63664
  // we can exercise all the lines below:
63481
- require: (path70) => {
63665
+ require: (path69) => {
63482
63666
  if (typeof require !== "undefined") {
63483
- return require(path70);
63484
- } else if (path70.match(/\.json$/)) {
63485
- return JSON.parse((0, import_fs2.readFileSync)(path70, "utf8"));
63667
+ return require(path69);
63668
+ } else if (path69.match(/\.json$/)) {
63669
+ return JSON.parse((0, import_fs2.readFileSync)(path69, "utf8"));
63486
63670
  } else {
63487
63671
  throw Error("only .json config files are supported in ESM");
63488
63672
  }
@@ -66008,12 +66192,12 @@ var YargsInstance = class {
66008
66192
  async getCompletion(args, done) {
66009
66193
  argsert("<array> [function]", [args, done], arguments.length);
66010
66194
  if (!done) {
66011
- return new Promise((resolve53, reject) => {
66195
+ return new Promise((resolve52, reject) => {
66012
66196
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
66013
66197
  if (err)
66014
66198
  reject(err);
66015
66199
  else
66016
- resolve53(completions);
66200
+ resolve52(completions);
66017
66201
  });
66018
66202
  });
66019
66203
  } else {
@@ -67058,33 +67242,33 @@ init_telemetry_config();
67058
67242
  init_sync_context();
67059
67243
 
67060
67244
  // src/cli/commands/agents.ts
67061
- var path34 = __toESM(require("path"));
67245
+ var path33 = __toESM(require("path"));
67062
67246
 
67063
67247
  // src/harness/agent-skills.ts
67064
67248
  var fs27 = __toESM(require("fs"));
67065
67249
  var os14 = __toESM(require("os"));
67066
- var path33 = __toESM(require("path"));
67250
+ var path32 = __toESM(require("path"));
67067
67251
  var readline = __toESM(require("readline"));
67068
67252
  init_file_ops();
67069
67253
  init_logging();
67070
67254
 
67071
67255
  // src/utils/paths.ts
67072
67256
  var fs26 = __toESM(require("fs"));
67073
- var path32 = __toESM(require("path"));
67257
+ var path31 = __toESM(require("path"));
67074
67258
  function resolveTemplatesDir() {
67075
67259
  const candidates = [
67076
- path32.join(__dirname, "templates"),
67077
- path32.join(__dirname, "..", "templates"),
67078
- path32.join(__dirname, "..", "harness", "templates")
67260
+ path31.join(__dirname, "templates"),
67261
+ path31.join(__dirname, "..", "templates"),
67262
+ path31.join(__dirname, "..", "harness", "templates")
67079
67263
  ];
67080
67264
  for (const dir of candidates) {
67081
- if (fs26.existsSync(path32.join(dir, "har-boilerplate"))) return dir;
67265
+ if (fs26.existsSync(path31.join(dir, "har-boilerplate"))) return dir;
67082
67266
  }
67083
67267
  throw new Error("Templates directory not found. Run npm run build.");
67084
67268
  }
67085
67269
  function resolveTemplateFile(name) {
67086
67270
  const dir = resolveTemplatesDir();
67087
- const filePath = path32.join(dir, name);
67271
+ const filePath = path31.join(dir, name);
67088
67272
  return fs26.existsSync(filePath) ? filePath : null;
67089
67273
  }
67090
67274
 
@@ -67093,18 +67277,18 @@ init_manifest();
67093
67277
  var AGENT_SKILL_TARGETS = ["claude", "cursor", "codex"];
67094
67278
  var MANAGED_HEADER = "<!-- managed by har \u2014 regenerated by `har agents install` / `har env maintain`; edit at your own risk -->";
67095
67279
  function agentSkillsTemplateDir() {
67096
- const dir = path33.join(resolveTemplatesDir(), "agent-skills");
67280
+ const dir = path32.join(resolveTemplatesDir(), "agent-skills");
67097
67281
  if (!fs27.existsSync(dir)) {
67098
67282
  throw new Error("Agent skills templates not found (templates/agent-skills). Run npm run build.");
67099
67283
  }
67100
67284
  return dir;
67101
67285
  }
67102
67286
  function readSkillsManifest() {
67103
- const manifestPath = path33.join(agentSkillsTemplateDir(), "skills.manifest.json");
67287
+ const manifestPath = path32.join(agentSkillsTemplateDir(), "skills.manifest.json");
67104
67288
  return JSON.parse(fs27.readFileSync(manifestPath, "utf8"));
67105
67289
  }
67106
67290
  function readSkillBody(entry) {
67107
- return fs27.readFileSync(path33.join(agentSkillsTemplateDir(), entry.body), "utf8");
67291
+ return fs27.readFileSync(path32.join(agentSkillsTemplateDir(), entry.body), "utf8");
67108
67292
  }
67109
67293
  function renderYamlValue(value) {
67110
67294
  if (typeof value === "string") return JSON.stringify(value);
@@ -67136,7 +67320,7 @@ function renderSkillFiles(agents) {
67136
67320
  agent: "claude",
67137
67321
  skill: entry.id,
67138
67322
  scope: "repo",
67139
- relPath: path33.join(".claude", "skills", entry.id, "SKILL.md"),
67323
+ relPath: path32.join(".claude", "skills", entry.id, "SKILL.md"),
67140
67324
  content: renderClaudeSkill(entry, body)
67141
67325
  });
67142
67326
  }
@@ -67145,7 +67329,7 @@ function renderSkillFiles(agents) {
67145
67329
  agent: "cursor",
67146
67330
  skill: entry.id,
67147
67331
  scope: "repo",
67148
- relPath: path33.join(".cursor", "commands", `${entry.id}.md`),
67332
+ relPath: path32.join(".cursor", "commands", `${entry.id}.md`),
67149
67333
  content: renderPlainSkill(body)
67150
67334
  });
67151
67335
  }
@@ -67154,7 +67338,7 @@ function renderSkillFiles(agents) {
67154
67338
  agent: "codex",
67155
67339
  skill: entry.id,
67156
67340
  scope: "global",
67157
- relPath: path33.posix.join("~", ".codex", "prompts", `${entry.codex.promptName}.md`),
67341
+ relPath: path32.posix.join("~", ".codex", "prompts", `${entry.codex.promptName}.md`),
67158
67342
  content: renderPlainSkill(body)
67159
67343
  });
67160
67344
  }
@@ -67163,9 +67347,9 @@ function renderSkillFiles(agents) {
67163
67347
  }
67164
67348
  function resolveScaffoldPath(repoPath, file) {
67165
67349
  if (file.scope === "global") {
67166
- return path33.join(os14.homedir(), file.relPath.replace(/^~\//, ""));
67350
+ return path32.join(os14.homedir(), file.relPath.replace(/^~\//, ""));
67167
67351
  }
67168
- return path33.join(repoPath, file.relPath);
67352
+ return path32.join(repoPath, file.relPath);
67169
67353
  }
67170
67354
  function isHarManaged(filePath) {
67171
67355
  return fs27.readFileSync(filePath, "utf8").includes(MANAGED_HEADER);
@@ -67217,7 +67401,7 @@ function removeAgentSkills(repoPath, agents) {
67217
67401
  }
67218
67402
  fs27.rmSync(destPath);
67219
67403
  removed.push(file.relPath);
67220
- const parent = path33.dirname(destPath);
67404
+ const parent = path32.dirname(destPath);
67221
67405
  if (fs27.existsSync(parent) && fs27.readdirSync(parent).length === 0) {
67222
67406
  fs27.rmdirSync(parent);
67223
67407
  }
@@ -67238,9 +67422,9 @@ function detectAgentTargets(repoPath) {
67238
67422
  const manifest = readManifest(repoPath);
67239
67423
  const scaffolded = new Set((manifest?.scaffoldedAgentFiles ?? []).map((entry) => entry.agent));
67240
67424
  const detected = new Set(scaffolded);
67241
- if (fs27.existsSync(path33.join(repoPath, ".claude"))) detected.add("claude");
67242
- if (fs27.existsSync(path33.join(repoPath, ".cursor"))) detected.add("cursor");
67243
- if (fs27.existsSync(path33.join(os14.homedir(), ".codex"))) detected.add("codex");
67425
+ if (fs27.existsSync(path32.join(repoPath, ".claude"))) detected.add("claude");
67426
+ if (fs27.existsSync(path32.join(repoPath, ".cursor"))) detected.add("cursor");
67427
+ if (fs27.existsSync(path32.join(os14.homedir(), ".codex"))) detected.add("codex");
67244
67428
  return AGENT_SKILL_TARGETS.filter((agent) => detected.has(agent));
67245
67429
  }
67246
67430
  function parseAgentTargets(raw) {
@@ -67284,16 +67468,16 @@ async function handleAgentSkills(options) {
67284
67468
  }
67285
67469
  async function askYesNo(question) {
67286
67470
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
67287
- return new Promise((resolve53) => {
67471
+ return new Promise((resolve52) => {
67288
67472
  process.stderr.write(`${question} `);
67289
67473
  rl.once("line", (answer) => {
67290
67474
  rl.close();
67291
67475
  const trimmed = answer.trim();
67292
67476
  if (trimmed === "") {
67293
- resolve53(true);
67477
+ resolve52(true);
67294
67478
  return;
67295
67479
  }
67296
- resolve53(/^y(es)?$/i.test(trimmed));
67480
+ resolve52(/^y(es)?$/i.test(trimmed));
67297
67481
  });
67298
67482
  });
67299
67483
  }
@@ -67327,7 +67511,7 @@ var agentsCommand = {
67327
67511
  }
67328
67512
  };
67329
67513
  function handleInstall(argv) {
67330
- const repoPath = path34.resolve(argv.repo);
67514
+ const repoPath = path33.resolve(argv.repo);
67331
67515
  header("har agents install");
67332
67516
  try {
67333
67517
  const targets = resolveTargets(argv, repoPath);
@@ -67353,7 +67537,7 @@ function handleInstall(argv) {
67353
67537
  }
67354
67538
  }
67355
67539
  function handleRemove(argv) {
67356
- const repoPath = path34.resolve(argv.repo);
67540
+ const repoPath = path33.resolve(argv.repo);
67357
67541
  header("har agents remove");
67358
67542
  try {
67359
67543
  const targets = resolveTargets(argv, repoPath);
@@ -67373,7 +67557,7 @@ function handleRemove(argv) {
67373
67557
  }
67374
67558
 
67375
67559
  // src/cli/commands/env.ts
67376
- var path58 = __toESM(require("path"));
67560
+ var path57 = __toESM(require("path"));
67377
67561
 
67378
67562
  // src/cli/finish-command.ts
67379
67563
  init_sync_context();
@@ -67384,23 +67568,23 @@ async function finishCommand(code) {
67384
67568
 
67385
67569
  // src/core/harness.ts
67386
67570
  var fs42 = __toESM(require("fs"));
67387
- var path49 = __toESM(require("path"));
67571
+ var path48 = __toESM(require("path"));
67388
67572
 
67389
67573
  // src/harness/generator.ts
67390
67574
  var fs32 = __toESM(require("fs"));
67391
- var path39 = __toESM(require("path"));
67575
+ var path38 = __toESM(require("path"));
67392
67576
  init_file_ops();
67393
67577
  init_logging();
67394
67578
 
67395
67579
  // src/core/gitignore.ts
67396
67580
  var fs28 = __toESM(require("fs"));
67397
- var path35 = __toESM(require("path"));
67581
+ var path34 = __toESM(require("path"));
67398
67582
  var HARNESS_ROOT_GITIGNORE_PATTERNS = [
67399
67583
  ".env.agent.*",
67400
67584
  "ecosystem.agent.*.config.cjs"
67401
67585
  ];
67402
67586
  function ensureRootGitignorePatterns(checkoutDir) {
67403
- const gitignorePath = path35.join(checkoutDir, ".gitignore");
67587
+ const gitignorePath = path34.join(checkoutDir, ".gitignore");
67404
67588
  const content = fs28.existsSync(gitignorePath) ? fs28.readFileSync(gitignorePath, "utf8") : "";
67405
67589
  const lines = content.split("\n").map((line) => line.trim());
67406
67590
  const missing = HARNESS_ROOT_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
@@ -67415,7 +67599,7 @@ function ensureRootGitignorePatterns(checkoutDir) {
67415
67599
 
67416
67600
  // src/harness/gitignore-template.ts
67417
67601
  var fs29 = __toESM(require("fs"));
67418
- var path36 = __toESM(require("path"));
67602
+ var path35 = __toESM(require("path"));
67419
67603
  var HARNESS_GITIGNORE_TEMPLATE = "gitignore.template";
67420
67604
  var HARNESS_GITIGNORE_FILE = ".gitignore";
67421
67605
  function harnessFileForTemplate(templateFile) {
@@ -67425,16 +67609,16 @@ function templateFileForHarness(harnessFile) {
67425
67609
  return harnessFile === HARNESS_GITIGNORE_FILE ? HARNESS_GITIGNORE_TEMPLATE : harnessFile;
67426
67610
  }
67427
67611
  function resolveGitignoreTemplateSource(boilerplateDir) {
67428
- const primary = path36.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
67612
+ const primary = path35.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
67429
67613
  if (fs29.existsSync(primary)) return primary;
67430
- const legacy = path36.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
67614
+ const legacy = path35.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
67431
67615
  if (fs29.existsSync(legacy)) return legacy;
67432
67616
  return null;
67433
67617
  }
67434
67618
  function writeHarnessGitignore(harnessDir, boilerplateDir) {
67435
67619
  const src = resolveGitignoreTemplateSource(boilerplateDir);
67436
67620
  if (!src) return;
67437
- fs29.writeFileSync(path36.join(harnessDir, HARNESS_GITIGNORE_FILE), fs29.readFileSync(src, "utf8"));
67621
+ fs29.writeFileSync(path35.join(harnessDir, HARNESS_GITIGNORE_FILE), fs29.readFileSync(src, "utf8"));
67438
67622
  }
67439
67623
  function isExpectedHarnessOnlyFile(harnessFile, templateFiles) {
67440
67624
  return harnessFile === HARNESS_GITIGNORE_FILE && templateFiles.includes(HARNESS_GITIGNORE_TEMPLATE);
@@ -67445,7 +67629,7 @@ init_manifest();
67445
67629
 
67446
67630
  // src/harness/plugin-ledger.ts
67447
67631
  var fs30 = __toESM(require("fs"));
67448
- var path37 = __toESM(require("path"));
67632
+ var path36 = __toESM(require("path"));
67449
67633
  init_zod();
67450
67634
  init_file_ops();
67451
67635
  init_manifest();
@@ -67468,7 +67652,7 @@ var PluginLedgerSchema = external_exports.object({
67468
67652
  plugins: external_exports.array(PluginLedgerEntrySchema).default([])
67469
67653
  });
67470
67654
  function getPluginLedgerPath(repoPath) {
67471
- return path37.join(path37.resolve(repoPath), DEFAULT_HAR_DIR, "plugins.json");
67655
+ return path36.join(path36.resolve(repoPath), DEFAULT_HAR_DIR, "plugins.json");
67472
67656
  }
67473
67657
  function readPluginLedger(repoPath) {
67474
67658
  const ledgerPath = getPluginLedgerPath(repoPath);
@@ -67483,7 +67667,7 @@ function readPluginLedger(repoPath) {
67483
67667
  }
67484
67668
  function writePluginLedger(repoPath, ledger) {
67485
67669
  const ledgerPath = getPluginLedgerPath(repoPath);
67486
- const harnessDir = path37.dirname(ledgerPath);
67670
+ const harnessDir = path36.dirname(ledgerPath);
67487
67671
  if (!fs30.existsSync(harnessDir)) {
67488
67672
  fs30.mkdirSync(harnessDir, { recursive: true });
67489
67673
  }
@@ -67521,7 +67705,7 @@ function ensurePluginLedgerScaffold(repoPath, options) {
67521
67705
 
67522
67706
  // src/harness/profiles.ts
67523
67707
  var fs31 = __toESM(require("fs"));
67524
- var path38 = __toESM(require("path"));
67708
+ var path37 = __toESM(require("path"));
67525
67709
  init_zod();
67526
67710
  var HARNESS_PROFILES = ["default", "cli", "ios"];
67527
67711
  var ProfileBundleRefSchema = external_exports.object({
@@ -67574,7 +67758,7 @@ var PROFILE_DIRS = {
67574
67758
  };
67575
67759
  function readProfileManifest(profile) {
67576
67760
  const templates = resolveTemplatesDir();
67577
- const manifestPath = path38.join(templates, "profiles", profile, "profile.manifest.json");
67761
+ const manifestPath = path37.join(templates, "profiles", profile, "profile.manifest.json");
67578
67762
  if (fs31.existsSync(manifestPath)) {
67579
67763
  const parsed = ProfileManifestSchema.safeParse(
67580
67764
  JSON.parse(fs31.readFileSync(manifestPath, "utf8"))
@@ -67590,7 +67774,7 @@ function readProfileManifest(profile) {
67590
67774
  return PROFILE_COMPOSITIONS[profile];
67591
67775
  }
67592
67776
  function resolveProfileBundleDir(bundle) {
67593
- const dir = path38.join(resolveTemplatesDir(), bundle.path);
67777
+ const dir = path37.join(resolveTemplatesDir(), bundle.path);
67594
67778
  if (!fs31.existsSync(dir)) {
67595
67779
  throw new Error(`Profile bundle not found: ${bundle.id} (${bundle.path}). Run npm run build.`);
67596
67780
  }
@@ -67606,20 +67790,20 @@ var CLI_PRUNE_FILES = [
67606
67790
  ];
67607
67791
  function pruneCliProfile(harnessDir) {
67608
67792
  for (const file of CLI_PRUNE_FILES) {
67609
- const filePath = path39.join(harnessDir, file);
67793
+ const filePath = path38.join(harnessDir, file);
67610
67794
  if (fs32.existsSync(filePath)) {
67611
67795
  fs32.unlinkSync(filePath);
67612
67796
  }
67613
67797
  }
67614
67798
  }
67615
67799
  function scaffoldHarnessBoilerplate(repoPath, options = {}) {
67616
- const harnessDir = path39.join(repoPath, DEFAULT_HAR_DIR);
67617
- const projectName = path39.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
67800
+ const harnessDir = path38.join(repoPath, DEFAULT_HAR_DIR);
67801
+ const projectName = path38.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
67618
67802
  const profile = options.profile ?? "default";
67619
67803
  const profileManifest = readProfileManifest(profile);
67620
67804
  const bundleIds = profileManifest.bundles.map((b2) => b2.id);
67621
67805
  const primaryOverlay = PROFILE_DIRS[profile];
67622
- const boilerplateDir = path39.join(resolveTemplatesDir(), primaryOverlay);
67806
+ const boilerplateDir = path38.join(resolveTemplatesDir(), primaryOverlay);
67623
67807
  if (fs32.existsSync(harnessDir) && !options.force) {
67624
67808
  throw new Error(
67625
67809
  '.har/ already exists. Use --force to overwrite or run "har env maintain" to update in place.'
@@ -67641,7 +67825,7 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
67641
67825
  pruneCliProfile(harnessDir);
67642
67826
  }
67643
67827
  syncAgentSlotsToHarnessEnv(repoPath);
67644
- const harnessEnvPath = path39.join(harnessDir, "harness.env");
67828
+ const harnessEnvPath = path38.join(harnessDir, "harness.env");
67645
67829
  if (fs32.existsSync(harnessEnvPath)) {
67646
67830
  let content = fs32.readFileSync(harnessEnvPath, "utf8");
67647
67831
  content = content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
@@ -67670,7 +67854,7 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
67670
67854
 
67671
67855
  // src/harness/agent-md.ts
67672
67856
  var fs34 = __toESM(require("fs"));
67673
- var path42 = __toESM(require("path"));
67857
+ var path41 = __toESM(require("path"));
67674
67858
  init_file_ops();
67675
67859
  init_logging();
67676
67860
  init_manifest();
@@ -67678,7 +67862,7 @@ init_manifest();
67678
67862
  // src/harness/instruction-files.ts
67679
67863
  var fs33 = __toESM(require("fs"));
67680
67864
  var os16 = __toESM(require("os"));
67681
- var path41 = __toESM(require("path"));
67865
+ var path40 = __toESM(require("path"));
67682
67866
 
67683
67867
  // node_modules/@inquirer/core/dist/esm/lib/key.js
67684
67868
  var isUpKey = (key, keybindings = []) => (
@@ -68712,13 +68896,13 @@ var PromisePolyfill = class extends Promise {
68712
68896
  // Available starting from Node 22
68713
68897
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
68714
68898
  static withResolver() {
68715
- let resolve53;
68899
+ let resolve52;
68716
68900
  let reject;
68717
68901
  const promise = new Promise((res, rej) => {
68718
- resolve53 = res;
68902
+ resolve52 = res;
68719
68903
  reject = rej;
68720
68904
  });
68721
- return { promise, resolve: resolve53, reject };
68905
+ return { promise, resolve: resolve52, reject };
68722
68906
  }
68723
68907
  };
68724
68908
 
@@ -68752,7 +68936,7 @@ function createPrompt(view) {
68752
68936
  output
68753
68937
  });
68754
68938
  const screen = new ScreenManager(rl);
68755
- const { promise, resolve: resolve53, reject } = PromisePolyfill.withResolver();
68939
+ const { promise, resolve: resolve52, reject } = PromisePolyfill.withResolver();
68756
68940
  const cancel = () => reject(new CancelPromptError());
68757
68941
  if (signal) {
68758
68942
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -68779,7 +68963,7 @@ function createPrompt(view) {
68779
68963
  cycle(() => {
68780
68964
  try {
68781
68965
  const nextView = view(config2, (value) => {
68782
- setImmediate(() => resolve53(value));
68966
+ setImmediate(() => resolve52(value));
68783
68967
  });
68784
68968
  if (nextView === void 0) {
68785
68969
  const callerFilename = callSites[1]?.getFileName();
@@ -70088,9 +70272,9 @@ var import_rxjs = __toESM(require_cjs(), 1);
70088
70272
  var import_run_async = __toESM(require_run_async(), 1);
70089
70273
  var import_mute_stream2 = __toESM(require_lib(), 1);
70090
70274
  var _ = {
70091
- set: (obj, path70 = "", value) => {
70275
+ set: (obj, path69 = "", value) => {
70092
70276
  let pointer = obj;
70093
- path70.split(".").forEach((key, index, arr) => {
70277
+ path69.split(".").forEach((key, index, arr) => {
70094
70278
  if (key === "__proto__" || key === "constructor")
70095
70279
  return;
70096
70280
  if (index === arr.length - 1) {
@@ -70101,8 +70285,8 @@ var _ = {
70101
70285
  pointer = pointer[key];
70102
70286
  });
70103
70287
  },
70104
- get: (obj, path70 = "", defaultValue) => {
70105
- const travel = (regexp) => String.prototype.split.call(path70, regexp).filter(Boolean).reduce(
70288
+ get: (obj, path69 = "", defaultValue) => {
70289
+ const travel = (regexp) => String.prototype.split.call(path69, regexp).filter(Boolean).reduce(
70106
70290
  // @ts-expect-error implicit any on res[key]
70107
70291
  (res, key) => res == null ? res : res[key],
70108
70292
  obj
@@ -70220,7 +70404,7 @@ var PromptsRunner = class {
70220
70404
  throw new Error(`Prompt for type ${question.type} not found`);
70221
70405
  }
70222
70406
  let cleanupSignal;
70223
- const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve53, reject) => {
70407
+ const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve52, reject) => {
70224
70408
  const { signal: signal2 } = opt;
70225
70409
  if (signal2.aborted) {
70226
70410
  reject(new AbortPromptError({ cause: signal2.reason }));
@@ -70257,7 +70441,7 @@ var PromptsRunner = class {
70257
70441
  signal2.removeEventListener("abort", abort);
70258
70442
  cleanupSignal = void 0;
70259
70443
  };
70260
- activePrompt.run().then(resolve53, reject).finally(cleanup);
70444
+ activePrompt.run().then(resolve52, reject).finally(cleanup);
70261
70445
  }) : prompt2;
70262
70446
  let cleanupModuleSignal;
70263
70447
  const { signal: moduleSignal } = this.opt;
@@ -70427,12 +70611,12 @@ function outsideContentShrinkMessage(beforeLines, afterLines) {
70427
70611
  }
70428
70612
  function detectInstructionFiles(repoPath) {
70429
70613
  return {
70430
- agentsMd: fs33.existsSync(path41.join(repoPath, AGENTS_MD)),
70431
- agentMd: fs33.existsSync(path41.join(repoPath, LEGACY_AGENT_MD)),
70432
- claudeMd: fs33.existsSync(path41.join(repoPath, CLAUDE_MD)),
70433
- cursorDir: fs33.existsSync(path41.join(repoPath, ".cursor")),
70434
- claudeDir: fs33.existsSync(path41.join(repoPath, ".claude")),
70435
- codexHome: fs33.existsSync(path41.join(os16.homedir(), ".codex"))
70614
+ agentsMd: fs33.existsSync(path40.join(repoPath, AGENTS_MD)),
70615
+ agentMd: fs33.existsSync(path40.join(repoPath, LEGACY_AGENT_MD)),
70616
+ claudeMd: fs33.existsSync(path40.join(repoPath, CLAUDE_MD)),
70617
+ cursorDir: fs33.existsSync(path40.join(repoPath, ".cursor")),
70618
+ claudeDir: fs33.existsSync(path40.join(repoPath, ".claude")),
70619
+ codexHome: fs33.existsSync(path40.join(os16.homedir(), ".codex"))
70436
70620
  };
70437
70621
  }
70438
70622
  function formatDetectionReport(detection) {
@@ -70533,7 +70717,7 @@ function mergeAgentsMdContent(existing, incoming) {
70533
70717
  return content;
70534
70718
  }
70535
70719
  function upsertAgentsMdHarSection(repoPath, options = {}) {
70536
- const dest = path41.join(repoPath, AGENTS_MD);
70720
+ const dest = path40.join(repoPath, AGENTS_MD);
70537
70721
  const section = loadHarAgentsSectionFromTemplate();
70538
70722
  if (!fs33.existsSync(dest)) {
70539
70723
  writeFileSafe(dest, loadAgentsMdTemplate());
@@ -70564,8 +70748,8 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
70564
70748
  return action;
70565
70749
  }
70566
70750
  function migrateLegacyAgentMd(repoPath) {
70567
- const legacyPath = path41.join(repoPath, LEGACY_AGENT_MD);
70568
- const agentsPath = path41.join(repoPath, AGENTS_MD);
70751
+ const legacyPath = path40.join(repoPath, LEGACY_AGENT_MD);
70752
+ const agentsPath = path40.join(repoPath, AGENTS_MD);
70569
70753
  if (!fs33.existsSync(legacyPath)) return false;
70570
70754
  const legacy = fs33.readFileSync(legacyPath, "utf8");
70571
70755
  if (!fs33.existsSync(agentsPath)) {
@@ -70606,8 +70790,8 @@ This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
70606
70790
  [\`.har/README.md\`](./.har/README.md) before making changes.
70607
70791
  ${CLAUDE_HAR_SECTION_END}`;
70608
70792
  function ensureClaudeMdPointer(repoPath, options = {}) {
70609
- const dest = path41.join(repoPath, CLAUDE_MD);
70610
- const projectName = path41.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
70793
+ const dest = path40.join(repoPath, CLAUDE_MD);
70794
+ const projectName = path40.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
70611
70795
  const thin = loadClaudeMdTemplate(projectName);
70612
70796
  if (!fs33.existsSync(dest)) {
70613
70797
  writeFileSafe(dest, thin);
@@ -70762,10 +70946,10 @@ var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
70762
70946
  var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
70763
70947
  function readAgentMdProposal(repoPath) {
70764
70948
  const harnessDir = getHarnessDir(repoPath);
70765
- const proposalPath = path42.join(harnessDir, AGENTS_MD_PROPOSAL);
70766
- const metaPath = path42.join(harnessDir, AGENTS_MD_PROPOSAL_META);
70767
- const legacyProposalPath = path42.join(harnessDir, AGENT_MD_PROPOSAL);
70768
- const legacyMetaPath = path42.join(harnessDir, AGENT_MD_PROPOSAL_META);
70949
+ const proposalPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL);
70950
+ const metaPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL_META);
70951
+ const legacyProposalPath = path41.join(harnessDir, AGENT_MD_PROPOSAL);
70952
+ const legacyMetaPath = path41.join(harnessDir, AGENT_MD_PROPOSAL_META);
70769
70953
  const resolvedProposal = fs34.existsSync(proposalPath) ? proposalPath : fs34.existsSync(legacyProposalPath) ? legacyProposalPath : null;
70770
70954
  if (!resolvedProposal) return null;
70771
70955
  const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
@@ -70791,7 +70975,7 @@ function clearAgentMdProposal(repoPath) {
70791
70975
  AGENT_MD_PROPOSAL,
70792
70976
  AGENT_MD_PROPOSAL_META
70793
70977
  ]) {
70794
- const p = path42.join(harnessDir, file);
70978
+ const p = path41.join(harnessDir, file);
70795
70979
  if (fs34.existsSync(p)) fs34.unlinkSync(p);
70796
70980
  }
70797
70981
  }
@@ -70805,7 +70989,7 @@ function wouldProposalShrinkExisting(existing, proposal) {
70805
70989
  function applyAgentMdProposalMerge(repoPath, options = {}) {
70806
70990
  const proposal = readAgentMdProposal(repoPath);
70807
70991
  if (!proposal) return false;
70808
- const agentsMdPath = path42.join(repoPath, AGENTS_MD);
70992
+ const agentsMdPath = path41.join(repoPath, AGENTS_MD);
70809
70993
  if (fs34.existsSync(agentsMdPath)) {
70810
70994
  const existing = fs34.readFileSync(agentsMdPath, "utf8");
70811
70995
  if (wouldProposalShrinkExisting(existing, proposal.content)) {
@@ -70831,7 +71015,7 @@ function finalizeAgentsMdInstructionFiles(repoPath) {
70831
71015
 
70832
71016
  // src/harness/validator.ts
70833
71017
  var fs35 = __toESM(require("fs"));
70834
- var path43 = __toESM(require("path"));
71018
+ var path42 = __toESM(require("path"));
70835
71019
  init_shell();
70836
71020
  init_manifest();
70837
71021
  init_stages();
@@ -70893,13 +71077,13 @@ function validateHarness(repoPath) {
70893
71077
  };
70894
71078
  }
70895
71079
  for (const file of getRequiredFiles(repoPath)) {
70896
- const filePath = path43.join(harnessDir, file);
71080
+ const filePath = path42.join(harnessDir, file);
70897
71081
  if (!fs35.existsSync(filePath)) {
70898
71082
  issues.push({ file, message: "Required file missing", severity: "error" });
70899
71083
  }
70900
71084
  }
70901
71085
  for (const script of SHELL_SCRIPTS) {
70902
- const scriptPath = path43.join(harnessDir, script);
71086
+ const scriptPath = path42.join(harnessDir, script);
70903
71087
  if (!fs35.existsSync(scriptPath)) continue;
70904
71088
  const stat = fs35.statSync(scriptPath);
70905
71089
  if (!(stat.mode & 73)) {
@@ -70916,7 +71100,7 @@ function validateHarness(repoPath) {
70916
71100
  }
70917
71101
  const manifest = readManifest(repoPath);
70918
71102
  const profile = manifest?.profile ?? "default";
70919
- const ecosystemPath = path43.join(harnessDir, "ecosystem.agent.template.cjs");
71103
+ const ecosystemPath = path42.join(harnessDir, "ecosystem.agent.template.cjs");
70920
71104
  if (profile !== "cli" && fs35.existsSync(ecosystemPath)) {
70921
71105
  const content = fs35.readFileSync(ecosystemPath, "utf8");
70922
71106
  if (!content.includes("module.exports")) {
@@ -70927,7 +71111,7 @@ function validateHarness(repoPath) {
70927
71111
  });
70928
71112
  }
70929
71113
  }
70930
- const harnessEnvPath = path43.join(harnessDir, "harness.env");
71114
+ const harnessEnvPath = path42.join(harnessDir, "harness.env");
70931
71115
  if (fs35.existsSync(harnessEnvPath)) {
70932
71116
  const content = fs35.readFileSync(harnessEnvPath, "utf8");
70933
71117
  if (content.includes("TODO: set migrate command")) {
@@ -70937,14 +71121,14 @@ function validateHarness(repoPath) {
70937
71121
  issues.push({ file: "harness.env", message: "Seed command still has TODO", severity: "warning" });
70938
71122
  }
70939
71123
  }
70940
- const verifyPath = path43.join(harnessDir, "verify.sh");
71124
+ const verifyPath = path42.join(harnessDir, "verify.sh");
70941
71125
  if (fs35.existsSync(verifyPath)) {
70942
71126
  const content = fs35.readFileSync(verifyPath, "utf8");
70943
71127
  if (content.includes("echo 'TODO:")) {
70944
71128
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
70945
71129
  }
70946
71130
  }
70947
- const stagesPath = path43.join(harnessDir, "stages.json");
71131
+ const stagesPath = path42.join(harnessDir, "stages.json");
70948
71132
  if (fs35.existsSync(stagesPath)) {
70949
71133
  try {
70950
71134
  JSON.parse(fs35.readFileSync(stagesPath, "utf8"));
@@ -70962,7 +71146,7 @@ function validateHarness(repoPath) {
70962
71146
  } else {
70963
71147
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
70964
71148
  }
70965
- const readmePath = path43.join(harnessDir, "README.md");
71149
+ const readmePath = path42.join(harnessDir, "README.md");
70966
71150
  if (fs35.existsSync(readmePath)) {
70967
71151
  const content = fs35.readFileSync(readmePath, "utf8");
70968
71152
  if (!content.includes(".har")) {
@@ -70978,7 +71162,7 @@ function validateHarness(repoPath) {
70978
71162
  async function smokeTestHarness(repoPath) {
70979
71163
  const harnessDir = getHarnessDir(repoPath);
70980
71164
  const issues = [];
70981
- const setupScript = path43.join(harnessDir, "setup-infra.sh");
71165
+ const setupScript = path42.join(harnessDir, "setup-infra.sh");
70982
71166
  if (fs35.existsSync(setupScript)) {
70983
71167
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
70984
71168
  if (result.code !== 0) {
@@ -70995,7 +71179,7 @@ async function smokeTestHarness(repoPath) {
70995
71179
 
70996
71180
  // src/harness/drift.ts
70997
71181
  var fs36 = __toESM(require("fs"));
70998
- var path44 = __toESM(require("path"));
71182
+ var path43 = __toESM(require("path"));
70999
71183
  init_env();
71000
71184
  init_manifest();
71001
71185
  init_stages();
@@ -71065,12 +71249,12 @@ function listBoilerplateFiles(boilerplateDir) {
71065
71249
  return fs36.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
71066
71250
  }
71067
71251
  function compareHarnessToTemplate(repoPath) {
71068
- const resolved = path44.resolve(repoPath);
71252
+ const resolved = path43.resolve(repoPath);
71069
71253
  const manifest = readManifest(resolved);
71070
71254
  const profile = manifest?.profile ?? "default";
71071
71255
  const harnessDir = getHarnessDir(resolved);
71072
- const projectName = path44.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
71073
- const boilerplateDir = path44.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
71256
+ const projectName = path43.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
71257
+ const boilerplateDir = path43.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
71074
71258
  const templateFiles = listBoilerplateFiles(boilerplateDir);
71075
71259
  const missing = [];
71076
71260
  const checksumMismatch = [];
@@ -71078,8 +71262,8 @@ function compareHarnessToTemplate(repoPath) {
71078
71262
  const unchanged = [];
71079
71263
  for (const file of templateFiles) {
71080
71264
  const harnessFile = harnessFileForTemplate(file);
71081
- const templatePath = path44.join(boilerplateDir, file);
71082
- const harnessPath = path44.join(harnessDir, harnessFile);
71265
+ const templatePath = path43.join(boilerplateDir, file);
71266
+ const harnessPath = path43.join(harnessDir, harnessFile);
71083
71267
  let templateContent = fs36.readFileSync(templatePath, "utf8");
71084
71268
  if (file === "harness.env") {
71085
71269
  templateContent = substituteProjectName(templateContent, projectName);
@@ -71098,7 +71282,7 @@ function compareHarnessToTemplate(repoPath) {
71098
71282
  }
71099
71283
  if (fs36.existsSync(harnessDir)) {
71100
71284
  for (const file of fs36.readdirSync(harnessDir)) {
71101
- const full = path44.join(harnessDir, file);
71285
+ const full = path43.join(harnessDir, file);
71102
71286
  if (!fs36.statSync(full).isFile()) continue;
71103
71287
  if (file === "manifest.json" || file === "plugins.json" || file.startsWith("ADAPT-PROMPT")) {
71104
71288
  continue;
@@ -71128,19 +71312,19 @@ function compareHarnessToTemplate(repoPath) {
71128
71312
  // src/harness/maintain-bundle.ts
71129
71313
  var fs41 = __toESM(require("fs"));
71130
71314
  var os18 = __toESM(require("os"));
71131
- var path48 = __toESM(require("path"));
71315
+ var path47 = __toESM(require("path"));
71132
71316
  init_file_ops();
71133
71317
  init_shell();
71134
71318
  init_manifest();
71135
71319
 
71136
71320
  // src/harness/plugin-drift.ts
71137
71321
  var fs40 = __toESM(require("fs"));
71138
- var path47 = __toESM(require("path"));
71322
+ var path46 = __toESM(require("path"));
71139
71323
  init_manifest();
71140
71324
 
71141
71325
  // src/harness/plugins.ts
71142
71326
  var fs39 = __toESM(require("fs"));
71143
- var path46 = __toESM(require("path"));
71327
+ var path45 = __toESM(require("path"));
71144
71328
  init_zod();
71145
71329
  init_logging();
71146
71330
 
@@ -71155,12 +71339,12 @@ function harnessExists(repoPath) {
71155
71339
  var import_child_process11 = require("child_process");
71156
71340
  var fs38 = __toESM(require("fs"));
71157
71341
  var os17 = __toESM(require("os"));
71158
- var path45 = __toESM(require("path"));
71342
+ var path44 = __toESM(require("path"));
71159
71343
  function hasManifest(dir) {
71160
- return fs38.existsSync(path45.join(dir, "template.manifest.json"));
71344
+ return fs38.existsSync(path44.join(dir, "template.manifest.json"));
71161
71345
  }
71162
71346
  function readPackageVersion(dir) {
71163
- const pkgPath = path45.join(dir, "package.json");
71347
+ const pkgPath = path44.join(dir, "package.json");
71164
71348
  if (!fs38.existsSync(pkgPath)) return void 0;
71165
71349
  try {
71166
71350
  const pkg = JSON.parse(fs38.readFileSync(pkgPath, "utf8"));
@@ -71170,7 +71354,7 @@ function readPackageVersion(dir) {
71170
71354
  }
71171
71355
  }
71172
71356
  function readManifestId(dir) {
71173
- const manifestPath = path45.join(dir, "template.manifest.json");
71357
+ const manifestPath = path44.join(dir, "template.manifest.json");
71174
71358
  if (!fs38.existsSync(manifestPath)) return void 0;
71175
71359
  try {
71176
71360
  const raw = JSON.parse(fs38.readFileSync(manifestPath, "utf8"));
@@ -71191,24 +71375,24 @@ function looksLikeNpm(spec) {
71191
71375
  return /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(@.+)?$/i.test(spec);
71192
71376
  }
71193
71377
  function resolveBundledDir(pluginId) {
71194
- const dir = path45.join(resolveTemplatesDir(), "plugins", pluginId);
71378
+ const dir = path44.join(resolveTemplatesDir(), "plugins", pluginId);
71195
71379
  return hasManifest(dir) ? dir : null;
71196
71380
  }
71197
71381
  function expandHome(p) {
71198
- if (p.startsWith("~/")) return path45.join(os17.homedir(), p.slice(2));
71382
+ if (p.startsWith("~/")) return path44.join(os17.homedir(), p.slice(2));
71199
71383
  if (p === "~") return os17.homedir();
71200
71384
  return p;
71201
71385
  }
71202
71386
  function resolvePathSpec(spec) {
71203
71387
  const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
71204
- const dir = path45.resolve(expandHome(raw));
71388
+ const dir = path44.resolve(expandHome(raw));
71205
71389
  if (!fs38.existsSync(dir) || !fs38.statSync(dir).isDirectory()) {
71206
71390
  throw new Error(`Plugin path not found: ${spec}`);
71207
71391
  }
71208
71392
  if (!hasManifest(dir)) {
71209
71393
  throw new Error(`No template.manifest.json in ${dir}`);
71210
71394
  }
71211
- const id = readManifestId(dir) ?? path45.basename(dir);
71395
+ const id = readManifestId(dir) ?? path44.basename(dir);
71212
71396
  return {
71213
71397
  id,
71214
71398
  kind: "path",
@@ -71219,7 +71403,7 @@ function resolvePathSpec(spec) {
71219
71403
  };
71220
71404
  }
71221
71405
  function makeTempDir(prefix) {
71222
- return fs38.mkdtempSync(path45.join(os17.tmpdir(), prefix));
71406
+ return fs38.mkdtempSync(path44.join(os17.tmpdir(), prefix));
71223
71407
  }
71224
71408
  function resolveNpmSpec(spec) {
71225
71409
  const tmp = makeTempDir("har-plugin-npm-");
@@ -71234,16 +71418,16 @@ function resolveNpmSpec(spec) {
71234
71418
  if (tarballs.length === 0) {
71235
71419
  throw new Error(`npm pack produced no tarball for ${spec}`);
71236
71420
  }
71237
- const extractDir = path45.join(tmp, "extract");
71421
+ const extractDir = path44.join(tmp, "extract");
71238
71422
  fs38.mkdirSync(extractDir);
71239
- (0, import_child_process11.execFileSync)("tar", ["-xzf", path45.join(tmp, tarballs[0]), "-C", extractDir], {
71423
+ (0, import_child_process11.execFileSync)("tar", ["-xzf", path44.join(tmp, tarballs[0]), "-C", extractDir], {
71240
71424
  encoding: "utf8",
71241
71425
  stdio: ["ignore", "pipe", "pipe"]
71242
71426
  });
71243
- const packageDir = path45.join(extractDir, "package");
71427
+ const packageDir = path44.join(extractDir, "package");
71244
71428
  let dir = packageDir;
71245
71429
  if (!hasManifest(dir)) {
71246
- const nested = fs38.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path45.join(extractDir, e.name)).find((d) => hasManifest(d));
71430
+ const nested = fs38.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(extractDir, e.name)).find((d) => hasManifest(d));
71247
71431
  if (!nested) {
71248
71432
  throw new Error(
71249
71433
  `npm package ${spec} has no template.manifest.json (not a HAR plugin bundle)`
@@ -71271,7 +71455,7 @@ function resolveNpmSpec(spec) {
71271
71455
  function resolveGitSpec(spec) {
71272
71456
  const tmp = makeTempDir("har-plugin-git-");
71273
71457
  const cleanupDirs = [tmp];
71274
- const cloneDir = path45.join(tmp, "repo");
71458
+ const cloneDir = path44.join(tmp, "repo");
71275
71459
  try {
71276
71460
  let url = spec;
71277
71461
  if (spec.startsWith("github:")) {
@@ -71290,16 +71474,16 @@ function resolveGitSpec(spec) {
71290
71474
  });
71291
71475
  let dir = cloneDir;
71292
71476
  if (!hasManifest(dir)) {
71293
- const pluginsRoot = path45.join(cloneDir, "plugins");
71477
+ const pluginsRoot = path44.join(cloneDir, "plugins");
71294
71478
  if (fs38.existsSync(pluginsRoot)) {
71295
- const child = fs38.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path45.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
71479
+ const child = fs38.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
71296
71480
  if (child) dir = child;
71297
71481
  }
71298
71482
  }
71299
71483
  if (!hasManifest(dir)) {
71300
71484
  throw new Error(`Git repo ${spec} has no template.manifest.json (not a HAR plugin bundle)`);
71301
71485
  }
71302
- const id = readManifestId(dir) ?? path45.basename(url.replace(/\.git$/, ""));
71486
+ const id = readManifestId(dir) ?? path44.basename(url.replace(/\.git$/, ""));
71303
71487
  return {
71304
71488
  id,
71305
71489
  kind: "git",
@@ -71358,9 +71542,9 @@ function resolvePluginSource(spec) {
71358
71542
  );
71359
71543
  }
71360
71544
  function listBundledPluginIds() {
71361
- const root = path45.join(resolveTemplatesDir(), "plugins");
71545
+ const root = path44.join(resolveTemplatesDir(), "plugins");
71362
71546
  if (!fs38.existsSync(root)) return [];
71363
- return fs38.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path45.join(root, name))).sort();
71547
+ return fs38.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path44.join(root, name))).sort();
71364
71548
  }
71365
71549
  function cleanupResolvedPlugin(source) {
71366
71550
  for (const dir of source.cleanupDirs) {
@@ -71416,14 +71600,14 @@ function primaryStageId(manifest) {
71416
71600
  return manifest.stageId ?? stages[0].id;
71417
71601
  }
71418
71602
  function resolveBundledPluginDir(pluginId) {
71419
- const dir = path46.join(resolveTemplatesDir(), "plugins", pluginId);
71603
+ const dir = path45.join(resolveTemplatesDir(), "plugins", pluginId);
71420
71604
  if (!fs39.existsSync(dir)) {
71421
71605
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
71422
71606
  }
71423
71607
  return dir;
71424
71608
  }
71425
71609
  function readPluginManifestFromDir(pluginDir, expectedId) {
71426
- const manifestPath = path46.join(pluginDir, "template.manifest.json");
71610
+ const manifestPath = path45.join(pluginDir, "template.manifest.json");
71427
71611
  if (!fs39.existsSync(manifestPath)) {
71428
71612
  throw new Error(`No template.manifest.json in ${pluginDir}`);
71429
71613
  }
@@ -71442,14 +71626,14 @@ function readPluginManifest(pluginId) {
71442
71626
  return readPluginManifestFromDir(resolveBundledPluginDir(pluginId), pluginId);
71443
71627
  }
71444
71628
  function ensureParentDir(filePath) {
71445
- const parent = path46.dirname(filePath);
71629
+ const parent = path45.dirname(filePath);
71446
71630
  if (!fs39.existsSync(parent)) {
71447
71631
  fs39.mkdirSync(parent, { recursive: true });
71448
71632
  }
71449
71633
  }
71450
71634
  function copyPluginFile(pluginDir, file, repoPath, force) {
71451
- const srcPath = path46.join(pluginDir, file.src);
71452
- const destPath = path46.join(repoPath, file.dest);
71635
+ const srcPath = path45.join(pluginDir, file.src);
71636
+ const destPath = path45.join(repoPath, file.dest);
71453
71637
  if (!fs39.existsSync(srcPath)) {
71454
71638
  throw new Error(`Plugin file missing: ${file.src}`);
71455
71639
  }
@@ -71466,11 +71650,11 @@ function copyPluginFile(pluginDir, file, repoPath, force) {
71466
71650
  return { written: true, path: file.dest };
71467
71651
  }
71468
71652
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
71469
- const packagePath = path46.join(repoPath, "package.json");
71653
+ const packagePath = path45.join(repoPath, "package.json");
71470
71654
  if (!fs39.existsSync(packagePath)) {
71471
71655
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
71472
71656
  }
71473
- const fragmentPath = path46.join(pluginDir, fragmentRelPath);
71657
+ const fragmentPath = path45.join(pluginDir, fragmentRelPath);
71474
71658
  if (!fs39.existsSync(fragmentPath)) {
71475
71659
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
71476
71660
  }
@@ -71532,7 +71716,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
71532
71716
  if (force) return;
71533
71717
  const registry2 = readStageRegistry(repoPath);
71534
71718
  for (const stageId of stageIds) {
71535
- const scriptPath = path46.join(repoPath, ".har", "stages", `${stageId}.sh`);
71719
+ const scriptPath = path45.join(repoPath, ".har", "stages", `${stageId}.sh`);
71536
71720
  if (fs39.existsSync(scriptPath)) {
71537
71721
  throw new Error(
71538
71722
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
@@ -71546,7 +71730,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
71546
71730
  }
71547
71731
  }
71548
71732
  function applyPluginFromDir(repoPath, pluginDir, options, meta) {
71549
- const resolved = path46.resolve(repoPath);
71733
+ const resolved = path45.resolve(repoPath);
71550
71734
  const force = options.force ?? false;
71551
71735
  const warnings = [];
71552
71736
  const filesWritten = [];
@@ -71566,7 +71750,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
71566
71750
  if (file.skipFlag === "skipCi" && options.skipCi) {
71567
71751
  continue;
71568
71752
  }
71569
- if (fs39.existsSync(path46.join(resolved, file.dest)) && !force) {
71753
+ if (fs39.existsSync(path45.join(resolved, file.dest)) && !force) {
71570
71754
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
71571
71755
  continue;
71572
71756
  }
@@ -71632,12 +71816,12 @@ function listPluginIds() {
71632
71816
  init_stages();
71633
71817
  var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
71634
71818
  function detectInstalledPlugins(repoPath) {
71635
- const resolved = path47.resolve(repoPath);
71819
+ const resolved = path46.resolve(repoPath);
71636
71820
  const ledger = readPluginLedger(resolved);
71637
71821
  if (ledger && ledger.plugins.length > 0) {
71638
71822
  return ledger.plugins.map((p) => p.id).sort();
71639
71823
  }
71640
- const registryPath = path47.join(resolved, ".har", "stages.json");
71824
+ const registryPath = path46.join(resolved, ".har", "stages.json");
71641
71825
  if (!fs40.existsSync(registryPath)) return [];
71642
71826
  const registry2 = readStageRegistry(resolved);
71643
71827
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
@@ -71655,7 +71839,7 @@ function detectInstalledPlugins(repoPath) {
71655
71839
  return installed.sort();
71656
71840
  }
71657
71841
  function pluginTemplatePath(pluginId, srcRel) {
71658
- return path47.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
71842
+ return path46.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
71659
71843
  }
71660
71844
  function resolvePluginTemplateDir(repoPath, pluginId) {
71661
71845
  const ledger = readPluginLedger(repoPath);
@@ -71667,8 +71851,8 @@ function resolvePluginTemplateDir(repoPath, pluginId) {
71667
71851
  } catch {
71668
71852
  }
71669
71853
  }
71670
- const bundled = path47.join(resolveTemplatesDir(), "plugins", pluginId);
71671
- if (fs40.existsSync(path47.join(bundled, "template.manifest.json"))) {
71854
+ const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId);
71855
+ if (fs40.existsSync(path46.join(bundled, "template.manifest.json"))) {
71672
71856
  return bundled;
71673
71857
  }
71674
71858
  return null;
@@ -71682,7 +71866,7 @@ function listPluginDestPaths(pluginId, repoPath) {
71682
71866
  const paths = manifest.files.map((file) => file.dest);
71683
71867
  if (manifest.optionalFiles) {
71684
71868
  for (const file of manifest.optionalFiles) {
71685
- if (fs40.existsSync(path47.join(repoPath, file.dest))) {
71869
+ if (fs40.existsSync(path46.join(repoPath, file.dest))) {
71686
71870
  paths.push(file.dest);
71687
71871
  }
71688
71872
  }
@@ -71741,7 +71925,7 @@ function readTemplatePluginFile(pluginId, dest) {
71741
71925
  return null;
71742
71926
  }
71743
71927
  function readInstalledPluginFile(repoPath, pluginId, dest) {
71744
- const installedPath = path47.join(path47.resolve(repoPath), dest);
71928
+ const installedPath = path46.join(path46.resolve(repoPath), dest);
71745
71929
  if (!fs40.existsSync(installedPath)) return null;
71746
71930
  const content = fs40.readFileSync(installedPath, "utf8");
71747
71931
  const manifest = readPluginManifest(pluginId);
@@ -71762,7 +71946,7 @@ function pluginActionHint(pluginId, dest, kind) {
71762
71946
  }
71763
71947
  function comparePluginToTemplate(repoPath, pluginId) {
71764
71948
  const manifest = readPluginManifest(pluginId);
71765
- const resolved = path47.resolve(repoPath);
71949
+ const resolved = path46.resolve(repoPath);
71766
71950
  const destPaths = listPluginDestPaths(pluginId, resolved);
71767
71951
  const missing = [];
71768
71952
  const checksumMismatch = [];
@@ -71777,7 +71961,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
71777
71961
  }
71778
71962
  if (dest === "package.json") {
71779
71963
  const fragmentRel = manifest.merge?.[dest];
71780
- const installedPath = path47.join(resolved, dest);
71964
+ const installedPath = path46.join(resolved, dest);
71781
71965
  const installedRaw = fs40.readFileSync(installedPath, "utf8");
71782
71966
  if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
71783
71967
  unchanged.push(dest);
@@ -71804,7 +71988,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
71804
71988
  }
71805
71989
  function compareInstalledPluginsToTemplate(repoPath) {
71806
71990
  return detectInstalledPlugins(repoPath).filter((pluginId) => {
71807
- const bundled = path47.join(resolveTemplatesDir(), "plugins", pluginId, "template.manifest.json");
71991
+ const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId, "template.manifest.json");
71808
71992
  return fs40.existsSync(bundled);
71809
71993
  }).map((pluginId) => comparePluginToTemplate(repoPath, pluginId));
71810
71994
  }
@@ -71843,13 +72027,13 @@ function substituteProjectName2(content, projectName) {
71843
72027
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
71844
72028
  }
71845
72029
  function projectNameFromRepo(repoPath) {
71846
- return path48.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
72030
+ return path47.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
71847
72031
  }
71848
72032
  function boilerplateDirForProfile(profile) {
71849
- return path48.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
72033
+ return path47.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
71850
72034
  }
71851
72035
  function readBundledTemplateContent(repoPath, profile, file) {
71852
- const templatePath = path48.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
72036
+ const templatePath = path47.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
71853
72037
  let content = fs41.readFileSync(templatePath, "utf8");
71854
72038
  if (file === "harness.env") {
71855
72039
  content = substituteProjectName2(content, projectNameFromRepo(repoPath));
@@ -71881,10 +72065,10 @@ function actionHint(file, kind) {
71881
72065
  return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
71882
72066
  }
71883
72067
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
71884
- const tmpDir = fs41.mkdtempSync(path48.join(os18.tmpdir(), "har-maintain-diff-"));
72068
+ const tmpDir = fs41.mkdtempSync(path47.join(os18.tmpdir(), "har-maintain-diff-"));
71885
72069
  try {
71886
- const installedPath = path48.join(tmpDir, "installed");
71887
- const templatePath = path48.join(tmpDir, "template");
72070
+ const installedPath = path47.join(tmpDir, "installed");
72071
+ const templatePath = path47.join(tmpDir, "template");
71888
72072
  fs41.writeFileSync(installedPath, installedContent);
71889
72073
  fs41.writeFileSync(templatePath, templateContent);
71890
72074
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
@@ -71910,7 +72094,7 @@ function buildActions(repoPath, profile, drift) {
71910
72094
  });
71911
72095
  }
71912
72096
  for (const file of drift.checksumMismatch) {
71913
- const installedPath = path48.join(harnessDir, file);
72097
+ const installedPath = path47.join(harnessDir, file);
71914
72098
  const installedRel = `maintain/installed/${file}`;
71915
72099
  const templateRel = `maintain/templates/${file}`;
71916
72100
  const diffRel = `maintain/diffs/${file}.diff`;
@@ -72070,16 +72254,16 @@ function buildReadme(report) {
72070
72254
  }
72071
72255
  function writeBundleArtifacts(repoPath, profile, drift, report) {
72072
72256
  const harnessDir = getHarnessDir(repoPath);
72073
- const bundleDir = path48.join(harnessDir, MAINTAIN_DIR);
72257
+ const bundleDir = path47.join(harnessDir, MAINTAIN_DIR);
72074
72258
  if (fs41.existsSync(bundleDir)) {
72075
72259
  fs41.rmSync(bundleDir, { recursive: true, force: true });
72076
72260
  }
72077
72261
  const dirs = [
72078
72262
  bundleDir,
72079
- path48.join(bundleDir, "templates"),
72080
- path48.join(bundleDir, "installed"),
72081
- path48.join(bundleDir, "diffs"),
72082
- path48.join(bundleDir, "stale")
72263
+ path47.join(bundleDir, "templates"),
72264
+ path47.join(bundleDir, "installed"),
72265
+ path47.join(bundleDir, "diffs"),
72266
+ path47.join(bundleDir, "stale")
72083
72267
  ];
72084
72268
  for (const dir of dirs) {
72085
72269
  fs41.mkdirSync(dir, { recursive: true });
@@ -72087,11 +72271,11 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72087
72271
  const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
72088
72272
  for (const file of affectedFiles) {
72089
72273
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
72090
- writeFileSafe(path48.join(bundleDir, "templates", file), templateContent);
72091
- const harnessPath = path48.join(harnessDir, file);
72274
+ writeFileSafe(path47.join(bundleDir, "templates", file), templateContent);
72275
+ const harnessPath = path47.join(harnessDir, file);
72092
72276
  if (fs41.existsSync(harnessPath)) {
72093
72277
  const installedContent = fs41.readFileSync(harnessPath, "utf8");
72094
- writeFileSafe(path48.join(bundleDir, "installed", file), installedContent);
72278
+ writeFileSafe(path47.join(bundleDir, "installed", file), installedContent);
72095
72279
  const diff = createUnifiedDiff(
72096
72280
  installedContent,
72097
72281
  templateContent,
@@ -72099,14 +72283,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72099
72283
  `templates/${file}`
72100
72284
  );
72101
72285
  if (diff) {
72102
- writeFileSafe(path48.join(bundleDir, "diffs", `${file}.diff`), diff);
72286
+ writeFileSafe(path47.join(bundleDir, "diffs", `${file}.diff`), diff);
72103
72287
  }
72104
72288
  }
72105
72289
  }
72106
- writeFileSafe(path48.join(bundleDir, "README.md"), buildReadme(report));
72107
- writeFileSafe(path48.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
72290
+ writeFileSafe(path47.join(bundleDir, "README.md"), buildReadme(report));
72291
+ writeFileSafe(path47.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
72108
72292
  writeFileSafe(
72109
- path48.join(bundleDir, "validation.json"),
72293
+ path47.join(bundleDir, "validation.json"),
72110
72294
  JSON.stringify(report.validation, null, 2) + "\n"
72111
72295
  );
72112
72296
  if (report.stale.length > 0) {
@@ -72118,12 +72302,12 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72118
72302
  ...report.stale.map((s) => `- **${s.file}** \u2014 ${s.hint}`),
72119
72303
  ""
72120
72304
  ];
72121
- writeFileSafe(path48.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
72305
+ writeFileSafe(path47.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
72122
72306
  }
72123
72307
  return bundleDir;
72124
72308
  }
72125
72309
  function ensureParentDir2(filePath) {
72126
- const parent = path48.dirname(filePath);
72310
+ const parent = path47.dirname(filePath);
72127
72311
  if (!fs41.existsSync(parent)) {
72128
72312
  fs41.mkdirSync(parent, { recursive: true });
72129
72313
  }
@@ -72131,21 +72315,21 @@ function ensureParentDir2(filePath) {
72131
72315
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
72132
72316
  if (report.pluginActions.length === 0) return;
72133
72317
  for (const action of report.pluginActions) {
72134
- const pluginRoot = path48.join(bundleDir, "plugins", action.pluginId);
72135
- const templatesDir = path48.join(pluginRoot, "templates");
72136
- const installedDir = path48.join(pluginRoot, "installed");
72137
- const diffsDir = path48.join(pluginRoot, "diffs");
72318
+ const pluginRoot = path47.join(bundleDir, "plugins", action.pluginId);
72319
+ const templatesDir = path47.join(pluginRoot, "templates");
72320
+ const installedDir = path47.join(pluginRoot, "installed");
72321
+ const diffsDir = path47.join(pluginRoot, "diffs");
72138
72322
  for (const dir of [templatesDir, installedDir, diffsDir]) {
72139
72323
  fs41.mkdirSync(dir, { recursive: true });
72140
72324
  }
72141
72325
  const templateContent = readTemplatePluginFile(action.pluginId, action.file);
72142
72326
  if (templateContent === null) continue;
72143
- const templatePath = path48.join(templatesDir, action.file);
72327
+ const templatePath = path47.join(templatesDir, action.file);
72144
72328
  ensureParentDir2(templatePath);
72145
72329
  writeFileSafe(templatePath, templateContent);
72146
72330
  const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
72147
72331
  if (installedContent !== null) {
72148
- const installedPath = path48.join(installedDir, action.file);
72332
+ const installedPath = path47.join(installedDir, action.file);
72149
72333
  ensureParentDir2(installedPath);
72150
72334
  writeFileSafe(installedPath, installedContent);
72151
72335
  const diff = createUnifiedDiff(
@@ -72155,7 +72339,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
72155
72339
  `templates/${action.file}`
72156
72340
  );
72157
72341
  if (diff) {
72158
- const diffPath = path48.join(diffsDir, `${action.file}.diff`);
72342
+ const diffPath = path47.join(diffsDir, `${action.file}.diff`);
72159
72343
  ensureParentDir2(diffPath);
72160
72344
  writeFileSafe(diffPath, diff);
72161
72345
  }
@@ -72190,7 +72374,7 @@ function buildMaintainBundle(repoPath, validation2, drift) {
72190
72374
  return { bundleDir, report };
72191
72375
  }
72192
72376
  function removeMaintainBundle(repoPath) {
72193
- const bundleDir = path48.join(getHarnessDir(repoPath), MAINTAIN_DIR);
72377
+ const bundleDir = path47.join(getHarnessDir(repoPath), MAINTAIN_DIR);
72194
72378
  if (fs41.existsSync(bundleDir)) {
72195
72379
  fs41.rmSync(bundleDir, { recursive: true, force: true });
72196
72380
  }
@@ -72285,7 +72469,7 @@ function listHarnessScripts(repoPath) {
72285
72469
  return fs42.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
72286
72470
  }
72287
72471
  function describeProject(repoPath) {
72288
- const resolved = path49.resolve(repoPath);
72472
+ const resolved = path48.resolve(repoPath);
72289
72473
  const manifest = readManifest(resolved);
72290
72474
  const present = harnessExists(resolved);
72291
72475
  return {
@@ -72305,7 +72489,7 @@ function describeProject(repoPath) {
72305
72489
  };
72306
72490
  }
72307
72491
  async function initHarness(options) {
72308
- const repoPath = path49.resolve(options.repoPath);
72492
+ const repoPath = path48.resolve(options.repoPath);
72309
72493
  if (!fs42.existsSync(repoPath)) {
72310
72494
  throw new Error(`Path not found: ${repoPath}`);
72311
72495
  }
@@ -72326,7 +72510,7 @@ async function initHarness(options) {
72326
72510
  };
72327
72511
  }
72328
72512
  async function maintainHarness(options) {
72329
- const repoPath = path49.resolve(options.repoPath);
72513
+ const repoPath = path48.resolve(options.repoPath);
72330
72514
  const harnessDir = getHarnessDir(repoPath);
72331
72515
  if (!fs42.existsSync(harnessDir)) {
72332
72516
  throw new Error('No .har/ found. Run "har env init" first.');
@@ -72364,12 +72548,12 @@ function addPlugin(repoPath, pluginId, options = {}) {
72364
72548
 
72365
72549
  // src/harness/custom-stage.ts
72366
72550
  var fs43 = __toESM(require("fs"));
72367
- var path50 = __toESM(require("path"));
72551
+ var path49 = __toESM(require("path"));
72368
72552
  init_schema2();
72369
72553
  init_stages();
72370
72554
  var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
72371
72555
  function addCustomStage(repoPath, options) {
72372
- const resolved = path50.resolve(repoPath);
72556
+ const resolved = path49.resolve(repoPath);
72373
72557
  if (!harnessExists(resolved)) {
72374
72558
  throw new Error('No .har/ harness found. Run "har env init" first.');
72375
72559
  }
@@ -72406,18 +72590,18 @@ function addCustomStage(repoPath, options) {
72406
72590
  if (options.command) {
72407
72591
  stage.command = options.command;
72408
72592
  } else {
72409
- const scriptRel = path50.join("stages", `${id}.sh`);
72410
- const scriptAbs = path50.join(resolved, ".har", scriptRel);
72593
+ const scriptRel = path49.join("stages", `${id}.sh`);
72594
+ const scriptAbs = path49.join(resolved, ".har", scriptRel);
72411
72595
  if (fs43.existsSync(scriptAbs) && !options.force) {
72412
72596
  throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
72413
72597
  }
72414
- const skeletonPath = path50.join(
72598
+ const skeletonPath = path49.join(
72415
72599
  resolveTemplatesDir(),
72416
72600
  "plugins",
72417
72601
  "custom-stage-skeleton.sh"
72418
72602
  );
72419
72603
  const skeleton = fs43.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind).replace(/__STAGE_DESCRIPTION__/g, stage.description);
72420
- fs43.mkdirSync(path50.dirname(scriptAbs), { recursive: true });
72604
+ fs43.mkdirSync(path49.dirname(scriptAbs), { recursive: true });
72421
72605
  fs43.writeFileSync(scriptAbs, skeleton);
72422
72606
  fs43.chmodSync(scriptAbs, 493);
72423
72607
  filesWritten.push(`.har/${scriptRel}`);
@@ -72468,7 +72652,7 @@ function addCustomStage(repoPath, options) {
72468
72652
 
72469
72653
  // src/harness/adaptation-prompt.ts
72470
72654
  var fs44 = __toESM(require("fs"));
72471
- var path51 = __toESM(require("path"));
72655
+ var path50 = __toESM(require("path"));
72472
72656
  var readline5 = __toESM(require("readline"));
72473
72657
 
72474
72658
  // src/utils/clipboard.ts
@@ -72580,7 +72764,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
72580
72764
  }
72581
72765
  function writeAdaptationPrompt(repoPath, content) {
72582
72766
  const harnessDir = getHarnessDir(repoPath);
72583
- const filePath = path51.join(harnessDir, ADAPTATION_PROMPT_FILE);
72767
+ const filePath = path50.join(harnessDir, ADAPTATION_PROMPT_FILE);
72584
72768
  writeFileSafe(filePath, content);
72585
72769
  return filePath;
72586
72770
  }
@@ -72599,12 +72783,12 @@ function printAdaptationPrompt(content) {
72599
72783
  }
72600
72784
  function askYesNo2(question) {
72601
72785
  const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
72602
- return new Promise((resolve53) => {
72786
+ return new Promise((resolve52) => {
72603
72787
  process.stderr.write(`${question} `);
72604
72788
  rl.once("line", (answer) => {
72605
72789
  rl.close();
72606
72790
  const trimmed = answer.trim();
72607
- resolve53(trimmed === "" || /^y(es)?$/i.test(trimmed));
72791
+ resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
72608
72792
  });
72609
72793
  });
72610
72794
  }
@@ -72636,16 +72820,16 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
72636
72820
 
72637
72821
  // src/harness/cursor-rule.ts
72638
72822
  var fs45 = __toESM(require("fs"));
72639
- var path52 = __toESM(require("path"));
72823
+ var path51 = __toESM(require("path"));
72640
72824
  var readline6 = __toESM(require("readline"));
72641
72825
  init_file_ops();
72642
72826
  init_logging();
72643
72827
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
72644
72828
  function getCursorRulePath(repoPath) {
72645
- return path52.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
72829
+ return path51.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
72646
72830
  }
72647
72831
  function isCursorWorkspace(repoPath) {
72648
- return fs45.existsSync(path52.join(repoPath, ".cursor"));
72832
+ return fs45.existsSync(path51.join(repoPath, ".cursor"));
72649
72833
  }
72650
72834
  function cursorRuleExists(repoPath) {
72651
72835
  return fs45.existsSync(getCursorRulePath(repoPath));
@@ -72693,16 +72877,16 @@ async function promptScaffoldCursorRule(exists) {
72693
72877
  }
72694
72878
  async function askYesNo3(question) {
72695
72879
  const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
72696
- return new Promise((resolve53) => {
72880
+ return new Promise((resolve52) => {
72697
72881
  process.stderr.write(`${question} `);
72698
72882
  rl.once("line", (answer) => {
72699
72883
  rl.close();
72700
72884
  const trimmed = answer.trim();
72701
72885
  if (trimmed === "") {
72702
- resolve53(true);
72886
+ resolve52(true);
72703
72887
  return;
72704
72888
  }
72705
- resolve53(/^y(es)?$/i.test(trimmed));
72889
+ resolve52(/^y(es)?$/i.test(trimmed));
72706
72890
  });
72707
72891
  });
72708
72892
  }
@@ -72745,7 +72929,7 @@ init_control_config();
72745
72929
 
72746
72930
  // src/core/control-lifecycle.ts
72747
72931
  var import_child_process13 = require("child_process");
72748
- var path53 = __toESM(require("path"));
72932
+ var path52 = __toESM(require("path"));
72749
72933
 
72750
72934
  // src/core/control-image.ts
72751
72935
  init_package_version();
@@ -72772,10 +72956,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
72772
72956
  var CONTROL_CONTAINER_PORT = 3847;
72773
72957
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
72774
72958
  function resolveControlDir() {
72775
- return path53.resolve(__dirname, "..", "control");
72959
+ return path52.resolve(__dirname, "..", "control");
72776
72960
  }
72777
72961
  function resolveControlBuildContext() {
72778
- return path53.resolve(resolveControlDir(), "..");
72962
+ return path52.resolve(resolveControlDir(), "..");
72779
72963
  }
72780
72964
  function buildDockerRunArgs(options) {
72781
72965
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -72831,7 +73015,7 @@ async function startMissionControl(options) {
72831
73015
  "-t",
72832
73016
  imageRef,
72833
73017
  "-f",
72834
- path53.join(resolveControlDir(), "Dockerfile"),
73018
+ path52.join(resolveControlDir(), "Dockerfile"),
72835
73019
  resolveControlBuildContext()
72836
73020
  ]);
72837
73021
  if (buildCode !== 0) {
@@ -72978,7 +73162,7 @@ async function ensureTelemetryInfrastructure(options) {
72978
73162
  // src/core/run-service.ts
72979
73163
  init_telemetry_config();
72980
73164
  init_telemetry_env();
72981
- var path55 = __toESM(require("path"));
73165
+ var path54 = __toESM(require("path"));
72982
73166
  init_local_executor();
72983
73167
  function extractShellOutput(result) {
72984
73168
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
@@ -73184,12 +73368,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
73184
73368
  suffix: session.suffix,
73185
73369
  createdAt: session.createdAt
73186
73370
  });
73187
- const envFile = path55.join(session.workDir, `.env.agent.${options.agentId}`);
73371
+ const envFile = path54.join(session.workDir, `.env.agent.${options.agentId}`);
73188
73372
  try {
73189
73373
  appendTelemetryEnvToFile(envFile, {
73190
73374
  sessionKey,
73191
73375
  agentId: options.agentId,
73192
- repoPath: path55.resolve(options.repoPath),
73376
+ repoPath: path54.resolve(options.repoPath),
73193
73377
  workDir: session.workDir,
73194
73378
  branch: session.branch,
73195
73379
  suffix: session.suffix,
@@ -73428,7 +73612,7 @@ init_slot_status();
73428
73612
  // src/core/cleanup-service.ts
73429
73613
  var fs47 = __toESM(require("fs"));
73430
73614
  var os20 = __toESM(require("os"));
73431
- var path56 = __toESM(require("path"));
73615
+ var path55 = __toESM(require("path"));
73432
73616
  var import_child_process15 = require("child_process");
73433
73617
  init_control_sync();
73434
73618
  init_control_repo_path();
@@ -73437,9 +73621,9 @@ init_manifest();
73437
73621
  var DEFAULT_STALE_DAYS = 7;
73438
73622
  function getWorktreesRoot() {
73439
73623
  if (process.env.HAR_WORKTREES_ROOT) {
73440
- return path56.resolve(process.env.HAR_WORKTREES_ROOT);
73624
+ return path55.resolve(process.env.HAR_WORKTREES_ROOT);
73441
73625
  }
73442
- return path56.join(process.env.HOME || os20.homedir(), "worktrees");
73626
+ return path55.join(process.env.HOME || os20.homedir(), "worktrees");
73443
73627
  }
73444
73628
  function runGit3(cwd, args) {
73445
73629
  try {
@@ -73453,7 +73637,7 @@ function runGit3(cwd, args) {
73453
73637
  }
73454
73638
  }
73455
73639
  function basenameRepo(repoPath) {
73456
- return path56.basename(canonicalizeControlRepoPath(repoPath));
73640
+ return path55.basename(canonicalizeControlRepoPath(repoPath));
73457
73641
  }
73458
73642
  function ageDaysFrom(iso) {
73459
73643
  if (!iso) return void 0;
@@ -73465,12 +73649,12 @@ function matchesKeep(candidate, keep) {
73465
73649
  if (!keep?.length) return false;
73466
73650
  for (const pin of keep) {
73467
73651
  if (pin.worktreePath && candidate.worktreePath) {
73468
- if (path56.resolve(pin.worktreePath) === path56.resolve(candidate.worktreePath)) return true;
73652
+ if (path55.resolve(pin.worktreePath) === path55.resolve(candidate.worktreePath)) return true;
73469
73653
  }
73470
73654
  if (pin.repoPath && pin.agentId !== void 0 && candidate.agentId !== void 0) {
73471
73655
  const repo = canonicalizeControlRepoPath(pin.repoPath);
73472
- const candidateRepo = path56.resolve(candidate.repoPath);
73473
- if ((repo === candidateRepo || path56.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
73656
+ const candidateRepo = path55.resolve(candidate.repoPath);
73657
+ if ((repo === candidateRepo || path55.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
73474
73658
  return true;
73475
73659
  }
73476
73660
  }
@@ -73528,7 +73712,7 @@ function resolveRepoForWorktree(worktreePath) {
73528
73712
  if (!fs47.existsSync(worktreePath)) return void 0;
73529
73713
  const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
73530
73714
  if (!commonDir) return void 0;
73531
- const gitRoot = path56.resolve(worktreePath, commonDir, "..");
73715
+ const gitRoot = path55.resolve(worktreePath, commonDir, "..");
73532
73716
  if (!readManifest(gitRoot)) return void 0;
73533
73717
  return canonicalizeControlRepoPath(gitRoot);
73534
73718
  }
@@ -73538,7 +73722,7 @@ function discoverOrphanWorktrees(knownPaths) {
73538
73722
  const orphans = [];
73539
73723
  for (const entry of fs47.readdirSync(worktreesRoot, { withFileTypes: true })) {
73540
73724
  if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
73541
- const worktreePath = path56.resolve(path56.join(worktreesRoot, entry.name));
73725
+ const worktreePath = path55.resolve(path55.join(worktreesRoot, entry.name));
73542
73726
  if (knownPaths.has(worktreePath)) continue;
73543
73727
  const repoPath = resolveRepoForWorktree(worktreePath) ?? worktreesRoot;
73544
73728
  const porcelain = runGit3(worktreePath, "status --porcelain");
@@ -73569,8 +73753,8 @@ async function discoverCleanupCandidates(options = {}) {
73569
73753
  const status = collectEnvironmentStatus(harnessRoot);
73570
73754
  const projectName = basenameRepo(harnessRoot);
73571
73755
  for (const slot of status.slots) {
73572
- if (slot.worktreePath) knownWorktreePaths.add(path56.resolve(slot.worktreePath));
73573
- if (slot.workDir) knownWorktreePaths.add(path56.resolve(slot.workDir));
73756
+ if (slot.worktreePath) knownWorktreePaths.add(path55.resolve(slot.worktreePath));
73757
+ if (slot.workDir) knownWorktreePaths.add(path55.resolve(slot.workDir));
73574
73758
  const candidate = classifySlotCandidate(canonicalRepo, projectName, slot, {
73575
73759
  staleDays: options.staleDays,
73576
73760
  keep: options.keep
@@ -73630,8 +73814,8 @@ async function askYesNo4(question) {
73630
73814
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
73631
73815
  const readline8 = await import("readline");
73632
73816
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
73633
- const answer = await new Promise((resolve53) => {
73634
- rl.question(question, resolve53);
73817
+ const answer = await new Promise((resolve52) => {
73818
+ rl.question(question, resolve52);
73635
73819
  });
73636
73820
  rl.close();
73637
73821
  return /^[Yy]$/.test(answer.trim());
@@ -73714,7 +73898,7 @@ function parseCleanupKeepPins(values) {
73714
73898
  }
73715
73899
  if (raw.startsWith("/") || raw.startsWith("~")) {
73716
73900
  return {
73717
- worktreePath: raw.startsWith("~") ? path56.join(process.env.HOME || os20.homedir(), raw.slice(2)) : path56.resolve(raw)
73901
+ worktreePath: raw.startsWith("~") ? path55.join(process.env.HOME || os20.homedir(), raw.slice(2)) : path55.resolve(raw)
73718
73902
  };
73719
73903
  }
73720
73904
  return { repoPath: raw };
@@ -73728,12 +73912,12 @@ init_stages();
73728
73912
  init_logging();
73729
73913
  function askYesNo5(question) {
73730
73914
  const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
73731
- return new Promise((resolve53) => {
73915
+ return new Promise((resolve52) => {
73732
73916
  process.stderr.write(`${question} `);
73733
73917
  rl.once("line", (answer) => {
73734
73918
  rl.close();
73735
73919
  const trimmed = answer.trim();
73736
- resolve53(trimmed === "" || /^y(es)?$/i.test(trimmed));
73920
+ resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
73737
73921
  });
73738
73922
  });
73739
73923
  }
@@ -73836,13 +74020,13 @@ function warnIfDockerUnavailable(status = detectDockerStatus()) {
73836
74020
  // src/core/onboarding-preferences.ts
73837
74021
  var fs48 = __toESM(require("fs"));
73838
74022
  var os21 = __toESM(require("os"));
73839
- var path57 = __toESM(require("path"));
74023
+ var path56 = __toESM(require("path"));
73840
74024
  init_schema2();
73841
74025
  function getOnboardingPreferencesPath() {
73842
74026
  if (process.env.HAR_PREFERENCES_PATH) {
73843
- return path57.resolve(process.env.HAR_PREFERENCES_PATH);
74027
+ return path56.resolve(process.env.HAR_PREFERENCES_PATH);
73844
74028
  }
73845
- return path57.join(os21.homedir(), ".har", "preferences.json");
74029
+ return path56.join(os21.homedir(), ".har", "preferences.json");
73846
74030
  }
73847
74031
  function readOnboardingPreferences() {
73848
74032
  const preferencePath = getOnboardingPreferencesPath();
@@ -73873,7 +74057,7 @@ function writeOnboardingPreferences(overrides) {
73873
74057
  };
73874
74058
  const parsed = OnboardingPreferencesSchema.parse(preference);
73875
74059
  const preferencePath = getOnboardingPreferencesPath();
73876
- fs48.mkdirSync(path57.dirname(preferencePath), { recursive: true });
74060
+ fs48.mkdirSync(path56.dirname(preferencePath), { recursive: true });
73877
74061
  fs48.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
73878
74062
  `);
73879
74063
  return parsed;
@@ -74219,7 +74403,7 @@ var envCommand = {
74219
74403
  }
74220
74404
  };
74221
74405
  async function handleInit(argv) {
74222
- const repoPath = path58.resolve(argv.repo);
74406
+ const repoPath = path57.resolve(argv.repo);
74223
74407
  const onboarding = resolveOnboardingOptions(argv);
74224
74408
  header("har env init");
74225
74409
  info(`Repository: ${repoPath}`);
@@ -74266,7 +74450,7 @@ async function handleInit(argv) {
74266
74450
  }
74267
74451
  }
74268
74452
  async function handleMaintain(argv) {
74269
- const repoPath = path58.resolve(argv.repo);
74453
+ const repoPath = path57.resolve(argv.repo);
74270
74454
  const onboarding = resolveOnboardingOptions(argv);
74271
74455
  header("har env maintain");
74272
74456
  info(`Repository: ${repoPath}`);
@@ -74397,7 +74581,7 @@ async function applyAgentIntegrations(options) {
74397
74581
  }
74398
74582
  }
74399
74583
  async function handleAddPlugin(argv) {
74400
- const repoPath = path58.resolve(argv.repo);
74584
+ const repoPath = path57.resolve(argv.repo);
74401
74585
  const available = listPluginIds();
74402
74586
  if (argv.list) {
74403
74587
  for (const id of available) {
@@ -74437,7 +74621,7 @@ async function handleAddPlugin(argv) {
74437
74621
  }
74438
74622
  }
74439
74623
  async function handleAddStage(argv) {
74440
- const repoPath = path58.resolve(argv.repo);
74624
+ const repoPath = path57.resolve(argv.repo);
74441
74625
  const available = listPluginIds();
74442
74626
  if (argv.list) {
74443
74627
  warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
@@ -74503,7 +74687,7 @@ async function handleAddStage(argv) {
74503
74687
  });
74504
74688
  }
74505
74689
  async function handlePreflight(argv) {
74506
- const repo = path58.resolve(argv.repo);
74690
+ const repo = path57.resolve(argv.repo);
74507
74691
  const agentId = validateAgentId(argv.id, repo);
74508
74692
  const result = await preflightEnvironment({
74509
74693
  repoPath: repo,
@@ -74519,7 +74703,7 @@ async function handlePreflight(argv) {
74519
74703
  return finishCommand(result.code);
74520
74704
  }
74521
74705
  async function handleLaunch(argv) {
74522
- const repo = path58.resolve(argv.repo);
74706
+ const repo = path57.resolve(argv.repo);
74523
74707
  const agentId = validateAgentId(argv.id, repo);
74524
74708
  if (!argv.resume) {
74525
74709
  const guard = checkLaunchGuard2(repo, agentId, { worktree: argv.worktree });
@@ -74568,7 +74752,7 @@ async function handleWorkLink(argv) {
74568
74752
  error("Provide --link or both --source and --url");
74569
74753
  return finishCommand(1);
74570
74754
  }
74571
- const harnessRoot = resolveHarnessRoot(path58.resolve(argv.repo));
74755
+ const harnessRoot = resolveHarnessRoot(path57.resolve(argv.repo));
74572
74756
  const links = argv.link ? [parseWorkLinkSpec(argv.link)] : [{ source: argv.source, url: argv.url, label: argv.label }];
74573
74757
  try {
74574
74758
  const record2 = addWorkUnitLinks(harnessRoot, argv.workId, links);
@@ -74594,7 +74778,7 @@ async function handleRecover(argv) {
74594
74778
  });
74595
74779
  }
74596
74780
  async function handleVerify(argv) {
74597
- const repo = path58.resolve(argv.repo);
74781
+ const repo = path57.resolve(argv.repo);
74598
74782
  const agentId = validateAgentId(argv.id, repo);
74599
74783
  const result = await runVerification({
74600
74784
  repoPath: repo,
@@ -74623,7 +74807,7 @@ async function handleVerify(argv) {
74623
74807
  return finishCommand(result.code);
74624
74808
  }
74625
74809
  async function handleTeardown(argv) {
74626
- const repo = path58.resolve(argv.repo);
74810
+ const repo = path57.resolve(argv.repo);
74627
74811
  const agentId = validateAgentId(argv.id, repo);
74628
74812
  const result = await teardownEnvironment({
74629
74813
  repoPath: repo,
@@ -74634,7 +74818,7 @@ async function handleTeardown(argv) {
74634
74818
  return finishCommand(result.code);
74635
74819
  }
74636
74820
  async function handleComplete(argv) {
74637
- const repo = path58.resolve(argv.repo);
74821
+ const repo = path57.resolve(argv.repo);
74638
74822
  const agentId = validateAgentId(argv.id, repo);
74639
74823
  const result = await completeEnvironment({
74640
74824
  repoPath: repo,
@@ -74655,7 +74839,7 @@ async function handleComplete(argv) {
74655
74839
  return finishCommand(result.code);
74656
74840
  }
74657
74841
  async function handleStatus(argv) {
74658
- const repoPath = path58.resolve(argv.repo);
74842
+ const repoPath = path57.resolve(argv.repo);
74659
74843
  if (argv.json) {
74660
74844
  const status = collectEnvironmentStatus(repoPath);
74661
74845
  const output = EnvironmentStatusSchema.parse(status);
@@ -74670,7 +74854,7 @@ async function handleStatus(argv) {
74670
74854
  async function handleCleanup(argv) {
74671
74855
  const keepValues = argv.keep?.split(",").map((value) => value.trim()).filter(Boolean);
74672
74856
  const keep = parseCleanupKeepPins(keepValues);
74673
- const repoPaths = argv.repo ? [path58.resolve(argv.repo)] : void 0;
74857
+ const repoPaths = argv.repo ? [path57.resolve(argv.repo)] : void 0;
74674
74858
  const plan = await discoverCleanupCandidates({
74675
74859
  cwd: process.cwd(),
74676
74860
  repoPaths,
@@ -74719,7 +74903,7 @@ async function handleCleanup(argv) {
74719
74903
  return finishCommand(failed > 0 ? 1 : 0);
74720
74904
  }
74721
74905
  async function handleRunsList(argv) {
74722
- const repoPath = path58.resolve(argv.repo);
74906
+ const repoPath = path57.resolve(argv.repo);
74723
74907
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
74724
74908
  if (argv.json) {
74725
74909
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -74736,7 +74920,7 @@ async function handleRunsList(argv) {
74736
74920
  }
74737
74921
  }
74738
74922
  async function handleRunsGet(argv) {
74739
- const run2 = getRun(path58.resolve(argv.repo), argv.runId);
74923
+ const run2 = getRun(path57.resolve(argv.repo), argv.runId);
74740
74924
  if (!run2) {
74741
74925
  error(`Run not found: ${argv.runId}`);
74742
74926
  return finishCommand(1);
@@ -74813,7 +74997,7 @@ function printNextSteps() {
74813
74997
  }
74814
74998
 
74815
74999
  // src/cli/commands/control.ts
74816
- var path63 = __toESM(require("path"));
75000
+ var path62 = __toESM(require("path"));
74817
75001
  init_control_config();
74818
75002
  init_portal_targets();
74819
75003
 
@@ -74822,7 +75006,7 @@ init_control_config();
74822
75006
 
74823
75007
  // src/core/portal-connect.ts
74824
75008
  var fs49 = __toESM(require("fs"));
74825
- var path59 = __toESM(require("path"));
75009
+ var path58 = __toESM(require("path"));
74826
75010
  var import_crypto2 = require("crypto");
74827
75011
  init_control_repo_path();
74828
75012
  init_control_registry();
@@ -74868,7 +75052,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
74868
75052
  const options = typeof openUrlOrOptions === "function" ? { openUrl: openUrlOrOptions } : openUrlOrOptions;
74869
75053
  const openUrl = options.openUrl ?? openBrowser;
74870
75054
  const state = (0, import_crypto.randomUUID)();
74871
- return new Promise((resolve53, reject) => {
75055
+ return new Promise((resolve52, reject) => {
74872
75056
  let timer;
74873
75057
  const server = http.createServer((req, res) => {
74874
75058
  const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
@@ -74896,7 +75080,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
74896
75080
  res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
74897
75081
  cleanup();
74898
75082
  const targets = parseCliTargetsParam(requestUrl.searchParams.get("targets"));
74899
- resolve53({
75083
+ resolve52({
74900
75084
  portalUrl,
74901
75085
  token,
74902
75086
  workspace: workspaceSlug ?? workspace,
@@ -74991,7 +75175,7 @@ function remainingConnections(connections, usedAliases) {
74991
75175
  // src/core/portal-connect.ts
74992
75176
  init_portal_targets();
74993
75177
  function attachRepoIfPresent(alias, repoPath) {
74994
- const resolved = path59.resolve(repoPath ?? ".");
75178
+ const resolved = path58.resolve(repoPath ?? ".");
74995
75179
  if (!fs49.existsSync(resolved)) return null;
74996
75180
  const canonical = canonicalizeControlRepoPath(resolved);
74997
75181
  attachRepoPortalTarget(canonical, alias);
@@ -75059,7 +75243,7 @@ async function runPortalConnect(input) {
75059
75243
  return { record: record2, attachedRepo, extraAttached, mappedInBrowser: true };
75060
75244
  }
75061
75245
  function listRegisteredReposForConnect(repoPath) {
75062
- const resolved = repoPath ? path59.resolve(repoPath) : null;
75246
+ const resolved = repoPath ? path58.resolve(repoPath) : null;
75063
75247
  const current = resolved && fs49.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
75064
75248
  return [.../* @__PURE__ */ new Set([...current ? [current] : [], ...listRegisteredRepos()])];
75065
75249
  }
@@ -75378,13 +75562,13 @@ init_control_sync();
75378
75562
  // src/core/control-sync-selection.ts
75379
75563
  var fs50 = __toESM(require("fs"));
75380
75564
  var os22 = __toESM(require("os"));
75381
- var path60 = __toESM(require("path"));
75565
+ var path59 = __toESM(require("path"));
75382
75566
  init_control_repo_path();
75383
75567
  function getSelectionPath() {
75384
75568
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
75385
- return path60.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
75569
+ return path59.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
75386
75570
  }
75387
- return path60.join(os22.homedir(), ".har", "sync-selection.json");
75571
+ return path59.join(os22.homedir(), ".har", "sync-selection.json");
75388
75572
  }
75389
75573
  function readSyncSelection() {
75390
75574
  const selectionPath = getSelectionPath();
@@ -75400,7 +75584,7 @@ function readSyncSelection() {
75400
75584
  function writeSyncSelection(repos) {
75401
75585
  const selectionPath = getSelectionPath();
75402
75586
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
75403
- fs50.mkdirSync(path60.dirname(selectionPath), { recursive: true });
75587
+ fs50.mkdirSync(path59.dirname(selectionPath), { recursive: true });
75404
75588
  fs50.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
75405
75589
  }
75406
75590
  function resolveSyncSelection(input) {
@@ -75429,7 +75613,7 @@ function resolveSyncSelection(input) {
75429
75613
 
75430
75614
  // src/core/control-unregister.ts
75431
75615
  var fs51 = __toESM(require("fs"));
75432
- var path61 = __toESM(require("path"));
75616
+ var path60 = __toESM(require("path"));
75433
75617
  init_control_repo_path();
75434
75618
  init_control_registry();
75435
75619
  init_control_config();
@@ -75439,7 +75623,7 @@ function listUnregisterWorktreeCandidates(repoPath) {
75439
75623
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
75440
75624
  const byPath = /* @__PURE__ */ new Map();
75441
75625
  const add = (partial2) => {
75442
- const resolved = path61.resolve(partial2.worktreePath);
75626
+ const resolved = path60.resolve(partial2.worktreePath);
75443
75627
  if (!resolved || resolved === harnessRoot) return;
75444
75628
  const exists = partial2.exists ?? fs51.existsSync(resolved);
75445
75629
  const prev = byPath.get(resolved);
@@ -75492,8 +75676,8 @@ async function askYesNo6(question) {
75492
75676
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
75493
75677
  const readline8 = await import("readline");
75494
75678
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
75495
- const answer = await new Promise((resolve53) => {
75496
- rl.question(question, resolve53);
75679
+ const answer = await new Promise((resolve52) => {
75680
+ rl.question(question, resolve52);
75497
75681
  });
75498
75682
  rl.close();
75499
75683
  return /^[Yy]$/.test(answer.trim());
@@ -75640,15 +75824,15 @@ init_control_registry();
75640
75824
 
75641
75825
  // src/core/harness-scrub.ts
75642
75826
  var fs52 = __toESM(require("fs"));
75643
- var path62 = __toESM(require("path"));
75827
+ var path61 = __toESM(require("path"));
75644
75828
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
75645
75829
  function scrubLocalHarnessDirs(repoPath) {
75646
75830
  const results = [];
75647
- const resolved = path62.resolve(repoPath);
75831
+ const resolved = path61.resolve(repoPath);
75648
75832
  if (!fs52.existsSync(resolved)) {
75649
75833
  for (const directory of HARNESS_SCRUB_DIRS) {
75650
75834
  results.push({
75651
- path: path62.join(resolved, ".har", directory),
75835
+ path: path61.join(resolved, ".har", directory),
75652
75836
  directory,
75653
75837
  deleted: false,
75654
75838
  error: "repository path does not exist"
@@ -75657,7 +75841,7 @@ function scrubLocalHarnessDirs(repoPath) {
75657
75841
  return results;
75658
75842
  }
75659
75843
  for (const directory of HARNESS_SCRUB_DIRS) {
75660
- const target = path62.join(resolved, ".har", directory);
75844
+ const target = path61.join(resolved, ".har", directory);
75661
75845
  if (!fs52.existsSync(target)) {
75662
75846
  results.push({ path: target, directory, deleted: true });
75663
75847
  continue;
@@ -75685,7 +75869,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
75685
75869
  const results = [];
75686
75870
  const seen = /* @__PURE__ */ new Set();
75687
75871
  for (const repoPath of repoPaths) {
75688
- const key = path62.resolve(repoPath);
75872
+ const key = path61.resolve(repoPath);
75689
75873
  if (seen.has(key)) continue;
75690
75874
  seen.add(key);
75691
75875
  results.push(...scrubLocalHarnessDirs(key));
@@ -75698,8 +75882,8 @@ async function askYesNo7(question) {
75698
75882
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
75699
75883
  const readline8 = await import("readline");
75700
75884
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
75701
- const answer = await new Promise((resolve53) => {
75702
- rl.question(question, resolve53);
75885
+ const answer = await new Promise((resolve52) => {
75886
+ rl.question(question, resolve52);
75703
75887
  });
75704
75888
  rl.close();
75705
75889
  return /^[Yy]$/.test(answer.trim());
@@ -75978,7 +76162,7 @@ async function handleDown() {
75978
76162
  return finishCommand(code);
75979
76163
  }
75980
76164
  async function handleRegister(argv) {
75981
- const repoPath = path63.resolve(argv.repo);
76165
+ const repoPath = path62.resolve(argv.repo);
75982
76166
  header("har control register");
75983
76167
  info(`Repository: ${repoPath}`);
75984
76168
  try {
@@ -76076,7 +76260,7 @@ async function handleReset(argv) {
76076
76260
  }
76077
76261
  }
76078
76262
  async function handleUnregister(argv) {
76079
- const repoPath = path63.resolve(argv.repo);
76263
+ const repoPath = path62.resolve(argv.repo);
76080
76264
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
76081
76265
  try {
76082
76266
  let deleteWorktrees = argv.deleteWorktrees;
@@ -76214,7 +76398,7 @@ async function handleSync(argv) {
76214
76398
  );
76215
76399
  }
76216
76400
  }
76217
- const { synced, failed, results } = await syncReposWithControl({
76401
+ const { synced, failed, incomplete, results } = await syncReposWithControl({
76218
76402
  repoPaths,
76219
76403
  apiUrl: argv.apiUrl,
76220
76404
  dryRun: argv.dryRun,
@@ -76223,7 +76407,9 @@ async function handleSync(argv) {
76223
76407
  portalTargets
76224
76408
  });
76225
76409
  if (argv.json) {
76226
- process.stdout.write(JSON.stringify({ ok: failed === 0, synced, failed, results }, null, 2) + "\n");
76410
+ process.stdout.write(
76411
+ JSON.stringify({ ok: failed === 0, synced, failed, incomplete, results }, null, 2) + "\n"
76412
+ );
76227
76413
  if (failed > 0) return finishCommand(1);
76228
76414
  return;
76229
76415
  }
@@ -76232,22 +76418,32 @@ async function handleSync(argv) {
76232
76418
  for (const target of result.targets) {
76233
76419
  const record2 = findPortalTargetRecord(target.alias);
76234
76420
  const label = record2 ? displayPortalTargetLabel(record2) : target.alias;
76235
- if (target.ok) {
76236
- success(`Synced ${result.repoPath} \u2192 ${label}`);
76237
- } else {
76421
+ if (!target.ok) {
76238
76422
  warn(`Failed ${result.repoPath} \u2192 ${label}: ${target.error}`);
76423
+ } else if (target.warnings && target.warnings.length > 0) {
76424
+ warn(`Synced ${result.repoPath} \u2192 ${label} \u2014 incomplete`);
76425
+ } else {
76426
+ success(`Synced ${result.repoPath} \u2192 ${label}`);
76239
76427
  }
76240
76428
  }
76241
76429
  continue;
76242
76430
  }
76243
- if (result.ok) {
76244
- success(`Synced ${result.repoPath}`);
76245
- } else {
76431
+ if (!result.ok) {
76246
76432
  warn(`Failed ${result.repoPath}: ${result.error}`);
76433
+ } else if (result.warnings && result.warnings.length > 0) {
76434
+ warn(`Synced ${result.repoPath} \u2014 incomplete`);
76435
+ } else {
76436
+ success(`Synced ${result.repoPath}`);
76247
76437
  }
76248
76438
  }
76249
- if (synced > 0) {
76250
- success(`Synced ${synced} ${synced === 1 ? "repository" : "repositories"}`);
76439
+ if (synced > incomplete) {
76440
+ const complete = synced - incomplete;
76441
+ success(`Synced ${complete} ${complete === 1 ? "repository" : "repositories"}`);
76442
+ }
76443
+ if (incomplete > 0) {
76444
+ warn(
76445
+ `${incomplete} ${incomplete === 1 ? "repository" : "repositories"} synced with incomplete telemetry \u2014 see the warnings above`
76446
+ );
76251
76447
  }
76252
76448
  if (failed > 0) {
76253
76449
  warn(`${failed} ${failed === 1 ? "repository" : "repositories"} could not be synced`);
@@ -76345,12 +76541,12 @@ async function handleTrajectory(argv) {
76345
76541
  }
76346
76542
 
76347
76543
  // src/cli/commands/hooks.ts
76348
- var path65 = __toESM(require("path"));
76544
+ var path64 = __toESM(require("path"));
76349
76545
  init_hooks();
76350
76546
 
76351
76547
  // src/core/claude-hooks.ts
76352
76548
  var fs53 = __toESM(require("fs"));
76353
- var path64 = __toESM(require("path"));
76549
+ var path63 = __toESM(require("path"));
76354
76550
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
76355
76551
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
76356
76552
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -76371,7 +76567,7 @@ function readSettings(settingsPath) {
76371
76567
  return parsed;
76372
76568
  }
76373
76569
  function writeSettings(settingsPath, settings) {
76374
- fs53.mkdirSync(path64.dirname(settingsPath), { recursive: true });
76570
+ fs53.mkdirSync(path63.dirname(settingsPath), { recursive: true });
76375
76571
  fs53.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
76376
76572
  }
76377
76573
  function installClaudeGuard(repoPath) {
@@ -76379,11 +76575,11 @@ function installClaudeGuard(repoPath) {
76379
76575
  if (!templatePath) {
76380
76576
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
76381
76577
  }
76382
- const guardScript = path64.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76383
- fs53.mkdirSync(path64.dirname(guardScript), { recursive: true });
76578
+ const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76579
+ fs53.mkdirSync(path63.dirname(guardScript), { recursive: true });
76384
76580
  fs53.copyFileSync(templatePath, guardScript);
76385
76581
  fs53.chmodSync(guardScript, 493);
76386
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76582
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76387
76583
  const settings = readSettings(settingsPath);
76388
76584
  const hooks = settings.hooks ?? {};
76389
76585
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -76397,14 +76593,14 @@ function installClaudeGuard(repoPath) {
76397
76593
  }
76398
76594
  function uninstallClaudeGuard(repoPath) {
76399
76595
  let removed = false;
76400
- const guardScript = path64.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76596
+ const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76401
76597
  if (fs53.existsSync(guardScript)) {
76402
76598
  fs53.rmSync(guardScript);
76403
76599
  removed = true;
76404
- const parent = path64.dirname(guardScript);
76600
+ const parent = path63.dirname(guardScript);
76405
76601
  if (fs53.existsSync(parent) && fs53.readdirSync(parent).length === 0) fs53.rmdirSync(parent);
76406
76602
  }
76407
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76603
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76408
76604
  if (fs53.existsSync(settingsPath)) {
76409
76605
  const settings = readSettings(settingsPath);
76410
76606
  const preToolUse = settings.hooks?.PreToolUse;
@@ -76430,7 +76626,7 @@ function uninstallClaudeGuard(repoPath) {
76430
76626
  return { removed };
76431
76627
  }
76432
76628
  function claudeGuardInstalled(repoPath) {
76433
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76629
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76434
76630
  if (!fs53.existsSync(settingsPath)) return false;
76435
76631
  try {
76436
76632
  const settings = readSettings(settingsPath);
@@ -76448,7 +76644,7 @@ function repoOption(y) {
76448
76644
  function handleInstall2(argv) {
76449
76645
  try {
76450
76646
  if (argv.claude) {
76451
- const result2 = installClaudeGuard(path65.resolve(argv.repo));
76647
+ const result2 = installClaudeGuard(path64.resolve(argv.repo));
76452
76648
  success("Claude Code worktree guard installed.");
76453
76649
  info(`Guard script: ${result2.guardScript}`);
76454
76650
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -76456,7 +76652,7 @@ function handleInstall2(argv) {
76456
76652
  info("Commit both files so the guard travels with the repo.");
76457
76653
  return;
76458
76654
  }
76459
- const result = installHooks({ repoPath: path65.resolve(argv.repo), force: argv.force });
76655
+ const result = installHooks({ repoPath: path64.resolve(argv.repo), force: argv.force });
76460
76656
  success(`Commit gate installed in ${result.hooksDir}`);
76461
76657
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
76462
76658
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -76469,7 +76665,7 @@ function handleInstall2(argv) {
76469
76665
  function handleUninstall(argv) {
76470
76666
  try {
76471
76667
  if (argv.claude) {
76472
- const result2 = uninstallClaudeGuard(path65.resolve(argv.repo));
76668
+ const result2 = uninstallClaudeGuard(path64.resolve(argv.repo));
76473
76669
  if (result2.removed) {
76474
76670
  success("Claude Code worktree guard removed.");
76475
76671
  } else {
@@ -76477,7 +76673,7 @@ function handleUninstall(argv) {
76477
76673
  }
76478
76674
  return;
76479
76675
  }
76480
- const result = uninstallHooks(path65.resolve(argv.repo));
76676
+ const result = uninstallHooks(path64.resolve(argv.repo));
76481
76677
  if (result.removed) {
76482
76678
  success(`Commit gate removed from ${result.hooksDir}`);
76483
76679
  } else {
@@ -76490,7 +76686,7 @@ function handleUninstall(argv) {
76490
76686
  }
76491
76687
  function handleStatus2(argv) {
76492
76688
  try {
76493
- const status = getHooksStatus(path65.resolve(argv.repo));
76689
+ const status = getHooksStatus(path64.resolve(argv.repo));
76494
76690
  if (argv.json) {
76495
76691
  process.stdout.write(`${JSON.stringify(status, null, 2)}
76496
76692
  `);
@@ -76508,7 +76704,7 @@ function handleStatus2(argv) {
76508
76704
  );
76509
76705
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
76510
76706
  info(
76511
- `Claude guard: ${claudeGuardInstalled(path65.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
76707
+ `Claude guard: ${claudeGuardInstalled(path64.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
76512
76708
  );
76513
76709
  } catch (err) {
76514
76710
  error(err instanceof Error ? err.message : String(err));
@@ -76769,10 +76965,10 @@ function assignProp(target, prop, value) {
76769
76965
  configurable: true
76770
76966
  });
76771
76967
  }
76772
- function getElementAtPath(obj, path70) {
76773
- if (!path70)
76968
+ function getElementAtPath(obj, path69) {
76969
+ if (!path69)
76774
76970
  return obj;
76775
- return path70.reduce((acc, key) => acc?.[key], obj);
76971
+ return path69.reduce((acc, key) => acc?.[key], obj);
76776
76972
  }
76777
76973
  function promiseAllObject(promisesObj) {
76778
76974
  const keys = Object.keys(promisesObj);
@@ -77092,11 +77288,11 @@ function aborted(x, startIndex = 0) {
77092
77288
  }
77093
77289
  return false;
77094
77290
  }
77095
- function prefixIssues(path70, issues) {
77291
+ function prefixIssues(path69, issues) {
77096
77292
  return issues.map((iss) => {
77097
77293
  var _a2;
77098
77294
  (_a2 = iss).path ?? (_a2.path = []);
77099
- iss.path.unshift(path70);
77295
+ iss.path.unshift(path69);
77100
77296
  return iss;
77101
77297
  });
77102
77298
  }
@@ -82419,7 +82615,7 @@ var Protocol = class {
82419
82615
  return;
82420
82616
  }
82421
82617
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
82422
- await new Promise((resolve53) => setTimeout(resolve53, pollInterval));
82618
+ await new Promise((resolve52) => setTimeout(resolve52, pollInterval));
82423
82619
  options?.signal?.throwIfAborted();
82424
82620
  }
82425
82621
  } catch (error3) {
@@ -82436,7 +82632,7 @@ var Protocol = class {
82436
82632
  */
82437
82633
  request(request, resultSchema, options) {
82438
82634
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
82439
- return new Promise((resolve53, reject) => {
82635
+ return new Promise((resolve52, reject) => {
82440
82636
  const earlyReject = (error3) => {
82441
82637
  reject(error3);
82442
82638
  };
@@ -82514,7 +82710,7 @@ var Protocol = class {
82514
82710
  if (!parseResult.success) {
82515
82711
  reject(parseResult.error);
82516
82712
  } else {
82517
- resolve53(parseResult.data);
82713
+ resolve52(parseResult.data);
82518
82714
  }
82519
82715
  } catch (error3) {
82520
82716
  reject(error3);
@@ -82775,12 +82971,12 @@ var Protocol = class {
82775
82971
  }
82776
82972
  } catch {
82777
82973
  }
82778
- return new Promise((resolve53, reject) => {
82974
+ return new Promise((resolve52, reject) => {
82779
82975
  if (signal.aborted) {
82780
82976
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
82781
82977
  return;
82782
82978
  }
82783
- const timeoutId = setTimeout(resolve53, interval);
82979
+ const timeoutId = setTimeout(resolve52, interval);
82784
82980
  signal.addEventListener("abort", () => {
82785
82981
  clearTimeout(timeoutId);
82786
82982
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -83570,7 +83766,7 @@ var Server = class extends Protocol {
83570
83766
  };
83571
83767
 
83572
83768
  // src/mcp/server.ts
83573
- var path66 = __toESM(require("path"));
83769
+ var path65 = __toESM(require("path"));
83574
83770
 
83575
83771
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
83576
83772
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -83653,12 +83849,12 @@ var StdioServerTransport = class {
83653
83849
  this.onclose?.();
83654
83850
  }
83655
83851
  send(message) {
83656
- return new Promise((resolve53) => {
83852
+ return new Promise((resolve52) => {
83657
83853
  const json = serializeMessage(message);
83658
83854
  if (this._stdout.write(json)) {
83659
- resolve53();
83855
+ resolve52();
83660
83856
  } else {
83661
- this._stdout.once("drain", resolve53);
83857
+ this._stdout.once("drain", resolve52);
83662
83858
  }
83663
83859
  });
83664
83860
  }
@@ -84297,7 +84493,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
84297
84493
  const input = ControlUpInputSchema.parse({ ...args, repo });
84298
84494
  const result = await startControlAndSync({
84299
84495
  detach: input.detach,
84300
- cwd: path66.resolve(input.repo)
84496
+ cwd: path65.resolve(input.repo)
84301
84497
  });
84302
84498
  if (result.code !== 0) {
84303
84499
  return {
@@ -84361,11 +84557,11 @@ var mcpCommand = {
84361
84557
  };
84362
84558
 
84363
84559
  // src/cli/commands/onboard.ts
84364
- var path68 = __toESM(require("path"));
84560
+ var path67 = __toESM(require("path"));
84365
84561
  init_stages();
84366
84562
 
84367
84563
  // src/core/onboarding.ts
84368
- var path67 = __toESM(require("path"));
84564
+ var path66 = __toESM(require("path"));
84369
84565
  init_control_config();
84370
84566
  init_control_sync();
84371
84567
  init_otel_hooks();
@@ -84509,7 +84705,7 @@ async function defaultEnsureControl(options) {
84509
84705
  return { started: true, apiUrl: result.apiUrl };
84510
84706
  }
84511
84707
  async function runOnboarding(options, deps = {}) {
84512
- const repoPath = path67.resolve(options.repoPath);
84708
+ const repoPath = path66.resolve(options.repoPath);
84513
84709
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
84514
84710
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
84515
84711
  const init = deps.initHarness ?? initHarness;
@@ -84707,7 +84903,7 @@ async function promptChoices(args, docker) {
84707
84903
  };
84708
84904
  }
84709
84905
  const pluginChoices = listPluginChoices();
84710
- const repoPath = path68.resolve(args.repo);
84906
+ const repoPath = path67.resolve(args.repo);
84711
84907
  const alreadyPresent = harnessExists(repoPath);
84712
84908
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
84713
84909
  const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
@@ -84828,7 +85024,7 @@ function printSummary(result) {
84828
85024
  console.error("");
84829
85025
  }
84830
85026
  async function handleOnboard(argv) {
84831
- const repoPath = path68.resolve(argv.repo);
85027
+ const repoPath = path67.resolve(argv.repo);
84832
85028
  header("har onboard");
84833
85029
  info(`Repository: ${repoPath}`);
84834
85030
  try {
@@ -85062,7 +85258,7 @@ var preferencesCommand = {
85062
85258
  };
85063
85259
 
85064
85260
  // src/cli/commands/telemetry.ts
85065
- var path69 = __toESM(require("path"));
85261
+ var path68 = __toESM(require("path"));
85066
85262
  init_control_config();
85067
85263
  init_control_sync();
85068
85264
  init_manifest();
@@ -85155,7 +85351,7 @@ async function handleOff() {
85155
85351
  info("Mission Control will not auto-start. Existing usage rows are kept.");
85156
85352
  }
85157
85353
  async function handleWriteEnv(argv) {
85158
- const repoPath = path69.resolve(argv.repo);
85354
+ const repoPath = path68.resolve(argv.repo);
85159
85355
  const harnessRoot = resolveHarnessRoot(repoPath);
85160
85356
  const session = readSlotRegistry(harnessRoot, argv.agentId);
85161
85357
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -85167,7 +85363,7 @@ async function handleWriteEnv(argv) {
85167
85363
  suffix,
85168
85364
  createdAt: session?.createdAt
85169
85365
  });
85170
- const envFile = argv.envFile ?? path69.join(workDir, `.env.agent.${argv.agentId}`);
85366
+ const envFile = argv.envFile ?? path68.join(workDir, `.env.agent.${argv.agentId}`);
85171
85367
  const attrs = {
85172
85368
  sessionKey,
85173
85369
  agentId: argv.agentId,
@@ -85183,7 +85379,7 @@ async function handleWriteEnv(argv) {
85183
85379
  success(`Wrote session attribution to ${envFile}`);
85184
85380
  }
85185
85381
  function handlePrintEnv(argv) {
85186
- const repoPath = path69.resolve(argv.repo);
85382
+ const repoPath = path68.resolve(argv.repo);
85187
85383
  const workDir = argv.workDir ?? repoPath;
85188
85384
  const sessionKey = buildSessionKey({
85189
85385
  branch: argv.branch,