@osfactory/har 0.64.1 → 0.64.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +725 -480
  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 = 2;
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;
@@ -28215,10 +28243,8 @@ function toGenaiPricesUsage(totals) {
28215
28243
  const rawInput = num(totals.tokensInput);
28216
28244
  const cacheRead = num(totals.tokensCacheRead);
28217
28245
  const cacheWrite = num(totals.tokensCacheCreation);
28218
- const uncached = rawInput >= cacheRead ? rawInput - cacheRead : rawInput;
28219
- const inclusiveInput = uncached + cacheRead + cacheWrite;
28220
28246
  return {
28221
- input_tokens: inclusiveInput,
28247
+ input_tokens: rawInput + cacheRead + cacheWrite,
28222
28248
  output_tokens: num(totals.tokensOutput),
28223
28249
  cache_read_tokens: cacheRead,
28224
28250
  cache_write_tokens: cacheWrite
@@ -28294,6 +28320,7 @@ var init_schema2 = __esm({
28294
28320
  "src/harness/schema.ts"() {
28295
28321
  "use strict";
28296
28322
  init_schema();
28323
+ init_usage_authority();
28297
28324
  init_usage_pricing();
28298
28325
  }
28299
28326
  });
@@ -28704,7 +28731,7 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
28704
28731
  const stream = options.stream ?? false;
28705
28732
  const echoStdout = stream && (options.streamStdout ?? true);
28706
28733
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
28707
- return new Promise((resolve53) => {
28734
+ return new Promise((resolve52) => {
28708
28735
  const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
28709
28736
  ...spawnOptions,
28710
28737
  stdio: ["inherit", "pipe", "pipe"]
@@ -28719,14 +28746,14 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
28719
28746
  stderr += d;
28720
28747
  if (stream) process.stderr.write(d);
28721
28748
  });
28722
- proc.on("close", (code) => resolve53({ stdout, stderr, code: code ?? 0 }));
28749
+ proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
28723
28750
  });
28724
28751
  }
28725
28752
  function runShellCommand(command2, options = {}) {
28726
28753
  const stream = options.stream ?? false;
28727
28754
  const echoStdout = stream && (options.streamStdout ?? true);
28728
28755
  const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
28729
- return new Promise((resolve53) => {
28756
+ return new Promise((resolve52) => {
28730
28757
  const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
28731
28758
  ...spawnOptions,
28732
28759
  stdio: ["inherit", "pipe", "pipe"]
@@ -28741,7 +28768,7 @@ function runShellCommand(command2, options = {}) {
28741
28768
  stderr += d;
28742
28769
  if (stream) process.stderr.write(d);
28743
28770
  });
28744
- proc.on("close", (code) => resolve53({ stdout, stderr, code: code ?? 0 }));
28771
+ proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
28745
28772
  });
28746
28773
  }
28747
28774
  var import_child_process;
@@ -31541,17 +31568,17 @@ function listWorkUnits(harnessRoot) {
31541
31568
  ).sort((a, b2) => b2.updatedAt.localeCompare(a.updatedAt));
31542
31569
  }
31543
31570
  function createWorkAttempt(harnessRoot, input) {
31544
- const attempt = WorkAttemptRecordSchema.parse({
31571
+ const attempt2 = WorkAttemptRecordSchema.parse({
31545
31572
  ...input,
31546
31573
  version: 1,
31547
31574
  createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
31548
31575
  });
31549
31576
  ensureWorkEvidenceIgnored(harnessRoot);
31550
31577
  writeRecord2(
31551
- hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt.attemptId),
31552
- attempt
31578
+ hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt2.attemptId),
31579
+ attempt2
31553
31580
  );
31554
- return attempt;
31581
+ return attempt2;
31555
31582
  }
31556
31583
  function listWorkAttempts(harnessRoot) {
31557
31584
  return listRecords(
@@ -32285,6 +32312,33 @@ var init_workspace_path_match = __esm({
32285
32312
  }
32286
32313
  });
32287
32314
 
32315
+ // src/core/usage-harvest/record-time-range.ts
32316
+ function recordTimestamp(record2) {
32317
+ if (!record2 || typeof record2 !== "object") return null;
32318
+ const payload = record2;
32319
+ const raw = typeof payload.timestamp === "string" ? payload.timestamp : payload.ts;
32320
+ if (typeof raw !== "string") return null;
32321
+ const ms = Date.parse(raw);
32322
+ return Number.isFinite(ms) ? ms : null;
32323
+ }
32324
+ function recordTimeRange(records) {
32325
+ let first = null;
32326
+ let last = null;
32327
+ for (const record2 of records) {
32328
+ const ms = recordTimestamp(record2);
32329
+ if (ms === null) continue;
32330
+ if (first === null || ms < first) first = ms;
32331
+ if (last === null || ms > last) last = ms;
32332
+ }
32333
+ if (first === null || last === null) return null;
32334
+ return { firstAt: new Date(first).toISOString(), lastAt: new Date(last).toISOString() };
32335
+ }
32336
+ var init_record_time_range = __esm({
32337
+ "src/core/usage-harvest/record-time-range.ts"() {
32338
+ "use strict";
32339
+ }
32340
+ });
32341
+
32288
32342
  // src/core/usage-harvest/claude.ts
32289
32343
  function claudeProjectsRoot() {
32290
32344
  return process.env.HAR_CLAUDE_PROJECTS_DIR ? path25.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path25.join(os11.homedir(), ".claude", "projects");
@@ -32311,8 +32365,12 @@ function extractClaudeUsageFromRecords(records) {
32311
32365
  let tokensOutput = 0;
32312
32366
  let tokensCacheRead = 0;
32313
32367
  let tokensCacheCreation = 0;
32314
- let costUsd = null;
32315
32368
  const modelBreakdown = {};
32369
+ let resultInput = 0;
32370
+ let resultOutput = 0;
32371
+ let resultCacheRead = 0;
32372
+ let resultCacheCreation = 0;
32373
+ let resultCostUsd = null;
32316
32374
  const billed = /* @__PURE__ */ new Map();
32317
32375
  const unkeyed = [];
32318
32376
  for (const record2 of records) {
@@ -32320,11 +32378,13 @@ function extractClaudeUsageFromRecords(records) {
32320
32378
  const payload = record2;
32321
32379
  if (payload.type === "result") {
32322
32380
  const usage2 = payload.usage ?? {};
32323
- tokensInput = Number(usage2.input_tokens ?? 0) + Number(usage2.cache_read_input_tokens ?? 0);
32324
- tokensOutput = Number(usage2.output_tokens ?? 0);
32325
- tokensCacheRead = Number(usage2.cache_read_input_tokens ?? 0);
32326
- tokensCacheCreation = Number(usage2.cache_creation_input_tokens ?? 0);
32327
- if (payload.total_cost_usd != null) costUsd = Number(payload.total_cost_usd);
32381
+ resultInput += Number(usage2.input_tokens ?? 0);
32382
+ resultOutput += Number(usage2.output_tokens ?? 0);
32383
+ resultCacheRead += Number(usage2.cache_read_input_tokens ?? 0);
32384
+ resultCacheCreation += Number(usage2.cache_creation_input_tokens ?? 0);
32385
+ if (payload.total_cost_usd != null) {
32386
+ resultCostUsd = (resultCostUsd ?? 0) + Number(payload.total_cost_usd);
32387
+ }
32328
32388
  }
32329
32389
  const message = payload.message;
32330
32390
  const nestedUsage = payload.usage ?? message?.usage;
@@ -32359,7 +32419,21 @@ function extractClaudeUsageFromRecords(records) {
32359
32419
  totals.tokensTotal += i + o + cr + cc;
32360
32420
  }
32361
32421
  }
32362
- return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd, modelBreakdown };
32422
+ const resultTotal = resultInput + resultOutput + resultCacheRead + resultCacheCreation;
32423
+ if (resultTotal > 0) {
32424
+ tokensInput = resultInput;
32425
+ tokensOutput = resultOutput;
32426
+ tokensCacheRead = resultCacheRead;
32427
+ tokensCacheCreation = resultCacheCreation;
32428
+ }
32429
+ return {
32430
+ tokensInput,
32431
+ tokensOutput,
32432
+ tokensCacheRead,
32433
+ tokensCacheCreation,
32434
+ costUsd: resultCostUsd,
32435
+ modelBreakdown
32436
+ };
32363
32437
  }
32364
32438
  function findMatchingClaudeTranscripts(slot) {
32365
32439
  const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
@@ -32456,11 +32530,13 @@ function harvestClaudeUsage(slot) {
32456
32530
  });
32457
32531
  const own = matches.filter((match) => match.primary);
32458
32532
  const usable = own.length > 0 ? own : matches;
32459
- const usage2 = extractClaudeUsageFromRecords(usable.flatMap((match) => match.records));
32533
+ const records = usable.flatMap((match) => match.records);
32534
+ const usage2 = extractClaudeUsageFromRecords(records);
32460
32535
  if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
32461
32536
  return null;
32462
32537
  }
32463
32538
  const now = (/* @__PURE__ */ new Date()).toISOString();
32539
+ const seen = recordTimeRange(records);
32464
32540
  const tokensTotal = usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead + usage2.tokensCacheCreation;
32465
32541
  return {
32466
32542
  sessionKey,
@@ -32477,8 +32553,9 @@ function harvestClaudeUsage(slot) {
32477
32553
  costUsd: usage2.costUsd,
32478
32554
  ...Object.keys(usage2.modelBreakdown).length > 0 ? { modelBreakdown: usage2.modelBreakdown } : {},
32479
32555
  sources: ["harvest"],
32480
- firstSeenAt: slot.sessionCreatedAt ?? now,
32481
- lastSeenAt: now
32556
+ harvestVersion: USAGE_HARVEST_VERSION,
32557
+ firstSeenAt: seen?.firstAt ?? slot.sessionCreatedAt ?? now,
32558
+ lastSeenAt: seen?.lastAt ?? now
32482
32559
  };
32483
32560
  }
32484
32561
  function harvestClaudeEvents(slot) {
@@ -32500,9 +32577,11 @@ var init_claude = __esm({
32500
32577
  fs23 = __toESM(require("fs"));
32501
32578
  os11 = __toESM(require("os"));
32502
32579
  path25 = __toESM(require("path"));
32580
+ init_schema2();
32503
32581
  init_telemetry_config();
32504
32582
  init_telemetry_env();
32505
32583
  init_workspace_path_match();
32584
+ init_record_time_range();
32506
32585
  }
32507
32586
  });
32508
32587
 
@@ -32563,7 +32642,7 @@ function extractCodexTokens(records) {
32563
32642
  tokensCacheRead = Math.max(tokensCacheRead, Number(payload.cached_token_count ?? 0));
32564
32643
  }
32565
32644
  }
32566
- return { tokensInput, tokensOutput, tokensCacheRead, cwd };
32645
+ return { tokensInput, tokensOutput, tokensCacheRead, cwd, seen: recordTimeRange(records) };
32567
32646
  }
32568
32647
  function harvestCodexUsage(slot) {
32569
32648
  const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
@@ -32618,8 +32697,9 @@ function harvestCodexUsage(slot) {
32618
32697
  tokensTotal,
32619
32698
  costUsd: null,
32620
32699
  sources: ["harvest"],
32621
- firstSeenAt: slot.sessionCreatedAt ?? now,
32622
- lastSeenAt: now
32700
+ harvestVersion: USAGE_HARVEST_VERSION,
32701
+ firstSeenAt: best.seen?.firstAt ?? slot.sessionCreatedAt ?? now,
32702
+ lastSeenAt: best.seen?.lastAt ?? now
32623
32703
  };
32624
32704
  }
32625
32705
  var fs24, os12, path26;
@@ -32629,8 +32709,10 @@ var init_codex = __esm({
32629
32709
  fs24 = __toESM(require("fs"));
32630
32710
  os12 = __toESM(require("os"));
32631
32711
  path26 = __toESM(require("path"));
32712
+ init_schema2();
32632
32713
  init_telemetry_env();
32633
32714
  init_workspace_path_match();
32715
+ init_record_time_range();
32634
32716
  }
32635
32717
  });
32636
32718
 
@@ -32758,25 +32840,85 @@ var init_portal_watermark = __esm({
32758
32840
  }
32759
32841
  });
32760
32842
 
32761
- // src/core/control-persisted-usage.ts
32762
- async function getJson(url) {
32843
+ // src/core/control-api-read.ts
32844
+ function numberFromEnv(name, fallback) {
32845
+ const raw = Number(process.env[name]);
32846
+ return Number.isFinite(raw) && raw > 0 ? raw : fallback;
32847
+ }
32848
+ async function attempt(url) {
32763
32849
  try {
32764
32850
  const response = await fetch(url, {
32765
32851
  method: "GET",
32766
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
32852
+ signal: AbortSignal.timeout(numberFromEnv("HAR_CONTROL_READ_TIMEOUT_MS", DEFAULT_TIMEOUT_MS))
32767
32853
  });
32768
- if (!response.ok) return null;
32769
- return await response.json();
32770
- } catch {
32771
- return null;
32772
- }
32854
+ if (!response.ok) {
32855
+ return {
32856
+ read: { ok: false, error: `HTTP ${response.status}` },
32857
+ retryable: response.status >= 500
32858
+ };
32859
+ }
32860
+ return { read: { ok: true, data: await response.json() }, retryable: false };
32861
+ } catch (err) {
32862
+ return {
32863
+ read: { ok: false, error: err instanceof Error ? err.message : String(err) },
32864
+ retryable: true
32865
+ };
32866
+ }
32867
+ }
32868
+ async function readControlJson(url) {
32869
+ const first = await attempt(url);
32870
+ if (first.read.ok || !first.retryable) return first.read;
32871
+ await new Promise((resolve52) => setTimeout(resolve52, RETRY_DELAY_MS));
32872
+ return (await attempt(url)).read;
32873
+ }
32874
+ async function readControlPages(options) {
32875
+ const limit = numberFromEnv("HAR_CONTROL_READ_PAGE_SIZE", DEFAULT_PAGE_SIZE);
32876
+ const collected = [];
32877
+ let since = options.since;
32878
+ let sinceId = null;
32879
+ for (let page = 0; page < MAX_PAGES; page++) {
32880
+ const query = new URLSearchParams({ limit: String(limit) });
32881
+ if (since) query.set("since", since);
32882
+ if (sinceId) query.set("sinceId", sinceId);
32883
+ const read = await readControlJson(`${options.url}?${query.toString()}`);
32884
+ if (!read.ok) return { ok: false, error: read.error };
32885
+ const rows = options.rows(read.data);
32886
+ collected.push(...rows);
32887
+ if (rows.length < limit) return { ok: true, rows: collected, truncated: false };
32888
+ const last = options.cursor(rows[rows.length - 1]);
32889
+ const nextSince = last.createdAt ?? null;
32890
+ const nextSinceId = last.id ?? null;
32891
+ if (!nextSince || nextSince === since && nextSinceId === sinceId) {
32892
+ return { ok: true, rows: collected, truncated: false };
32893
+ }
32894
+ since = nextSince;
32895
+ sinceId = nextSinceId;
32896
+ }
32897
+ return { ok: true, rows: collected, truncated: true };
32773
32898
  }
32774
32899
  async function resolveControlRepoId(apiUrl, repoPath) {
32775
- const repos = await getJson(`${apiUrl}/api/repos`);
32776
- if (!Array.isArray(repos)) return null;
32900
+ const repos = await readControlJson(`${apiUrl}/api/repos`);
32901
+ if (!repos.ok) return repos;
32902
+ if (!Array.isArray(repos.data)) return { ok: false, error: "unexpected /api/repos payload" };
32777
32903
  const target = path28.resolve(repoPath);
32778
- return repos.find((repo) => path28.resolve(repo.path) === target)?.id ?? null;
32904
+ return {
32905
+ ok: true,
32906
+ data: repos.data.find((repo) => path28.resolve(repo.path) === target)?.id ?? null
32907
+ };
32779
32908
  }
32909
+ var path28, DEFAULT_TIMEOUT_MS, RETRY_DELAY_MS, DEFAULT_PAGE_SIZE, MAX_PAGES;
32910
+ var init_control_api_read = __esm({
32911
+ "src/core/control-api-read.ts"() {
32912
+ "use strict";
32913
+ path28 = __toESM(require("path"));
32914
+ DEFAULT_TIMEOUT_MS = 1e4;
32915
+ RETRY_DELAY_MS = 250;
32916
+ DEFAULT_PAGE_SIZE = 1e3;
32917
+ MAX_PAGES = 20;
32918
+ }
32919
+ });
32920
+
32921
+ // src/core/control-persisted-usage.ts
32780
32922
  function optionalString(value) {
32781
32923
  return value == null ? void 0 : value;
32782
32924
  }
@@ -32802,6 +32944,7 @@ function normalizeUsage(row) {
32802
32944
  costUsd: row.costUsd == null ? null : Number(row.costUsd),
32803
32945
  ...row.modelBreakdown ? { modelBreakdown: row.modelBreakdown } : {},
32804
32946
  sources: toSources(row.sources),
32947
+ harvestVersion: Number(row.harvestVersion ?? 0),
32805
32948
  firstSeenAt: row.firstSeenAt,
32806
32949
  lastSeenAt: row.lastSeenAt
32807
32950
  };
@@ -32829,50 +32972,54 @@ function maxTimestamp(a, b2) {
32829
32972
  return a > b2 ? a : b2;
32830
32973
  }
32831
32974
  async function fetchPersistedPortalTelemetry(repoPath, apiUrl, options) {
32832
- const repoId = await resolveControlRepoId(apiUrl, repoPath);
32833
- if (!repoId) return { usage: [], events: [], maxSyncedAt: null };
32975
+ const empty = { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
32976
+ const repo = await resolveControlRepoId(apiUrl, repoPath);
32977
+ if (!repo.ok) {
32978
+ return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
32979
+ }
32980
+ if (!repo.data) return empty;
32834
32981
  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`)
32982
+ const [usageRead, eventsRead] = await Promise.all([
32983
+ readControlJson(`${apiUrl}/api/repos/${repo.data}/usage`),
32984
+ readControlPages({
32985
+ url: `${apiUrl}/api/repos/${repo.data}/events`,
32986
+ since,
32987
+ rows: (data) => data?.events ?? [],
32988
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
32989
+ })
32838
32990
  ]);
32839
- const usage2 = selectSince(usageResponse?.usage ?? [], since, (row) => row.updatedAt ?? row.lastSeenAt);
32840
- const events = selectSince(eventsResponse?.events ?? [], since, (row) => row.createdAt ?? row.timestamp);
32991
+ const failures = [];
32992
+ const truncated = [];
32993
+ if (!usageRead.ok) failures.push({ channel: "usage", reason: usageRead.error });
32994
+ if (!eventsRead.ok) failures.push({ channel: "events", reason: eventsRead.error });
32995
+ else if (eventsRead.truncated) truncated.push("events");
32996
+ const usage2 = selectSince(
32997
+ usageRead.ok ? usageRead.data?.usage ?? [] : [],
32998
+ since,
32999
+ (row) => row.updatedAt ?? row.lastSeenAt
33000
+ );
33001
+ const events = selectSince(
33002
+ eventsRead.ok ? eventsRead.rows : [],
33003
+ since,
33004
+ (row) => row.createdAt ?? row.timestamp
33005
+ );
32841
33006
  return {
32842
33007
  usage: usage2.selected.map(normalizeUsage),
32843
33008
  events: events.selected.map(normalizeEvent),
32844
- maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt)
33009
+ maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt),
33010
+ failures,
33011
+ truncated
32845
33012
  };
32846
33013
  }
32847
- var path28, FETCH_TIMEOUT_MS;
32848
33014
  var init_control_persisted_usage = __esm({
32849
33015
  "src/core/control-persisted-usage.ts"() {
32850
33016
  "use strict";
32851
- path28 = __toESM(require("path"));
32852
33017
  init_portal_watermark();
32853
- FETCH_TIMEOUT_MS = 3e3;
33018
+ init_control_api_read();
32854
33019
  }
32855
33020
  });
32856
33021
 
32857
33022
  // 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
33023
  function optional(value) {
32877
33024
  return value == null ? void 0 : value;
32878
33025
  }
@@ -32928,24 +33075,44 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
32928
33075
  records: [],
32929
33076
  spans: [],
32930
33077
  recordsMaxSyncedAt: null,
32931
- spansMaxSyncedAt: null
33078
+ spansMaxSyncedAt: null,
33079
+ failures: [],
33080
+ truncated: []
32932
33081
  };
32933
33082
  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
33083
+ const repo = await resolveControlRepoId(apiUrl, repoPath);
33084
+ if (!repo.ok) return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
33085
+ if (!repo.data) return empty;
33086
+ const [trajectoryRead, spansRead] = await Promise.all([
33087
+ request.records ? readControlPages({
33088
+ url: `${apiUrl}/api/repos/${repo.data}/trajectory`,
33089
+ since: request.records.since,
33090
+ rows: (data) => data?.records ?? [],
33091
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
33092
+ }) : null,
33093
+ request.spans ? readControlPages({
33094
+ url: `${apiUrl}/api/repos/${repo.data}/spans`,
33095
+ since: request.spans.since,
33096
+ rows: (data) => data?.spans ?? [],
33097
+ cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
33098
+ }) : null
32941
33099
  ]);
33100
+ const failures = [];
33101
+ const truncated = [];
33102
+ if (trajectoryRead && !trajectoryRead.ok) {
33103
+ failures.push({ channel: "trajectory", reason: trajectoryRead.error });
33104
+ } else if (trajectoryRead?.ok && trajectoryRead.truncated) {
33105
+ truncated.push("trajectory");
33106
+ }
33107
+ if (spansRead && !spansRead.ok) failures.push({ channel: "spans", reason: spansRead.error });
33108
+ else if (spansRead?.ok && spansRead.truncated) truncated.push("spans");
32942
33109
  const trajectory = selectSince(
32943
- trajectoryResponse?.records ?? [],
33110
+ trajectoryRead?.ok ? trajectoryRead.rows : [],
32944
33111
  request.records ? request.records.since : null,
32945
33112
  (row) => row.createdAt ?? null
32946
33113
  );
32947
33114
  const spans = selectSince(
32948
- spansResponse?.spans ?? [],
33115
+ spansRead?.ok ? spansRead.rows : [],
32949
33116
  request.spans ? request.spans.since : null,
32950
33117
  (row) => row.createdAt ?? null
32951
33118
  );
@@ -32956,17 +33123,17 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
32956
33123
  }),
32957
33124
  spans: spans.selected.map(toPortalSpan),
32958
33125
  recordsMaxSyncedAt: trajectory.maxSyncedAt,
32959
- spansMaxSyncedAt: spans.maxSyncedAt
33126
+ spansMaxSyncedAt: spans.maxSyncedAt,
33127
+ failures,
33128
+ truncated
32960
33129
  };
32961
33130
  }
32962
- var path29, FETCH_TIMEOUT_MS2;
32963
33131
  var init_control_persisted_trajectory = __esm({
32964
33132
  "src/core/control-persisted-trajectory.ts"() {
32965
33133
  "use strict";
32966
- path29 = __toESM(require("path"));
32967
33134
  init_schema2();
32968
33135
  init_portal_watermark();
32969
- FETCH_TIMEOUT_MS2 = 5e3;
33136
+ init_control_api_read();
32970
33137
  }
32971
33138
  });
32972
33139
 
@@ -33007,10 +33174,34 @@ function mergeModelBreakdown(a, b2) {
33007
33174
  }
33008
33175
  return out;
33009
33176
  }
33010
- function mergeUsageRow(a, b2) {
33177
+ function replaceCounters(row) {
33178
+ return {
33179
+ tokensInput: num2(row.tokensInput),
33180
+ tokensOutput: num2(row.tokensOutput),
33181
+ tokensCacheRead: num2(row.tokensCacheRead),
33182
+ tokensCacheCreation: num2(row.tokensCacheCreation),
33183
+ tokensTotal: num2(row.tokensTotal),
33184
+ costUsd: row.costUsd ?? null,
33185
+ modelBreakdown: row.modelBreakdown,
33186
+ harvestVersion: usageHarvestVersion(row)
33187
+ };
33188
+ }
33189
+ function maxCounters(a, b2) {
33011
33190
  const costA = a.costUsd ?? null;
33012
33191
  const costB = b2.costUsd ?? null;
33013
- const costUsd = costA != null || costB != null ? Math.max(num2(costA), num2(costB)) : a.costUsd ?? b2.costUsd;
33192
+ return {
33193
+ tokensInput: Math.max(num2(a.tokensInput), num2(b2.tokensInput)),
33194
+ tokensOutput: Math.max(num2(a.tokensOutput), num2(b2.tokensOutput)),
33195
+ tokensCacheRead: Math.max(num2(a.tokensCacheRead), num2(b2.tokensCacheRead)),
33196
+ tokensCacheCreation: Math.max(num2(a.tokensCacheCreation), num2(b2.tokensCacheCreation)),
33197
+ tokensTotal: Math.max(num2(a.tokensTotal), num2(b2.tokensTotal)),
33198
+ costUsd: costA != null || costB != null ? Math.max(num2(costA), num2(costB)) : a.costUsd ?? b2.costUsd,
33199
+ modelBreakdown: mergeModelBreakdown(a.modelBreakdown, b2.modelBreakdown),
33200
+ harvestVersion: mergedHarvestVersion(a, b2)
33201
+ };
33202
+ }
33203
+ function mergeUsageRow(a, b2) {
33204
+ const counters = harvestSupersedes(a, b2) ? replaceCounters(b2) : harvestSupersedes(b2, a) ? replaceCounters(a) : maxCounters(a, b2);
33014
33205
  return {
33015
33206
  ...a,
33016
33207
  ...b2,
@@ -33019,13 +33210,7 @@ function mergeUsageRow(a, b2) {
33019
33210
  suffix: b2.suffix ?? a.suffix,
33020
33211
  workUnitId: b2.workUnitId ?? a.workUnitId,
33021
33212
  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),
33213
+ ...counters,
33029
33214
  sources: [.../* @__PURE__ */ new Set([...a.sources ?? [], ...b2.sources ?? []])],
33030
33215
  firstSeenAt: earlier(a.firstSeenAt, b2.firstSeenAt),
33031
33216
  lastSeenAt: later(a.lastSeenAt, b2.lastSeenAt)
@@ -33052,6 +33237,7 @@ var KEY_SEP;
33052
33237
  var init_portal_usage_merge = __esm({
33053
33238
  "src/core/portal-usage-merge.ts"() {
33054
33239
  "use strict";
33240
+ init_schema2();
33055
33241
  KEY_SEP = "\0";
33056
33242
  }
33057
33243
  });
@@ -33161,13 +33347,13 @@ function describeFetchFailure(url, bodyBytes, err) {
33161
33347
  }
33162
33348
  async function postForResponse(url, headers, payload) {
33163
33349
  let lastErr;
33164
- for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS; attempt++) {
33350
+ for (let attempt2 = 1; attempt2 <= MAX_FETCH_ATTEMPTS; attempt2++) {
33165
33351
  try {
33166
33352
  return await fetch(url, { method: "POST", headers, body: payload });
33167
33353
  } catch (err) {
33168
33354
  lastErr = err;
33169
- if (attempt < MAX_FETCH_ATTEMPTS) {
33170
- await new Promise((resolve53) => setTimeout(resolve53, attempt * 100));
33355
+ if (attempt2 < MAX_FETCH_ATTEMPTS) {
33356
+ await new Promise((resolve52) => setTimeout(resolve52, attempt2 * 100));
33171
33357
  }
33172
33358
  }
33173
33359
  }
@@ -33262,8 +33448,17 @@ function modelsFromBreakdown(breakdown) {
33262
33448
  ...totals && typeof totals === "object" ? totals : {}
33263
33449
  }));
33264
33450
  }
33451
+ function describeReadFailures(repoPath, failures) {
33452
+ const detail = failures.map((f) => `${f.channel} (${f.reason})`).join(", ");
33453
+ 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.`;
33454
+ }
33455
+ function describeTruncatedReads(repoPath, channels) {
33456
+ return `${path29.basename(repoPath)}: ${channels.join(", ")} hit the read page cap \u2014 the remainder syncs on the next run.`;
33457
+ }
33265
33458
  async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, portal) {
33266
- if (!isTelemetryEnabled()) return { usage: [], events: [], maxSyncedAt: null };
33459
+ if (!isTelemetryEnabled()) {
33460
+ return { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
33461
+ }
33267
33462
  try {
33268
33463
  const userEmail = resolvePortalUserEmail(portal);
33269
33464
  const fallbackAgentId = slots.length > 0 ? Math.min(...slots.map((slot) => slot.agentId)) : null;
@@ -33322,9 +33517,23 @@ async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, por
33322
33517
  const events = dedupePortalEvents(harvestedEvents, persisted.events).map(
33323
33518
  (event) => dropNullFields({ ...event })
33324
33519
  );
33325
- return { usage: usage2, events, maxSyncedAt: persisted.maxSyncedAt };
33326
- } catch {
33327
- return { usage: [], events: [], maxSyncedAt: null };
33520
+ return {
33521
+ usage: usage2,
33522
+ events,
33523
+ maxSyncedAt: persisted.maxSyncedAt,
33524
+ failures: persisted.failures,
33525
+ truncated: persisted.truncated
33526
+ };
33527
+ } catch (err) {
33528
+ return {
33529
+ usage: [],
33530
+ events: [],
33531
+ maxSyncedAt: null,
33532
+ failures: [
33533
+ { channel: "telemetry", reason: err instanceof Error ? err.message : String(err) }
33534
+ ],
33535
+ truncated: []
33536
+ };
33328
33537
  }
33329
33538
  }
33330
33539
  async function buildPortalPayload(repoPath, controlApiUrl, since, full = false, portal) {
@@ -33338,16 +33547,16 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
33338
33547
  const attempts = listWorkAttempts(harnessRoot);
33339
33548
  const validationBindings = listValidationBindings(harnessRoot);
33340
33549
  const userEmail = resolvePortalUserEmail(portal);
33341
- const { usage: usage2, events, maxSyncedAt } = await collectPortalTelemetry(
33550
+ const { usage: usage2, events, maxSyncedAt, failures, truncated } = await collectPortalTelemetry(
33342
33551
  repoPath,
33343
33552
  status.slots,
33344
33553
  controlApiUrl,
33345
33554
  since,
33346
33555
  portal
33347
33556
  );
33348
- if (full && isTelemetryEnabled() && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
33557
+ if (full && isTelemetryEnabled() && failures.length === 0 && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
33349
33558
  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\`.`
33559
+ `${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
33560
  );
33352
33561
  }
33353
33562
  const syncBody = {
@@ -33367,7 +33576,7 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
33367
33576
  ...usage2.length > 0 ? { usage: usage2 } : {}
33368
33577
  };
33369
33578
  const runsPayload = userEmail ? runs.map((run2) => ({ ...run2, userEmail })) : runs;
33370
- return { syncBody, runs: runsPayload, events, maxSyncedAt };
33579
+ return { syncBody, runs: runsPayload, events, maxSyncedAt, failures, truncated };
33371
33580
  }
33372
33581
  async function isControlApiReachable(apiUrl = getControlApiUrl()) {
33373
33582
  try {
@@ -33384,7 +33593,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
33384
33593
  const deadline = Date.now() + timeoutMs;
33385
33594
  while (Date.now() < deadline) {
33386
33595
  if (await isControlApiReachable(apiUrl)) return true;
33387
- await new Promise((resolve53) => setTimeout(resolve53, intervalMs));
33596
+ await new Promise((resolve52) => setTimeout(resolve52, intervalMs));
33388
33597
  }
33389
33598
  return false;
33390
33599
  }
@@ -33401,13 +33610,14 @@ async function syncReposWithControl(options) {
33401
33610
  const results = [];
33402
33611
  let synced = 0;
33403
33612
  let failed = 0;
33613
+ let incomplete = 0;
33404
33614
  for (const repoPath of options.repoPaths) {
33405
33615
  const destinationAliases = destinationAliasesForSync(repoPath, options.portalTargets);
33406
33616
  if (destinationAliases.length > 1) {
33407
33617
  const targetResults = [];
33408
33618
  for (const alias of destinationAliases) {
33409
33619
  try {
33410
- await withTimeout(
33620
+ const outcome = await withTimeout(
33411
33621
  syncRepoWithControl({
33412
33622
  repoPath,
33413
33623
  apiUrl,
@@ -33419,7 +33629,11 @@ async function syncReposWithControl(options) {
33419
33629
  EXPLICIT_SYNC_TIMEOUT_MS,
33420
33630
  "control sync"
33421
33631
  );
33422
- targetResults.push({ alias, ok: true });
33632
+ targetResults.push({
33633
+ alias,
33634
+ ok: true,
33635
+ ...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
33636
+ });
33423
33637
  } catch (err) {
33424
33638
  targetResults.push({
33425
33639
  alias,
@@ -33431,11 +33645,12 @@ async function syncReposWithControl(options) {
33431
33645
  const ok = targetResults.every((entry) => entry.ok);
33432
33646
  if (ok) synced++;
33433
33647
  else failed++;
33648
+ if (ok && targetResults.some((entry) => entry.warnings)) incomplete++;
33434
33649
  results.push({ repoPath, ok, targets: targetResults, error: ok ? void 0 : "one or more targets failed" });
33435
33650
  continue;
33436
33651
  }
33437
33652
  try {
33438
- await withTimeout(
33653
+ const outcome = await withTimeout(
33439
33654
  syncRepoWithControl({
33440
33655
  repoPath,
33441
33656
  apiUrl,
@@ -33448,13 +33663,18 @@ async function syncReposWithControl(options) {
33448
33663
  "control sync"
33449
33664
  );
33450
33665
  synced++;
33451
- results.push({ repoPath, ok: true });
33666
+ if (outcome.warnings.length > 0) incomplete++;
33667
+ results.push({
33668
+ repoPath,
33669
+ ok: true,
33670
+ ...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
33671
+ });
33452
33672
  } catch (err) {
33453
33673
  failed++;
33454
33674
  results.push({ repoPath, ok: false, error: err instanceof Error ? err.message : String(err) });
33455
33675
  }
33456
33676
  }
33457
- return { synced, failed, results };
33677
+ return { synced, failed, incomplete, results };
33458
33678
  }
33459
33679
  function destinationAliasesForSync(repoPath, explicit) {
33460
33680
  if (explicit && explicit.length > 0) return explicit;
@@ -33519,7 +33739,7 @@ async function syncRepoWithLocalControl(options) {
33519
33739
  const listResponse = await fetch(`${apiUrl}/api/repos`);
33520
33740
  if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
33521
33741
  const repos = await listResponse.json();
33522
- const existing = repos.find((r) => path30.resolve(r.path) === repoPath);
33742
+ const existing = repos.find((r) => path29.resolve(r.path) === repoPath);
33523
33743
  if (!existing) {
33524
33744
  return;
33525
33745
  }
@@ -33531,7 +33751,7 @@ async function syncRepoWithLocalControl(options) {
33531
33751
  }
33532
33752
  }
33533
33753
  async function syncRepoWithPortal(options, controlApiUrl, portal) {
33534
- if (!isRepoPortalSyncEnabled(options.repoPath)) return;
33754
+ if (!isRepoPortalSyncEnabled(options.repoPath)) return [];
33535
33755
  const { repoPath, dryRun, full } = options;
33536
33756
  const watermarkKey = watermarkKeyForTarget(portal);
33537
33757
  const since = full ? null : readPortalWatermarkForTarget(repoPath, portal);
@@ -33544,7 +33764,7 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
33544
33764
  }
33545
33765
  }
33546
33766
  const runsSince = rewindSince(stored?.lastSyncedAt ?? null);
33547
- const { syncBody, runs, events, maxSyncedAt } = await buildPortalPayload(
33767
+ const { syncBody, runs, events, maxSyncedAt, failures, truncated } = await buildPortalPayload(
33548
33768
  repoPath,
33549
33769
  controlApiUrl,
33550
33770
  since,
@@ -33567,18 +33787,25 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
33567
33787
  for (const batch of chunkBySerializedSize(events, maxSyncBatchBytes())) {
33568
33788
  await postPortal(portal, "/api/otel", { path: repoPath, events: batch }, dryRun);
33569
33789
  }
33570
- if (!dryRun && maxSyncedAt) {
33790
+ if (!dryRun && maxSyncedAt && failures.length === 0) {
33571
33791
  writePortalWatermark(repoPath, watermarkKey, maxSyncedAt);
33572
33792
  }
33573
- await syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full);
33793
+ const warnings = [];
33794
+ if (failures.length > 0) warnings.push(describeReadFailures(repoPath, failures));
33795
+ if (truncated.length > 0) warnings.push(describeTruncatedReads(repoPath, truncated));
33796
+ warnings.push(
33797
+ ...await syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full)
33798
+ );
33799
+ for (const message of warnings) warn(message);
33800
+ return warnings;
33574
33801
  }
33575
33802
  async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full) {
33576
33803
  const wantRecords = isPortalTrajectoryEnabledForTarget(portal);
33577
33804
  const wantSpans = isTelemetryEnabled();
33578
- if (!wantRecords && !wantSpans) return;
33805
+ if (!wantRecords && !wantSpans) return [];
33579
33806
  const recordsTarget = trajectoryWatermarkTarget(portal);
33580
33807
  const spansTarget = spansWatermarkTarget(portal);
33581
- const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
33808
+ const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt, failures, truncated } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
33582
33809
  records: wantRecords ? {
33583
33810
  since: full ? null : readScopedPortalWatermark(
33584
33811
  repoPath,
@@ -33594,10 +33821,11 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
33594
33821
  )
33595
33822
  } : false
33596
33823
  });
33824
+ const failedChannel = (channel) => failures.some((failure) => failure.channel === channel || failure.channel === "repos");
33597
33825
  for (const batch of chunkBySerializedSize(spans, maxSyncBatchBytes())) {
33598
33826
  await postPortal(portal, "/api/otel", { path: repoPath, spans: batch }, dryRun);
33599
33827
  }
33600
- if (!dryRun && spansMaxSyncedAt) {
33828
+ if (!dryRun && spansMaxSyncedAt && !failedChannel("spans")) {
33601
33829
  writePortalWatermark(repoPath, spansTarget, spansMaxSyncedAt);
33602
33830
  }
33603
33831
  let recordsLanded = true;
@@ -33611,14 +33839,18 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
33611
33839
  if (!supported) {
33612
33840
  recordsLanded = false;
33613
33841
  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).`
33842
+ `${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
33843
  );
33616
33844
  break;
33617
33845
  }
33618
33846
  }
33619
- if (!dryRun && recordsLanded && recordsMaxSyncedAt) {
33847
+ if (!dryRun && recordsLanded && recordsMaxSyncedAt && !failedChannel("trajectory")) {
33620
33848
  writePortalWatermark(repoPath, recordsTarget, recordsMaxSyncedAt);
33621
33849
  }
33850
+ return [
33851
+ ...failures.length > 0 ? [describeReadFailures(repoPath, failures)] : [],
33852
+ ...truncated.length > 0 ? [describeTruncatedReads(repoPath, truncated)] : []
33853
+ ];
33622
33854
  }
33623
33855
  async function syncRepoWithControl(options) {
33624
33856
  const repoPath = canonicalizeControlRepoPath(options.repoPath);
@@ -33650,19 +33882,20 @@ async function syncRepoWithControl(options) {
33650
33882
  if (!response.ok) {
33651
33883
  throw new Error(`Cloud sync failed: ${response.status}`);
33652
33884
  }
33653
- return;
33885
+ return { warnings: [] };
33654
33886
  }
33655
33887
  await syncRepoWithLocalControl({ ...options, repoPath, apiUrl });
33656
- if (!isRepoPortalSyncEnabled(repoPath)) return;
33888
+ if (!isRepoPortalSyncEnabled(repoPath)) return { warnings: [] };
33657
33889
  const resolved = resolvePortalTargetsForRepo({
33658
33890
  repoPath,
33659
33891
  explicitTargets: options.portalTargets
33660
33892
  });
33661
- if (!resolved) return;
33893
+ if (!resolved) return { warnings: [] };
33894
+ const warnings = [];
33662
33895
  const failures = [];
33663
33896
  for (const portal of resolved.targets) {
33664
33897
  try {
33665
- await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal);
33898
+ warnings.push(...await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal));
33666
33899
  } catch (err) {
33667
33900
  failures.push({
33668
33901
  alias: portal.alias ?? portal.identityKey,
@@ -33670,7 +33903,7 @@ async function syncRepoWithControl(options) {
33670
33903
  });
33671
33904
  }
33672
33905
  }
33673
- if (failures.length === 0) return;
33906
+ if (failures.length === 0) return { warnings };
33674
33907
  if (failures.length === resolved.targets.length && failures.length === 1) {
33675
33908
  throw new Error(failures[0].error);
33676
33909
  }
@@ -33810,7 +34043,7 @@ async function syncRunWithLocalControl(repoPath, run2, apiUrl) {
33810
34043
  const listResponse = await fetch(`${apiUrl}/api/repos`);
33811
34044
  if (!listResponse.ok) return;
33812
34045
  const repos = await listResponse.json();
33813
- repoId = repos.find((r) => path30.resolve(r.path) === repoPath)?.id;
34046
+ repoId = repos.find((r) => path29.resolve(r.path) === repoPath)?.id;
33814
34047
  }
33815
34048
  if (!repoId) return;
33816
34049
  const runsBody = SyncRunsInputSchema.parse({ runs: [run2] });
@@ -33843,11 +34076,11 @@ async function syncRunWithControlAsync(repoPath, run2) {
33843
34076
  }
33844
34077
  }
33845
34078
  }
33846
- var path30, DEFAULT_MAX_BATCH_BYTES, DEFAULT_SYNC_OVERLAP_MS, MAX_FETCH_ATTEMPTS, SYNC_TIMEOUT_MS, EXPLICIT_SYNC_TIMEOUT_MS;
34079
+ var path29, DEFAULT_MAX_BATCH_BYTES, DEFAULT_SYNC_OVERLAP_MS, MAX_FETCH_ATTEMPTS, SYNC_TIMEOUT_MS, EXPLICIT_SYNC_TIMEOUT_MS;
33847
34080
  var init_control_sync = __esm({
33848
34081
  "src/core/control-sync.ts"() {
33849
34082
  "use strict";
33850
- path30 = __toESM(require("path"));
34083
+ path29 = __toESM(require("path"));
33851
34084
  init_manifest();
33852
34085
  init_stages();
33853
34086
  init_schema2();
@@ -33882,7 +34115,7 @@ var init_control_sync = __esm({
33882
34115
  // src/core/sync-context.ts
33883
34116
  function markDirty(repoPath) {
33884
34117
  if (!repoPath) return;
33885
- dirtyRepos.add(path31.resolve(repoPath));
34118
+ dirtyRepos.add(path30.resolve(repoPath));
33886
34119
  }
33887
34120
  function markAllRegisteredDirty() {
33888
34121
  syncAllRegistered = true;
@@ -33907,11 +34140,11 @@ async function syncDirtyRepos() {
33907
34140
  } catch {
33908
34141
  }
33909
34142
  }
33910
- var path31, dirtyRepos, syncAllRegistered;
34143
+ var path30, dirtyRepos, syncAllRegistered;
33911
34144
  var init_sync_context = __esm({
33912
34145
  "src/core/sync-context.ts"() {
33913
34146
  "use strict";
33914
- path31 = __toESM(require("path"));
34147
+ path30 = __toESM(require("path"));
33915
34148
  dirtyRepos = /* @__PURE__ */ new Set();
33916
34149
  syncAllRegistered = false;
33917
34150
  }
@@ -35009,15 +35242,15 @@ var require_route = __commonJS({
35009
35242
  };
35010
35243
  }
35011
35244
  function wrapConversion(toModel, graph) {
35012
- const path70 = [graph[toModel].parent, toModel];
35245
+ const path69 = [graph[toModel].parent, toModel];
35013
35246
  let fn = conversions[graph[toModel].parent][toModel];
35014
35247
  let cur = graph[toModel].parent;
35015
35248
  while (graph[cur].parent) {
35016
- path70.unshift(graph[cur].parent);
35249
+ path69.unshift(graph[cur].parent);
35017
35250
  fn = link(conversions[graph[cur].parent][cur], fn);
35018
35251
  cur = graph[cur].parent;
35019
35252
  }
35020
- fn.conversion = path70;
35253
+ fn.conversion = path69;
35021
35254
  return fn;
35022
35255
  }
35023
35256
  module2.exports = function(fromModel) {
@@ -41511,7 +41744,7 @@ var require_lib2 = __commonJS({
41511
41744
  return matches;
41512
41745
  };
41513
41746
  exports2.analyse = analyse;
41514
- var detectFile = (filepath, opts = {}) => new Promise((resolve53, reject) => {
41747
+ var detectFile = (filepath, opts = {}) => new Promise((resolve52, reject) => {
41515
41748
  let fd;
41516
41749
  const fs54 = (0, node_1.default)();
41517
41750
  const handler = (err, buffer) => {
@@ -41521,7 +41754,7 @@ var require_lib2 = __commonJS({
41521
41754
  if (err) {
41522
41755
  reject(err);
41523
41756
  } else if (buffer) {
41524
- resolve53((0, exports2.detect)(buffer));
41757
+ resolve52((0, exports2.detect)(buffer));
41525
41758
  } else {
41526
41759
  reject(new Error("No error and no buffer received"));
41527
41760
  }
@@ -46070,7 +46303,7 @@ var require_Observable = __commonJS({
46070
46303
  Observable2.prototype.forEach = function(next, promiseCtor) {
46071
46304
  var _this = this;
46072
46305
  promiseCtor = getPromiseCtor(promiseCtor);
46073
- return new promiseCtor(function(resolve53, reject) {
46306
+ return new promiseCtor(function(resolve52, reject) {
46074
46307
  var subscriber = new Subscriber_1.SafeSubscriber({
46075
46308
  next: function(value) {
46076
46309
  try {
@@ -46081,7 +46314,7 @@ var require_Observable = __commonJS({
46081
46314
  }
46082
46315
  },
46083
46316
  error: reject,
46084
- complete: resolve53
46317
+ complete: resolve52
46085
46318
  });
46086
46319
  _this.subscribe(subscriber);
46087
46320
  });
@@ -46103,14 +46336,14 @@ var require_Observable = __commonJS({
46103
46336
  Observable2.prototype.toPromise = function(promiseCtor) {
46104
46337
  var _this = this;
46105
46338
  promiseCtor = getPromiseCtor(promiseCtor);
46106
- return new promiseCtor(function(resolve53, reject) {
46339
+ return new promiseCtor(function(resolve52, reject) {
46107
46340
  var value;
46108
46341
  _this.subscribe(function(x) {
46109
46342
  return value = x;
46110
46343
  }, function(err) {
46111
46344
  return reject(err);
46112
46345
  }, function() {
46113
- return resolve53(value);
46346
+ return resolve52(value);
46114
46347
  });
46115
46348
  });
46116
46349
  };
@@ -48206,11 +48439,11 @@ var require_innerFrom = __commonJS({
48206
48439
  "use strict";
48207
48440
  var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
48208
48441
  function adopt(value) {
48209
- return value instanceof P2 ? value : new P2(function(resolve53) {
48210
- resolve53(value);
48442
+ return value instanceof P2 ? value : new P2(function(resolve52) {
48443
+ resolve52(value);
48211
48444
  });
48212
48445
  }
48213
- return new (P2 || (P2 = Promise))(function(resolve53, reject) {
48446
+ return new (P2 || (P2 = Promise))(function(resolve52, reject) {
48214
48447
  function fulfilled(value) {
48215
48448
  try {
48216
48449
  step(generator.next(value));
@@ -48226,7 +48459,7 @@ var require_innerFrom = __commonJS({
48226
48459
  }
48227
48460
  }
48228
48461
  function step(result) {
48229
- result.done ? resolve53(result.value) : adopt(result.value).then(fulfilled, rejected);
48462
+ result.done ? resolve52(result.value) : adopt(result.value).then(fulfilled, rejected);
48230
48463
  }
48231
48464
  step((generator = generator.apply(thisArg, _arguments || [])).next());
48232
48465
  });
@@ -48308,14 +48541,14 @@ var require_innerFrom = __commonJS({
48308
48541
  }, i);
48309
48542
  function verb(n) {
48310
48543
  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);
48544
+ return new Promise(function(resolve52, reject) {
48545
+ v2 = o[n](v2), settle(resolve52, reject, v2.done, v2.value);
48313
48546
  });
48314
48547
  };
48315
48548
  }
48316
- function settle(resolve53, reject, d, v2) {
48549
+ function settle(resolve52, reject, d, v2) {
48317
48550
  Promise.resolve(v2).then(function(v3) {
48318
- resolve53({ value: v3, done: d });
48551
+ resolve52({ value: v3, done: d });
48319
48552
  }, reject);
48320
48553
  }
48321
48554
  };
@@ -48934,7 +49167,7 @@ var require_lastValueFrom = __commonJS({
48934
49167
  var EmptyError_1 = require_EmptyError();
48935
49168
  function lastValueFrom2(source, config2) {
48936
49169
  var hasConfig = typeof config2 === "object";
48937
- return new Promise(function(resolve53, reject) {
49170
+ return new Promise(function(resolve52, reject) {
48938
49171
  var _hasValue = false;
48939
49172
  var _value;
48940
49173
  source.subscribe({
@@ -48945,9 +49178,9 @@ var require_lastValueFrom = __commonJS({
48945
49178
  error: reject,
48946
49179
  complete: function() {
48947
49180
  if (_hasValue) {
48948
- resolve53(_value);
49181
+ resolve52(_value);
48949
49182
  } else if (hasConfig) {
48950
- resolve53(config2.defaultValue);
49183
+ resolve52(config2.defaultValue);
48951
49184
  } else {
48952
49185
  reject(new EmptyError_1.EmptyError());
48953
49186
  }
@@ -48969,16 +49202,16 @@ var require_firstValueFrom = __commonJS({
48969
49202
  var Subscriber_1 = require_Subscriber();
48970
49203
  function firstValueFrom(source, config2) {
48971
49204
  var hasConfig = typeof config2 === "object";
48972
- return new Promise(function(resolve53, reject) {
49205
+ return new Promise(function(resolve52, reject) {
48973
49206
  var subscriber = new Subscriber_1.SafeSubscriber({
48974
49207
  next: function(value) {
48975
- resolve53(value);
49208
+ resolve52(value);
48976
49209
  subscriber.unsubscribe();
48977
49210
  },
48978
49211
  error: reject,
48979
49212
  complete: function() {
48980
49213
  if (hasConfig) {
48981
- resolve53(config2.defaultValue);
49214
+ resolve52(config2.defaultValue);
48982
49215
  } else {
48983
49216
  reject(new EmptyError_1.EmptyError());
48984
49217
  }
@@ -54770,14 +55003,14 @@ var require_run_async = __commonJS({
54770
55003
  return function() {
54771
55004
  var args = arguments;
54772
55005
  var originalThis = this;
54773
- var promise = new Promise(function(resolve53, reject) {
55006
+ var promise = new Promise(function(resolve52, reject) {
54774
55007
  var resolved = false;
54775
55008
  const wrappedResolve = function(value) {
54776
55009
  if (resolved) {
54777
55010
  console.warn("Run-async promise already resolved.");
54778
55011
  }
54779
55012
  resolved = true;
54780
- resolve53(value);
55013
+ resolve52(value);
54781
55014
  };
54782
55015
  var rejected = false;
54783
55016
  const wrappedReject = function(value) {
@@ -54885,25 +55118,25 @@ __export(otel_hooks_exports, {
54885
55118
  });
54886
55119
  function getOtelHooksHome() {
54887
55120
  if (process.env.HAR_OTEL_HOOKS_HOME) {
54888
- return path54.resolve(process.env.HAR_OTEL_HOOKS_HOME);
55121
+ return path53.resolve(process.env.HAR_OTEL_HOOKS_HOME);
54889
55122
  }
54890
- return path54.join(os19.homedir(), ".har", "otel-hooks");
55123
+ return path53.join(os19.homedir(), ".har", "otel-hooks");
54891
55124
  }
54892
55125
  function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
54893
- return path54.join(hooksHome, "otel_config.json");
55126
+ return path53.join(hooksHome, "otel_config.json");
54894
55127
  }
54895
55128
  function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
54896
- return path54.join(hooksHome, "run-otel-hook.sh");
55129
+ return path53.join(hooksHome, "run-otel-hook.sh");
54897
55130
  }
54898
55131
  function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
54899
- return path54.join(hooksHome, "state");
55132
+ return path53.join(hooksHome, "state");
54900
55133
  }
54901
55134
  function localOtelHookBin(hooksHome) {
54902
- return path54.join(hooksHome, "node_modules", ".bin", "otel-hook");
55135
+ return path53.join(hooksHome, "node_modules", ".bin", "otel-hook");
54903
55136
  }
54904
55137
  function installedPackageVersion(hooksHome) {
54905
55138
  try {
54906
- const pkgPath = path54.join(
55139
+ const pkgPath = path53.join(
54907
55140
  hooksHome,
54908
55141
  "node_modules",
54909
55142
  "@osfactory",
@@ -55050,9 +55283,9 @@ function uninstallLegacyPythonHooks(hooksHome) {
55050
55283
  }
55051
55284
  function removeLegacyPythonArtifacts(hooksHome) {
55052
55285
  const legacyPaths = [
55053
- path54.join(hooksHome, ".venv"),
55054
- path54.join(hooksHome, "otel_config.yaml"),
55055
- path54.join(hooksHome, "venv")
55286
+ path53.join(hooksHome, ".venv"),
55287
+ path53.join(hooksHome, "otel_config.yaml"),
55288
+ path53.join(hooksHome, "venv")
55056
55289
  ];
55057
55290
  for (const target of legacyPaths) {
55058
55291
  try {
@@ -55198,14 +55431,14 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
55198
55431
  function rewriteKnownHookRegistrations(wrapperPath) {
55199
55432
  const home = os19.homedir();
55200
55433
  const candidates = [
55201
- path54.join(home, ".cursor", "hooks.json"),
55202
- path54.join(home, ".claude", "settings.json"),
55203
- path54.join(home, ".codex", "hooks.json")
55434
+ path53.join(home, ".cursor", "hooks.json"),
55435
+ path53.join(home, ".claude", "settings.json"),
55436
+ path53.join(home, ".codex", "hooks.json")
55204
55437
  ];
55205
55438
  for (const filePath of candidates) {
55206
55439
  try {
55207
55440
  rewriteHookCommandsToWrapper(filePath, wrapperPath);
55208
- if (filePath.endsWith(`${path54.sep}.cursor${path54.sep}hooks.json`)) {
55441
+ if (filePath.endsWith(`${path53.sep}.cursor${path53.sep}hooks.json`)) {
55209
55442
  pruneLegacyCursorHookEvents(filePath, wrapperPath);
55210
55443
  }
55211
55444
  } catch {
@@ -55315,14 +55548,14 @@ function ensureOtelHooks(options) {
55315
55548
  function disableOtelHooksExport() {
55316
55549
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
55317
55550
  }
55318
- var import_child_process14, fs46, os19, path54, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
55551
+ var import_child_process14, fs46, os19, path53, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
55319
55552
  var init_otel_hooks = __esm({
55320
55553
  "src/core/otel-hooks.ts"() {
55321
55554
  "use strict";
55322
55555
  import_child_process14 = require("child_process");
55323
55556
  fs46 = __toESM(require("fs"));
55324
55557
  os19 = __toESM(require("os"));
55325
- path54 = __toESM(require("path"));
55558
+ path53 = __toESM(require("path"));
55326
55559
  init_control_config();
55327
55560
  init_telemetry_config();
55328
55561
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.2.0";
@@ -58297,7 +58530,7 @@ var require_compile = __commonJS({
58297
58530
  const schOrFunc = root.refs[ref];
58298
58531
  if (schOrFunc)
58299
58532
  return schOrFunc;
58300
- let _sch = resolve53.call(this, root, ref);
58533
+ let _sch = resolve52.call(this, root, ref);
58301
58534
  if (_sch === void 0) {
58302
58535
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
58303
58536
  const { schemaId } = this.opts;
@@ -58324,7 +58557,7 @@ var require_compile = __commonJS({
58324
58557
  function sameSchemaEnv(s1, s2) {
58325
58558
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
58326
58559
  }
58327
- function resolve53(root, ref) {
58560
+ function resolve52(root, ref) {
58328
58561
  let sch;
58329
58562
  while (typeof (sch = this.refs[ref]) == "string")
58330
58563
  ref = sch;
@@ -58542,8 +58775,8 @@ var require_utils2 = __commonJS({
58542
58775
  }
58543
58776
  return ind;
58544
58777
  }
58545
- function removeDotSegments(path70) {
58546
- let input = path70;
58778
+ function removeDotSegments(path69) {
58779
+ let input = path69;
58547
58780
  const output = [];
58548
58781
  let nextSlash = -1;
58549
58782
  let len = 0;
@@ -58795,8 +59028,8 @@ var require_schemes = __commonJS({
58795
59028
  wsComponent.secure = void 0;
58796
59029
  }
58797
59030
  if (wsComponent.resourceName) {
58798
- const [path70, query] = wsComponent.resourceName.split("?");
58799
- wsComponent.path = path70 && path70 !== "/" ? path70 : void 0;
59031
+ const [path69, query] = wsComponent.resourceName.split("?");
59032
+ wsComponent.path = path69 && path69 !== "/" ? path69 : void 0;
58800
59033
  wsComponent.query = query;
58801
59034
  wsComponent.resourceName = void 0;
58802
59035
  }
@@ -58955,7 +59188,7 @@ var require_fast_uri = __commonJS({
58955
59188
  }
58956
59189
  return uri;
58957
59190
  }
58958
- function resolve53(baseURI, relativeURI, options) {
59191
+ function resolve52(baseURI, relativeURI, options) {
58959
59192
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
58960
59193
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
58961
59194
  schemelessOptions.skipEscape = true;
@@ -59213,7 +59446,7 @@ var require_fast_uri = __commonJS({
59213
59446
  var fastUri = {
59214
59447
  SCHEMES,
59215
59448
  normalize: normalize3,
59216
- resolve: resolve53,
59449
+ resolve: resolve52,
59217
59450
  resolveComponent,
59218
59451
  equal,
59219
59452
  serialize,
@@ -63478,11 +63711,11 @@ var parser = new YargsParser({
63478
63711
  resolve: import_path2.resolve,
63479
63712
  // TODO: figure out a way to combine ESM and CJS coverage, such that
63480
63713
  // we can exercise all the lines below:
63481
- require: (path70) => {
63714
+ require: (path69) => {
63482
63715
  if (typeof require !== "undefined") {
63483
- return require(path70);
63484
- } else if (path70.match(/\.json$/)) {
63485
- return JSON.parse((0, import_fs2.readFileSync)(path70, "utf8"));
63716
+ return require(path69);
63717
+ } else if (path69.match(/\.json$/)) {
63718
+ return JSON.parse((0, import_fs2.readFileSync)(path69, "utf8"));
63486
63719
  } else {
63487
63720
  throw Error("only .json config files are supported in ESM");
63488
63721
  }
@@ -66008,12 +66241,12 @@ var YargsInstance = class {
66008
66241
  async getCompletion(args, done) {
66009
66242
  argsert("<array> [function]", [args, done], arguments.length);
66010
66243
  if (!done) {
66011
- return new Promise((resolve53, reject) => {
66244
+ return new Promise((resolve52, reject) => {
66012
66245
  __classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
66013
66246
  if (err)
66014
66247
  reject(err);
66015
66248
  else
66016
- resolve53(completions);
66249
+ resolve52(completions);
66017
66250
  });
66018
66251
  });
66019
66252
  } else {
@@ -67058,33 +67291,33 @@ init_telemetry_config();
67058
67291
  init_sync_context();
67059
67292
 
67060
67293
  // src/cli/commands/agents.ts
67061
- var path34 = __toESM(require("path"));
67294
+ var path33 = __toESM(require("path"));
67062
67295
 
67063
67296
  // src/harness/agent-skills.ts
67064
67297
  var fs27 = __toESM(require("fs"));
67065
67298
  var os14 = __toESM(require("os"));
67066
- var path33 = __toESM(require("path"));
67299
+ var path32 = __toESM(require("path"));
67067
67300
  var readline = __toESM(require("readline"));
67068
67301
  init_file_ops();
67069
67302
  init_logging();
67070
67303
 
67071
67304
  // src/utils/paths.ts
67072
67305
  var fs26 = __toESM(require("fs"));
67073
- var path32 = __toESM(require("path"));
67306
+ var path31 = __toESM(require("path"));
67074
67307
  function resolveTemplatesDir() {
67075
67308
  const candidates = [
67076
- path32.join(__dirname, "templates"),
67077
- path32.join(__dirname, "..", "templates"),
67078
- path32.join(__dirname, "..", "harness", "templates")
67309
+ path31.join(__dirname, "templates"),
67310
+ path31.join(__dirname, "..", "templates"),
67311
+ path31.join(__dirname, "..", "harness", "templates")
67079
67312
  ];
67080
67313
  for (const dir of candidates) {
67081
- if (fs26.existsSync(path32.join(dir, "har-boilerplate"))) return dir;
67314
+ if (fs26.existsSync(path31.join(dir, "har-boilerplate"))) return dir;
67082
67315
  }
67083
67316
  throw new Error("Templates directory not found. Run npm run build.");
67084
67317
  }
67085
67318
  function resolveTemplateFile(name) {
67086
67319
  const dir = resolveTemplatesDir();
67087
- const filePath = path32.join(dir, name);
67320
+ const filePath = path31.join(dir, name);
67088
67321
  return fs26.existsSync(filePath) ? filePath : null;
67089
67322
  }
67090
67323
 
@@ -67093,18 +67326,18 @@ init_manifest();
67093
67326
  var AGENT_SKILL_TARGETS = ["claude", "cursor", "codex"];
67094
67327
  var MANAGED_HEADER = "<!-- managed by har \u2014 regenerated by `har agents install` / `har env maintain`; edit at your own risk -->";
67095
67328
  function agentSkillsTemplateDir() {
67096
- const dir = path33.join(resolveTemplatesDir(), "agent-skills");
67329
+ const dir = path32.join(resolveTemplatesDir(), "agent-skills");
67097
67330
  if (!fs27.existsSync(dir)) {
67098
67331
  throw new Error("Agent skills templates not found (templates/agent-skills). Run npm run build.");
67099
67332
  }
67100
67333
  return dir;
67101
67334
  }
67102
67335
  function readSkillsManifest() {
67103
- const manifestPath = path33.join(agentSkillsTemplateDir(), "skills.manifest.json");
67336
+ const manifestPath = path32.join(agentSkillsTemplateDir(), "skills.manifest.json");
67104
67337
  return JSON.parse(fs27.readFileSync(manifestPath, "utf8"));
67105
67338
  }
67106
67339
  function readSkillBody(entry) {
67107
- return fs27.readFileSync(path33.join(agentSkillsTemplateDir(), entry.body), "utf8");
67340
+ return fs27.readFileSync(path32.join(agentSkillsTemplateDir(), entry.body), "utf8");
67108
67341
  }
67109
67342
  function renderYamlValue(value) {
67110
67343
  if (typeof value === "string") return JSON.stringify(value);
@@ -67136,7 +67369,7 @@ function renderSkillFiles(agents) {
67136
67369
  agent: "claude",
67137
67370
  skill: entry.id,
67138
67371
  scope: "repo",
67139
- relPath: path33.join(".claude", "skills", entry.id, "SKILL.md"),
67372
+ relPath: path32.join(".claude", "skills", entry.id, "SKILL.md"),
67140
67373
  content: renderClaudeSkill(entry, body)
67141
67374
  });
67142
67375
  }
@@ -67145,7 +67378,7 @@ function renderSkillFiles(agents) {
67145
67378
  agent: "cursor",
67146
67379
  skill: entry.id,
67147
67380
  scope: "repo",
67148
- relPath: path33.join(".cursor", "commands", `${entry.id}.md`),
67381
+ relPath: path32.join(".cursor", "commands", `${entry.id}.md`),
67149
67382
  content: renderPlainSkill(body)
67150
67383
  });
67151
67384
  }
@@ -67154,7 +67387,7 @@ function renderSkillFiles(agents) {
67154
67387
  agent: "codex",
67155
67388
  skill: entry.id,
67156
67389
  scope: "global",
67157
- relPath: path33.posix.join("~", ".codex", "prompts", `${entry.codex.promptName}.md`),
67390
+ relPath: path32.posix.join("~", ".codex", "prompts", `${entry.codex.promptName}.md`),
67158
67391
  content: renderPlainSkill(body)
67159
67392
  });
67160
67393
  }
@@ -67163,9 +67396,9 @@ function renderSkillFiles(agents) {
67163
67396
  }
67164
67397
  function resolveScaffoldPath(repoPath, file) {
67165
67398
  if (file.scope === "global") {
67166
- return path33.join(os14.homedir(), file.relPath.replace(/^~\//, ""));
67399
+ return path32.join(os14.homedir(), file.relPath.replace(/^~\//, ""));
67167
67400
  }
67168
- return path33.join(repoPath, file.relPath);
67401
+ return path32.join(repoPath, file.relPath);
67169
67402
  }
67170
67403
  function isHarManaged(filePath) {
67171
67404
  return fs27.readFileSync(filePath, "utf8").includes(MANAGED_HEADER);
@@ -67217,7 +67450,7 @@ function removeAgentSkills(repoPath, agents) {
67217
67450
  }
67218
67451
  fs27.rmSync(destPath);
67219
67452
  removed.push(file.relPath);
67220
- const parent = path33.dirname(destPath);
67453
+ const parent = path32.dirname(destPath);
67221
67454
  if (fs27.existsSync(parent) && fs27.readdirSync(parent).length === 0) {
67222
67455
  fs27.rmdirSync(parent);
67223
67456
  }
@@ -67238,9 +67471,9 @@ function detectAgentTargets(repoPath) {
67238
67471
  const manifest = readManifest(repoPath);
67239
67472
  const scaffolded = new Set((manifest?.scaffoldedAgentFiles ?? []).map((entry) => entry.agent));
67240
67473
  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");
67474
+ if (fs27.existsSync(path32.join(repoPath, ".claude"))) detected.add("claude");
67475
+ if (fs27.existsSync(path32.join(repoPath, ".cursor"))) detected.add("cursor");
67476
+ if (fs27.existsSync(path32.join(os14.homedir(), ".codex"))) detected.add("codex");
67244
67477
  return AGENT_SKILL_TARGETS.filter((agent) => detected.has(agent));
67245
67478
  }
67246
67479
  function parseAgentTargets(raw) {
@@ -67284,16 +67517,16 @@ async function handleAgentSkills(options) {
67284
67517
  }
67285
67518
  async function askYesNo(question) {
67286
67519
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
67287
- return new Promise((resolve53) => {
67520
+ return new Promise((resolve52) => {
67288
67521
  process.stderr.write(`${question} `);
67289
67522
  rl.once("line", (answer) => {
67290
67523
  rl.close();
67291
67524
  const trimmed = answer.trim();
67292
67525
  if (trimmed === "") {
67293
- resolve53(true);
67526
+ resolve52(true);
67294
67527
  return;
67295
67528
  }
67296
- resolve53(/^y(es)?$/i.test(trimmed));
67529
+ resolve52(/^y(es)?$/i.test(trimmed));
67297
67530
  });
67298
67531
  });
67299
67532
  }
@@ -67327,7 +67560,7 @@ var agentsCommand = {
67327
67560
  }
67328
67561
  };
67329
67562
  function handleInstall(argv) {
67330
- const repoPath = path34.resolve(argv.repo);
67563
+ const repoPath = path33.resolve(argv.repo);
67331
67564
  header("har agents install");
67332
67565
  try {
67333
67566
  const targets = resolveTargets(argv, repoPath);
@@ -67353,7 +67586,7 @@ function handleInstall(argv) {
67353
67586
  }
67354
67587
  }
67355
67588
  function handleRemove(argv) {
67356
- const repoPath = path34.resolve(argv.repo);
67589
+ const repoPath = path33.resolve(argv.repo);
67357
67590
  header("har agents remove");
67358
67591
  try {
67359
67592
  const targets = resolveTargets(argv, repoPath);
@@ -67373,7 +67606,7 @@ function handleRemove(argv) {
67373
67606
  }
67374
67607
 
67375
67608
  // src/cli/commands/env.ts
67376
- var path58 = __toESM(require("path"));
67609
+ var path57 = __toESM(require("path"));
67377
67610
 
67378
67611
  // src/cli/finish-command.ts
67379
67612
  init_sync_context();
@@ -67384,23 +67617,23 @@ async function finishCommand(code) {
67384
67617
 
67385
67618
  // src/core/harness.ts
67386
67619
  var fs42 = __toESM(require("fs"));
67387
- var path49 = __toESM(require("path"));
67620
+ var path48 = __toESM(require("path"));
67388
67621
 
67389
67622
  // src/harness/generator.ts
67390
67623
  var fs32 = __toESM(require("fs"));
67391
- var path39 = __toESM(require("path"));
67624
+ var path38 = __toESM(require("path"));
67392
67625
  init_file_ops();
67393
67626
  init_logging();
67394
67627
 
67395
67628
  // src/core/gitignore.ts
67396
67629
  var fs28 = __toESM(require("fs"));
67397
- var path35 = __toESM(require("path"));
67630
+ var path34 = __toESM(require("path"));
67398
67631
  var HARNESS_ROOT_GITIGNORE_PATTERNS = [
67399
67632
  ".env.agent.*",
67400
67633
  "ecosystem.agent.*.config.cjs"
67401
67634
  ];
67402
67635
  function ensureRootGitignorePatterns(checkoutDir) {
67403
- const gitignorePath = path35.join(checkoutDir, ".gitignore");
67636
+ const gitignorePath = path34.join(checkoutDir, ".gitignore");
67404
67637
  const content = fs28.existsSync(gitignorePath) ? fs28.readFileSync(gitignorePath, "utf8") : "";
67405
67638
  const lines = content.split("\n").map((line) => line.trim());
67406
67639
  const missing = HARNESS_ROOT_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
@@ -67415,7 +67648,7 @@ function ensureRootGitignorePatterns(checkoutDir) {
67415
67648
 
67416
67649
  // src/harness/gitignore-template.ts
67417
67650
  var fs29 = __toESM(require("fs"));
67418
- var path36 = __toESM(require("path"));
67651
+ var path35 = __toESM(require("path"));
67419
67652
  var HARNESS_GITIGNORE_TEMPLATE = "gitignore.template";
67420
67653
  var HARNESS_GITIGNORE_FILE = ".gitignore";
67421
67654
  function harnessFileForTemplate(templateFile) {
@@ -67425,16 +67658,16 @@ function templateFileForHarness(harnessFile) {
67425
67658
  return harnessFile === HARNESS_GITIGNORE_FILE ? HARNESS_GITIGNORE_TEMPLATE : harnessFile;
67426
67659
  }
67427
67660
  function resolveGitignoreTemplateSource(boilerplateDir) {
67428
- const primary = path36.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
67661
+ const primary = path35.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
67429
67662
  if (fs29.existsSync(primary)) return primary;
67430
- const legacy = path36.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
67663
+ const legacy = path35.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
67431
67664
  if (fs29.existsSync(legacy)) return legacy;
67432
67665
  return null;
67433
67666
  }
67434
67667
  function writeHarnessGitignore(harnessDir, boilerplateDir) {
67435
67668
  const src = resolveGitignoreTemplateSource(boilerplateDir);
67436
67669
  if (!src) return;
67437
- fs29.writeFileSync(path36.join(harnessDir, HARNESS_GITIGNORE_FILE), fs29.readFileSync(src, "utf8"));
67670
+ fs29.writeFileSync(path35.join(harnessDir, HARNESS_GITIGNORE_FILE), fs29.readFileSync(src, "utf8"));
67438
67671
  }
67439
67672
  function isExpectedHarnessOnlyFile(harnessFile, templateFiles) {
67440
67673
  return harnessFile === HARNESS_GITIGNORE_FILE && templateFiles.includes(HARNESS_GITIGNORE_TEMPLATE);
@@ -67445,7 +67678,7 @@ init_manifest();
67445
67678
 
67446
67679
  // src/harness/plugin-ledger.ts
67447
67680
  var fs30 = __toESM(require("fs"));
67448
- var path37 = __toESM(require("path"));
67681
+ var path36 = __toESM(require("path"));
67449
67682
  init_zod();
67450
67683
  init_file_ops();
67451
67684
  init_manifest();
@@ -67468,7 +67701,7 @@ var PluginLedgerSchema = external_exports.object({
67468
67701
  plugins: external_exports.array(PluginLedgerEntrySchema).default([])
67469
67702
  });
67470
67703
  function getPluginLedgerPath(repoPath) {
67471
- return path37.join(path37.resolve(repoPath), DEFAULT_HAR_DIR, "plugins.json");
67704
+ return path36.join(path36.resolve(repoPath), DEFAULT_HAR_DIR, "plugins.json");
67472
67705
  }
67473
67706
  function readPluginLedger(repoPath) {
67474
67707
  const ledgerPath = getPluginLedgerPath(repoPath);
@@ -67483,7 +67716,7 @@ function readPluginLedger(repoPath) {
67483
67716
  }
67484
67717
  function writePluginLedger(repoPath, ledger) {
67485
67718
  const ledgerPath = getPluginLedgerPath(repoPath);
67486
- const harnessDir = path37.dirname(ledgerPath);
67719
+ const harnessDir = path36.dirname(ledgerPath);
67487
67720
  if (!fs30.existsSync(harnessDir)) {
67488
67721
  fs30.mkdirSync(harnessDir, { recursive: true });
67489
67722
  }
@@ -67521,7 +67754,7 @@ function ensurePluginLedgerScaffold(repoPath, options) {
67521
67754
 
67522
67755
  // src/harness/profiles.ts
67523
67756
  var fs31 = __toESM(require("fs"));
67524
- var path38 = __toESM(require("path"));
67757
+ var path37 = __toESM(require("path"));
67525
67758
  init_zod();
67526
67759
  var HARNESS_PROFILES = ["default", "cli", "ios"];
67527
67760
  var ProfileBundleRefSchema = external_exports.object({
@@ -67574,7 +67807,7 @@ var PROFILE_DIRS = {
67574
67807
  };
67575
67808
  function readProfileManifest(profile) {
67576
67809
  const templates = resolveTemplatesDir();
67577
- const manifestPath = path38.join(templates, "profiles", profile, "profile.manifest.json");
67810
+ const manifestPath = path37.join(templates, "profiles", profile, "profile.manifest.json");
67578
67811
  if (fs31.existsSync(manifestPath)) {
67579
67812
  const parsed = ProfileManifestSchema.safeParse(
67580
67813
  JSON.parse(fs31.readFileSync(manifestPath, "utf8"))
@@ -67590,7 +67823,7 @@ function readProfileManifest(profile) {
67590
67823
  return PROFILE_COMPOSITIONS[profile];
67591
67824
  }
67592
67825
  function resolveProfileBundleDir(bundle) {
67593
- const dir = path38.join(resolveTemplatesDir(), bundle.path);
67826
+ const dir = path37.join(resolveTemplatesDir(), bundle.path);
67594
67827
  if (!fs31.existsSync(dir)) {
67595
67828
  throw new Error(`Profile bundle not found: ${bundle.id} (${bundle.path}). Run npm run build.`);
67596
67829
  }
@@ -67606,20 +67839,20 @@ var CLI_PRUNE_FILES = [
67606
67839
  ];
67607
67840
  function pruneCliProfile(harnessDir) {
67608
67841
  for (const file of CLI_PRUNE_FILES) {
67609
- const filePath = path39.join(harnessDir, file);
67842
+ const filePath = path38.join(harnessDir, file);
67610
67843
  if (fs32.existsSync(filePath)) {
67611
67844
  fs32.unlinkSync(filePath);
67612
67845
  }
67613
67846
  }
67614
67847
  }
67615
67848
  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, "_");
67849
+ const harnessDir = path38.join(repoPath, DEFAULT_HAR_DIR);
67850
+ const projectName = path38.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
67618
67851
  const profile = options.profile ?? "default";
67619
67852
  const profileManifest = readProfileManifest(profile);
67620
67853
  const bundleIds = profileManifest.bundles.map((b2) => b2.id);
67621
67854
  const primaryOverlay = PROFILE_DIRS[profile];
67622
- const boilerplateDir = path39.join(resolveTemplatesDir(), primaryOverlay);
67855
+ const boilerplateDir = path38.join(resolveTemplatesDir(), primaryOverlay);
67623
67856
  if (fs32.existsSync(harnessDir) && !options.force) {
67624
67857
  throw new Error(
67625
67858
  '.har/ already exists. Use --force to overwrite or run "har env maintain" to update in place.'
@@ -67641,7 +67874,7 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
67641
67874
  pruneCliProfile(harnessDir);
67642
67875
  }
67643
67876
  syncAgentSlotsToHarnessEnv(repoPath);
67644
- const harnessEnvPath = path39.join(harnessDir, "harness.env");
67877
+ const harnessEnvPath = path38.join(harnessDir, "harness.env");
67645
67878
  if (fs32.existsSync(harnessEnvPath)) {
67646
67879
  let content = fs32.readFileSync(harnessEnvPath, "utf8");
67647
67880
  content = content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
@@ -67670,7 +67903,7 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
67670
67903
 
67671
67904
  // src/harness/agent-md.ts
67672
67905
  var fs34 = __toESM(require("fs"));
67673
- var path42 = __toESM(require("path"));
67906
+ var path41 = __toESM(require("path"));
67674
67907
  init_file_ops();
67675
67908
  init_logging();
67676
67909
  init_manifest();
@@ -67678,7 +67911,7 @@ init_manifest();
67678
67911
  // src/harness/instruction-files.ts
67679
67912
  var fs33 = __toESM(require("fs"));
67680
67913
  var os16 = __toESM(require("os"));
67681
- var path41 = __toESM(require("path"));
67914
+ var path40 = __toESM(require("path"));
67682
67915
 
67683
67916
  // node_modules/@inquirer/core/dist/esm/lib/key.js
67684
67917
  var isUpKey = (key, keybindings = []) => (
@@ -68712,13 +68945,13 @@ var PromisePolyfill = class extends Promise {
68712
68945
  // Available starting from Node 22
68713
68946
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
68714
68947
  static withResolver() {
68715
- let resolve53;
68948
+ let resolve52;
68716
68949
  let reject;
68717
68950
  const promise = new Promise((res, rej) => {
68718
- resolve53 = res;
68951
+ resolve52 = res;
68719
68952
  reject = rej;
68720
68953
  });
68721
- return { promise, resolve: resolve53, reject };
68954
+ return { promise, resolve: resolve52, reject };
68722
68955
  }
68723
68956
  };
68724
68957
 
@@ -68752,7 +68985,7 @@ function createPrompt(view) {
68752
68985
  output
68753
68986
  });
68754
68987
  const screen = new ScreenManager(rl);
68755
- const { promise, resolve: resolve53, reject } = PromisePolyfill.withResolver();
68988
+ const { promise, resolve: resolve52, reject } = PromisePolyfill.withResolver();
68756
68989
  const cancel = () => reject(new CancelPromptError());
68757
68990
  if (signal) {
68758
68991
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -68779,7 +69012,7 @@ function createPrompt(view) {
68779
69012
  cycle(() => {
68780
69013
  try {
68781
69014
  const nextView = view(config2, (value) => {
68782
- setImmediate(() => resolve53(value));
69015
+ setImmediate(() => resolve52(value));
68783
69016
  });
68784
69017
  if (nextView === void 0) {
68785
69018
  const callerFilename = callSites[1]?.getFileName();
@@ -70088,9 +70321,9 @@ var import_rxjs = __toESM(require_cjs(), 1);
70088
70321
  var import_run_async = __toESM(require_run_async(), 1);
70089
70322
  var import_mute_stream2 = __toESM(require_lib(), 1);
70090
70323
  var _ = {
70091
- set: (obj, path70 = "", value) => {
70324
+ set: (obj, path69 = "", value) => {
70092
70325
  let pointer = obj;
70093
- path70.split(".").forEach((key, index, arr) => {
70326
+ path69.split(".").forEach((key, index, arr) => {
70094
70327
  if (key === "__proto__" || key === "constructor")
70095
70328
  return;
70096
70329
  if (index === arr.length - 1) {
@@ -70101,8 +70334,8 @@ var _ = {
70101
70334
  pointer = pointer[key];
70102
70335
  });
70103
70336
  },
70104
- get: (obj, path70 = "", defaultValue) => {
70105
- const travel = (regexp) => String.prototype.split.call(path70, regexp).filter(Boolean).reduce(
70337
+ get: (obj, path69 = "", defaultValue) => {
70338
+ const travel = (regexp) => String.prototype.split.call(path69, regexp).filter(Boolean).reduce(
70106
70339
  // @ts-expect-error implicit any on res[key]
70107
70340
  (res, key) => res == null ? res : res[key],
70108
70341
  obj
@@ -70220,7 +70453,7 @@ var PromptsRunner = class {
70220
70453
  throw new Error(`Prompt for type ${question.type} not found`);
70221
70454
  }
70222
70455
  let cleanupSignal;
70223
- const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve53, reject) => {
70456
+ const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve52, reject) => {
70224
70457
  const { signal: signal2 } = opt;
70225
70458
  if (signal2.aborted) {
70226
70459
  reject(new AbortPromptError({ cause: signal2.reason }));
@@ -70257,7 +70490,7 @@ var PromptsRunner = class {
70257
70490
  signal2.removeEventListener("abort", abort);
70258
70491
  cleanupSignal = void 0;
70259
70492
  };
70260
- activePrompt.run().then(resolve53, reject).finally(cleanup);
70493
+ activePrompt.run().then(resolve52, reject).finally(cleanup);
70261
70494
  }) : prompt2;
70262
70495
  let cleanupModuleSignal;
70263
70496
  const { signal: moduleSignal } = this.opt;
@@ -70427,12 +70660,12 @@ function outsideContentShrinkMessage(beforeLines, afterLines) {
70427
70660
  }
70428
70661
  function detectInstructionFiles(repoPath) {
70429
70662
  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"))
70663
+ agentsMd: fs33.existsSync(path40.join(repoPath, AGENTS_MD)),
70664
+ agentMd: fs33.existsSync(path40.join(repoPath, LEGACY_AGENT_MD)),
70665
+ claudeMd: fs33.existsSync(path40.join(repoPath, CLAUDE_MD)),
70666
+ cursorDir: fs33.existsSync(path40.join(repoPath, ".cursor")),
70667
+ claudeDir: fs33.existsSync(path40.join(repoPath, ".claude")),
70668
+ codexHome: fs33.existsSync(path40.join(os16.homedir(), ".codex"))
70436
70669
  };
70437
70670
  }
70438
70671
  function formatDetectionReport(detection) {
@@ -70533,7 +70766,7 @@ function mergeAgentsMdContent(existing, incoming) {
70533
70766
  return content;
70534
70767
  }
70535
70768
  function upsertAgentsMdHarSection(repoPath, options = {}) {
70536
- const dest = path41.join(repoPath, AGENTS_MD);
70769
+ const dest = path40.join(repoPath, AGENTS_MD);
70537
70770
  const section = loadHarAgentsSectionFromTemplate();
70538
70771
  if (!fs33.existsSync(dest)) {
70539
70772
  writeFileSafe(dest, loadAgentsMdTemplate());
@@ -70564,8 +70797,8 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
70564
70797
  return action;
70565
70798
  }
70566
70799
  function migrateLegacyAgentMd(repoPath) {
70567
- const legacyPath = path41.join(repoPath, LEGACY_AGENT_MD);
70568
- const agentsPath = path41.join(repoPath, AGENTS_MD);
70800
+ const legacyPath = path40.join(repoPath, LEGACY_AGENT_MD);
70801
+ const agentsPath = path40.join(repoPath, AGENTS_MD);
70569
70802
  if (!fs33.existsSync(legacyPath)) return false;
70570
70803
  const legacy = fs33.readFileSync(legacyPath, "utf8");
70571
70804
  if (!fs33.existsSync(agentsPath)) {
@@ -70606,8 +70839,8 @@ This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
70606
70839
  [\`.har/README.md\`](./.har/README.md) before making changes.
70607
70840
  ${CLAUDE_HAR_SECTION_END}`;
70608
70841
  function ensureClaudeMdPointer(repoPath, options = {}) {
70609
- const dest = path41.join(repoPath, CLAUDE_MD);
70610
- const projectName = path41.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
70842
+ const dest = path40.join(repoPath, CLAUDE_MD);
70843
+ const projectName = path40.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
70611
70844
  const thin = loadClaudeMdTemplate(projectName);
70612
70845
  if (!fs33.existsSync(dest)) {
70613
70846
  writeFileSafe(dest, thin);
@@ -70762,10 +70995,10 @@ var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
70762
70995
  var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
70763
70996
  function readAgentMdProposal(repoPath) {
70764
70997
  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);
70998
+ const proposalPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL);
70999
+ const metaPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL_META);
71000
+ const legacyProposalPath = path41.join(harnessDir, AGENT_MD_PROPOSAL);
71001
+ const legacyMetaPath = path41.join(harnessDir, AGENT_MD_PROPOSAL_META);
70769
71002
  const resolvedProposal = fs34.existsSync(proposalPath) ? proposalPath : fs34.existsSync(legacyProposalPath) ? legacyProposalPath : null;
70770
71003
  if (!resolvedProposal) return null;
70771
71004
  const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
@@ -70791,7 +71024,7 @@ function clearAgentMdProposal(repoPath) {
70791
71024
  AGENT_MD_PROPOSAL,
70792
71025
  AGENT_MD_PROPOSAL_META
70793
71026
  ]) {
70794
- const p = path42.join(harnessDir, file);
71027
+ const p = path41.join(harnessDir, file);
70795
71028
  if (fs34.existsSync(p)) fs34.unlinkSync(p);
70796
71029
  }
70797
71030
  }
@@ -70805,7 +71038,7 @@ function wouldProposalShrinkExisting(existing, proposal) {
70805
71038
  function applyAgentMdProposalMerge(repoPath, options = {}) {
70806
71039
  const proposal = readAgentMdProposal(repoPath);
70807
71040
  if (!proposal) return false;
70808
- const agentsMdPath = path42.join(repoPath, AGENTS_MD);
71041
+ const agentsMdPath = path41.join(repoPath, AGENTS_MD);
70809
71042
  if (fs34.existsSync(agentsMdPath)) {
70810
71043
  const existing = fs34.readFileSync(agentsMdPath, "utf8");
70811
71044
  if (wouldProposalShrinkExisting(existing, proposal.content)) {
@@ -70831,7 +71064,7 @@ function finalizeAgentsMdInstructionFiles(repoPath) {
70831
71064
 
70832
71065
  // src/harness/validator.ts
70833
71066
  var fs35 = __toESM(require("fs"));
70834
- var path43 = __toESM(require("path"));
71067
+ var path42 = __toESM(require("path"));
70835
71068
  init_shell();
70836
71069
  init_manifest();
70837
71070
  init_stages();
@@ -70893,13 +71126,13 @@ function validateHarness(repoPath) {
70893
71126
  };
70894
71127
  }
70895
71128
  for (const file of getRequiredFiles(repoPath)) {
70896
- const filePath = path43.join(harnessDir, file);
71129
+ const filePath = path42.join(harnessDir, file);
70897
71130
  if (!fs35.existsSync(filePath)) {
70898
71131
  issues.push({ file, message: "Required file missing", severity: "error" });
70899
71132
  }
70900
71133
  }
70901
71134
  for (const script of SHELL_SCRIPTS) {
70902
- const scriptPath = path43.join(harnessDir, script);
71135
+ const scriptPath = path42.join(harnessDir, script);
70903
71136
  if (!fs35.existsSync(scriptPath)) continue;
70904
71137
  const stat = fs35.statSync(scriptPath);
70905
71138
  if (!(stat.mode & 73)) {
@@ -70916,7 +71149,7 @@ function validateHarness(repoPath) {
70916
71149
  }
70917
71150
  const manifest = readManifest(repoPath);
70918
71151
  const profile = manifest?.profile ?? "default";
70919
- const ecosystemPath = path43.join(harnessDir, "ecosystem.agent.template.cjs");
71152
+ const ecosystemPath = path42.join(harnessDir, "ecosystem.agent.template.cjs");
70920
71153
  if (profile !== "cli" && fs35.existsSync(ecosystemPath)) {
70921
71154
  const content = fs35.readFileSync(ecosystemPath, "utf8");
70922
71155
  if (!content.includes("module.exports")) {
@@ -70927,7 +71160,7 @@ function validateHarness(repoPath) {
70927
71160
  });
70928
71161
  }
70929
71162
  }
70930
- const harnessEnvPath = path43.join(harnessDir, "harness.env");
71163
+ const harnessEnvPath = path42.join(harnessDir, "harness.env");
70931
71164
  if (fs35.existsSync(harnessEnvPath)) {
70932
71165
  const content = fs35.readFileSync(harnessEnvPath, "utf8");
70933
71166
  if (content.includes("TODO: set migrate command")) {
@@ -70937,14 +71170,14 @@ function validateHarness(repoPath) {
70937
71170
  issues.push({ file: "harness.env", message: "Seed command still has TODO", severity: "warning" });
70938
71171
  }
70939
71172
  }
70940
- const verifyPath = path43.join(harnessDir, "verify.sh");
71173
+ const verifyPath = path42.join(harnessDir, "verify.sh");
70941
71174
  if (fs35.existsSync(verifyPath)) {
70942
71175
  const content = fs35.readFileSync(verifyPath, "utf8");
70943
71176
  if (content.includes("echo 'TODO:")) {
70944
71177
  issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
70945
71178
  }
70946
71179
  }
70947
- const stagesPath = path43.join(harnessDir, "stages.json");
71180
+ const stagesPath = path42.join(harnessDir, "stages.json");
70948
71181
  if (fs35.existsSync(stagesPath)) {
70949
71182
  try {
70950
71183
  JSON.parse(fs35.readFileSync(stagesPath, "utf8"));
@@ -70962,7 +71195,7 @@ function validateHarness(repoPath) {
70962
71195
  } else {
70963
71196
  issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
70964
71197
  }
70965
- const readmePath = path43.join(harnessDir, "README.md");
71198
+ const readmePath = path42.join(harnessDir, "README.md");
70966
71199
  if (fs35.existsSync(readmePath)) {
70967
71200
  const content = fs35.readFileSync(readmePath, "utf8");
70968
71201
  if (!content.includes(".har")) {
@@ -70978,7 +71211,7 @@ function validateHarness(repoPath) {
70978
71211
  async function smokeTestHarness(repoPath) {
70979
71212
  const harnessDir = getHarnessDir(repoPath);
70980
71213
  const issues = [];
70981
- const setupScript = path43.join(harnessDir, "setup-infra.sh");
71214
+ const setupScript = path42.join(harnessDir, "setup-infra.sh");
70982
71215
  if (fs35.existsSync(setupScript)) {
70983
71216
  const result = run(`bash "${setupScript}"`, { cwd: repoPath });
70984
71217
  if (result.code !== 0) {
@@ -70995,7 +71228,7 @@ async function smokeTestHarness(repoPath) {
70995
71228
 
70996
71229
  // src/harness/drift.ts
70997
71230
  var fs36 = __toESM(require("fs"));
70998
- var path44 = __toESM(require("path"));
71231
+ var path43 = __toESM(require("path"));
70999
71232
  init_env();
71000
71233
  init_manifest();
71001
71234
  init_stages();
@@ -71065,12 +71298,12 @@ function listBoilerplateFiles(boilerplateDir) {
71065
71298
  return fs36.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
71066
71299
  }
71067
71300
  function compareHarnessToTemplate(repoPath) {
71068
- const resolved = path44.resolve(repoPath);
71301
+ const resolved = path43.resolve(repoPath);
71069
71302
  const manifest = readManifest(resolved);
71070
71303
  const profile = manifest?.profile ?? "default";
71071
71304
  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]);
71305
+ const projectName = path43.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
71306
+ const boilerplateDir = path43.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
71074
71307
  const templateFiles = listBoilerplateFiles(boilerplateDir);
71075
71308
  const missing = [];
71076
71309
  const checksumMismatch = [];
@@ -71078,8 +71311,8 @@ function compareHarnessToTemplate(repoPath) {
71078
71311
  const unchanged = [];
71079
71312
  for (const file of templateFiles) {
71080
71313
  const harnessFile = harnessFileForTemplate(file);
71081
- const templatePath = path44.join(boilerplateDir, file);
71082
- const harnessPath = path44.join(harnessDir, harnessFile);
71314
+ const templatePath = path43.join(boilerplateDir, file);
71315
+ const harnessPath = path43.join(harnessDir, harnessFile);
71083
71316
  let templateContent = fs36.readFileSync(templatePath, "utf8");
71084
71317
  if (file === "harness.env") {
71085
71318
  templateContent = substituteProjectName(templateContent, projectName);
@@ -71098,7 +71331,7 @@ function compareHarnessToTemplate(repoPath) {
71098
71331
  }
71099
71332
  if (fs36.existsSync(harnessDir)) {
71100
71333
  for (const file of fs36.readdirSync(harnessDir)) {
71101
- const full = path44.join(harnessDir, file);
71334
+ const full = path43.join(harnessDir, file);
71102
71335
  if (!fs36.statSync(full).isFile()) continue;
71103
71336
  if (file === "manifest.json" || file === "plugins.json" || file.startsWith("ADAPT-PROMPT")) {
71104
71337
  continue;
@@ -71128,19 +71361,19 @@ function compareHarnessToTemplate(repoPath) {
71128
71361
  // src/harness/maintain-bundle.ts
71129
71362
  var fs41 = __toESM(require("fs"));
71130
71363
  var os18 = __toESM(require("os"));
71131
- var path48 = __toESM(require("path"));
71364
+ var path47 = __toESM(require("path"));
71132
71365
  init_file_ops();
71133
71366
  init_shell();
71134
71367
  init_manifest();
71135
71368
 
71136
71369
  // src/harness/plugin-drift.ts
71137
71370
  var fs40 = __toESM(require("fs"));
71138
- var path47 = __toESM(require("path"));
71371
+ var path46 = __toESM(require("path"));
71139
71372
  init_manifest();
71140
71373
 
71141
71374
  // src/harness/plugins.ts
71142
71375
  var fs39 = __toESM(require("fs"));
71143
- var path46 = __toESM(require("path"));
71376
+ var path45 = __toESM(require("path"));
71144
71377
  init_zod();
71145
71378
  init_logging();
71146
71379
 
@@ -71155,12 +71388,12 @@ function harnessExists(repoPath) {
71155
71388
  var import_child_process11 = require("child_process");
71156
71389
  var fs38 = __toESM(require("fs"));
71157
71390
  var os17 = __toESM(require("os"));
71158
- var path45 = __toESM(require("path"));
71391
+ var path44 = __toESM(require("path"));
71159
71392
  function hasManifest(dir) {
71160
- return fs38.existsSync(path45.join(dir, "template.manifest.json"));
71393
+ return fs38.existsSync(path44.join(dir, "template.manifest.json"));
71161
71394
  }
71162
71395
  function readPackageVersion(dir) {
71163
- const pkgPath = path45.join(dir, "package.json");
71396
+ const pkgPath = path44.join(dir, "package.json");
71164
71397
  if (!fs38.existsSync(pkgPath)) return void 0;
71165
71398
  try {
71166
71399
  const pkg = JSON.parse(fs38.readFileSync(pkgPath, "utf8"));
@@ -71170,7 +71403,7 @@ function readPackageVersion(dir) {
71170
71403
  }
71171
71404
  }
71172
71405
  function readManifestId(dir) {
71173
- const manifestPath = path45.join(dir, "template.manifest.json");
71406
+ const manifestPath = path44.join(dir, "template.manifest.json");
71174
71407
  if (!fs38.existsSync(manifestPath)) return void 0;
71175
71408
  try {
71176
71409
  const raw = JSON.parse(fs38.readFileSync(manifestPath, "utf8"));
@@ -71191,24 +71424,24 @@ function looksLikeNpm(spec) {
71191
71424
  return /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(@.+)?$/i.test(spec);
71192
71425
  }
71193
71426
  function resolveBundledDir(pluginId) {
71194
- const dir = path45.join(resolveTemplatesDir(), "plugins", pluginId);
71427
+ const dir = path44.join(resolveTemplatesDir(), "plugins", pluginId);
71195
71428
  return hasManifest(dir) ? dir : null;
71196
71429
  }
71197
71430
  function expandHome(p) {
71198
- if (p.startsWith("~/")) return path45.join(os17.homedir(), p.slice(2));
71431
+ if (p.startsWith("~/")) return path44.join(os17.homedir(), p.slice(2));
71199
71432
  if (p === "~") return os17.homedir();
71200
71433
  return p;
71201
71434
  }
71202
71435
  function resolvePathSpec(spec) {
71203
71436
  const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
71204
- const dir = path45.resolve(expandHome(raw));
71437
+ const dir = path44.resolve(expandHome(raw));
71205
71438
  if (!fs38.existsSync(dir) || !fs38.statSync(dir).isDirectory()) {
71206
71439
  throw new Error(`Plugin path not found: ${spec}`);
71207
71440
  }
71208
71441
  if (!hasManifest(dir)) {
71209
71442
  throw new Error(`No template.manifest.json in ${dir}`);
71210
71443
  }
71211
- const id = readManifestId(dir) ?? path45.basename(dir);
71444
+ const id = readManifestId(dir) ?? path44.basename(dir);
71212
71445
  return {
71213
71446
  id,
71214
71447
  kind: "path",
@@ -71219,7 +71452,7 @@ function resolvePathSpec(spec) {
71219
71452
  };
71220
71453
  }
71221
71454
  function makeTempDir(prefix) {
71222
- return fs38.mkdtempSync(path45.join(os17.tmpdir(), prefix));
71455
+ return fs38.mkdtempSync(path44.join(os17.tmpdir(), prefix));
71223
71456
  }
71224
71457
  function resolveNpmSpec(spec) {
71225
71458
  const tmp = makeTempDir("har-plugin-npm-");
@@ -71234,16 +71467,16 @@ function resolveNpmSpec(spec) {
71234
71467
  if (tarballs.length === 0) {
71235
71468
  throw new Error(`npm pack produced no tarball for ${spec}`);
71236
71469
  }
71237
- const extractDir = path45.join(tmp, "extract");
71470
+ const extractDir = path44.join(tmp, "extract");
71238
71471
  fs38.mkdirSync(extractDir);
71239
- (0, import_child_process11.execFileSync)("tar", ["-xzf", path45.join(tmp, tarballs[0]), "-C", extractDir], {
71472
+ (0, import_child_process11.execFileSync)("tar", ["-xzf", path44.join(tmp, tarballs[0]), "-C", extractDir], {
71240
71473
  encoding: "utf8",
71241
71474
  stdio: ["ignore", "pipe", "pipe"]
71242
71475
  });
71243
- const packageDir = path45.join(extractDir, "package");
71476
+ const packageDir = path44.join(extractDir, "package");
71244
71477
  let dir = packageDir;
71245
71478
  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));
71479
+ const nested = fs38.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(extractDir, e.name)).find((d) => hasManifest(d));
71247
71480
  if (!nested) {
71248
71481
  throw new Error(
71249
71482
  `npm package ${spec} has no template.manifest.json (not a HAR plugin bundle)`
@@ -71271,7 +71504,7 @@ function resolveNpmSpec(spec) {
71271
71504
  function resolveGitSpec(spec) {
71272
71505
  const tmp = makeTempDir("har-plugin-git-");
71273
71506
  const cleanupDirs = [tmp];
71274
- const cloneDir = path45.join(tmp, "repo");
71507
+ const cloneDir = path44.join(tmp, "repo");
71275
71508
  try {
71276
71509
  let url = spec;
71277
71510
  if (spec.startsWith("github:")) {
@@ -71290,16 +71523,16 @@ function resolveGitSpec(spec) {
71290
71523
  });
71291
71524
  let dir = cloneDir;
71292
71525
  if (!hasManifest(dir)) {
71293
- const pluginsRoot = path45.join(cloneDir, "plugins");
71526
+ const pluginsRoot = path44.join(cloneDir, "plugins");
71294
71527
  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));
71528
+ const child = fs38.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
71296
71529
  if (child) dir = child;
71297
71530
  }
71298
71531
  }
71299
71532
  if (!hasManifest(dir)) {
71300
71533
  throw new Error(`Git repo ${spec} has no template.manifest.json (not a HAR plugin bundle)`);
71301
71534
  }
71302
- const id = readManifestId(dir) ?? path45.basename(url.replace(/\.git$/, ""));
71535
+ const id = readManifestId(dir) ?? path44.basename(url.replace(/\.git$/, ""));
71303
71536
  return {
71304
71537
  id,
71305
71538
  kind: "git",
@@ -71358,9 +71591,9 @@ function resolvePluginSource(spec) {
71358
71591
  );
71359
71592
  }
71360
71593
  function listBundledPluginIds() {
71361
- const root = path45.join(resolveTemplatesDir(), "plugins");
71594
+ const root = path44.join(resolveTemplatesDir(), "plugins");
71362
71595
  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();
71596
+ return fs38.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path44.join(root, name))).sort();
71364
71597
  }
71365
71598
  function cleanupResolvedPlugin(source) {
71366
71599
  for (const dir of source.cleanupDirs) {
@@ -71416,14 +71649,14 @@ function primaryStageId(manifest) {
71416
71649
  return manifest.stageId ?? stages[0].id;
71417
71650
  }
71418
71651
  function resolveBundledPluginDir(pluginId) {
71419
- const dir = path46.join(resolveTemplatesDir(), "plugins", pluginId);
71652
+ const dir = path45.join(resolveTemplatesDir(), "plugins", pluginId);
71420
71653
  if (!fs39.existsSync(dir)) {
71421
71654
  throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
71422
71655
  }
71423
71656
  return dir;
71424
71657
  }
71425
71658
  function readPluginManifestFromDir(pluginDir, expectedId) {
71426
- const manifestPath = path46.join(pluginDir, "template.manifest.json");
71659
+ const manifestPath = path45.join(pluginDir, "template.manifest.json");
71427
71660
  if (!fs39.existsSync(manifestPath)) {
71428
71661
  throw new Error(`No template.manifest.json in ${pluginDir}`);
71429
71662
  }
@@ -71442,14 +71675,14 @@ function readPluginManifest(pluginId) {
71442
71675
  return readPluginManifestFromDir(resolveBundledPluginDir(pluginId), pluginId);
71443
71676
  }
71444
71677
  function ensureParentDir(filePath) {
71445
- const parent = path46.dirname(filePath);
71678
+ const parent = path45.dirname(filePath);
71446
71679
  if (!fs39.existsSync(parent)) {
71447
71680
  fs39.mkdirSync(parent, { recursive: true });
71448
71681
  }
71449
71682
  }
71450
71683
  function copyPluginFile(pluginDir, file, repoPath, force) {
71451
- const srcPath = path46.join(pluginDir, file.src);
71452
- const destPath = path46.join(repoPath, file.dest);
71684
+ const srcPath = path45.join(pluginDir, file.src);
71685
+ const destPath = path45.join(repoPath, file.dest);
71453
71686
  if (!fs39.existsSync(srcPath)) {
71454
71687
  throw new Error(`Plugin file missing: ${file.src}`);
71455
71688
  }
@@ -71466,11 +71699,11 @@ function copyPluginFile(pluginDir, file, repoPath, force) {
71466
71699
  return { written: true, path: file.dest };
71467
71700
  }
71468
71701
  function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
71469
- const packagePath = path46.join(repoPath, "package.json");
71702
+ const packagePath = path45.join(repoPath, "package.json");
71470
71703
  if (!fs39.existsSync(packagePath)) {
71471
71704
  throw new Error("No package.json in repo root. Add one before applying this plugin.");
71472
71705
  }
71473
- const fragmentPath = path46.join(pluginDir, fragmentRelPath);
71706
+ const fragmentPath = path45.join(pluginDir, fragmentRelPath);
71474
71707
  if (!fs39.existsSync(fragmentPath)) {
71475
71708
  throw new Error(`Package fragment missing: ${fragmentRelPath}`);
71476
71709
  }
@@ -71532,7 +71765,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
71532
71765
  if (force) return;
71533
71766
  const registry2 = readStageRegistry(repoPath);
71534
71767
  for (const stageId of stageIds) {
71535
- const scriptPath = path46.join(repoPath, ".har", "stages", `${stageId}.sh`);
71768
+ const scriptPath = path45.join(repoPath, ".har", "stages", `${stageId}.sh`);
71536
71769
  if (fs39.existsSync(scriptPath)) {
71537
71770
  throw new Error(
71538
71771
  `Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
@@ -71546,7 +71779,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
71546
71779
  }
71547
71780
  }
71548
71781
  function applyPluginFromDir(repoPath, pluginDir, options, meta) {
71549
- const resolved = path46.resolve(repoPath);
71782
+ const resolved = path45.resolve(repoPath);
71550
71783
  const force = options.force ?? false;
71551
71784
  const warnings = [];
71552
71785
  const filesWritten = [];
@@ -71566,7 +71799,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
71566
71799
  if (file.skipFlag === "skipCi" && options.skipCi) {
71567
71800
  continue;
71568
71801
  }
71569
- if (fs39.existsSync(path46.join(resolved, file.dest)) && !force) {
71802
+ if (fs39.existsSync(path45.join(resolved, file.dest)) && !force) {
71570
71803
  warnings.push(`Skipped optional file (exists): ${file.dest}`);
71571
71804
  continue;
71572
71805
  }
@@ -71632,12 +71865,12 @@ function listPluginIds() {
71632
71865
  init_stages();
71633
71866
  var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
71634
71867
  function detectInstalledPlugins(repoPath) {
71635
- const resolved = path47.resolve(repoPath);
71868
+ const resolved = path46.resolve(repoPath);
71636
71869
  const ledger = readPluginLedger(resolved);
71637
71870
  if (ledger && ledger.plugins.length > 0) {
71638
71871
  return ledger.plugins.map((p) => p.id).sort();
71639
71872
  }
71640
- const registryPath = path47.join(resolved, ".har", "stages.json");
71873
+ const registryPath = path46.join(resolved, ".har", "stages.json");
71641
71874
  if (!fs40.existsSync(registryPath)) return [];
71642
71875
  const registry2 = readStageRegistry(resolved);
71643
71876
  const stageIds = new Set(registry2.stages.map((stage) => stage.id));
@@ -71655,7 +71888,7 @@ function detectInstalledPlugins(repoPath) {
71655
71888
  return installed.sort();
71656
71889
  }
71657
71890
  function pluginTemplatePath(pluginId, srcRel) {
71658
- return path47.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
71891
+ return path46.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
71659
71892
  }
71660
71893
  function resolvePluginTemplateDir(repoPath, pluginId) {
71661
71894
  const ledger = readPluginLedger(repoPath);
@@ -71667,8 +71900,8 @@ function resolvePluginTemplateDir(repoPath, pluginId) {
71667
71900
  } catch {
71668
71901
  }
71669
71902
  }
71670
- const bundled = path47.join(resolveTemplatesDir(), "plugins", pluginId);
71671
- if (fs40.existsSync(path47.join(bundled, "template.manifest.json"))) {
71903
+ const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId);
71904
+ if (fs40.existsSync(path46.join(bundled, "template.manifest.json"))) {
71672
71905
  return bundled;
71673
71906
  }
71674
71907
  return null;
@@ -71682,7 +71915,7 @@ function listPluginDestPaths(pluginId, repoPath) {
71682
71915
  const paths = manifest.files.map((file) => file.dest);
71683
71916
  if (manifest.optionalFiles) {
71684
71917
  for (const file of manifest.optionalFiles) {
71685
- if (fs40.existsSync(path47.join(repoPath, file.dest))) {
71918
+ if (fs40.existsSync(path46.join(repoPath, file.dest))) {
71686
71919
  paths.push(file.dest);
71687
71920
  }
71688
71921
  }
@@ -71741,7 +71974,7 @@ function readTemplatePluginFile(pluginId, dest) {
71741
71974
  return null;
71742
71975
  }
71743
71976
  function readInstalledPluginFile(repoPath, pluginId, dest) {
71744
- const installedPath = path47.join(path47.resolve(repoPath), dest);
71977
+ const installedPath = path46.join(path46.resolve(repoPath), dest);
71745
71978
  if (!fs40.existsSync(installedPath)) return null;
71746
71979
  const content = fs40.readFileSync(installedPath, "utf8");
71747
71980
  const manifest = readPluginManifest(pluginId);
@@ -71762,7 +71995,7 @@ function pluginActionHint(pluginId, dest, kind) {
71762
71995
  }
71763
71996
  function comparePluginToTemplate(repoPath, pluginId) {
71764
71997
  const manifest = readPluginManifest(pluginId);
71765
- const resolved = path47.resolve(repoPath);
71998
+ const resolved = path46.resolve(repoPath);
71766
71999
  const destPaths = listPluginDestPaths(pluginId, resolved);
71767
72000
  const missing = [];
71768
72001
  const checksumMismatch = [];
@@ -71777,7 +72010,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
71777
72010
  }
71778
72011
  if (dest === "package.json") {
71779
72012
  const fragmentRel = manifest.merge?.[dest];
71780
- const installedPath = path47.join(resolved, dest);
72013
+ const installedPath = path46.join(resolved, dest);
71781
72014
  const installedRaw = fs40.readFileSync(installedPath, "utf8");
71782
72015
  if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
71783
72016
  unchanged.push(dest);
@@ -71804,7 +72037,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
71804
72037
  }
71805
72038
  function compareInstalledPluginsToTemplate(repoPath) {
71806
72039
  return detectInstalledPlugins(repoPath).filter((pluginId) => {
71807
- const bundled = path47.join(resolveTemplatesDir(), "plugins", pluginId, "template.manifest.json");
72040
+ const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId, "template.manifest.json");
71808
72041
  return fs40.existsSync(bundled);
71809
72042
  }).map((pluginId) => comparePluginToTemplate(repoPath, pluginId));
71810
72043
  }
@@ -71843,13 +72076,13 @@ function substituteProjectName2(content, projectName) {
71843
72076
  return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
71844
72077
  }
71845
72078
  function projectNameFromRepo(repoPath) {
71846
- return path48.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
72079
+ return path47.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
71847
72080
  }
71848
72081
  function boilerplateDirForProfile(profile) {
71849
- return path48.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
72082
+ return path47.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
71850
72083
  }
71851
72084
  function readBundledTemplateContent(repoPath, profile, file) {
71852
- const templatePath = path48.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
72085
+ const templatePath = path47.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
71853
72086
  let content = fs41.readFileSync(templatePath, "utf8");
71854
72087
  if (file === "harness.env") {
71855
72088
  content = substituteProjectName2(content, projectNameFromRepo(repoPath));
@@ -71881,10 +72114,10 @@ function actionHint(file, kind) {
71881
72114
  return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
71882
72115
  }
71883
72116
  function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
71884
- const tmpDir = fs41.mkdtempSync(path48.join(os18.tmpdir(), "har-maintain-diff-"));
72117
+ const tmpDir = fs41.mkdtempSync(path47.join(os18.tmpdir(), "har-maintain-diff-"));
71885
72118
  try {
71886
- const installedPath = path48.join(tmpDir, "installed");
71887
- const templatePath = path48.join(tmpDir, "template");
72119
+ const installedPath = path47.join(tmpDir, "installed");
72120
+ const templatePath = path47.join(tmpDir, "template");
71888
72121
  fs41.writeFileSync(installedPath, installedContent);
71889
72122
  fs41.writeFileSync(templatePath, templateContent);
71890
72123
  const result = run(`diff -u "${installedPath}" "${templatePath}"`);
@@ -71910,7 +72143,7 @@ function buildActions(repoPath, profile, drift) {
71910
72143
  });
71911
72144
  }
71912
72145
  for (const file of drift.checksumMismatch) {
71913
- const installedPath = path48.join(harnessDir, file);
72146
+ const installedPath = path47.join(harnessDir, file);
71914
72147
  const installedRel = `maintain/installed/${file}`;
71915
72148
  const templateRel = `maintain/templates/${file}`;
71916
72149
  const diffRel = `maintain/diffs/${file}.diff`;
@@ -72070,16 +72303,16 @@ function buildReadme(report) {
72070
72303
  }
72071
72304
  function writeBundleArtifacts(repoPath, profile, drift, report) {
72072
72305
  const harnessDir = getHarnessDir(repoPath);
72073
- const bundleDir = path48.join(harnessDir, MAINTAIN_DIR);
72306
+ const bundleDir = path47.join(harnessDir, MAINTAIN_DIR);
72074
72307
  if (fs41.existsSync(bundleDir)) {
72075
72308
  fs41.rmSync(bundleDir, { recursive: true, force: true });
72076
72309
  }
72077
72310
  const dirs = [
72078
72311
  bundleDir,
72079
- path48.join(bundleDir, "templates"),
72080
- path48.join(bundleDir, "installed"),
72081
- path48.join(bundleDir, "diffs"),
72082
- path48.join(bundleDir, "stale")
72312
+ path47.join(bundleDir, "templates"),
72313
+ path47.join(bundleDir, "installed"),
72314
+ path47.join(bundleDir, "diffs"),
72315
+ path47.join(bundleDir, "stale")
72083
72316
  ];
72084
72317
  for (const dir of dirs) {
72085
72318
  fs41.mkdirSync(dir, { recursive: true });
@@ -72087,11 +72320,11 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72087
72320
  const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
72088
72321
  for (const file of affectedFiles) {
72089
72322
  const templateContent = readBundledTemplateContent(repoPath, profile, file);
72090
- writeFileSafe(path48.join(bundleDir, "templates", file), templateContent);
72091
- const harnessPath = path48.join(harnessDir, file);
72323
+ writeFileSafe(path47.join(bundleDir, "templates", file), templateContent);
72324
+ const harnessPath = path47.join(harnessDir, file);
72092
72325
  if (fs41.existsSync(harnessPath)) {
72093
72326
  const installedContent = fs41.readFileSync(harnessPath, "utf8");
72094
- writeFileSafe(path48.join(bundleDir, "installed", file), installedContent);
72327
+ writeFileSafe(path47.join(bundleDir, "installed", file), installedContent);
72095
72328
  const diff = createUnifiedDiff(
72096
72329
  installedContent,
72097
72330
  templateContent,
@@ -72099,14 +72332,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72099
72332
  `templates/${file}`
72100
72333
  );
72101
72334
  if (diff) {
72102
- writeFileSafe(path48.join(bundleDir, "diffs", `${file}.diff`), diff);
72335
+ writeFileSafe(path47.join(bundleDir, "diffs", `${file}.diff`), diff);
72103
72336
  }
72104
72337
  }
72105
72338
  }
72106
- writeFileSafe(path48.join(bundleDir, "README.md"), buildReadme(report));
72107
- writeFileSafe(path48.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
72339
+ writeFileSafe(path47.join(bundleDir, "README.md"), buildReadme(report));
72340
+ writeFileSafe(path47.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
72108
72341
  writeFileSafe(
72109
- path48.join(bundleDir, "validation.json"),
72342
+ path47.join(bundleDir, "validation.json"),
72110
72343
  JSON.stringify(report.validation, null, 2) + "\n"
72111
72344
  );
72112
72345
  if (report.stale.length > 0) {
@@ -72118,12 +72351,12 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
72118
72351
  ...report.stale.map((s) => `- **${s.file}** \u2014 ${s.hint}`),
72119
72352
  ""
72120
72353
  ];
72121
- writeFileSafe(path48.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
72354
+ writeFileSafe(path47.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
72122
72355
  }
72123
72356
  return bundleDir;
72124
72357
  }
72125
72358
  function ensureParentDir2(filePath) {
72126
- const parent = path48.dirname(filePath);
72359
+ const parent = path47.dirname(filePath);
72127
72360
  if (!fs41.existsSync(parent)) {
72128
72361
  fs41.mkdirSync(parent, { recursive: true });
72129
72362
  }
@@ -72131,21 +72364,21 @@ function ensureParentDir2(filePath) {
72131
72364
  function writePluginBundleArtifacts(repoPath, bundleDir, report) {
72132
72365
  if (report.pluginActions.length === 0) return;
72133
72366
  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");
72367
+ const pluginRoot = path47.join(bundleDir, "plugins", action.pluginId);
72368
+ const templatesDir = path47.join(pluginRoot, "templates");
72369
+ const installedDir = path47.join(pluginRoot, "installed");
72370
+ const diffsDir = path47.join(pluginRoot, "diffs");
72138
72371
  for (const dir of [templatesDir, installedDir, diffsDir]) {
72139
72372
  fs41.mkdirSync(dir, { recursive: true });
72140
72373
  }
72141
72374
  const templateContent = readTemplatePluginFile(action.pluginId, action.file);
72142
72375
  if (templateContent === null) continue;
72143
- const templatePath = path48.join(templatesDir, action.file);
72376
+ const templatePath = path47.join(templatesDir, action.file);
72144
72377
  ensureParentDir2(templatePath);
72145
72378
  writeFileSafe(templatePath, templateContent);
72146
72379
  const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
72147
72380
  if (installedContent !== null) {
72148
- const installedPath = path48.join(installedDir, action.file);
72381
+ const installedPath = path47.join(installedDir, action.file);
72149
72382
  ensureParentDir2(installedPath);
72150
72383
  writeFileSafe(installedPath, installedContent);
72151
72384
  const diff = createUnifiedDiff(
@@ -72155,7 +72388,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
72155
72388
  `templates/${action.file}`
72156
72389
  );
72157
72390
  if (diff) {
72158
- const diffPath = path48.join(diffsDir, `${action.file}.diff`);
72391
+ const diffPath = path47.join(diffsDir, `${action.file}.diff`);
72159
72392
  ensureParentDir2(diffPath);
72160
72393
  writeFileSafe(diffPath, diff);
72161
72394
  }
@@ -72190,7 +72423,7 @@ function buildMaintainBundle(repoPath, validation2, drift) {
72190
72423
  return { bundleDir, report };
72191
72424
  }
72192
72425
  function removeMaintainBundle(repoPath) {
72193
- const bundleDir = path48.join(getHarnessDir(repoPath), MAINTAIN_DIR);
72426
+ const bundleDir = path47.join(getHarnessDir(repoPath), MAINTAIN_DIR);
72194
72427
  if (fs41.existsSync(bundleDir)) {
72195
72428
  fs41.rmSync(bundleDir, { recursive: true, force: true });
72196
72429
  }
@@ -72285,7 +72518,7 @@ function listHarnessScripts(repoPath) {
72285
72518
  return fs42.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
72286
72519
  }
72287
72520
  function describeProject(repoPath) {
72288
- const resolved = path49.resolve(repoPath);
72521
+ const resolved = path48.resolve(repoPath);
72289
72522
  const manifest = readManifest(resolved);
72290
72523
  const present = harnessExists(resolved);
72291
72524
  return {
@@ -72305,7 +72538,7 @@ function describeProject(repoPath) {
72305
72538
  };
72306
72539
  }
72307
72540
  async function initHarness(options) {
72308
- const repoPath = path49.resolve(options.repoPath);
72541
+ const repoPath = path48.resolve(options.repoPath);
72309
72542
  if (!fs42.existsSync(repoPath)) {
72310
72543
  throw new Error(`Path not found: ${repoPath}`);
72311
72544
  }
@@ -72326,7 +72559,7 @@ async function initHarness(options) {
72326
72559
  };
72327
72560
  }
72328
72561
  async function maintainHarness(options) {
72329
- const repoPath = path49.resolve(options.repoPath);
72562
+ const repoPath = path48.resolve(options.repoPath);
72330
72563
  const harnessDir = getHarnessDir(repoPath);
72331
72564
  if (!fs42.existsSync(harnessDir)) {
72332
72565
  throw new Error('No .har/ found. Run "har env init" first.');
@@ -72364,12 +72597,12 @@ function addPlugin(repoPath, pluginId, options = {}) {
72364
72597
 
72365
72598
  // src/harness/custom-stage.ts
72366
72599
  var fs43 = __toESM(require("fs"));
72367
- var path50 = __toESM(require("path"));
72600
+ var path49 = __toESM(require("path"));
72368
72601
  init_schema2();
72369
72602
  init_stages();
72370
72603
  var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
72371
72604
  function addCustomStage(repoPath, options) {
72372
- const resolved = path50.resolve(repoPath);
72605
+ const resolved = path49.resolve(repoPath);
72373
72606
  if (!harnessExists(resolved)) {
72374
72607
  throw new Error('No .har/ harness found. Run "har env init" first.');
72375
72608
  }
@@ -72406,18 +72639,18 @@ function addCustomStage(repoPath, options) {
72406
72639
  if (options.command) {
72407
72640
  stage.command = options.command;
72408
72641
  } else {
72409
- const scriptRel = path50.join("stages", `${id}.sh`);
72410
- const scriptAbs = path50.join(resolved, ".har", scriptRel);
72642
+ const scriptRel = path49.join("stages", `${id}.sh`);
72643
+ const scriptAbs = path49.join(resolved, ".har", scriptRel);
72411
72644
  if (fs43.existsSync(scriptAbs) && !options.force) {
72412
72645
  throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
72413
72646
  }
72414
- const skeletonPath = path50.join(
72647
+ const skeletonPath = path49.join(
72415
72648
  resolveTemplatesDir(),
72416
72649
  "plugins",
72417
72650
  "custom-stage-skeleton.sh"
72418
72651
  );
72419
72652
  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 });
72653
+ fs43.mkdirSync(path49.dirname(scriptAbs), { recursive: true });
72421
72654
  fs43.writeFileSync(scriptAbs, skeleton);
72422
72655
  fs43.chmodSync(scriptAbs, 493);
72423
72656
  filesWritten.push(`.har/${scriptRel}`);
@@ -72468,7 +72701,7 @@ function addCustomStage(repoPath, options) {
72468
72701
 
72469
72702
  // src/harness/adaptation-prompt.ts
72470
72703
  var fs44 = __toESM(require("fs"));
72471
- var path51 = __toESM(require("path"));
72704
+ var path50 = __toESM(require("path"));
72472
72705
  var readline5 = __toESM(require("readline"));
72473
72706
 
72474
72707
  // src/utils/clipboard.ts
@@ -72580,7 +72813,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
72580
72813
  }
72581
72814
  function writeAdaptationPrompt(repoPath, content) {
72582
72815
  const harnessDir = getHarnessDir(repoPath);
72583
- const filePath = path51.join(harnessDir, ADAPTATION_PROMPT_FILE);
72816
+ const filePath = path50.join(harnessDir, ADAPTATION_PROMPT_FILE);
72584
72817
  writeFileSafe(filePath, content);
72585
72818
  return filePath;
72586
72819
  }
@@ -72599,12 +72832,12 @@ function printAdaptationPrompt(content) {
72599
72832
  }
72600
72833
  function askYesNo2(question) {
72601
72834
  const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
72602
- return new Promise((resolve53) => {
72835
+ return new Promise((resolve52) => {
72603
72836
  process.stderr.write(`${question} `);
72604
72837
  rl.once("line", (answer) => {
72605
72838
  rl.close();
72606
72839
  const trimmed = answer.trim();
72607
- resolve53(trimmed === "" || /^y(es)?$/i.test(trimmed));
72840
+ resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
72608
72841
  });
72609
72842
  });
72610
72843
  }
@@ -72636,16 +72869,16 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
72636
72869
 
72637
72870
  // src/harness/cursor-rule.ts
72638
72871
  var fs45 = __toESM(require("fs"));
72639
- var path52 = __toESM(require("path"));
72872
+ var path51 = __toESM(require("path"));
72640
72873
  var readline6 = __toESM(require("readline"));
72641
72874
  init_file_ops();
72642
72875
  init_logging();
72643
72876
  var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
72644
72877
  function getCursorRulePath(repoPath) {
72645
- return path52.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
72878
+ return path51.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
72646
72879
  }
72647
72880
  function isCursorWorkspace(repoPath) {
72648
- return fs45.existsSync(path52.join(repoPath, ".cursor"));
72881
+ return fs45.existsSync(path51.join(repoPath, ".cursor"));
72649
72882
  }
72650
72883
  function cursorRuleExists(repoPath) {
72651
72884
  return fs45.existsSync(getCursorRulePath(repoPath));
@@ -72693,16 +72926,16 @@ async function promptScaffoldCursorRule(exists) {
72693
72926
  }
72694
72927
  async function askYesNo3(question) {
72695
72928
  const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
72696
- return new Promise((resolve53) => {
72929
+ return new Promise((resolve52) => {
72697
72930
  process.stderr.write(`${question} `);
72698
72931
  rl.once("line", (answer) => {
72699
72932
  rl.close();
72700
72933
  const trimmed = answer.trim();
72701
72934
  if (trimmed === "") {
72702
- resolve53(true);
72935
+ resolve52(true);
72703
72936
  return;
72704
72937
  }
72705
- resolve53(/^y(es)?$/i.test(trimmed));
72938
+ resolve52(/^y(es)?$/i.test(trimmed));
72706
72939
  });
72707
72940
  });
72708
72941
  }
@@ -72745,7 +72978,7 @@ init_control_config();
72745
72978
 
72746
72979
  // src/core/control-lifecycle.ts
72747
72980
  var import_child_process13 = require("child_process");
72748
- var path53 = __toESM(require("path"));
72981
+ var path52 = __toESM(require("path"));
72749
72982
 
72750
72983
  // src/core/control-image.ts
72751
72984
  init_package_version();
@@ -72772,10 +73005,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
72772
73005
  var CONTROL_CONTAINER_PORT = 3847;
72773
73006
  var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
72774
73007
  function resolveControlDir() {
72775
- return path53.resolve(__dirname, "..", "control");
73008
+ return path52.resolve(__dirname, "..", "control");
72776
73009
  }
72777
73010
  function resolveControlBuildContext() {
72778
- return path53.resolve(resolveControlDir(), "..");
73011
+ return path52.resolve(resolveControlDir(), "..");
72779
73012
  }
72780
73013
  function buildDockerRunArgs(options) {
72781
73014
  const name = options.containerName ?? CONTROL_CONTAINER_NAME;
@@ -72831,7 +73064,7 @@ async function startMissionControl(options) {
72831
73064
  "-t",
72832
73065
  imageRef,
72833
73066
  "-f",
72834
- path53.join(resolveControlDir(), "Dockerfile"),
73067
+ path52.join(resolveControlDir(), "Dockerfile"),
72835
73068
  resolveControlBuildContext()
72836
73069
  ]);
72837
73070
  if (buildCode !== 0) {
@@ -72978,7 +73211,7 @@ async function ensureTelemetryInfrastructure(options) {
72978
73211
  // src/core/run-service.ts
72979
73212
  init_telemetry_config();
72980
73213
  init_telemetry_env();
72981
- var path55 = __toESM(require("path"));
73214
+ var path54 = __toESM(require("path"));
72982
73215
  init_local_executor();
72983
73216
  function extractShellOutput(result) {
72984
73217
  const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
@@ -73184,12 +73417,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
73184
73417
  suffix: session.suffix,
73185
73418
  createdAt: session.createdAt
73186
73419
  });
73187
- const envFile = path55.join(session.workDir, `.env.agent.${options.agentId}`);
73420
+ const envFile = path54.join(session.workDir, `.env.agent.${options.agentId}`);
73188
73421
  try {
73189
73422
  appendTelemetryEnvToFile(envFile, {
73190
73423
  sessionKey,
73191
73424
  agentId: options.agentId,
73192
- repoPath: path55.resolve(options.repoPath),
73425
+ repoPath: path54.resolve(options.repoPath),
73193
73426
  workDir: session.workDir,
73194
73427
  branch: session.branch,
73195
73428
  suffix: session.suffix,
@@ -73428,7 +73661,7 @@ init_slot_status();
73428
73661
  // src/core/cleanup-service.ts
73429
73662
  var fs47 = __toESM(require("fs"));
73430
73663
  var os20 = __toESM(require("os"));
73431
- var path56 = __toESM(require("path"));
73664
+ var path55 = __toESM(require("path"));
73432
73665
  var import_child_process15 = require("child_process");
73433
73666
  init_control_sync();
73434
73667
  init_control_repo_path();
@@ -73437,9 +73670,9 @@ init_manifest();
73437
73670
  var DEFAULT_STALE_DAYS = 7;
73438
73671
  function getWorktreesRoot() {
73439
73672
  if (process.env.HAR_WORKTREES_ROOT) {
73440
- return path56.resolve(process.env.HAR_WORKTREES_ROOT);
73673
+ return path55.resolve(process.env.HAR_WORKTREES_ROOT);
73441
73674
  }
73442
- return path56.join(process.env.HOME || os20.homedir(), "worktrees");
73675
+ return path55.join(process.env.HOME || os20.homedir(), "worktrees");
73443
73676
  }
73444
73677
  function runGit3(cwd, args) {
73445
73678
  try {
@@ -73453,7 +73686,7 @@ function runGit3(cwd, args) {
73453
73686
  }
73454
73687
  }
73455
73688
  function basenameRepo(repoPath) {
73456
- return path56.basename(canonicalizeControlRepoPath(repoPath));
73689
+ return path55.basename(canonicalizeControlRepoPath(repoPath));
73457
73690
  }
73458
73691
  function ageDaysFrom(iso) {
73459
73692
  if (!iso) return void 0;
@@ -73465,12 +73698,12 @@ function matchesKeep(candidate, keep) {
73465
73698
  if (!keep?.length) return false;
73466
73699
  for (const pin of keep) {
73467
73700
  if (pin.worktreePath && candidate.worktreePath) {
73468
- if (path56.resolve(pin.worktreePath) === path56.resolve(candidate.worktreePath)) return true;
73701
+ if (path55.resolve(pin.worktreePath) === path55.resolve(candidate.worktreePath)) return true;
73469
73702
  }
73470
73703
  if (pin.repoPath && pin.agentId !== void 0 && candidate.agentId !== void 0) {
73471
73704
  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) {
73705
+ const candidateRepo = path55.resolve(candidate.repoPath);
73706
+ if ((repo === candidateRepo || path55.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
73474
73707
  return true;
73475
73708
  }
73476
73709
  }
@@ -73528,7 +73761,7 @@ function resolveRepoForWorktree(worktreePath) {
73528
73761
  if (!fs47.existsSync(worktreePath)) return void 0;
73529
73762
  const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
73530
73763
  if (!commonDir) return void 0;
73531
- const gitRoot = path56.resolve(worktreePath, commonDir, "..");
73764
+ const gitRoot = path55.resolve(worktreePath, commonDir, "..");
73532
73765
  if (!readManifest(gitRoot)) return void 0;
73533
73766
  return canonicalizeControlRepoPath(gitRoot);
73534
73767
  }
@@ -73538,7 +73771,7 @@ function discoverOrphanWorktrees(knownPaths) {
73538
73771
  const orphans = [];
73539
73772
  for (const entry of fs47.readdirSync(worktreesRoot, { withFileTypes: true })) {
73540
73773
  if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
73541
- const worktreePath = path56.resolve(path56.join(worktreesRoot, entry.name));
73774
+ const worktreePath = path55.resolve(path55.join(worktreesRoot, entry.name));
73542
73775
  if (knownPaths.has(worktreePath)) continue;
73543
73776
  const repoPath = resolveRepoForWorktree(worktreePath) ?? worktreesRoot;
73544
73777
  const porcelain = runGit3(worktreePath, "status --porcelain");
@@ -73569,8 +73802,8 @@ async function discoverCleanupCandidates(options = {}) {
73569
73802
  const status = collectEnvironmentStatus(harnessRoot);
73570
73803
  const projectName = basenameRepo(harnessRoot);
73571
73804
  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));
73805
+ if (slot.worktreePath) knownWorktreePaths.add(path55.resolve(slot.worktreePath));
73806
+ if (slot.workDir) knownWorktreePaths.add(path55.resolve(slot.workDir));
73574
73807
  const candidate = classifySlotCandidate(canonicalRepo, projectName, slot, {
73575
73808
  staleDays: options.staleDays,
73576
73809
  keep: options.keep
@@ -73630,8 +73863,8 @@ async function askYesNo4(question) {
73630
73863
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
73631
73864
  const readline8 = await import("readline");
73632
73865
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
73633
- const answer = await new Promise((resolve53) => {
73634
- rl.question(question, resolve53);
73866
+ const answer = await new Promise((resolve52) => {
73867
+ rl.question(question, resolve52);
73635
73868
  });
73636
73869
  rl.close();
73637
73870
  return /^[Yy]$/.test(answer.trim());
@@ -73714,7 +73947,7 @@ function parseCleanupKeepPins(values) {
73714
73947
  }
73715
73948
  if (raw.startsWith("/") || raw.startsWith("~")) {
73716
73949
  return {
73717
- worktreePath: raw.startsWith("~") ? path56.join(process.env.HOME || os20.homedir(), raw.slice(2)) : path56.resolve(raw)
73950
+ worktreePath: raw.startsWith("~") ? path55.join(process.env.HOME || os20.homedir(), raw.slice(2)) : path55.resolve(raw)
73718
73951
  };
73719
73952
  }
73720
73953
  return { repoPath: raw };
@@ -73728,12 +73961,12 @@ init_stages();
73728
73961
  init_logging();
73729
73962
  function askYesNo5(question) {
73730
73963
  const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
73731
- return new Promise((resolve53) => {
73964
+ return new Promise((resolve52) => {
73732
73965
  process.stderr.write(`${question} `);
73733
73966
  rl.once("line", (answer) => {
73734
73967
  rl.close();
73735
73968
  const trimmed = answer.trim();
73736
- resolve53(trimmed === "" || /^y(es)?$/i.test(trimmed));
73969
+ resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
73737
73970
  });
73738
73971
  });
73739
73972
  }
@@ -73836,13 +74069,13 @@ function warnIfDockerUnavailable(status = detectDockerStatus()) {
73836
74069
  // src/core/onboarding-preferences.ts
73837
74070
  var fs48 = __toESM(require("fs"));
73838
74071
  var os21 = __toESM(require("os"));
73839
- var path57 = __toESM(require("path"));
74072
+ var path56 = __toESM(require("path"));
73840
74073
  init_schema2();
73841
74074
  function getOnboardingPreferencesPath() {
73842
74075
  if (process.env.HAR_PREFERENCES_PATH) {
73843
- return path57.resolve(process.env.HAR_PREFERENCES_PATH);
74076
+ return path56.resolve(process.env.HAR_PREFERENCES_PATH);
73844
74077
  }
73845
- return path57.join(os21.homedir(), ".har", "preferences.json");
74078
+ return path56.join(os21.homedir(), ".har", "preferences.json");
73846
74079
  }
73847
74080
  function readOnboardingPreferences() {
73848
74081
  const preferencePath = getOnboardingPreferencesPath();
@@ -73873,7 +74106,7 @@ function writeOnboardingPreferences(overrides) {
73873
74106
  };
73874
74107
  const parsed = OnboardingPreferencesSchema.parse(preference);
73875
74108
  const preferencePath = getOnboardingPreferencesPath();
73876
- fs48.mkdirSync(path57.dirname(preferencePath), { recursive: true });
74109
+ fs48.mkdirSync(path56.dirname(preferencePath), { recursive: true });
73877
74110
  fs48.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
73878
74111
  `);
73879
74112
  return parsed;
@@ -74219,7 +74452,7 @@ var envCommand = {
74219
74452
  }
74220
74453
  };
74221
74454
  async function handleInit(argv) {
74222
- const repoPath = path58.resolve(argv.repo);
74455
+ const repoPath = path57.resolve(argv.repo);
74223
74456
  const onboarding = resolveOnboardingOptions(argv);
74224
74457
  header("har env init");
74225
74458
  info(`Repository: ${repoPath}`);
@@ -74266,7 +74499,7 @@ async function handleInit(argv) {
74266
74499
  }
74267
74500
  }
74268
74501
  async function handleMaintain(argv) {
74269
- const repoPath = path58.resolve(argv.repo);
74502
+ const repoPath = path57.resolve(argv.repo);
74270
74503
  const onboarding = resolveOnboardingOptions(argv);
74271
74504
  header("har env maintain");
74272
74505
  info(`Repository: ${repoPath}`);
@@ -74397,7 +74630,7 @@ async function applyAgentIntegrations(options) {
74397
74630
  }
74398
74631
  }
74399
74632
  async function handleAddPlugin(argv) {
74400
- const repoPath = path58.resolve(argv.repo);
74633
+ const repoPath = path57.resolve(argv.repo);
74401
74634
  const available = listPluginIds();
74402
74635
  if (argv.list) {
74403
74636
  for (const id of available) {
@@ -74437,7 +74670,7 @@ async function handleAddPlugin(argv) {
74437
74670
  }
74438
74671
  }
74439
74672
  async function handleAddStage(argv) {
74440
- const repoPath = path58.resolve(argv.repo);
74673
+ const repoPath = path57.resolve(argv.repo);
74441
74674
  const available = listPluginIds();
74442
74675
  if (argv.list) {
74443
74676
  warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
@@ -74503,7 +74736,7 @@ async function handleAddStage(argv) {
74503
74736
  });
74504
74737
  }
74505
74738
  async function handlePreflight(argv) {
74506
- const repo = path58.resolve(argv.repo);
74739
+ const repo = path57.resolve(argv.repo);
74507
74740
  const agentId = validateAgentId(argv.id, repo);
74508
74741
  const result = await preflightEnvironment({
74509
74742
  repoPath: repo,
@@ -74519,7 +74752,7 @@ async function handlePreflight(argv) {
74519
74752
  return finishCommand(result.code);
74520
74753
  }
74521
74754
  async function handleLaunch(argv) {
74522
- const repo = path58.resolve(argv.repo);
74755
+ const repo = path57.resolve(argv.repo);
74523
74756
  const agentId = validateAgentId(argv.id, repo);
74524
74757
  if (!argv.resume) {
74525
74758
  const guard = checkLaunchGuard2(repo, agentId, { worktree: argv.worktree });
@@ -74568,7 +74801,7 @@ async function handleWorkLink(argv) {
74568
74801
  error("Provide --link or both --source and --url");
74569
74802
  return finishCommand(1);
74570
74803
  }
74571
- const harnessRoot = resolveHarnessRoot(path58.resolve(argv.repo));
74804
+ const harnessRoot = resolveHarnessRoot(path57.resolve(argv.repo));
74572
74805
  const links = argv.link ? [parseWorkLinkSpec(argv.link)] : [{ source: argv.source, url: argv.url, label: argv.label }];
74573
74806
  try {
74574
74807
  const record2 = addWorkUnitLinks(harnessRoot, argv.workId, links);
@@ -74594,7 +74827,7 @@ async function handleRecover(argv) {
74594
74827
  });
74595
74828
  }
74596
74829
  async function handleVerify(argv) {
74597
- const repo = path58.resolve(argv.repo);
74830
+ const repo = path57.resolve(argv.repo);
74598
74831
  const agentId = validateAgentId(argv.id, repo);
74599
74832
  const result = await runVerification({
74600
74833
  repoPath: repo,
@@ -74623,7 +74856,7 @@ async function handleVerify(argv) {
74623
74856
  return finishCommand(result.code);
74624
74857
  }
74625
74858
  async function handleTeardown(argv) {
74626
- const repo = path58.resolve(argv.repo);
74859
+ const repo = path57.resolve(argv.repo);
74627
74860
  const agentId = validateAgentId(argv.id, repo);
74628
74861
  const result = await teardownEnvironment({
74629
74862
  repoPath: repo,
@@ -74634,7 +74867,7 @@ async function handleTeardown(argv) {
74634
74867
  return finishCommand(result.code);
74635
74868
  }
74636
74869
  async function handleComplete(argv) {
74637
- const repo = path58.resolve(argv.repo);
74870
+ const repo = path57.resolve(argv.repo);
74638
74871
  const agentId = validateAgentId(argv.id, repo);
74639
74872
  const result = await completeEnvironment({
74640
74873
  repoPath: repo,
@@ -74655,7 +74888,7 @@ async function handleComplete(argv) {
74655
74888
  return finishCommand(result.code);
74656
74889
  }
74657
74890
  async function handleStatus(argv) {
74658
- const repoPath = path58.resolve(argv.repo);
74891
+ const repoPath = path57.resolve(argv.repo);
74659
74892
  if (argv.json) {
74660
74893
  const status = collectEnvironmentStatus(repoPath);
74661
74894
  const output = EnvironmentStatusSchema.parse(status);
@@ -74670,7 +74903,7 @@ async function handleStatus(argv) {
74670
74903
  async function handleCleanup(argv) {
74671
74904
  const keepValues = argv.keep?.split(",").map((value) => value.trim()).filter(Boolean);
74672
74905
  const keep = parseCleanupKeepPins(keepValues);
74673
- const repoPaths = argv.repo ? [path58.resolve(argv.repo)] : void 0;
74906
+ const repoPaths = argv.repo ? [path57.resolve(argv.repo)] : void 0;
74674
74907
  const plan = await discoverCleanupCandidates({
74675
74908
  cwd: process.cwd(),
74676
74909
  repoPaths,
@@ -74719,7 +74952,7 @@ async function handleCleanup(argv) {
74719
74952
  return finishCommand(failed > 0 ? 1 : 0);
74720
74953
  }
74721
74954
  async function handleRunsList(argv) {
74722
- const repoPath = path58.resolve(argv.repo);
74955
+ const repoPath = path57.resolve(argv.repo);
74723
74956
  const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
74724
74957
  if (argv.json) {
74725
74958
  process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
@@ -74736,7 +74969,7 @@ async function handleRunsList(argv) {
74736
74969
  }
74737
74970
  }
74738
74971
  async function handleRunsGet(argv) {
74739
- const run2 = getRun(path58.resolve(argv.repo), argv.runId);
74972
+ const run2 = getRun(path57.resolve(argv.repo), argv.runId);
74740
74973
  if (!run2) {
74741
74974
  error(`Run not found: ${argv.runId}`);
74742
74975
  return finishCommand(1);
@@ -74813,7 +75046,7 @@ function printNextSteps() {
74813
75046
  }
74814
75047
 
74815
75048
  // src/cli/commands/control.ts
74816
- var path63 = __toESM(require("path"));
75049
+ var path62 = __toESM(require("path"));
74817
75050
  init_control_config();
74818
75051
  init_portal_targets();
74819
75052
 
@@ -74822,7 +75055,7 @@ init_control_config();
74822
75055
 
74823
75056
  // src/core/portal-connect.ts
74824
75057
  var fs49 = __toESM(require("fs"));
74825
- var path59 = __toESM(require("path"));
75058
+ var path58 = __toESM(require("path"));
74826
75059
  var import_crypto2 = require("crypto");
74827
75060
  init_control_repo_path();
74828
75061
  init_control_registry();
@@ -74868,7 +75101,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
74868
75101
  const options = typeof openUrlOrOptions === "function" ? { openUrl: openUrlOrOptions } : openUrlOrOptions;
74869
75102
  const openUrl = options.openUrl ?? openBrowser;
74870
75103
  const state = (0, import_crypto.randomUUID)();
74871
- return new Promise((resolve53, reject) => {
75104
+ return new Promise((resolve52, reject) => {
74872
75105
  let timer;
74873
75106
  const server = http.createServer((req, res) => {
74874
75107
  const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
@@ -74896,7 +75129,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
74896
75129
  res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
74897
75130
  cleanup();
74898
75131
  const targets = parseCliTargetsParam(requestUrl.searchParams.get("targets"));
74899
- resolve53({
75132
+ resolve52({
74900
75133
  portalUrl,
74901
75134
  token,
74902
75135
  workspace: workspaceSlug ?? workspace,
@@ -74991,7 +75224,7 @@ function remainingConnections(connections, usedAliases) {
74991
75224
  // src/core/portal-connect.ts
74992
75225
  init_portal_targets();
74993
75226
  function attachRepoIfPresent(alias, repoPath) {
74994
- const resolved = path59.resolve(repoPath ?? ".");
75227
+ const resolved = path58.resolve(repoPath ?? ".");
74995
75228
  if (!fs49.existsSync(resolved)) return null;
74996
75229
  const canonical = canonicalizeControlRepoPath(resolved);
74997
75230
  attachRepoPortalTarget(canonical, alias);
@@ -75059,7 +75292,7 @@ async function runPortalConnect(input) {
75059
75292
  return { record: record2, attachedRepo, extraAttached, mappedInBrowser: true };
75060
75293
  }
75061
75294
  function listRegisteredReposForConnect(repoPath) {
75062
- const resolved = repoPath ? path59.resolve(repoPath) : null;
75295
+ const resolved = repoPath ? path58.resolve(repoPath) : null;
75063
75296
  const current = resolved && fs49.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
75064
75297
  return [.../* @__PURE__ */ new Set([...current ? [current] : [], ...listRegisteredRepos()])];
75065
75298
  }
@@ -75378,13 +75611,13 @@ init_control_sync();
75378
75611
  // src/core/control-sync-selection.ts
75379
75612
  var fs50 = __toESM(require("fs"));
75380
75613
  var os22 = __toESM(require("os"));
75381
- var path60 = __toESM(require("path"));
75614
+ var path59 = __toESM(require("path"));
75382
75615
  init_control_repo_path();
75383
75616
  function getSelectionPath() {
75384
75617
  if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
75385
- return path60.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
75618
+ return path59.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
75386
75619
  }
75387
- return path60.join(os22.homedir(), ".har", "sync-selection.json");
75620
+ return path59.join(os22.homedir(), ".har", "sync-selection.json");
75388
75621
  }
75389
75622
  function readSyncSelection() {
75390
75623
  const selectionPath = getSelectionPath();
@@ -75400,7 +75633,7 @@ function readSyncSelection() {
75400
75633
  function writeSyncSelection(repos) {
75401
75634
  const selectionPath = getSelectionPath();
75402
75635
  const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
75403
- fs50.mkdirSync(path60.dirname(selectionPath), { recursive: true });
75636
+ fs50.mkdirSync(path59.dirname(selectionPath), { recursive: true });
75404
75637
  fs50.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
75405
75638
  }
75406
75639
  function resolveSyncSelection(input) {
@@ -75429,7 +75662,7 @@ function resolveSyncSelection(input) {
75429
75662
 
75430
75663
  // src/core/control-unregister.ts
75431
75664
  var fs51 = __toESM(require("fs"));
75432
- var path61 = __toESM(require("path"));
75665
+ var path60 = __toESM(require("path"));
75433
75666
  init_control_repo_path();
75434
75667
  init_control_registry();
75435
75668
  init_control_config();
@@ -75439,7 +75672,7 @@ function listUnregisterWorktreeCandidates(repoPath) {
75439
75672
  const harnessRoot = canonicalizeControlRepoPath(repoPath);
75440
75673
  const byPath = /* @__PURE__ */ new Map();
75441
75674
  const add = (partial2) => {
75442
- const resolved = path61.resolve(partial2.worktreePath);
75675
+ const resolved = path60.resolve(partial2.worktreePath);
75443
75676
  if (!resolved || resolved === harnessRoot) return;
75444
75677
  const exists = partial2.exists ?? fs51.existsSync(resolved);
75445
75678
  const prev = byPath.get(resolved);
@@ -75492,8 +75725,8 @@ async function askYesNo6(question) {
75492
75725
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
75493
75726
  const readline8 = await import("readline");
75494
75727
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
75495
- const answer = await new Promise((resolve53) => {
75496
- rl.question(question, resolve53);
75728
+ const answer = await new Promise((resolve52) => {
75729
+ rl.question(question, resolve52);
75497
75730
  });
75498
75731
  rl.close();
75499
75732
  return /^[Yy]$/.test(answer.trim());
@@ -75640,15 +75873,15 @@ init_control_registry();
75640
75873
 
75641
75874
  // src/core/harness-scrub.ts
75642
75875
  var fs52 = __toESM(require("fs"));
75643
- var path62 = __toESM(require("path"));
75876
+ var path61 = __toESM(require("path"));
75644
75877
  var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
75645
75878
  function scrubLocalHarnessDirs(repoPath) {
75646
75879
  const results = [];
75647
- const resolved = path62.resolve(repoPath);
75880
+ const resolved = path61.resolve(repoPath);
75648
75881
  if (!fs52.existsSync(resolved)) {
75649
75882
  for (const directory of HARNESS_SCRUB_DIRS) {
75650
75883
  results.push({
75651
- path: path62.join(resolved, ".har", directory),
75884
+ path: path61.join(resolved, ".har", directory),
75652
75885
  directory,
75653
75886
  deleted: false,
75654
75887
  error: "repository path does not exist"
@@ -75657,7 +75890,7 @@ function scrubLocalHarnessDirs(repoPath) {
75657
75890
  return results;
75658
75891
  }
75659
75892
  for (const directory of HARNESS_SCRUB_DIRS) {
75660
- const target = path62.join(resolved, ".har", directory);
75893
+ const target = path61.join(resolved, ".har", directory);
75661
75894
  if (!fs52.existsSync(target)) {
75662
75895
  results.push({ path: target, directory, deleted: true });
75663
75896
  continue;
@@ -75685,7 +75918,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
75685
75918
  const results = [];
75686
75919
  const seen = /* @__PURE__ */ new Set();
75687
75920
  for (const repoPath of repoPaths) {
75688
- const key = path62.resolve(repoPath);
75921
+ const key = path61.resolve(repoPath);
75689
75922
  if (seen.has(key)) continue;
75690
75923
  seen.add(key);
75691
75924
  results.push(...scrubLocalHarnessDirs(key));
@@ -75698,8 +75931,8 @@ async function askYesNo7(question) {
75698
75931
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
75699
75932
  const readline8 = await import("readline");
75700
75933
  const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
75701
- const answer = await new Promise((resolve53) => {
75702
- rl.question(question, resolve53);
75934
+ const answer = await new Promise((resolve52) => {
75935
+ rl.question(question, resolve52);
75703
75936
  });
75704
75937
  rl.close();
75705
75938
  return /^[Yy]$/.test(answer.trim());
@@ -75978,7 +76211,7 @@ async function handleDown() {
75978
76211
  return finishCommand(code);
75979
76212
  }
75980
76213
  async function handleRegister(argv) {
75981
- const repoPath = path63.resolve(argv.repo);
76214
+ const repoPath = path62.resolve(argv.repo);
75982
76215
  header("har control register");
75983
76216
  info(`Repository: ${repoPath}`);
75984
76217
  try {
@@ -76076,7 +76309,7 @@ async function handleReset(argv) {
76076
76309
  }
76077
76310
  }
76078
76311
  async function handleUnregister(argv) {
76079
- const repoPath = path63.resolve(argv.repo);
76312
+ const repoPath = path62.resolve(argv.repo);
76080
76313
  const worktrees = listUnregisterWorktreeCandidates(repoPath);
76081
76314
  try {
76082
76315
  let deleteWorktrees = argv.deleteWorktrees;
@@ -76214,7 +76447,7 @@ async function handleSync(argv) {
76214
76447
  );
76215
76448
  }
76216
76449
  }
76217
- const { synced, failed, results } = await syncReposWithControl({
76450
+ const { synced, failed, incomplete, results } = await syncReposWithControl({
76218
76451
  repoPaths,
76219
76452
  apiUrl: argv.apiUrl,
76220
76453
  dryRun: argv.dryRun,
@@ -76223,7 +76456,9 @@ async function handleSync(argv) {
76223
76456
  portalTargets
76224
76457
  });
76225
76458
  if (argv.json) {
76226
- process.stdout.write(JSON.stringify({ ok: failed === 0, synced, failed, results }, null, 2) + "\n");
76459
+ process.stdout.write(
76460
+ JSON.stringify({ ok: failed === 0, synced, failed, incomplete, results }, null, 2) + "\n"
76461
+ );
76227
76462
  if (failed > 0) return finishCommand(1);
76228
76463
  return;
76229
76464
  }
@@ -76232,22 +76467,32 @@ async function handleSync(argv) {
76232
76467
  for (const target of result.targets) {
76233
76468
  const record2 = findPortalTargetRecord(target.alias);
76234
76469
  const label = record2 ? displayPortalTargetLabel(record2) : target.alias;
76235
- if (target.ok) {
76236
- success(`Synced ${result.repoPath} \u2192 ${label}`);
76237
- } else {
76470
+ if (!target.ok) {
76238
76471
  warn(`Failed ${result.repoPath} \u2192 ${label}: ${target.error}`);
76472
+ } else if (target.warnings && target.warnings.length > 0) {
76473
+ warn(`Synced ${result.repoPath} \u2192 ${label} \u2014 incomplete`);
76474
+ } else {
76475
+ success(`Synced ${result.repoPath} \u2192 ${label}`);
76239
76476
  }
76240
76477
  }
76241
76478
  continue;
76242
76479
  }
76243
- if (result.ok) {
76244
- success(`Synced ${result.repoPath}`);
76245
- } else {
76480
+ if (!result.ok) {
76246
76481
  warn(`Failed ${result.repoPath}: ${result.error}`);
76482
+ } else if (result.warnings && result.warnings.length > 0) {
76483
+ warn(`Synced ${result.repoPath} \u2014 incomplete`);
76484
+ } else {
76485
+ success(`Synced ${result.repoPath}`);
76247
76486
  }
76248
76487
  }
76249
- if (synced > 0) {
76250
- success(`Synced ${synced} ${synced === 1 ? "repository" : "repositories"}`);
76488
+ if (synced > incomplete) {
76489
+ const complete = synced - incomplete;
76490
+ success(`Synced ${complete} ${complete === 1 ? "repository" : "repositories"}`);
76491
+ }
76492
+ if (incomplete > 0) {
76493
+ warn(
76494
+ `${incomplete} ${incomplete === 1 ? "repository" : "repositories"} synced with incomplete telemetry \u2014 see the warnings above`
76495
+ );
76251
76496
  }
76252
76497
  if (failed > 0) {
76253
76498
  warn(`${failed} ${failed === 1 ? "repository" : "repositories"} could not be synced`);
@@ -76345,12 +76590,12 @@ async function handleTrajectory(argv) {
76345
76590
  }
76346
76591
 
76347
76592
  // src/cli/commands/hooks.ts
76348
- var path65 = __toESM(require("path"));
76593
+ var path64 = __toESM(require("path"));
76349
76594
  init_hooks();
76350
76595
 
76351
76596
  // src/core/claude-hooks.ts
76352
76597
  var fs53 = __toESM(require("fs"));
76353
- var path64 = __toESM(require("path"));
76598
+ var path63 = __toESM(require("path"));
76354
76599
  var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
76355
76600
  var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
76356
76601
  var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
@@ -76371,7 +76616,7 @@ function readSettings(settingsPath) {
76371
76616
  return parsed;
76372
76617
  }
76373
76618
  function writeSettings(settingsPath, settings) {
76374
- fs53.mkdirSync(path64.dirname(settingsPath), { recursive: true });
76619
+ fs53.mkdirSync(path63.dirname(settingsPath), { recursive: true });
76375
76620
  fs53.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
76376
76621
  }
76377
76622
  function installClaudeGuard(repoPath) {
@@ -76379,11 +76624,11 @@ function installClaudeGuard(repoPath) {
76379
76624
  if (!templatePath) {
76380
76625
  throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
76381
76626
  }
76382
- const guardScript = path64.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76383
- fs53.mkdirSync(path64.dirname(guardScript), { recursive: true });
76627
+ const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76628
+ fs53.mkdirSync(path63.dirname(guardScript), { recursive: true });
76384
76629
  fs53.copyFileSync(templatePath, guardScript);
76385
76630
  fs53.chmodSync(guardScript, 493);
76386
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76631
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76387
76632
  const settings = readSettings(settingsPath);
76388
76633
  const hooks = settings.hooks ?? {};
76389
76634
  const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
@@ -76397,14 +76642,14 @@ function installClaudeGuard(repoPath) {
76397
76642
  }
76398
76643
  function uninstallClaudeGuard(repoPath) {
76399
76644
  let removed = false;
76400
- const guardScript = path64.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76645
+ const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
76401
76646
  if (fs53.existsSync(guardScript)) {
76402
76647
  fs53.rmSync(guardScript);
76403
76648
  removed = true;
76404
- const parent = path64.dirname(guardScript);
76649
+ const parent = path63.dirname(guardScript);
76405
76650
  if (fs53.existsSync(parent) && fs53.readdirSync(parent).length === 0) fs53.rmdirSync(parent);
76406
76651
  }
76407
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76652
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76408
76653
  if (fs53.existsSync(settingsPath)) {
76409
76654
  const settings = readSettings(settingsPath);
76410
76655
  const preToolUse = settings.hooks?.PreToolUse;
@@ -76430,7 +76675,7 @@ function uninstallClaudeGuard(repoPath) {
76430
76675
  return { removed };
76431
76676
  }
76432
76677
  function claudeGuardInstalled(repoPath) {
76433
- const settingsPath = path64.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76678
+ const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
76434
76679
  if (!fs53.existsSync(settingsPath)) return false;
76435
76680
  try {
76436
76681
  const settings = readSettings(settingsPath);
@@ -76448,7 +76693,7 @@ function repoOption(y) {
76448
76693
  function handleInstall2(argv) {
76449
76694
  try {
76450
76695
  if (argv.claude) {
76451
- const result2 = installClaudeGuard(path65.resolve(argv.repo));
76696
+ const result2 = installClaudeGuard(path64.resolve(argv.repo));
76452
76697
  success("Claude Code worktree guard installed.");
76453
76698
  info(`Guard script: ${result2.guardScript}`);
76454
76699
  info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
@@ -76456,7 +76701,7 @@ function handleInstall2(argv) {
76456
76701
  info("Commit both files so the guard travels with the repo.");
76457
76702
  return;
76458
76703
  }
76459
- const result = installHooks({ repoPath: path65.resolve(argv.repo), force: argv.force });
76704
+ const result = installHooks({ repoPath: path64.resolve(argv.repo), force: argv.force });
76460
76705
  success(`Commit gate installed in ${result.hooksDir}`);
76461
76706
  info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
76462
76707
  info("Commits of unverified change batches will be blocked in agent worktrees.");
@@ -76469,7 +76714,7 @@ function handleInstall2(argv) {
76469
76714
  function handleUninstall(argv) {
76470
76715
  try {
76471
76716
  if (argv.claude) {
76472
- const result2 = uninstallClaudeGuard(path65.resolve(argv.repo));
76717
+ const result2 = uninstallClaudeGuard(path64.resolve(argv.repo));
76473
76718
  if (result2.removed) {
76474
76719
  success("Claude Code worktree guard removed.");
76475
76720
  } else {
@@ -76477,7 +76722,7 @@ function handleUninstall(argv) {
76477
76722
  }
76478
76723
  return;
76479
76724
  }
76480
- const result = uninstallHooks(path65.resolve(argv.repo));
76725
+ const result = uninstallHooks(path64.resolve(argv.repo));
76481
76726
  if (result.removed) {
76482
76727
  success(`Commit gate removed from ${result.hooksDir}`);
76483
76728
  } else {
@@ -76490,7 +76735,7 @@ function handleUninstall(argv) {
76490
76735
  }
76491
76736
  function handleStatus2(argv) {
76492
76737
  try {
76493
- const status = getHooksStatus(path65.resolve(argv.repo));
76738
+ const status = getHooksStatus(path64.resolve(argv.repo));
76494
76739
  if (argv.json) {
76495
76740
  process.stdout.write(`${JSON.stringify(status, null, 2)}
76496
76741
  `);
@@ -76508,7 +76753,7 @@ function handleStatus2(argv) {
76508
76753
  );
76509
76754
  info(`Effective: ${status.effectiveMode} (in this checkout)`);
76510
76755
  info(
76511
- `Claude guard: ${claudeGuardInstalled(path65.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
76756
+ `Claude guard: ${claudeGuardInstalled(path64.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
76512
76757
  );
76513
76758
  } catch (err) {
76514
76759
  error(err instanceof Error ? err.message : String(err));
@@ -76769,10 +77014,10 @@ function assignProp(target, prop, value) {
76769
77014
  configurable: true
76770
77015
  });
76771
77016
  }
76772
- function getElementAtPath(obj, path70) {
76773
- if (!path70)
77017
+ function getElementAtPath(obj, path69) {
77018
+ if (!path69)
76774
77019
  return obj;
76775
- return path70.reduce((acc, key) => acc?.[key], obj);
77020
+ return path69.reduce((acc, key) => acc?.[key], obj);
76776
77021
  }
76777
77022
  function promiseAllObject(promisesObj) {
76778
77023
  const keys = Object.keys(promisesObj);
@@ -77092,11 +77337,11 @@ function aborted(x, startIndex = 0) {
77092
77337
  }
77093
77338
  return false;
77094
77339
  }
77095
- function prefixIssues(path70, issues) {
77340
+ function prefixIssues(path69, issues) {
77096
77341
  return issues.map((iss) => {
77097
77342
  var _a2;
77098
77343
  (_a2 = iss).path ?? (_a2.path = []);
77099
- iss.path.unshift(path70);
77344
+ iss.path.unshift(path69);
77100
77345
  return iss;
77101
77346
  });
77102
77347
  }
@@ -82419,7 +82664,7 @@ var Protocol = class {
82419
82664
  return;
82420
82665
  }
82421
82666
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
82422
- await new Promise((resolve53) => setTimeout(resolve53, pollInterval));
82667
+ await new Promise((resolve52) => setTimeout(resolve52, pollInterval));
82423
82668
  options?.signal?.throwIfAborted();
82424
82669
  }
82425
82670
  } catch (error3) {
@@ -82436,7 +82681,7 @@ var Protocol = class {
82436
82681
  */
82437
82682
  request(request, resultSchema, options) {
82438
82683
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
82439
- return new Promise((resolve53, reject) => {
82684
+ return new Promise((resolve52, reject) => {
82440
82685
  const earlyReject = (error3) => {
82441
82686
  reject(error3);
82442
82687
  };
@@ -82514,7 +82759,7 @@ var Protocol = class {
82514
82759
  if (!parseResult.success) {
82515
82760
  reject(parseResult.error);
82516
82761
  } else {
82517
- resolve53(parseResult.data);
82762
+ resolve52(parseResult.data);
82518
82763
  }
82519
82764
  } catch (error3) {
82520
82765
  reject(error3);
@@ -82775,12 +83020,12 @@ var Protocol = class {
82775
83020
  }
82776
83021
  } catch {
82777
83022
  }
82778
- return new Promise((resolve53, reject) => {
83023
+ return new Promise((resolve52, reject) => {
82779
83024
  if (signal.aborted) {
82780
83025
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
82781
83026
  return;
82782
83027
  }
82783
- const timeoutId = setTimeout(resolve53, interval);
83028
+ const timeoutId = setTimeout(resolve52, interval);
82784
83029
  signal.addEventListener("abort", () => {
82785
83030
  clearTimeout(timeoutId);
82786
83031
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -83570,7 +83815,7 @@ var Server = class extends Protocol {
83570
83815
  };
83571
83816
 
83572
83817
  // src/mcp/server.ts
83573
- var path66 = __toESM(require("path"));
83818
+ var path65 = __toESM(require("path"));
83574
83819
 
83575
83820
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
83576
83821
  var import_node_process3 = __toESM(require("node:process"), 1);
@@ -83653,12 +83898,12 @@ var StdioServerTransport = class {
83653
83898
  this.onclose?.();
83654
83899
  }
83655
83900
  send(message) {
83656
- return new Promise((resolve53) => {
83901
+ return new Promise((resolve52) => {
83657
83902
  const json = serializeMessage(message);
83658
83903
  if (this._stdout.write(json)) {
83659
- resolve53();
83904
+ resolve52();
83660
83905
  } else {
83661
- this._stdout.once("drain", resolve53);
83906
+ this._stdout.once("drain", resolve52);
83662
83907
  }
83663
83908
  });
83664
83909
  }
@@ -84297,7 +84542,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
84297
84542
  const input = ControlUpInputSchema.parse({ ...args, repo });
84298
84543
  const result = await startControlAndSync({
84299
84544
  detach: input.detach,
84300
- cwd: path66.resolve(input.repo)
84545
+ cwd: path65.resolve(input.repo)
84301
84546
  });
84302
84547
  if (result.code !== 0) {
84303
84548
  return {
@@ -84361,11 +84606,11 @@ var mcpCommand = {
84361
84606
  };
84362
84607
 
84363
84608
  // src/cli/commands/onboard.ts
84364
- var path68 = __toESM(require("path"));
84609
+ var path67 = __toESM(require("path"));
84365
84610
  init_stages();
84366
84611
 
84367
84612
  // src/core/onboarding.ts
84368
- var path67 = __toESM(require("path"));
84613
+ var path66 = __toESM(require("path"));
84369
84614
  init_control_config();
84370
84615
  init_control_sync();
84371
84616
  init_otel_hooks();
@@ -84509,7 +84754,7 @@ async function defaultEnsureControl(options) {
84509
84754
  return { started: true, apiUrl: result.apiUrl };
84510
84755
  }
84511
84756
  async function runOnboarding(options, deps = {}) {
84512
- const repoPath = path67.resolve(options.repoPath);
84757
+ const repoPath = path66.resolve(options.repoPath);
84513
84758
  const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
84514
84759
  const ensureControl = deps.ensureControl ?? defaultEnsureControl;
84515
84760
  const init = deps.initHarness ?? initHarness;
@@ -84707,7 +84952,7 @@ async function promptChoices(args, docker) {
84707
84952
  };
84708
84953
  }
84709
84954
  const pluginChoices = listPluginChoices();
84710
- const repoPath = path68.resolve(args.repo);
84955
+ const repoPath = path67.resolve(args.repo);
84711
84956
  const alreadyPresent = harnessExists(repoPath);
84712
84957
  const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
84713
84958
  const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
@@ -84828,7 +85073,7 @@ function printSummary(result) {
84828
85073
  console.error("");
84829
85074
  }
84830
85075
  async function handleOnboard(argv) {
84831
- const repoPath = path68.resolve(argv.repo);
85076
+ const repoPath = path67.resolve(argv.repo);
84832
85077
  header("har onboard");
84833
85078
  info(`Repository: ${repoPath}`);
84834
85079
  try {
@@ -85062,7 +85307,7 @@ var preferencesCommand = {
85062
85307
  };
85063
85308
 
85064
85309
  // src/cli/commands/telemetry.ts
85065
- var path69 = __toESM(require("path"));
85310
+ var path68 = __toESM(require("path"));
85066
85311
  init_control_config();
85067
85312
  init_control_sync();
85068
85313
  init_manifest();
@@ -85155,7 +85400,7 @@ async function handleOff() {
85155
85400
  info("Mission Control will not auto-start. Existing usage rows are kept.");
85156
85401
  }
85157
85402
  async function handleWriteEnv(argv) {
85158
- const repoPath = path69.resolve(argv.repo);
85403
+ const repoPath = path68.resolve(argv.repo);
85159
85404
  const harnessRoot = resolveHarnessRoot(repoPath);
85160
85405
  const session = readSlotRegistry(harnessRoot, argv.agentId);
85161
85406
  const workDir = argv.workDir ?? session?.workDir ?? repoPath;
@@ -85167,7 +85412,7 @@ async function handleWriteEnv(argv) {
85167
85412
  suffix,
85168
85413
  createdAt: session?.createdAt
85169
85414
  });
85170
- const envFile = argv.envFile ?? path69.join(workDir, `.env.agent.${argv.agentId}`);
85415
+ const envFile = argv.envFile ?? path68.join(workDir, `.env.agent.${argv.agentId}`);
85171
85416
  const attrs = {
85172
85417
  sessionKey,
85173
85418
  agentId: argv.agentId,
@@ -85183,7 +85428,7 @@ async function handleWriteEnv(argv) {
85183
85428
  success(`Wrote session attribution to ${envFile}`);
85184
85429
  }
85185
85430
  function handlePrintEnv(argv) {
85186
- const repoPath = path69.resolve(argv.repo);
85431
+ const repoPath = path68.resolve(argv.repo);
85187
85432
  const workDir = argv.workDir ?? repoPath;
85188
85433
  const sessionKey = buildSessionKey({
85189
85434
  branch: argv.branch,