claude-use 9.19.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -472,7 +472,7 @@ var init_schema = __esm({
472
472
  context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
473
473
  }
474
474
  });
475
- HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@53525f479f2f48e8ef6b08cf729601feab7d2382";
475
+ HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@ca7589c574bfd52919503a74f09f4d1fe5ecf106";
476
476
  HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
477
477
  FrontDoorGlobalConfigSchema = import_zod.z.strictObject({
478
478
  /** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
@@ -2607,9 +2607,71 @@ function writeFrontDoorState(fs12, stateFile, state) {
2607
2607
  fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
2608
2608
  `);
2609
2609
  }
2610
+ function directOrigin(port) {
2611
+ return `http://127.0.0.1:${String(port)}`;
2612
+ }
2610
2613
  function frontDoorOrigin(state) {
2611
2614
  const port = state?.directPort ?? state?.lastDirectPort;
2612
- return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
2615
+ return port === void 0 ? void 0 : directOrigin(port);
2616
+ }
2617
+ function writeFrontDoorDirectRecord(fs12, recordsDir, record) {
2618
+ fs12.mkdirp(recordsDir);
2619
+ fs12.writeFilePrivate(import_node_path8.default.join(recordsDir, `${String(record.pid)}.json`), `${JSON.stringify({ directPort: record.directPort })}
2620
+ `);
2621
+ }
2622
+ function removeFrontDoorDirectRecord(fs12, recordsDir, pid) {
2623
+ fs12.removeRecursive(import_node_path8.default.join(recordsDir, `${String(pid)}.json`));
2624
+ }
2625
+ function recordPid(file) {
2626
+ const pidText = /^([1-9]\d*)\.json$/.exec(file)?.[1];
2627
+ const pid = pidText === void 0 ? void 0 : Number(pidText);
2628
+ return pid !== void 0 && Number.isSafeInteger(pid) ? pid : void 0;
2629
+ }
2630
+ function readDirectRecordEntry(fs12, recordsDir, file) {
2631
+ const pid = recordPid(file);
2632
+ if (pid === void 0) {
2633
+ return void 0;
2634
+ }
2635
+ let raw;
2636
+ try {
2637
+ raw = fs12.readFileUtf8(import_node_path8.default.join(recordsDir, file));
2638
+ } catch {
2639
+ return void 0;
2640
+ }
2641
+ if (raw === void 0) {
2642
+ return void 0;
2643
+ }
2644
+ try {
2645
+ const parsed = FrontDoorDirectRecordSchema.safeParse(JSON.parse(raw));
2646
+ return parsed.success ? { record: { pid, directPort: parsed.data.directPort } } : { malformed: true };
2647
+ } catch {
2648
+ return { malformed: true };
2649
+ }
2650
+ }
2651
+ function listFrontDoorDirectRecords(fs12, recordsDir) {
2652
+ return fs12.readdir(recordsDir).flatMap((file) => {
2653
+ const entry = readDirectRecordEntry(fs12, recordsDir, file);
2654
+ return entry?.record === void 0 ? [] : [entry.record];
2655
+ }).sort((a, b) => a.pid - b.pid);
2656
+ }
2657
+ function pruneMalformedFrontDoorDirectFiles(fs12, recordsDir, isRunning) {
2658
+ for (const file of fs12.readdir(recordsDir)) {
2659
+ const writer = RECORD_TEMPORARY_FILE.exec(file)?.[1];
2660
+ const stale = writer !== void 0 && !isRunning(Number(writer));
2661
+ if (stale || readDirectRecordEntry(fs12, recordsDir, file)?.malformed === true) {
2662
+ fs12.removeRecursive(import_node_path8.default.join(recordsDir, file));
2663
+ }
2664
+ }
2665
+ }
2666
+ function liveFrontDoorDirectRecords(records, liveness) {
2667
+ return records.filter((record) => liveness.doors.has(record.pid) || liveness.unknown.has(record.pid));
2668
+ }
2669
+ function pruneDeadFrontDoorDirectRecords(fs12, recordsDir, records, liveness) {
2670
+ for (const record of records) {
2671
+ if (!liveness.doors.has(record.pid) && !liveness.unknown.has(record.pid)) {
2672
+ removeFrontDoorDirectRecord(fs12, recordsDir, record.pid);
2673
+ }
2674
+ }
2613
2675
  }
2614
2676
  function writeFrontDoorSession(fs12, sessionsDir, session) {
2615
2677
  fs12.mkdirPrivate(sessionsDir);
@@ -2646,7 +2708,7 @@ function pruneDeadFrontDoorSessions(fs12, sessionsDir, isRunning) {
2646
2708
  }
2647
2709
  return removed;
2648
2710
  }
2649
- var import_node_path8, import_zod3, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema;
2711
+ var import_node_path8, import_zod3, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
2650
2712
  var init_state = __esm({
2651
2713
  "src/frontdoor/state.ts"() {
2652
2714
  "use strict";
@@ -2676,7 +2738,7 @@ var init_state = __esm({
2676
2738
  */
2677
2739
  lastConnectPort: import_zod3.z.number().int().positive().optional(),
2678
2740
  /**
2679
- * The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin and an ephemeral port would invalidate the allowlist on every restart.
2741
+ * The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin: the headroom supervisor rewrites the daemon's allowlist file when the origin moves, but a provider launch waits at its gate until it has, so an ephemeral port would hold launches up after every restart.
2680
2742
  */
2681
2743
  directPort: import_zod3.z.number().int().positive().optional(),
2682
2744
  /** The sticky port preference for the direct listener, for the reason `directPort` gives. */
@@ -2684,6 +2746,9 @@ var init_state = __esm({
2684
2746
  /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
2685
2747
  lastError: import_zod3.z.string().optional()
2686
2748
  });
2749
+ MAX_TCP_PORT = 65535;
2750
+ FrontDoorDirectRecordSchema = import_zod3.z.strictObject({ directPort: import_zod3.z.number().int().positive().max(MAX_TCP_PORT) });
2751
+ RECORD_TEMPORARY_FILE = /^[1-9]\d*\.json\.([1-9]\d*)\.tmp$/;
2687
2752
  }
2688
2753
  });
2689
2754
 
@@ -2693,7 +2758,7 @@ var init_package = __esm({
2693
2758
  "package.json"() {
2694
2759
  package_default = {
2695
2760
  name: "claude-use",
2696
- version: "9.19.0",
2761
+ version: "10.0.0",
2697
2762
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
2698
2763
  license: "MIT",
2699
2764
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -2818,11 +2883,75 @@ function listFrontDoorSupervisors(run, uid) {
2818
2883
  }
2819
2884
  return { ok: true, pids: parseFrontDoorSupervisorPids(result.stdout) };
2820
2885
  }
2821
- var FRONT_DOOR_SUPERVISOR_ARGUMENT;
2886
+ function frontDoorLivenessFromPs(run, asked) {
2887
+ if (refusedEveryPidAsTooLarge(run, asked)) {
2888
+ return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
2889
+ }
2890
+ const failure = psFailure(run);
2891
+ if (failure !== void 0) {
2892
+ return { doors: /* @__PURE__ */ new Set(), unknown: new Map(asked.map((pid) => [pid, failure])) };
2893
+ }
2894
+ const askedSet = new Set(asked);
2895
+ const seen = /* @__PURE__ */ new Set();
2896
+ const doors = /* @__PURE__ */ new Set();
2897
+ for (const line of run.stdout.split("\n")) {
2898
+ const [pidText, stat, ...argumentsList] = line.trim().split(/\s+/);
2899
+ const pid = Number(pidText);
2900
+ if (!askedSet.has(pid) || seen.has(pid)) {
2901
+ continue;
2902
+ }
2903
+ seen.add(pid);
2904
+ if (stat !== void 0 && !stat.startsWith("Z") && argumentsList.includes(FRONT_DOOR_SUPERVISOR_ARGUMENT)) {
2905
+ doors.add(pid);
2906
+ }
2907
+ }
2908
+ return { doors, unknown: /* @__PURE__ */ new Map() };
2909
+ }
2910
+ function refusedEveryPidAsTooLarge(run, asked) {
2911
+ const lines = run.stderr.split("\n").filter((line) => line.trim() !== "");
2912
+ const tooLarge = new Set(lines.map((line) => Number(PID_TOO_LARGE.exec(line.trim())?.[1])));
2913
+ return run.status === 1 && run.stdout.trim() === "" && lines.length > 0 && lines.every((line) => PID_TOO_LARGE.test(line.trim())) && asked.every((pid) => tooLarge.has(pid));
2914
+ }
2915
+ function psFailure(run) {
2916
+ if (run.error !== void 0) {
2917
+ return run.error.message;
2918
+ }
2919
+ if (run.status === null) {
2920
+ return "ps was terminated before it answered";
2921
+ }
2922
+ const noneExist = run.status === 1 && run.stdout.trim() === "" && run.stderr.trim() === "";
2923
+ if (run.status !== 0 && !noneExist) {
2924
+ return `ps exited ${String(run.status)}${run.stderr.trim() === "" ? "" : `: ${run.stderr.trim()}`}`;
2925
+ }
2926
+ return void 0;
2927
+ }
2928
+ function frontDoorLivenessOf(pids, runPs) {
2929
+ if (pids.length === 0) {
2930
+ return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
2931
+ }
2932
+ const batch = frontDoorLivenessFromPs(runPs(pids), pids);
2933
+ if (batch.unknown.size === 0 || pids.length === 1) {
2934
+ return batch;
2935
+ }
2936
+ const doors = /* @__PURE__ */ new Set();
2937
+ const unknown = /* @__PURE__ */ new Map();
2938
+ for (const pid of pids) {
2939
+ const single = frontDoorLivenessFromPs(runPs([pid]), [pid]);
2940
+ for (const door of single.doors) {
2941
+ doors.add(door);
2942
+ }
2943
+ for (const [unanswered, reason] of single.unknown) {
2944
+ unknown.set(unanswered, reason);
2945
+ }
2946
+ }
2947
+ return { doors, unknown };
2948
+ }
2949
+ var FRONT_DOOR_SUPERVISOR_ARGUMENT, PID_TOO_LARGE;
2822
2950
  var init_supervisorProcesses = __esm({
2823
2951
  "src/frontdoor/supervisorProcesses.ts"() {
2824
2952
  "use strict";
2825
2953
  FRONT_DOOR_SUPERVISOR_ARGUMENT = "__frontdoor-supervisor";
2954
+ PID_TOO_LARGE = /^ps: process id too large: (\d+)$/;
2826
2955
  }
2827
2956
  });
2828
2957
 
@@ -2872,22 +3001,49 @@ function migrateHeadroomState(fs12, files, isRunning) {
2872
3001
  }
2873
3002
  fs12.removeRecursive(files.legacyStateFile);
2874
3003
  }
2875
- function headroomAllowlist(providers) {
2876
- const urls = /* @__PURE__ */ new Set([HEADROOM_ANTHROPIC_UPSTREAM]);
2877
- for (const provider of providers) {
2878
- urls.add(provider.baseUrl);
3004
+ function hashAllowlist(allowlist) {
3005
+ return (0, import_node_crypto6.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
3006
+ }
3007
+ function formatAllowlistFile(allowlist) {
3008
+ return allowlist.map((entry) => `${entry}
3009
+ `).join("");
3010
+ }
3011
+ function hashAllowlistFile(content) {
3012
+ return hashAllowlist([...new Set(parseAllowlistFile(content))].sort());
3013
+ }
3014
+ function isBareHost(entry) {
3015
+ if (/[/?#@]/.test(entry)) {
3016
+ return false;
2879
3017
  }
2880
- return [...urls].sort();
3018
+ if (entry.startsWith("[")) {
3019
+ const close = entry.indexOf("]");
3020
+ return close > 1 && !entry.slice(close + 1).includes(":");
3021
+ }
3022
+ return entry !== "" && !entry.includes(":");
2881
3023
  }
2882
- function headroomUpstreams(providers, frontDoorOrigin2) {
2883
- const upstreams = providers.filter((provider) => !isCodexProvider(provider)).map((provider) => ({ baseUrl: provider.baseUrl }));
2884
- if (providers.length > 0 && frontDoorOrigin2 !== void 0) {
2885
- upstreams.push({ baseUrl: frontDoorOrigin2 });
3024
+ function isAdmissibleUrl(entry) {
3025
+ try {
3026
+ const url = new URL(entry);
3027
+ return ALLOWLIST_SAFE_SCHEMES.has(url.protocol) && url.hostname !== "";
3028
+ } catch {
3029
+ return false;
2886
3030
  }
2887
- return upstreams;
2888
3031
  }
2889
- function hashAllowlist(allowlist) {
2890
- return (0, import_node_crypto6.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
3032
+ function parseAllowlistFile(content) {
3033
+ return content.replace(/^\uFEFF/, "").replace(ALLOWLIST_FILE_COMMENT, "").split(ALLOWLIST_FILE_SEPARATORS).map((entry) => entry.replace(ALLOWLIST_SURROUNDING_WHITESPACE, "")).filter((entry) => entry !== "" && !ALLOWLIST_ENTRY_WHITESPACE.test(entry) && (entry.includes("://") ? isAdmissibleUrl(entry) : isBareHost(entry)));
3034
+ }
3035
+ function writeAllowlistFile(fs12, allowlistFile, allowlist) {
3036
+ fs12.mkdirPrivate(import_node_path11.default.dirname(allowlistFile));
3037
+ fs12.writeFilePrivate(allowlistFile, formatAllowlistFile(allowlist));
3038
+ }
3039
+ function pruneStaleAllowlistTemporaries(fs12, allowlistFile, isRunning) {
3040
+ const prefix = `${import_node_path11.default.basename(allowlistFile)}.`;
3041
+ for (const name of fs12.readdir(import_node_path11.default.dirname(allowlistFile))) {
3042
+ const writer = name.startsWith(prefix) ? /^([1-9]\d*)\.tmp$/.exec(name.slice(prefix.length))?.[1] : void 0;
3043
+ if (writer !== void 0 && !isRunning(Number(writer))) {
3044
+ fs12.removeRecursive(import_node_path11.default.join(import_node_path11.default.dirname(allowlistFile), name));
3045
+ }
3046
+ }
2891
3047
  }
2892
3048
  function readAllProviders(fs12, providersDir) {
2893
3049
  const result = [];
@@ -2951,7 +3107,7 @@ function readStartLock(fs12, lockFile) {
2951
3107
  return void 0;
2952
3108
  }
2953
3109
  }
2954
- var import_node_crypto6, import_node_path11, import_zod8, HEADROOM_ANTHROPIC_UPSTREAM, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema;
3110
+ var import_node_crypto6, import_node_path11, import_zod8, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema, HEADROOM_ALLOWLIST_FILE_FLAG, ALLOWLIST_LINE_BREAKS, ALLOWLIST_WHITESPACE, ALLOWLIST_FILE_SEPARATORS, ALLOWLIST_FILE_COMMENT, ALLOWLIST_ENTRY_WHITESPACE, ALLOWLIST_SURROUNDING_WHITESPACE, ALLOWLIST_SAFE_SCHEMES;
2955
3111
  var init_state2 = __esm({
2956
3112
  "src/headroom/state.ts"() {
2957
3113
  "use strict";
@@ -2959,11 +3115,10 @@ var init_state2 = __esm({
2959
3115
  import_node_path11 = __toESM(require("node:path"), 1);
2960
3116
  import_zod8 = require("zod");
2961
3117
  init_schema();
2962
- HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
2963
3118
  HeadroomStateSchema = import_zod8.z.strictObject({
2964
3119
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
2965
3120
  supervisorPid: import_zod8.z.number().int().positive().optional(),
2966
- /** The headroom proxy process itself. Absent while the supervisor is between restarts. */
3121
+ /** The headroom proxy process itself, recorded as soon as it is spawned (before it is ready, which `socketPath` signals) so a successor can find a daemon whose supervisor died during its start. Absent while the supervisor is between restarts. */
2967
3122
  headroomPid: import_zod8.z.number().int().positive().optional(),
2968
3123
  /**
2969
3124
  * The unix socket the proxy serves on, inside the owner-only socket directory. Absent until the proxy has passed its readiness check, so "socketPath is set" is itself the ready signal a launcher polls for. The front door reads it on every hop, so a restart (which keeps the generation's path) is followed without anything being relaunched.
@@ -2971,7 +3126,9 @@ var init_state2 = __esm({
2971
3126
  socketPath: import_zod8.z.string().min(1).optional(),
2972
3127
  /** The `headroom --version` output of the running install. */
2973
3128
  version: import_zod8.z.string().optional(),
2974
- /** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
3129
+ /**
3130
+ * Hash of the allowlist the running proxy serves. The supervisor records it in the same tick it writes that allowlist to `LayoutPaths.headroomAllowlistFile`, which the proxy re-reads on its next request, so a provider launch, whose requests come back through its front door's direct origin, waits until this names an allowlist holding that origin. A supervisor from an earlier release records here the hash of the allowlist its daemon was started with instead (see `earlierRelease.ts`).
3131
+ */
2975
3132
  allowlistHash: import_zod8.z.string().optional(),
2976
3133
  /** Hash of the token-saving settings the running proxy was started with, so a settings change is detected as drift. */
2977
3134
  settingsHash: import_zod8.z.string().optional(),
@@ -2982,33 +3139,133 @@ var init_state2 = __esm({
2982
3139
  });
2983
3140
  HeadroomSessionSchema = import_zod8.z.strictObject({ pid: import_zod8.z.number().int().positive(), startedAt: import_zod8.z.number(), supervisorPid: import_zod8.z.number().int().positive() });
2984
3141
  HeadroomLockSchema = import_zod8.z.strictObject({ pid: import_zod8.z.number().int().positive(), at: import_zod8.z.number() });
3142
+ HEADROOM_ALLOWLIST_FILE_FLAG = "--allowed-base-urls-file";
3143
+ ALLOWLIST_LINE_BREAKS = "\\n\\r\\u000b\\u000c\\u001c\\u001d\\u001e\\u0085\\u2028\\u2029";
3144
+ ALLOWLIST_WHITESPACE = "\\t\\n\\u000b\\u000c\\r\\u001c-\\u001f \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
3145
+ ALLOWLIST_FILE_SEPARATORS = new RegExp(`[,\\t${ALLOWLIST_LINE_BREAKS}]`, "u");
3146
+ ALLOWLIST_FILE_COMMENT = new RegExp(`(?:^|(?<=[${ALLOWLIST_WHITESPACE}]))#[^${ALLOWLIST_LINE_BREAKS}]*`, "gu");
3147
+ ALLOWLIST_ENTRY_WHITESPACE = new RegExp(`[${ALLOWLIST_WHITESPACE}]`, "u");
3148
+ ALLOWLIST_SURROUNDING_WHITESPACE = new RegExp(`^[${ALLOWLIST_WHITESPACE}]+|[${ALLOWLIST_WHITESPACE}]+$`, "gu");
3149
+ ALLOWLIST_SAFE_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "ws:", "wss:"]);
3150
+ }
3151
+ });
3152
+
3153
+ // src/headroom/earlierRelease.ts
3154
+ function withoutOurSocket(commandLine, socketPath) {
3155
+ for (const argument of [`--uds ${socketPath}`, `--uds=${socketPath}`]) {
3156
+ let from = 0;
3157
+ for (; ; ) {
3158
+ const index = commandLine.indexOf(argument, from);
3159
+ if (index === -1) {
3160
+ break;
3161
+ }
3162
+ const end = index + argument.length;
3163
+ const startsArgument = index === 0 || /\s/.test(commandLine.charAt(index - 1));
3164
+ const endsArgument = end === commandLine.length || /\s/.test(commandLine.charAt(end));
3165
+ if (startsArgument && endsArgument) {
3166
+ return `${commandLine.slice(0, index)} ${commandLine.slice(end)}`;
3167
+ }
3168
+ from = index + 1;
3169
+ }
3170
+ }
3171
+ return void 0;
3172
+ }
3173
+ function daemonIdentity(commandLine, socketPath) {
3174
+ if (commandLine === void 0) {
3175
+ return "unreadable";
3176
+ }
3177
+ const rest = withoutOurSocket(commandLine, socketPath);
3178
+ const argumentsList = rest === void 0 ? [] : rest.trim().split(/\s+/);
3179
+ if (rest === void 0 || !argumentsList.includes("proxy")) {
3180
+ return "not-headroom";
3181
+ }
3182
+ return argumentsList.some((argument) => argument === HEADROOM_ALLOWLIST_FILE_FLAG || argument.startsWith(`${HEADROOM_ALLOWLIST_FILE_FLAG}=`)) ? "this-release" : "earlier-release";
3183
+ }
3184
+ function earlierReleaseAllowlistHash(providers, doorOrigin) {
3185
+ const entries = /* @__PURE__ */ new Set([EARLIER_RELEASE_ANTHROPIC_UPSTREAM]);
3186
+ for (const provider of providers) {
3187
+ if (!isCodexProvider(provider)) {
3188
+ entries.add(provider.baseUrl);
3189
+ }
3190
+ }
3191
+ if (providers.length > 0 && doorOrigin !== void 0) {
3192
+ entries.add(doorOrigin);
3193
+ }
3194
+ return hashAllowlist([...entries].sort());
3195
+ }
3196
+ function earlierReleaseDaemon(fs12, paths, daemon) {
3197
+ if (daemonIdentity(daemon.commandLine, daemon.socketPath) !== "earlier-release") {
3198
+ return void 0;
3199
+ }
3200
+ const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
3201
+ const expected = earlierReleaseAllowlistHash(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile)));
3202
+ return { admitsServingDoor: daemon.recordedHash === expected };
3203
+ }
3204
+ var EARLIER_RELEASE_ALLOWLIST, EARLIER_RELEASE_ANTHROPIC_UPSTREAM;
3205
+ var init_earlierRelease = __esm({
3206
+ "src/headroom/earlierRelease.ts"() {
3207
+ "use strict";
3208
+ init_schema();
3209
+ init_state();
3210
+ init_state2();
3211
+ EARLIER_RELEASE_ALLOWLIST = "started by an earlier release with an allowlist fixed at start; it restarts once its sessions end";
3212
+ EARLIER_RELEASE_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
2985
3213
  }
2986
3214
  });
2987
3215
 
2988
3216
  // src/headroom/ensure.ts
3217
+ function awaitingCause(daemonPid, identity, allowlistFile) {
3218
+ if (identity === "unreadable") {
3219
+ return `could not read the command line of the headroom daemon (pid ${String(daemonPid)}), so whether it reads an allowlist file is unknown, and its allowlist was not recorded as admitting this launch's upstreams within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
3220
+ }
3221
+ if (identity === "not-headroom") {
3222
+ return `the headroom daemon pid ${String(daemonPid)} the state records is no longer a headroom proxy on its socket, and no daemon was recorded as admitting this launch's upstreams within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
3223
+ }
3224
+ return `the headroom supervisor has not written an allowlist admitting this launch's upstreams to ${allowlistFile} within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
3225
+ }
3226
+ function daemonAdmits(fs12, allowlistFile, recordedHash, required) {
3227
+ const content = fs12.readFileUtf8(allowlistFile);
3228
+ if (content === void 0 || recordedHash === void 0) {
3229
+ return false;
3230
+ }
3231
+ const served = parseAllowlistFile(content);
3232
+ return recordedHash === hashAllowlistFile(content) && required.every((upstream) => served.includes(upstream));
3233
+ }
2989
3234
  function ensureHeadroom(params) {
2990
3235
  const { paths, ports } = params;
2991
3236
  const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
2992
3237
  let spawnedSupervisor = false;
2993
- let awaitingAllowlist = false;
2994
3238
  migrateHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
3239
+ const commandLines = /* @__PURE__ */ new Map();
3240
+ const commandLineOf = (pid) => {
3241
+ if (!commandLines.has(pid)) {
3242
+ commandLines.set(pid, ports.daemonCommandLine(pid));
3243
+ }
3244
+ return commandLines.get(pid);
3245
+ };
2995
3246
  for (; ; ) {
3247
+ let awaiting;
2996
3248
  const state = resolveServingHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
2997
3249
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
2998
3250
  const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
2999
- if (daemonUp && state.socketPath !== void 0) {
3000
- const required = params.requiredAllowlistHash?.();
3001
- if (required === void 0 || state.allowlistHash === required) {
3251
+ if (daemonUp && state.socketPath !== void 0 && state.headroomPid !== void 0) {
3252
+ const required = params.requiredUpstreams?.();
3253
+ if (required === void 0 || daemonAdmits(ports.fs, paths.headroomAllowlistFile, state.allowlistHash, required)) {
3002
3254
  writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
3003
3255
  return { socketPath: state.socketPath };
3004
3256
  }
3005
- const holders = sessionsForSupervisor(ports.fs, paths.headroomSessionsDir, state.supervisorPid).filter((session) => ports.isRunning(session.pid));
3006
- if (holders.length > 0) {
3257
+ const commandLine = commandLineOf(state.headroomPid);
3258
+ const earlierRelease = earlierReleaseDaemon(ports.fs, paths, { commandLine, socketPath: state.socketPath, recordedHash: state.allowlistHash });
3259
+ if (earlierRelease !== void 0) {
3260
+ if (earlierRelease.admitsServingDoor) {
3261
+ writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
3262
+ return { socketPath: state.socketPath };
3263
+ }
3007
3264
  throw new HeadroomStartError(
3008
- `the running headroom daemon was started before this launch's front door address and would refuse every request this launch sends through it. It restarts once the launches using it end (pid ${holders.map((session) => String(session.pid)).join(", ")}); end them and launch again, or launch with --no-headroom.`
3265
+ `the running headroom daemon (pid ${String(state.headroomPid)}) was ${EARLIER_RELEASE_ALLOWLIST}, and its allowlist cannot be shown to admit the serving front door; launch with --no-headroom until then. Supervisor and daemon log: ${paths.headroomLogPath}`
3009
3266
  );
3010
3267
  }
3011
- awaitingAllowlist = true;
3268
+ awaiting = { daemonPid: state.headroomPid, identity: daemonIdentity(commandLine, state.socketPath) };
3012
3269
  }
3013
3270
  if (state.lastError !== void 0) {
3014
3271
  throw new HeadroomStartError(
@@ -3034,10 +3291,11 @@ function ensureHeadroom(params) {
3034
3291
  }
3035
3292
  }
3036
3293
  if (ports.now() >= deadline) {
3037
- const lastError = state?.lastError;
3038
- throw new HeadroomStartError(
3039
- `the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (awaitingAllowlist ? " (the running daemon's allowlist does not admit this launch's front door, and it did not restart)" : "") + `. Daemon log: ${paths.headroomLogPath}`
3040
- );
3294
+ const lastError = state?.lastError === void 0 ? "" : ` (last error: ${state.lastError})`;
3295
+ if (awaiting !== void 0) {
3296
+ throw new HeadroomStartError(`${awaitingCause(awaiting.daemonPid, awaiting.identity, paths.headroomAllowlistFile)}${lastError}, so the daemon would refuse every request this launch sends through it; launch with --no-headroom to bypass it. Supervisor and daemon log: ${paths.headroomLogPath}`);
3297
+ }
3298
+ throw new HeadroomStartError(`the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms${lastError}. Daemon log: ${paths.headroomLogPath}`);
3041
3299
  }
3042
3300
  ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
3043
3301
  }
@@ -3047,6 +3305,7 @@ var init_ensure = __esm({
3047
3305
  "src/headroom/ensure.ts"() {
3048
3306
  "use strict";
3049
3307
  init_cliError();
3308
+ init_earlierRelease();
3050
3309
  init_state2();
3051
3310
  HEADROOM_START_TIMEOUT_MS = 12e4;
3052
3311
  HEADROOM_LAUNCHER_POLL_MS = 250;
@@ -3094,6 +3353,22 @@ var init_settings = __esm({
3094
3353
  }
3095
3354
  });
3096
3355
 
3356
+ // src/frontdoor/capture.ts
3357
+ function redactText(text) {
3358
+ return SECRET_BODY_PATTERNS.reduce((accumulated, { pattern, replacement }) => accumulated.replace(pattern, replacement), text);
3359
+ }
3360
+ var SECRET_BODY_PATTERNS;
3361
+ var init_capture = __esm({
3362
+ "src/frontdoor/capture.ts"() {
3363
+ "use strict";
3364
+ SECRET_BODY_PATTERNS = [
3365
+ { pattern: /sk-ant-[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" },
3366
+ { pattern: /Bearer\s+[A-Za-z0-9._~+/=-]{8,}/gi, replacement: "Bearer <redacted>" },
3367
+ { pattern: /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" }
3368
+ ];
3369
+ }
3370
+ });
3371
+
3097
3372
  // src/headroom/socket.ts
3098
3373
  function headroomSocketPath(paths, supervisorPid) {
3099
3374
  return import_node_path12.default.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
@@ -3106,10 +3381,10 @@ function ownerOnlyRefusal(label, target, stat, expected, uid) {
3106
3381
  return `the headroom ${label} ${target} does not exist`;
3107
3382
  }
3108
3383
  if (stat.kind === "symlink") {
3109
- return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
3384
+ return `the headroom ${label} ${target} is a symlink; it must be the real ${KIND_NAMES[expected]}`;
3110
3385
  }
3111
3386
  if (stat.kind !== expected) {
3112
- return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
3387
+ return `the headroom ${label} ${target} is not a ${KIND_NAMES[expected]}`;
3113
3388
  }
3114
3389
  if (stat.uid !== uid) {
3115
3390
  return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
@@ -3129,6 +3404,86 @@ function verifyHeadroomSocket(socketPath, ports) {
3129
3404
  const refusal2 = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
3130
3405
  return refusal2 === void 0 ? { socketPath } : { refused: refusal2 };
3131
3406
  }
3407
+ function pathDirectories(target, ports) {
3408
+ const pending = target.split("/").reverse();
3409
+ let current = "/";
3410
+ const directories = [];
3411
+ let hops = 0;
3412
+ for (let name = pending.pop(); name !== void 0; name = pending.pop()) {
3413
+ if (name === "" || name === ".") {
3414
+ continue;
3415
+ }
3416
+ if (name === "..") {
3417
+ current = import_node_path12.default.dirname(current);
3418
+ continue;
3419
+ }
3420
+ if (!directories.includes(current)) {
3421
+ directories.push(current);
3422
+ }
3423
+ const entry = import_node_path12.default.join(current, name);
3424
+ if (pending.length > 0 && ports.lstat(entry)?.kind === "symlink") {
3425
+ hops += 1;
3426
+ if (hops > MAX_SYMLINK_HOPS) {
3427
+ return `the symlinks on the allowlist file's path go more than ${String(MAX_SYMLINK_HOPS)} deep`;
3428
+ }
3429
+ const linkTarget = ports.readlink(entry);
3430
+ if (import_node_path12.default.isAbsolute(linkTarget)) {
3431
+ current = "/";
3432
+ }
3433
+ pending.push(...linkTarget.split("/").reverse());
3434
+ } else if (pending.length > 0) {
3435
+ current = entry;
3436
+ }
3437
+ }
3438
+ return directories;
3439
+ }
3440
+ function headroomDirectoryRefusal(directory, stat, uid, remedy) {
3441
+ if (stat?.kind !== "dir") {
3442
+ return `the directory ${directory} on the allowlist file's path is ${stat === void 0 ? "missing" : "not a directory"}, so headroom refuses the file`;
3443
+ }
3444
+ if (stat.uid !== uid && stat.uid !== ROOT_UID) {
3445
+ return `the directory ${directory} on the allowlist file's path is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)}) or root, so headroom refuses the file${remedy ? `; ${MOVE_ROOT_REMEDY}` : ""}`;
3446
+ }
3447
+ if ((stat.mode & GROUP_OR_OTHER_WRITE_BITS) !== 0) {
3448
+ return `the directory ${directory} on the allowlist file's path is writable by group or others (mode ${stat.mode.toString(OCTAL_RADIX).padStart(MODE_DIGITS, "0")}), so headroom refuses the file${remedy ? `; ${stat.uid === uid && (stat.mode & STICKY_BIT) === 0 ? `run \`chmod go-w ${directory}\`` : MOVE_ROOT_REMEDY}` : ""}`;
3449
+ }
3450
+ return void 0;
3451
+ }
3452
+ function reportableAllowlistFileProblem(allowlistFile, ports, served) {
3453
+ const problem = verifyAllowlistFile(allowlistFile, ports);
3454
+ return problem?.repairable === false || served ? problem : void 0;
3455
+ }
3456
+ function verifyAllowlistFile(allowlistFile, ports) {
3457
+ const uid = ports.currentUid();
3458
+ const directories = pathDirectories(allowlistFile, ports);
3459
+ if (typeof directories === "string") {
3460
+ return { message: directories, repairable: false };
3461
+ }
3462
+ const socketDirectory = directories.at(-1);
3463
+ const headroomDirectory = socketDirectory === void 0 ? void 0 : import_node_path12.default.dirname(socketDirectory);
3464
+ for (const directory of directories) {
3465
+ const stat = ports.lstat(directory);
3466
+ if (directory === socketDirectory) {
3467
+ const refusal4 = ownerOnlyRefusal("allowlist directory", directory, stat, "dir", uid);
3468
+ if (refusal4 !== void 0) {
3469
+ return { message: refusal4, repairable: true };
3470
+ }
3471
+ continue;
3472
+ }
3473
+ const own = directory === headroomDirectory;
3474
+ const refusal3 = headroomDirectoryRefusal(directory, stat, uid, !own);
3475
+ if (refusal3 !== void 0) {
3476
+ return { message: refusal3, repairable: own };
3477
+ }
3478
+ }
3479
+ const fileStat = ports.lstat(allowlistFile);
3480
+ const refusal2 = ownerOnlyRefusal("allowlist file", allowlistFile, fileStat, "file", uid);
3481
+ if (refusal2 === void 0) {
3482
+ return void 0;
3483
+ }
3484
+ const replaceable = fileStat === void 0 || fileStat.kind === "file" || fileStat.kind === "symlink";
3485
+ return { message: refusal2, repairable: replaceable };
3486
+ }
3132
3487
  function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
3133
3488
  const unsupported = platformRefusal(ports.platform);
3134
3489
  if (unsupported !== void 0) {
@@ -3160,7 +3515,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
3160
3515
  }
3161
3516
  return removed;
3162
3517
  }
3163
- var import_node_path12, GROUP_OR_OTHER_BITS, OCTAL_RADIX, MODE_DIGITS, HEADROOM_SOCKET_SUFFIX, HEADROOM_SOCKET_NAME, UNIX_SOCKET_PATH_MAX_BYTES, PLATFORMS_WITHOUT_UNIX_SOCKETS;
3518
+ var import_node_path12, GROUP_OR_OTHER_BITS, OCTAL_RADIX, MODE_DIGITS, HEADROOM_SOCKET_SUFFIX, HEADROOM_SOCKET_NAME, UNIX_SOCKET_PATH_MAX_BYTES, PLATFORMS_WITHOUT_UNIX_SOCKETS, KIND_NAMES, MAX_SYMLINK_HOPS, ROOT_UID, GROUP_OR_OTHER_WRITE_BITS, STICKY_BIT, MOVE_ROOT_REMEDY;
3164
3519
  var init_socket = __esm({
3165
3520
  "src/headroom/socket.ts"() {
3166
3521
  "use strict";
@@ -3172,6 +3527,12 @@ var init_socket = __esm({
3172
3527
  HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
3173
3528
  UNIX_SOCKET_PATH_MAX_BYTES = 103;
3174
3529
  PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
3530
+ KIND_NAMES = { dir: "directory", file: "file", socket: "socket" };
3531
+ MAX_SYMLINK_HOPS = 40;
3532
+ ROOT_UID = 0;
3533
+ GROUP_OR_OTHER_WRITE_BITS = 18;
3534
+ STICKY_BIT = 512;
3535
+ MOVE_ROOT_REMEDY = "move the agent-shim root (AGENT_SHIM_HOME) to where every directory above it is owned by this user or root and not writable by group or others";
3175
3536
  }
3176
3537
  });
3177
3538
 
@@ -3288,6 +3649,36 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3288
3649
  ports.log(`agent-shim headroom supervisor: ${message}`);
3289
3650
  return 1;
3290
3651
  };
3652
+ const syncAllowlistFile = (allowlist) => {
3653
+ try {
3654
+ if (fs12.readFileUtf8(paths.headroomAllowlistFile) !== formatAllowlistFile(allowlist)) {
3655
+ writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
3656
+ ports.log(`agent-shim headroom supervisor: wrote allowlist [${allowlist.join(", ")}] to ${paths.headroomAllowlistFile}`);
3657
+ }
3658
+ return void 0;
3659
+ } catch (error) {
3660
+ return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
3661
+ }
3662
+ };
3663
+ const allowlistFileRefusal = (allowlist) => {
3664
+ const problem = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
3665
+ if (problem === void 0) {
3666
+ return void 0;
3667
+ }
3668
+ if (!problem.repairable) {
3669
+ return `headroom would refuse its allowlist file, and agent-shim cannot repair it: ${problem.message}`;
3670
+ }
3671
+ ports.log(`agent-shim headroom supervisor: repairing the allowlist file: ${problem.message}`);
3672
+ try {
3673
+ fs12.mkdirPrivate(paths.headroomDir);
3674
+ fs12.mkdirPrivate(import_node_path13.default.dirname(paths.headroomAllowlistFile));
3675
+ writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
3676
+ } catch (error) {
3677
+ return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
3678
+ }
3679
+ const remaining = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
3680
+ return remaining === void 0 ? void 0 : `the allowlist file breaks agent-shim's rules for it, and rewriting it did not repair it: ${remaining.message}`;
3681
+ };
3291
3682
  const ensureInstalled = () => {
3292
3683
  const version2 = ports.headroomVersion();
3293
3684
  const versionOk = version2 !== void 0 && versionSatisfies(version2, config.source);
@@ -3311,14 +3702,20 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3311
3702
  }
3312
3703
  const { socketPath } = socket;
3313
3704
  pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
3705
+ pruneStaleAllowlistTemporaries(fs12, paths.headroomAllowlistFile, ports.isRunning);
3314
3706
  if (!ensureInstalled()) {
3315
3707
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
3316
3708
  }
3317
3709
  const version = ports.headroomVersion() ?? "unknown";
3318
3710
  writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
3319
- ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
3711
+ ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness).frontDoorOrigins.join(", ")}]`);
3320
3712
  const orphanPid = previousState?.headroomPid;
3321
- if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
3713
+ const orphanSocket = previousState?.socketPath ?? (previousState?.supervisorPid === void 0 ? void 0 : headroomSocketPath(paths, previousState.supervisorPid));
3714
+ const orphanIdentity = orphanPid === void 0 || orphanSocket === void 0 || !ports.isRunning(orphanPid) ? void 0 : daemonIdentity(ports.daemonCommandLine(orphanPid), orphanSocket);
3715
+ if (orphanPid !== void 0 && (orphanIdentity === "not-headroom" || orphanIdentity === "unreadable")) {
3716
+ ports.log(`agent-shim headroom supervisor: leaving pid ${String(orphanPid)} alone: the state records it as the previous daemon, but it ${orphanIdentity === "unreadable" ? "cannot be identified" : "is no longer a headroom proxy on that generation's socket"}`);
3717
+ }
3718
+ if (orphanPid !== void 0 && (orphanIdentity === "this-release" || orphanIdentity === "earlier-release")) {
3322
3719
  ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
3323
3720
  ports.stopProcess(orphanPid);
3324
3721
  }
@@ -3326,9 +3723,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3326
3723
  let runningHash;
3327
3724
  let runningSettingsHash;
3328
3725
  let consecutiveFailures = 0;
3726
+ let lastExitOutput;
3329
3727
  let idleSince;
3330
3728
  let superseded = false;
3331
3729
  let ticks = 0;
3730
+ const servingState = (pid) => ({
3731
+ supervisorPid: ports.ownPid,
3732
+ headroomPid: pid,
3733
+ socketPath,
3734
+ version,
3735
+ allowlistHash: runningHash,
3736
+ settingsHash: runningSettingsHash,
3737
+ installedSource
3738
+ });
3332
3739
  for (; ; ) {
3333
3740
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
3334
3741
  return HEADROOM_SUPERVISOR_STILL_RUNNING;
@@ -3336,7 +3743,10 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3336
3743
  ticks += 1;
3337
3744
  config = ports.readConfig();
3338
3745
  const settingsHash = hashSettings(config.settings);
3339
- const allowlist = allowlistOf(ports);
3746
+ const inputs = currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness);
3747
+ pruneDeadFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir, inputs.frontDoorRecords, inputs.frontDoorLiveness);
3748
+ pruneMalformedFrontDoorDirectFiles(fs12, paths.frontdoorDirectRecordsDir, ports.isRunning);
3749
+ const allowlist = inputs.frontDoorOrigins;
3340
3750
  const allowlistHash = hashAllowlist(allowlist);
3341
3751
  pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
3342
3752
  const ownsNow = ownsState();
@@ -3344,6 +3754,13 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3344
3754
  ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
3345
3755
  }
3346
3756
  superseded = !ownsNow;
3757
+ const allowlistFailure = ownsNow ? syncAllowlistFile(allowlist) ?? allowlistFileRefusal(allowlist) : void 0;
3758
+ if (allowlistFailure !== void 0) {
3759
+ if (headroomPid !== void 0 && ports.isRunning(headroomPid)) {
3760
+ ports.stopProcess(headroomPid);
3761
+ }
3762
+ return fail(allowlistFailure);
3763
+ }
3347
3764
  const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
3348
3765
  if (headroomPid === void 0 || crashed) {
3349
3766
  if (crashed) {
@@ -3358,43 +3775,53 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3358
3775
  });
3359
3776
  }
3360
3777
  if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
3361
- return fail(`headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up`);
3778
+ return fail(
3779
+ `headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up` + (lastExitOutput === void 0 ? "" : `; the last attempt exited before it was ready, and its log ends: ${lastExitOutput}`)
3780
+ );
3362
3781
  }
3363
3782
  if (installedSource !== config.source && !ensureInstalled()) {
3364
3783
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
3365
3784
  }
3366
- const pid = ports.spawnHeadroom(socketPath, allowlist, config.settings);
3367
- const ready = await waitUntilReady(ports, socketPath);
3368
- if (ready) {
3785
+ const logOffset = ports.daemonLogSize();
3786
+ const pid = ports.spawnHeadroom(socketPath, paths.headroomAllowlistFile, config.settings);
3787
+ writeOwnState({ supervisorPid: ports.ownPid, headroomPid: pid, version, installedSource });
3788
+ const outcome = await waitUntilReady(ports, socketPath, pid);
3789
+ if (outcome === "ready") {
3369
3790
  consecutiveFailures = 0;
3791
+ lastExitOutput = void 0;
3370
3792
  headroomPid = pid;
3371
3793
  runningHash = allowlistHash;
3372
3794
  runningSettingsHash = settingsHash;
3373
- const recorded = writeOwnState({
3374
- supervisorPid: ports.ownPid,
3375
- headroomPid: pid,
3376
- socketPath,
3377
- version,
3378
- allowlistHash,
3379
- settingsHash,
3380
- installedSource: config.source
3381
- });
3795
+ const recorded = writeOwnState(servingState(pid));
3382
3796
  if (recorded) {
3383
3797
  fs12.removeRecursive(paths.headroomLockFile);
3384
3798
  }
3385
3799
  idleSince = void 0;
3386
3800
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
3387
3801
  } else {
3388
- ports.stopProcess(pid);
3389
3802
  consecutiveFailures += 1;
3390
- ports.log(
3391
- `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
3392
- );
3803
+ if (outcome === "exited") {
3804
+ lastExitOutput = lastLines(ports.readDaemonLogTail(logOffset, DAEMON_LOG_TAIL_BYTES));
3805
+ ports.log(
3806
+ `agent-shim headroom supervisor: headroom exited before it was ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
3807
+ );
3808
+ } else {
3809
+ lastExitOutput = void 0;
3810
+ ports.stopProcess(pid);
3811
+ ports.log(
3812
+ `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
3813
+ );
3814
+ }
3393
3815
  await ports.sleep(backoffForAttempt(consecutiveFailures));
3394
3816
  continue;
3395
3817
  }
3396
3818
  } else {
3397
- if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
3819
+ if (runningHash !== allowlistHash) {
3820
+ runningHash = allowlistHash;
3821
+ writeOwnState(servingState(headroomPid));
3822
+ ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} now serves allowlist [${allowlist.join(", ")}]`);
3823
+ }
3824
+ if (runningSettingsHash !== settingsHash || installedSource !== config.source) {
3398
3825
  if (sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid).length === 0) {
3399
3826
  ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
3400
3827
  ports.stopProcess(headroomPid);
@@ -3423,45 +3850,66 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3423
3850
  await ports.sleep(HEADROOM_POLL_MS);
3424
3851
  }
3425
3852
  }
3426
- function currentHeadroomAllowlistInputs(fs12, paths) {
3853
+ function undeterminedFrontDoors(inputs) {
3854
+ return inputs.frontDoorRecords.flatMap((record) => {
3855
+ const reason = inputs.frontDoorLiveness.unknown.get(record.pid);
3856
+ return reason === void 0 ? [] : [{ pid: record.pid, origin: directOrigin(record.directPort), reason }];
3857
+ });
3858
+ }
3859
+ function currentHeadroomAllowlistInputs(fs12, paths, frontDoorLiveness) {
3860
+ const named = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
3861
+ const records = listFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir);
3862
+ const liveness = frontDoorLiveness(records.map((record) => record.pid));
3863
+ const live = liveFrontDoorDirectRecords(records, liveness).map((record) => directOrigin(record.directPort));
3427
3864
  return {
3428
- providers: readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider),
3429
- frontDoorOrigin: frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile))
3865
+ frontDoorRecords: records,
3866
+ frontDoorLiveness: liveness,
3867
+ frontDoorOrigins: [.../* @__PURE__ */ new Set([...named === void 0 ? [] : [named], ...live])].sort()
3430
3868
  };
3431
3869
  }
3432
- function currentHeadroomAllowlist(fs12, paths) {
3433
- const inputs = currentHeadroomAllowlistInputs(fs12, paths);
3434
- return headroomAllowlist(headroomUpstreams(inputs.providers, inputs.frontDoorOrigin));
3435
- }
3436
- function allowlistOf(ports) {
3437
- return currentHeadroomAllowlist(ports.fs, ports.paths);
3870
+ function launchRequiredUpstreams(fs12, paths) {
3871
+ const door = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
3872
+ return door === void 0 ? [] : [door];
3438
3873
  }
3439
- async function waitUntilReady(ports, socketPath) {
3874
+ async function waitUntilReady(ports, socketPath, pid) {
3440
3875
  const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
3441
3876
  for (; ; ) {
3442
3877
  if (await ports.ready(socketPath)) {
3443
- return true;
3878
+ return "ready";
3879
+ }
3880
+ if (!ports.isRunning(pid)) {
3881
+ return "exited";
3444
3882
  }
3445
3883
  if (ports.now() >= deadline) {
3446
- return false;
3884
+ return "timed-out";
3447
3885
  }
3448
3886
  await ports.sleep(HEADROOM_POLL_MS);
3449
3887
  }
3450
3888
  }
3451
- var HEADROOM_BACKOFF_BASE_MS, HEADROOM_BACKOFF_CAP_MS, HEADROOM_START_RETRY_BUDGET, HEADROOM_READY_TIMEOUT_MS, HEADROOM_POLL_MS, MS_PER_MINUTE2, HEADROOM_SUPERVISOR_STILL_RUNNING;
3889
+ function lastLines(output) {
3890
+ const lines = redactText(output).split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => line.length > DAEMON_EXIT_LOG_LINE_CHARS ? `${line.slice(0, DAEMON_EXIT_LOG_LINE_CHARS)}...` : line);
3891
+ return lines.length === 0 ? "(the daemon wrote nothing)" : lines.slice(-DAEMON_EXIT_LOG_LINES).join(" | ");
3892
+ }
3893
+ var import_node_path13, HEADROOM_BACKOFF_BASE_MS, HEADROOM_BACKOFF_CAP_MS, HEADROOM_START_RETRY_BUDGET, HEADROOM_READY_TIMEOUT_MS, DAEMON_EXIT_LOG_LINES, DAEMON_EXIT_LOG_LINE_CHARS, DAEMON_LOG_TAIL_BYTES, HEADROOM_POLL_MS, MS_PER_MINUTE2, HEADROOM_SUPERVISOR_STILL_RUNNING;
3452
3894
  var init_supervisor = __esm({
3453
3895
  "src/headroom/supervisor.ts"() {
3454
3896
  "use strict";
3897
+ import_node_path13 = __toESM(require("node:path"), 1);
3455
3898
  init_schema();
3456
3899
  init_state();
3457
3900
  init_settings();
3901
+ init_capture();
3458
3902
  init_socket();
3903
+ init_earlierRelease();
3459
3904
  init_source();
3460
3905
  init_state2();
3461
3906
  HEADROOM_BACKOFF_BASE_MS = 500;
3462
3907
  HEADROOM_BACKOFF_CAP_MS = 3e4;
3463
3908
  HEADROOM_START_RETRY_BUDGET = 5;
3464
3909
  HEADROOM_READY_TIMEOUT_MS = 15e3;
3910
+ DAEMON_EXIT_LOG_LINES = 6;
3911
+ DAEMON_EXIT_LOG_LINE_CHARS = 400;
3912
+ DAEMON_LOG_TAIL_BYTES = 8192;
3465
3913
  HEADROOM_POLL_MS = 1e3;
3466
3914
  MS_PER_MINUTE2 = 6e4;
3467
3915
  HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
@@ -3497,8 +3945,18 @@ function realIsFrontDoorSupervisor(pid) {
3497
3945
  const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
3498
3946
  return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
3499
3947
  }
3948
+ function realProcessCommandLine(pid) {
3949
+ const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
3950
+ return result.status === 0 ? result.stdout.trim() : void 0;
3951
+ }
3952
+ function realFrontDoorLiveness(pids) {
3953
+ return frontDoorLivenessOf(pids, (asked) => {
3954
+ const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
3955
+ return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
3956
+ });
3957
+ }
3500
3958
  function expandHome2(filePath) {
3501
- return filePath.startsWith("~/") ? import_node_path13.default.join(import_node_os2.default.homedir(), filePath.slice(1)) : filePath;
3959
+ return filePath.startsWith("~/") ? import_node_path14.default.join(import_node_os2.default.homedir(), filePath.slice(1)) : filePath;
3502
3960
  }
3503
3961
  function hasDesktopSession() {
3504
3962
  if (process.platform === "darwin") {
@@ -3542,7 +4000,7 @@ function spawnDaemonThroughScript(script) {
3542
4000
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
3543
4001
  }
3544
4002
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
3545
- import_node_fs2.default.mkdirSync(import_node_path13.default.dirname(logPath), { recursive: true });
4003
+ import_node_fs2.default.mkdirSync(import_node_path14.default.dirname(logPath), { recursive: true });
3546
4004
  const logFd = import_node_fs2.default.openSync(logPath, "a");
3547
4005
  try {
3548
4006
  const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -3564,13 +4022,14 @@ function realHeadroomPort(paths, options) {
3564
4022
  const up = ensureHeadroom({
3565
4023
  paths,
3566
4024
  launcherPid: process.pid,
3567
- ...routesProvider ? { requiredAllowlistHash: () => hashAllowlist(currentHeadroomAllowlist(realFarmFs, paths)) } : {},
4025
+ ...routesProvider ? { requiredUpstreams: () => launchRequiredUpstreams(realFarmFs, paths) } : {},
3568
4026
  ports: {
3569
4027
  fs: realFarmFs,
3570
4028
  // Zombie-aware on purpose: a supervisor that died while still a child of this launcher sits unreaped until the launcher itself exits, and a defunct supervisor answering signal 0 as alive would stretch every launch to the full start timeout.
3571
4029
  isRunning: realIsProcessRunning,
3572
4030
  now: () => Date.now(),
3573
4031
  sleep: realSleepSync,
4032
+ daemonCommandLine: realProcessCommandLine,
3574
4033
  spawnSupervisor: (layout) => spawnHeadroomSupervisor(layout, options.spawnDaemon)
3575
4034
  }
3576
4035
  });
@@ -3595,7 +4054,7 @@ function listVersionsDir(dir) {
3595
4054
  throw error;
3596
4055
  }
3597
4056
  return entries.filter((entry) => entry.isFile()).map((entry) => {
3598
- const fullPath = import_node_path13.default.join(dir, entry.name);
4057
+ const fullPath = import_node_path14.default.join(dir, entry.name);
3599
4058
  const stat = import_node_fs2.default.statSync(fullPath);
3600
4059
  return {
3601
4060
  name: entry.name,
@@ -3609,7 +4068,7 @@ function windowsPathExtensions(pathext) {
3609
4068
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
3610
4069
  }
3611
4070
  function resolveExecutableCandidate(dir, name, env) {
3612
- const candidate = import_node_path13.default.join(dir, name);
4071
+ const candidate = import_node_path14.default.join(dir, name);
3613
4072
  if (env.platform === "win32") {
3614
4073
  const extensions = windowsPathExtensions(env.pathext);
3615
4074
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -3658,13 +4117,13 @@ function resolveOwnExecutablePath(env) {
3658
4117
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
3659
4118
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
3660
4119
  }
3661
- const candidate = env.argv1 === void 0 ? env.execPath : import_node_path13.default.resolve(env.cwd, env.argv1);
3662
- const candidateDir = import_node_path13.default.dirname(candidate);
3663
- const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path13.default.resolve(dir) === candidateDir);
4120
+ const candidate = env.argv1 === void 0 ? env.execPath : import_node_path14.default.resolve(env.cwd, env.argv1);
4121
+ const candidateDir = import_node_path14.default.dirname(candidate);
4122
+ const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path14.default.resolve(dir) === candidateDir);
3664
4123
  if (candidateDirOnPath) {
3665
4124
  return candidate;
3666
4125
  }
3667
- const viaPath = searchPathForExecutable(env.pathDirs, import_node_path13.default.basename(candidate), env.findExecutableInDir);
4126
+ const viaPath = searchPathForExecutable(env.pathDirs, import_node_path14.default.basename(candidate), env.findExecutableInDir);
3668
4127
  return viaPath ?? candidate;
3669
4128
  }
3670
4129
  function realOwnExecutablePath() {
@@ -3672,7 +4131,7 @@ function realOwnExecutablePath() {
3672
4131
  argv1: process.argv[1],
3673
4132
  execPath: process.execPath,
3674
4133
  cwd: process.cwd(),
3675
- pathDirs: (process.env.PATH ?? "").split(import_node_path13.default.delimiter).filter((dir) => dir !== ""),
4134
+ pathDirs: (process.env.PATH ?? "").split(import_node_path14.default.delimiter).filter((dir) => dir !== ""),
3676
4135
  findExecutableInDir
3677
4136
  });
3678
4137
  }
@@ -3685,7 +4144,7 @@ function realContentSourcePath() {
3685
4144
  function realResolveClaudeBinary(isOwnBinary) {
3686
4145
  return (request4) => discoverClaudeBinary({
3687
4146
  listVersionsDir,
3688
- pathDirs: (process.env.PATH ?? "").split(import_node_path13.default.delimiter).filter((dir) => dir !== ""),
4147
+ pathDirs: (process.env.PATH ?? "").split(import_node_path14.default.delimiter).filter((dir) => dir !== ""),
3689
4148
  findExecutableInDir,
3690
4149
  isOwnBinary,
3691
4150
  ...request4?.version === void 0 ? {} : { version: request4.version }
@@ -3694,7 +4153,7 @@ function realResolveClaudeBinary(isOwnBinary) {
3694
4153
  function realInstalledClaudeVersions() {
3695
4154
  return installedVersions(listVersionsDir(defaultVersionsDir()));
3696
4155
  }
3697
- var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path13, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
4156
+ var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
3698
4157
  var init_realPorts = __esm({
3699
4158
  "src/realPorts.ts"() {
3700
4159
  "use strict";
@@ -3702,7 +4161,7 @@ var init_realPorts = __esm({
3702
4161
  import_node_crypto8 = require("node:crypto");
3703
4162
  import_node_fs2 = __toESM(require("node:fs"), 1);
3704
4163
  import_node_os2 = __toESM(require("node:os"), 1);
3705
- import_node_path13 = __toESM(require("node:path"), 1);
4164
+ import_node_path14 = __toESM(require("node:path"), 1);
3706
4165
  import_node_sea = require("node:sea");
3707
4166
  init_load();
3708
4167
  init_versionDiscovery();
@@ -3794,9 +4253,14 @@ var init_realPorts = __esm({
3794
4253
  },
3795
4254
  writeFilePrivate(filePath, contents) {
3796
4255
  const temp = `${filePath}.${String(process.pid)}.tmp`;
3797
- import_node_fs2.default.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
3798
- import_node_fs2.default.chmodSync(temp, OWNER_ONLY_FILE_MODE);
3799
- import_node_fs2.default.renameSync(temp, filePath);
4256
+ try {
4257
+ import_node_fs2.default.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
4258
+ import_node_fs2.default.chmodSync(temp, OWNER_ONLY_FILE_MODE);
4259
+ import_node_fs2.default.renameSync(temp, filePath);
4260
+ } catch (error) {
4261
+ import_node_fs2.default.rmSync(temp, { force: true });
4262
+ throw error;
4263
+ }
3800
4264
  },
3801
4265
  appendFilePrivate(filePath, contents) {
3802
4266
  const descriptor = import_node_fs2.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
@@ -3836,6 +4300,7 @@ var init_realPorts = __esm({
3836
4300
  }
3837
4301
  };
3838
4302
  INT32_BYTE_LENGTH = 4;
4303
+ PS_TIMEOUT_MS = 2e3;
3839
4304
  realRunPort = {
3840
4305
  run(command, args) {
3841
4306
  const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
@@ -3874,7 +4339,7 @@ var init_realPorts = __esm({
3874
4339
  },
3875
4340
  personPresent: () => process.stdin.isTTY || hasDesktopSession()
3876
4341
  };
3877
- SOCKET_PERMISSION_BITS = 511;
4342
+ SOCKET_PERMISSION_BITS = 4095;
3878
4343
  realHeadroomSocketTrust = {
3879
4344
  platform: process.platform,
3880
4345
  currentUid: () => {
@@ -3893,9 +4358,10 @@ var init_realPorts = __esm({
3893
4358
  }
3894
4359
  throw error;
3895
4360
  }
3896
- const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
4361
+ const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isFile() ? "file" : stat.isSocket() ? "socket" : "other";
3897
4362
  return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
3898
- }
4363
+ },
4364
+ readlink: (target) => import_node_fs2.default.readlinkSync(target, "utf8")
3899
4365
  };
3900
4366
  realSpawnPort = {
3901
4367
  spawnSync(command, args, options) {
@@ -3919,18 +4385,18 @@ function expandTilde(value, home) {
3919
4385
  return home;
3920
4386
  }
3921
4387
  if (value.startsWith("~/")) {
3922
- return import_node_path14.default.join(home, value.slice(2));
4388
+ return import_node_path15.default.join(home, value.slice(2));
3923
4389
  }
3924
4390
  return value;
3925
4391
  }
3926
4392
  function normaliseRulePath(rulePath, home) {
3927
- return import_node_path14.default.resolve(expandTilde(rulePath, home));
4393
+ return import_node_path15.default.resolve(expandTilde(rulePath, home));
3928
4394
  }
3929
- var import_node_path14;
4395
+ var import_node_path15;
3930
4396
  var init_pathNorm = __esm({
3931
4397
  "src/pathNorm.ts"() {
3932
4398
  "use strict";
3933
- import_node_path14 = __toESM(require("node:path"), 1);
4399
+ import_node_path15 = __toESM(require("node:path"), 1);
3934
4400
  }
3935
4401
  });
3936
4402
 
@@ -3939,7 +4405,7 @@ function loadCascadeInput(params) {
3939
4405
  const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
3940
4406
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
3941
4407
  const loadProfile = (name) => {
3942
- const filepath = import_node_path15.default.join(params.paths.configProfilesDir, `${name}.json`);
4408
+ const filepath = import_node_path16.default.join(params.paths.configProfilesDir, `${name}.json`);
3943
4409
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
3944
4410
  if (loaded === void 0) {
3945
4411
  return void 0;
@@ -3954,8 +4420,8 @@ function loadCascadeInput(params) {
3954
4420
  });
3955
4421
  const levels = [];
3956
4422
  for (const dir of dirs) {
3957
- const portable = loadConfigFile(import_node_path15.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path15.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
3958
- const portableLocal = loadConfigFile(import_node_path15.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path15.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
4423
+ const portable = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
4424
+ const portableLocal = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
3959
4425
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
3960
4426
  const entryOrder = directoryRules?.ruleEntryOrders[index];
3961
4427
  return {
@@ -4002,11 +4468,11 @@ function readDirectorySelections(loaded) {
4002
4468
  }
4003
4469
  return { ...identity === void 0 ? {} : { identity }, ...configProfile === void 0 ? {} : { configProfile } };
4004
4470
  }
4005
- var import_node_path15, PORTABLE_CONFIG_FILENAME, PORTABLE_LOCAL_CONFIG_FILENAME;
4471
+ var import_node_path16, PORTABLE_CONFIG_FILENAME, PORTABLE_LOCAL_CONFIG_FILENAME;
4006
4472
  var init_cascade = __esm({
4007
4473
  "src/launcher/cascade.ts"() {
4008
4474
  "use strict";
4009
- import_node_path15 = __toESM(require("node:path"), 1);
4475
+ import_node_path16 = __toESM(require("node:path"), 1);
4010
4476
  init_load();
4011
4477
  init_schema();
4012
4478
  init_pathNorm();
@@ -4070,13 +4536,13 @@ function decideConfigProfile(params) {
4070
4536
  return { source: "none" };
4071
4537
  }
4072
4538
  function loadIdentity(identitiesDir, name, fs12) {
4073
- return loadConfigFile(import_node_path16.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4539
+ return loadConfigFile(import_node_path17.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4074
4540
  }
4075
- var import_node_path16, IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
4541
+ var import_node_path17, IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
4076
4542
  var init_identity = __esm({
4077
4543
  "src/launcher/identity.ts"() {
4078
4544
  "use strict";
4079
- import_node_path16 = __toESM(require("node:path"), 1);
4545
+ import_node_path17 = __toESM(require("node:path"), 1);
4080
4546
  init_load();
4081
4547
  init_schema();
4082
4548
  IDENTITY_DECISION_SOURCES = [
@@ -4298,7 +4764,7 @@ function isIdentityName(name) {
4298
4764
  return IdentitySchema.shape.name.safeParse(name).success;
4299
4765
  }
4300
4766
  function claudeJsonPath(identitiesDir, identity) {
4301
- return import_node_path17.default.join(identitiesDir, identity, CLAUDE_JSON);
4767
+ return import_node_path18.default.join(identitiesDir, identity, CLAUDE_JSON);
4302
4768
  }
4303
4769
  function readAccountMetadata(fs12, identitiesDir, identity) {
4304
4770
  if (!isIdentityName(identity)) {
@@ -4352,11 +4818,11 @@ function createAccountReader(fs12, identitiesDir) {
4352
4818
  return account;
4353
4819
  };
4354
4820
  }
4355
- var import_node_path17, CLAUDE_JSON, AccountMetadataError;
4821
+ var import_node_path18, CLAUDE_JSON, AccountMetadataError;
4356
4822
  var init_account = __esm({
4357
4823
  "src/usage/account.ts"() {
4358
4824
  "use strict";
4359
- import_node_path17 = __toESM(require("node:path"), 1);
4825
+ import_node_path18 = __toESM(require("node:path"), 1);
4360
4826
  init_cliError();
4361
4827
  init_schema();
4362
4828
  init_schema2();
@@ -4915,7 +5381,7 @@ function readUsageLog(fs12, logDir, options = {}) {
4915
5381
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
4916
5382
  continue;
4917
5383
  }
4918
- const contents = fs12.readFileUtf8(import_node_path18.default.join(logDir, segment.name));
5384
+ const contents = fs12.readFileUtf8(import_node_path19.default.join(logDir, segment.name));
4919
5385
  if (contents === void 0) {
4920
5386
  continue;
4921
5387
  }
@@ -4949,7 +5415,7 @@ function snapshotPath(snapshotsDir, identity) {
4949
5415
  if (!isIdentityName(identity)) {
4950
5416
  throw new Error(`"${identity}" is not a valid identity name.`);
4951
5417
  }
4952
- return import_node_path18.default.join(snapshotsDir, `${identity}.json`);
5418
+ return import_node_path19.default.join(snapshotsDir, `${identity}.json`);
4953
5419
  }
4954
5420
  function readUsageSnapshot(fs12, snapshotsDir, identity) {
4955
5421
  const file = snapshotPath(snapshotsDir, identity);
@@ -4982,11 +5448,11 @@ function listUsageSnapshots(fs12, snapshotsDir) {
4982
5448
  return snapshot === void 0 ? [] : [snapshot];
4983
5449
  }).sort((left, right) => left.identity.localeCompare(right.identity));
4984
5450
  }
4985
- var import_node_path18, SEGMENT_RE, DAY_MS, UsageSnapshotError;
5451
+ var import_node_path19, SEGMENT_RE, DAY_MS, UsageSnapshotError;
4986
5452
  var init_read = __esm({
4987
5453
  "src/usage/read.ts"() {
4988
5454
  "use strict";
4989
- import_node_path18 = __toESM(require("node:path"), 1);
5455
+ import_node_path19 = __toESM(require("node:path"), 1);
4990
5456
  init_account();
4991
5457
  init_schema2();
4992
5458
  SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
@@ -5007,7 +5473,7 @@ function pruneUsageLog(fs12, logDir, nowMs) {
5007
5473
  const cutoff = nowMs - USAGE_RETENTION_MS;
5008
5474
  for (const segment of listLogSegments(fs12, logDir)) {
5009
5475
  if (segment.endsAt <= cutoff) {
5010
- fs12.removeRecursive(import_node_path19.default.join(logDir, segment.name));
5476
+ fs12.removeRecursive(import_node_path20.default.join(logDir, segment.name));
5011
5477
  }
5012
5478
  }
5013
5479
  }
@@ -5089,7 +5555,7 @@ function createUsageStore(deps) {
5089
5555
  pruneUsageLog(fs12, paths.usageLogDir, nowMs);
5090
5556
  prunedDay = day;
5091
5557
  }
5092
- fs12.appendFilePrivate(import_node_path19.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
5558
+ fs12.appendFilePrivate(import_node_path20.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
5093
5559
  `);
5094
5560
  if (record.identity !== void 0) {
5095
5561
  rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
@@ -5112,11 +5578,11 @@ function createUsageStore(deps) {
5112
5578
  })
5113
5579
  };
5114
5580
  }
5115
- var import_node_path19, DAY_MS2, DAYS_IN_WEEK, USAGE_RETENTION_MS;
5581
+ var import_node_path20, DAY_MS2, DAYS_IN_WEEK, USAGE_RETENTION_MS;
5116
5582
  var init_store2 = __esm({
5117
5583
  "src/usage/store.ts"() {
5118
5584
  "use strict";
5119
- import_node_path19 = __toESM(require("node:path"), 1);
5585
+ import_node_path20 = __toESM(require("node:path"), 1);
5120
5586
  init_account();
5121
5587
  init_rateLimit();
5122
5588
  init_read();
@@ -5254,15 +5720,15 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
5254
5720
  const current = readPicksFile(fs12, picksFile).file.picks;
5255
5721
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
5256
5722
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
5257
- fs12.mkdirPrivate(import_node_path20.default.dirname(picksFile));
5723
+ fs12.mkdirPrivate(import_node_path21.default.dirname(picksFile));
5258
5724
  fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
5259
5725
  `);
5260
5726
  }
5261
- var import_node_path20, import_zod13, PoolGraphError, SCHEMA_VERSION, PickEntrySchema, PicksFileSchema;
5727
+ var import_node_path21, import_zod13, PoolGraphError, SCHEMA_VERSION, PickEntrySchema, PicksFileSchema;
5262
5728
  var init_poolPick = __esm({
5263
5729
  "src/usage/poolPick.ts"() {
5264
5730
  "use strict";
5265
- import_node_path20 = __toESM(require("node:path"), 1);
5731
+ import_node_path21 = __toESM(require("node:path"), 1);
5266
5732
  import_zod13 = require("zod");
5267
5733
  init_cliError();
5268
5734
  init_identity();
@@ -5293,8 +5759,8 @@ function resolveAgentShimHome(env = process.env, home = import_node_os4.default.
5293
5759
  if (fromEnv !== void 0 && fromEnv !== "") {
5294
5760
  return fromEnv;
5295
5761
  }
5296
- const current = import_node_path22.default.join(home, HOME_DIRNAME);
5297
- const legacy = import_node_path22.default.join(home, LEGACY_HOME_DIRNAME);
5762
+ const current = import_node_path23.default.join(home, HOME_DIRNAME);
5763
+ const legacy = import_node_path23.default.join(home, LEGACY_HOME_DIRNAME);
5298
5764
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
5299
5765
  }
5300
5766
  function isExistingDirectory(candidate) {
@@ -5305,59 +5771,61 @@ function resolveClaudeHome() {
5305
5771
  if (fromEnv !== void 0 && fromEnv !== "") {
5306
5772
  return fromEnv;
5307
5773
  }
5308
- return import_node_path22.default.join(import_node_os4.default.homedir(), ".claude");
5774
+ return import_node_path23.default.join(import_node_os4.default.homedir(), ".claude");
5309
5775
  }
5310
5776
  function buildLayoutPaths(root) {
5311
5777
  return {
5312
5778
  root,
5313
- identitiesDir: import_node_path22.default.join(root, "identities"),
5314
- configProfilesDir: import_node_path22.default.join(root, "config-profiles"),
5315
- providersDir: import_node_path22.default.join(root, "providers"),
5316
- directoryRulesFile: import_node_path22.default.join(root, "directory-rules.json"),
5317
- activeIdentityFile: import_node_path22.default.join(root, "active-identity"),
5318
- globalConfigFile: import_node_path22.default.join(root, "config.json"),
5319
- categoriesLocalFile: import_node_path22.default.join(root, "categories.local.json"),
5320
- claudeShimFile: import_node_path22.default.join(root, "claude-shim.json"),
5321
- headroomDir: import_node_path22.default.join(root, "headroom"),
5322
- headroomStateFile: import_node_path22.default.join(root, "headroom", "state.json"),
5323
- headroomLegacyStateFile: import_node_path22.default.join(root, "headroom", "state.v2.json"),
5324
- headroomSocketDir: import_node_path22.default.join(root, "headroom", "run"),
5325
- headroomLockFile: import_node_path22.default.join(root, "headroom", "start.lock"),
5326
- headroomSessionsDir: import_node_path22.default.join(root, "headroom", "sessions"),
5327
- logsDir: import_node_path22.default.join(root, "logs"),
5328
- headroomLogPath: import_node_path22.default.join(root, "logs", "headroom.log"),
5329
- frontdoorDir: import_node_path22.default.join(root, "frontdoor"),
5330
- frontdoorCaDir: import_node_path22.default.join(root, "frontdoor", "ca"),
5331
- frontdoorCaCertFile: import_node_path22.default.join(root, "frontdoor", "ca", "ca.pem"),
5332
- frontdoorCaKeyFile: import_node_path22.default.join(root, "frontdoor", "ca", "ca.key"),
5333
- frontdoorCaBundlesDir: import_node_path22.default.join(root, "frontdoor", "ca", "bundles"),
5334
- chatgptSignInFile: import_node_path22.default.join(root, "codex", "chatgpt-sign-in.json"),
5335
- frontdoorStateFile: import_node_path22.default.join(root, "frontdoor", "state.json"),
5336
- frontdoorLockFile: import_node_path22.default.join(root, "frontdoor", "start.lock"),
5337
- frontdoorControlTokenFile: import_node_path22.default.join(root, "frontdoor", "control-token"),
5338
- frontdoorSessionsDir: import_node_path22.default.join(root, "frontdoor", "sessions"),
5339
- frontdoorRcCredentialsDir: import_node_path22.default.join(root, "frontdoor", "rc-credentials"),
5340
- frontdoorLogPath: import_node_path22.default.join(root, "logs", "frontdoor.log"),
5341
- usageDir: import_node_path22.default.join(root, "usage"),
5342
- usageLogDir: import_node_path22.default.join(root, "usage", "log"),
5343
- usageSnapshotsDir: import_node_path22.default.join(root, "usage", "snapshots"),
5344
- usagePicksFile: import_node_path22.default.join(root, "usage", "picks.json"),
5345
- usageAnchorsFile: import_node_path22.default.join(root, "usage", "anchors.json"),
5346
- usageJobsFile: import_node_path22.default.join(root, "usage", "jobs.json"),
5347
- jobLogsDir: import_node_path22.default.join(root, "logs", "jobs"),
5348
- mcpPermissionsFile: import_node_path22.default.join(root, "mcp", "permissions.json")
5779
+ identitiesDir: import_node_path23.default.join(root, "identities"),
5780
+ configProfilesDir: import_node_path23.default.join(root, "config-profiles"),
5781
+ providersDir: import_node_path23.default.join(root, "providers"),
5782
+ directoryRulesFile: import_node_path23.default.join(root, "directory-rules.json"),
5783
+ activeIdentityFile: import_node_path23.default.join(root, "active-identity"),
5784
+ globalConfigFile: import_node_path23.default.join(root, "config.json"),
5785
+ categoriesLocalFile: import_node_path23.default.join(root, "categories.local.json"),
5786
+ claudeShimFile: import_node_path23.default.join(root, "claude-shim.json"),
5787
+ headroomDir: import_node_path23.default.join(root, "headroom"),
5788
+ headroomStateFile: import_node_path23.default.join(root, "headroom", "state.json"),
5789
+ headroomLegacyStateFile: import_node_path23.default.join(root, "headroom", "state.v2.json"),
5790
+ headroomAllowlistFile: import_node_path23.default.join(root, "headroom", "run", "allowlist.txt"),
5791
+ headroomSocketDir: import_node_path23.default.join(root, "headroom", "run"),
5792
+ headroomLockFile: import_node_path23.default.join(root, "headroom", "start.lock"),
5793
+ headroomSessionsDir: import_node_path23.default.join(root, "headroom", "sessions"),
5794
+ logsDir: import_node_path23.default.join(root, "logs"),
5795
+ headroomLogPath: import_node_path23.default.join(root, "logs", "headroom.log"),
5796
+ frontdoorDir: import_node_path23.default.join(root, "frontdoor"),
5797
+ frontdoorCaDir: import_node_path23.default.join(root, "frontdoor", "ca"),
5798
+ frontdoorCaCertFile: import_node_path23.default.join(root, "frontdoor", "ca", "ca.pem"),
5799
+ frontdoorCaKeyFile: import_node_path23.default.join(root, "frontdoor", "ca", "ca.key"),
5800
+ frontdoorCaBundlesDir: import_node_path23.default.join(root, "frontdoor", "ca", "bundles"),
5801
+ chatgptSignInFile: import_node_path23.default.join(root, "codex", "chatgpt-sign-in.json"),
5802
+ frontdoorStateFile: import_node_path23.default.join(root, "frontdoor", "state.json"),
5803
+ frontdoorLockFile: import_node_path23.default.join(root, "frontdoor", "start.lock"),
5804
+ frontdoorControlTokenFile: import_node_path23.default.join(root, "frontdoor", "control-token"),
5805
+ frontdoorSessionsDir: import_node_path23.default.join(root, "frontdoor", "sessions"),
5806
+ frontdoorDirectRecordsDir: import_node_path23.default.join(root, "frontdoor", "direct"),
5807
+ frontdoorRcCredentialsDir: import_node_path23.default.join(root, "frontdoor", "rc-credentials"),
5808
+ frontdoorLogPath: import_node_path23.default.join(root, "logs", "frontdoor.log"),
5809
+ usageDir: import_node_path23.default.join(root, "usage"),
5810
+ usageLogDir: import_node_path23.default.join(root, "usage", "log"),
5811
+ usageSnapshotsDir: import_node_path23.default.join(root, "usage", "snapshots"),
5812
+ usagePicksFile: import_node_path23.default.join(root, "usage", "picks.json"),
5813
+ usageAnchorsFile: import_node_path23.default.join(root, "usage", "anchors.json"),
5814
+ usageJobsFile: import_node_path23.default.join(root, "usage", "jobs.json"),
5815
+ jobLogsDir: import_node_path23.default.join(root, "logs", "jobs"),
5816
+ mcpPermissionsFile: import_node_path23.default.join(root, "mcp", "permissions.json")
5349
5817
  };
5350
5818
  }
5351
5819
  function resolveLayoutPaths() {
5352
5820
  return buildLayoutPaths(resolveAgentShimHome());
5353
5821
  }
5354
- var import_node_fs4, import_node_os4, import_node_path22;
5822
+ var import_node_fs4, import_node_os4, import_node_path23;
5355
5823
  var init_paths = __esm({
5356
5824
  "src/paths.ts"() {
5357
5825
  "use strict";
5358
5826
  import_node_fs4 = __toESM(require("node:fs"), 1);
5359
5827
  import_node_os4 = __toESM(require("node:os"), 1);
5360
- import_node_path22 = __toESM(require("node:path"), 1);
5828
+ import_node_path23 = __toESM(require("node:path"), 1);
5361
5829
  init_legacy();
5362
5830
  }
5363
5831
  });
@@ -5462,8 +5930,8 @@ function security(args, stdin) {
5462
5930
  return { status: result.status, stdout: result.stdout };
5463
5931
  }
5464
5932
  function createRealCredentialCache(root) {
5465
- const dir = import_node_path23.default.join(root, "credential-cache");
5466
- const filePath = (owner) => import_node_path23.default.join(dir, cacheFileNameFor(owner));
5933
+ const dir = import_node_path24.default.join(root, "credential-cache");
5934
+ const filePath = (owner) => import_node_path24.default.join(dir, cacheFileNameFor(owner));
5467
5935
  return {
5468
5936
  read(store, owner) {
5469
5937
  if (store === "file") {
@@ -5509,13 +5977,13 @@ function createRealCredentialCache(root) {
5509
5977
  function realCredentialCacheEnv(paths) {
5510
5978
  return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
5511
5979
  }
5512
- var import_node_child_process3, import_node_fs5, import_node_path23, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
5980
+ var import_node_child_process3, import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
5513
5981
  var init_realCredentialCache = __esm({
5514
5982
  "src/realCredentialCache.ts"() {
5515
5983
  "use strict";
5516
5984
  import_node_child_process3 = require("node:child_process");
5517
5985
  import_node_fs5 = __toESM(require("node:fs"), 1);
5518
- import_node_path23 = __toESM(require("node:path"), 1);
5986
+ import_node_path24 = __toESM(require("node:path"), 1);
5519
5987
  init_credentialCache();
5520
5988
  KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
5521
5989
  CACHE_DIR_MODE = 448;
@@ -5698,7 +6166,7 @@ var init_credential = __esm({
5698
6166
 
5699
6167
  // src/providersStore.ts
5700
6168
  function providerJsonPath(paths, name) {
5701
- return import_node_path24.default.join(paths.providersDir, `${name}.json`);
6169
+ return import_node_path25.default.join(paths.providersDir, `${name}.json`);
5702
6170
  }
5703
6171
  function providerExists(paths, name) {
5704
6172
  return import_node_fs6.default.existsSync(providerJsonPath(paths, name));
@@ -5758,7 +6226,7 @@ function readProvider(paths, name) {
5758
6226
  return parseProviderFile(filePath, raw);
5759
6227
  }
5760
6228
  function loadProvider(providersDir, name, port) {
5761
- const filePath = import_node_path24.default.join(providersDir, `${name}.json`);
6229
+ const filePath = import_node_path25.default.join(providersDir, `${name}.json`);
5762
6230
  const raw = port.readConfigFile(filePath);
5763
6231
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
5764
6232
  }
@@ -5920,12 +6388,12 @@ function resolveProvider(params) {
5920
6388
  }
5921
6389
  return { ok: true, provider: { name, definition, credential: resolution.credential }, warnings: resolution.credential.warnings };
5922
6390
  }
5923
- var import_node_fs6, import_node_path24, ProviderNotFoundError, ProviderAlreadyExistsError, InvalidProviderNameError, PROVIDER_NAME_RE, LEGACY_PROVIDER_FIELDS, LEGACY_ENV_CREDENTIAL_KEYS, LEGACY_LITERAL_PLACEHOLDER, LegacyProviderFileError, ProviderKindMismatchError;
6391
+ var import_node_fs6, import_node_path25, ProviderNotFoundError, ProviderAlreadyExistsError, InvalidProviderNameError, PROVIDER_NAME_RE, LEGACY_PROVIDER_FIELDS, LEGACY_ENV_CREDENTIAL_KEYS, LEGACY_LITERAL_PLACEHOLDER, LegacyProviderFileError, ProviderKindMismatchError;
5924
6392
  var init_providersStore = __esm({
5925
6393
  "src/providersStore.ts"() {
5926
6394
  "use strict";
5927
6395
  import_node_fs6 = __toESM(require("node:fs"), 1);
5928
- import_node_path24 = __toESM(require("node:path"), 1);
6396
+ import_node_path25 = __toESM(require("node:path"), 1);
5929
6397
  init_load();
5930
6398
  init_store();
5931
6399
  init_schema();
@@ -6137,10 +6605,10 @@ function commandFilename(ownExecutablePath, commandName) {
6137
6605
  }
6138
6606
  function resolveOwnBinaryCheck(paths, contentSourcePath) {
6139
6607
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6140
- const recordedTarget = state === void 0 ? void 0 : import_node_path26.default.resolve(state.targetPath);
6608
+ const recordedTarget = state === void 0 ? void 0 : import_node_path27.default.resolve(state.targetPath);
6141
6609
  let ownStat;
6142
6610
  return (candidate) => {
6143
- if (recordedTarget !== void 0 && import_node_path26.default.resolve(candidate) === recordedTarget) {
6611
+ if (recordedTarget !== void 0 && import_node_path27.default.resolve(candidate) === recordedTarget) {
6144
6612
  return true;
6145
6613
  }
6146
6614
  ownStat ??= statOrUndefined(contentSourcePath);
@@ -6163,22 +6631,22 @@ function statOrUndefined(target) {
6163
6631
  }
6164
6632
  }
6165
6633
  function findPathShadow(params) {
6166
- const resolvedTargetDir = import_node_path26.default.resolve(params.targetDir);
6634
+ const resolvedTargetDir = import_node_path27.default.resolve(params.targetDir);
6167
6635
  for (const dir of params.pathDirs) {
6168
6636
  const found = params.findExecutableInDir(dir, params.targetFilename);
6169
6637
  if (found === void 0) {
6170
6638
  continue;
6171
6639
  }
6172
- return import_node_path26.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6640
+ return import_node_path27.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6173
6641
  }
6174
- return params.pathDirs.some((dir) => import_node_path26.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6642
+ return params.pathDirs.some((dir) => import_node_path27.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6175
6643
  }
6176
- var import_node_fs7, import_node_path26, import_zod19, ClaudeShimStateSchema, nodeLinkFs;
6644
+ var import_node_fs7, import_node_path27, import_zod19, ClaudeShimStateSchema, nodeLinkFs;
6177
6645
  var init_claudeShim = __esm({
6178
6646
  "src/claudeShim.ts"() {
6179
6647
  "use strict";
6180
6648
  import_node_fs7 = __toESM(require("node:fs"), 1);
6181
- import_node_path26 = __toESM(require("node:path"), 1);
6649
+ import_node_path27 = __toESM(require("node:path"), 1);
6182
6650
  import_zod19 = require("zod");
6183
6651
  init_commandDeps();
6184
6652
  init_store();
@@ -6692,7 +7160,7 @@ function buildEnv(params) {
6692
7160
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
6693
7161
  let providerCustomHeaders;
6694
7162
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
6695
- env.CLAUDE_CONFIG_DIR = import_node_path35.default.join(params.identitiesDir, params.resolvedIdentityName);
7163
+ env.CLAUDE_CONFIG_DIR = import_node_path36.default.join(params.identitiesDir, params.resolvedIdentityName);
6696
7164
  }
6697
7165
  if (params.provider !== void 0) {
6698
7166
  const providerEnv = params.provider.definition.env ?? {};
@@ -6736,11 +7204,11 @@ function buildEnv(params) {
6736
7204
  }
6737
7205
  return env;
6738
7206
  }
6739
- var import_node_path35, LOOPBACK_HOSTS;
7207
+ var import_node_path36, LOOPBACK_HOSTS;
6740
7208
  var init_flags = __esm({
6741
7209
  "src/launcher/flags.ts"() {
6742
7210
  "use strict";
6743
- import_node_path35 = __toESM(require("node:path"), 1);
7211
+ import_node_path36 = __toESM(require("node:path"), 1);
6744
7212
  init_envBool();
6745
7213
  init_credential();
6746
7214
  init_headers();
@@ -7073,7 +7541,7 @@ function decideLaunch(params, readOnly) {
7073
7541
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
7074
7542
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
7075
7543
  });
7076
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path36.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7544
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path37.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7077
7545
  log.error(
7078
7546
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
7079
7547
  );
@@ -7185,7 +7653,7 @@ function decideLaunch(params, readOnly) {
7185
7653
  extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7186
7654
  passthrough: parsedArgv.rest
7187
7655
  });
7188
- const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path36.default.join(paths.identitiesDir, identityDecision.name);
7656
+ const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path37.default.join(paths.identitiesDir, identityDecision.name);
7189
7657
  const decision = {
7190
7658
  identitySource: identityDecision.source,
7191
7659
  configDirEscapeHatch: identityDecision.configDirEscapeHatch,
@@ -7226,7 +7694,7 @@ function prepareLaunch(params) {
7226
7694
  );
7227
7695
  const updateCheck = runLaunchUpdateCheck({
7228
7696
  mode: params.updateMode ?? "off",
7229
- checkPath: import_node_path36.default.join(paths.root, "update.check"),
7697
+ checkPath: import_node_path37.default.join(paths.root, "update.check"),
7230
7698
  currentVersion: package_default.version,
7231
7699
  port: params.update
7232
7700
  });
@@ -7357,12 +7825,12 @@ function runLaunchPlan(plan, spawn3) {
7357
7825
  function runLauncher(params) {
7358
7826
  params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
7359
7827
  }
7360
- var import_node_crypto10, import_node_path36;
7828
+ var import_node_crypto10, import_node_path37;
7361
7829
  var init_launcher = __esm({
7362
7830
  "src/launcher.ts"() {
7363
7831
  "use strict";
7364
7832
  import_node_crypto10 = require("node:crypto");
7365
- import_node_path36 = __toESM(require("node:path"), 1);
7833
+ import_node_path37 = __toESM(require("node:path"), 1);
7366
7834
  init_package();
7367
7835
  init_envBool();
7368
7836
  init_argv();
@@ -7393,13 +7861,13 @@ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string"
7393
7861
  if (distDir === void 0) {
7394
7862
  throw new OwnCliPathUnknownError();
7395
7863
  }
7396
- return import_node_path37.default.join(distDir, OWN_CLI_FILE_NAME);
7864
+ return import_node_path38.default.join(distDir, OWN_CLI_FILE_NAME);
7397
7865
  }
7398
- var import_node_path37, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7866
+ var import_node_path38, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7399
7867
  var init_ownCli = __esm({
7400
7868
  "src/ownCli.ts"() {
7401
7869
  "use strict";
7402
- import_node_path37 = __toESM(require("node:path"), 1);
7870
+ import_node_path38 = __toESM(require("node:path"), 1);
7403
7871
  init_cliError();
7404
7872
  OWN_CLI_FILE_NAME = "cli.cjs";
7405
7873
  OwnCliPathUnknownError = class extends CliError {
@@ -7484,7 +7952,7 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
7484
7952
  // src/frontdoor/trust.ts
7485
7953
  function resolveTrustBundle(params) {
7486
7954
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7487
- if (inherited === void 0 || inherited === "" || import_node_path38.default.resolve(inherited) === import_node_path38.default.resolve(caCertFile)) {
7955
+ if (inherited === void 0 || inherited === "" || import_node_path39.default.resolve(inherited) === import_node_path39.default.resolve(caCertFile)) {
7488
7956
  return { path: caCertFile };
7489
7957
  }
7490
7958
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7502,19 +7970,19 @@ function resolveTrustBundle(params) {
7502
7970
  }
7503
7971
  const combined = `${inheritedPem.trimEnd()}
7504
7972
  ${caPem}`;
7505
- const bundle = import_node_path38.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7973
+ const bundle = import_node_path39.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7506
7974
  if (!fs12.exists(bundle)) {
7507
7975
  fs12.mkdirp(bundlesDir);
7508
7976
  fs12.writeFileAtomic(bundle, combined);
7509
7977
  }
7510
7978
  return { path: bundle };
7511
7979
  }
7512
- var import_node_crypto11, import_node_path38, BUNDLE_NAME_HEX_DIGITS;
7980
+ var import_node_crypto11, import_node_path39, BUNDLE_NAME_HEX_DIGITS;
7513
7981
  var init_trust = __esm({
7514
7982
  "src/frontdoor/trust.ts"() {
7515
7983
  "use strict";
7516
7984
  import_node_crypto11 = require("node:crypto");
7517
- import_node_path38 = __toESM(require("node:path"), 1);
7985
+ import_node_path39 = __toESM(require("node:path"), 1);
7518
7986
  BUNDLE_NAME_HEX_DIGITS = 16;
7519
7987
  }
7520
7988
  });
@@ -8308,6 +8776,7 @@ __export(index_exports, {
8308
8776
  isRcReadFileEncoding: () => isRcReadFileEncoding,
8309
8777
  lateRcEventDial: () => lateRcEventDial,
8310
8778
  lateRcStreamDial: () => lateRcStreamDial,
8779
+ launchRequiredUpstreams: () => launchRequiredUpstreams,
8311
8780
  listDirectoryRules: () => listDirectoryRules,
8312
8781
  listIdentities: () => listIdentities,
8313
8782
  listProfiles: () => listProfiles,
@@ -8748,6 +9217,7 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
8748
9217
  // src/frontdoor/connect.ts
8749
9218
  init_capability();
8750
9219
  init_route();
9220
+ init_state();
8751
9221
 
8752
9222
  // src/frontdoor/supervisor.ts
8753
9223
  var import_node_path9 = __toESM(require("node:path"), 1);
@@ -8819,9 +9289,10 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
8819
9289
  return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
8820
9290
  }
8821
9291
  if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
8822
- ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
9292
+ ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom admits the new address once its supervisor rewrites the allowlist file)`);
8823
9293
  }
8824
9294
  lastDirectPort = direct.port;
9295
+ writeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
8825
9296
  writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
8826
9297
  ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
8827
9298
  fs12.removeRecursive(paths.frontdoorLockFile);
@@ -8843,6 +9314,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
8843
9314
  await connect3.close();
8844
9315
  await http3.close();
8845
9316
  ports.closeRcStreamHub();
9317
+ removeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, ports.ownPid);
8846
9318
  };
8847
9319
  const shutdown = async () => {
8848
9320
  await closeServing();
@@ -8906,7 +9378,6 @@ var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
8906
9378
  var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
8907
9379
  var ROUTED_PATH_PREFIX = "/v1/";
8908
9380
  var HTTPS_PORT = 443;
8909
- var MAX_PORT = 65535;
8910
9381
  var HTTP_BAD_GATEWAY = 502;
8911
9382
  var CA_KEY_FILE_MODE = 384;
8912
9383
  var CONNECT_LINE_TOKENS = 3;
@@ -8938,7 +9409,7 @@ function parseConnectTarget(authority) {
8938
9409
  }
8939
9410
  const host = authority.slice(0, colon).trim().toLowerCase();
8940
9411
  const port = Number.parseInt(authority.slice(colon + 1), 10);
8941
- if (host === "" || !Number.isInteger(port) || port <= 0 || port > MAX_PORT) {
9412
+ if (host === "" || !Number.isInteger(port) || port <= 0 || port > MAX_TCP_PORT) {
8942
9413
  return void 0;
8943
9414
  }
8944
9415
  return { host, port };
@@ -8946,8 +9417,8 @@ function parseConnectTarget(authority) {
8946
9417
  function isInterceptedHost(host, interceptHosts) {
8947
9418
  return interceptHosts.includes(host);
8948
9419
  }
8949
- function servedByPipeline(path39) {
8950
- return path39?.startsWith(ROUTED_PATH_PREFIX) === true;
9420
+ function servedByPipeline(path40) {
9421
+ return path40?.startsWith(ROUTED_PATH_PREFIX) === true;
8951
9422
  }
8952
9423
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
8953
9424
  "connection",
@@ -9741,11 +10212,11 @@ function createRcSessionTracker(deps) {
9741
10212
  };
9742
10213
  const observeExchange = (request4) => {
9743
10214
  const method = (request4.method ?? "").toUpperCase();
9744
- const path39 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
9745
- if (!path39.startsWith(RC_SESSIONS_PATH_PREFIX)) {
10215
+ const path40 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
10216
+ if (!path40.startsWith(RC_SESSIONS_PATH_PREFIX)) {
9746
10217
  return void 0;
9747
10218
  }
9748
- const tail = path39.slice(RC_SESSIONS_PATH_PREFIX.length);
10219
+ const tail = path40.slice(RC_SESSIONS_PATH_PREFIX.length);
9749
10220
  const facts = {
9750
10221
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
9751
10222
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -10135,8 +10606,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
10135
10606
  function isRcReadFileEncoding(value) {
10136
10607
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
10137
10608
  }
10138
- function buildRcReadFilePayload(requestId, path39, options) {
10139
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path39, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
10609
+ function buildRcReadFilePayload(requestId, path40, options) {
10610
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path40, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
10140
10611
  }
10141
10612
  function buildRcFileSuggestionsPayload(requestId, query) {
10142
10613
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -10238,15 +10709,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
10238
10709
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
10239
10710
  return result.ok ? { ...result, requestId } : result;
10240
10711
  }
10241
- async function readRcSessionFile(deps, sessionId, path39, options) {
10242
- if (path39 === "") {
10712
+ async function readRcSessionFile(deps, sessionId, path40, options) {
10713
+ if (path40 === "") {
10243
10714
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
10244
10715
  }
10245
10716
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
10246
10717
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
10247
10718
  }
10248
10719
  const requestId = deps.newUuid();
10249
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path39, options), `read ${path39} from session ${sessionId}`);
10720
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path40, options), `read ${path40} from session ${sessionId}`);
10250
10721
  return result.ok ? { ...result, requestId } : result;
10251
10722
  }
10252
10723
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -10415,11 +10886,11 @@ function createRcControlHandler(deps) {
10415
10886
  path: "read-file",
10416
10887
  read: (body) => {
10417
10888
  const session = bodyString(body, "session");
10418
- const path39 = bodyString(body, "path");
10889
+ const path40 = bodyString(body, "path");
10419
10890
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
10420
10891
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
10421
- const refused2 = session === void 0 || path39 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
10422
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path39, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
10892
+ const refused2 = session === void 0 || path40 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
10893
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path40, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
10423
10894
  }
10424
10895
  },
10425
10896
  {
@@ -10729,9 +11200,9 @@ function requestIdOfBody(body) {
10729
11200
  }
10730
11201
  function frontDoorRcControl(transport, token) {
10731
11202
  const headers = { authorization: `Bearer ${token}` };
10732
- const listAnswerOf = async (path39, what) => {
11203
+ const listAnswerOf = async (path40, what) => {
10733
11204
  try {
10734
- return await transport.request({ method: "GET", path: path39, headers });
11205
+ return await transport.request({ method: "GET", path: path40, headers });
10735
11206
  } catch (error) {
10736
11207
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
10737
11208
  }
@@ -10803,10 +11274,10 @@ function frontDoorRcControl(transport, token) {
10803
11274
  }
10804
11275
  return pending;
10805
11276
  };
10806
- const writeOf = async (path39, body, describeFailure2) => {
11277
+ const writeOf = async (path40, body, describeFailure2) => {
10807
11278
  let answer;
10808
11279
  try {
10809
- answer = await transport.request({ method: "POST", path: path39, headers: { ...headers, "content-type": "application/json" }, body });
11280
+ answer = await transport.request({ method: "POST", path: path40, headers: { ...headers, "content-type": "application/json" }, body });
10810
11281
  } catch (error) {
10811
11282
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
10812
11283
  }
@@ -10837,10 +11308,10 @@ function frontDoorRcControl(transport, token) {
10837
11308
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10838
11309
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10839
11310
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10840
- readFile: async (sessionId, path39, options) => await writeOf(
11311
+ readFile: async (sessionId, path40, options) => await writeOf(
10841
11312
  `${CONTROL_PATH_PREFIX}/read-file`,
10842
- JSON.stringify({ session: sessionId, path: path39, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
10843
- (status, message) => `reading ${path39} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
11313
+ JSON.stringify({ session: sessionId, path: path40, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
11314
+ (status, message) => `reading ${path40} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
10844
11315
  ),
10845
11316
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10846
11317
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -10999,12 +11470,12 @@ function tlsFacts(options) {
10999
11470
  }
11000
11471
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
11001
11472
  const agent = new ExemptTlsAgent();
11002
- const post = async (path39, headers, body) => await new Promise((resolve, reject) => {
11473
+ const post = async (path40, headers, body) => await new Promise((resolve, reject) => {
11003
11474
  const options = {
11004
11475
  host: target.host,
11005
11476
  port: target.port,
11006
11477
  method: "POST",
11007
- path: path39,
11478
+ path: path40,
11008
11479
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
11009
11480
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
11010
11481
  agent
@@ -11069,12 +11540,12 @@ function lateRcStreamDial(resolve) {
11069
11540
  }
11070
11541
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
11071
11542
  const agent = new ExemptTlsAgent();
11072
- const request4 = async (method, path39, headers, body, signal) => await new Promise((resolve, reject) => {
11543
+ const request4 = async (method, path40, headers, body, signal) => await new Promise((resolve, reject) => {
11073
11544
  const options = {
11074
11545
  host: target.host,
11075
11546
  port: target.port,
11076
11547
  method,
11077
- path: path39,
11548
+ path: path40,
11078
11549
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
11079
11550
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
11080
11551
  agent,
@@ -11116,9 +11587,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
11116
11587
  return { status, body: await readAll(response) };
11117
11588
  },
11118
11589
  openStream: async (sessionId, headers, resume, signal) => {
11119
- const path39 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
11590
+ const path40 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
11120
11591
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
11121
- const { status, response } = await request4("GET", path39, streamHeaders, void 0, signal);
11592
+ const { status, response } = await request4("GET", path40, streamHeaders, void 0, signal);
11122
11593
  if (!isSuccessful2(status)) {
11123
11594
  await readAll(response);
11124
11595
  return { status, chunks: NO_CHUNKS };
@@ -12058,7 +12529,7 @@ init_cliError();
12058
12529
 
12059
12530
  // src/configProfilesStore.ts
12060
12531
  var import_node_fs3 = __toESM(require("node:fs"), 1);
12061
- var import_node_path21 = __toESM(require("node:path"), 1);
12532
+ var import_node_path22 = __toESM(require("node:path"), 1);
12062
12533
  init_store();
12063
12534
  init_schema();
12064
12535
  init_cliError();
@@ -12088,7 +12559,7 @@ var InvalidCategoryNameError = class extends CliError {
12088
12559
  categoryName;
12089
12560
  };
12090
12561
  function profileJsonPath(paths, name) {
12091
- return import_node_path21.default.join(paths.configProfilesDir, `${name}.json`);
12562
+ return import_node_path22.default.join(paths.configProfilesDir, `${name}.json`);
12092
12563
  }
12093
12564
  function profileExists(paths, name) {
12094
12565
  return import_node_fs3.default.existsSync(profileJsonPath(paths, name));
@@ -12270,19 +12741,19 @@ function writePools(paths, pools) {
12270
12741
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
12271
12742
  }
12272
12743
  function poolCycleOf(pools, name) {
12273
- const walk = (current, path39) => {
12744
+ const walk = (current, path40) => {
12274
12745
  for (const entry of pools[current]?.identities ?? []) {
12275
12746
  const nested = poolNameOf(poolMemberIdentity(entry));
12276
12747
  if (nested === void 0) {
12277
12748
  continue;
12278
12749
  }
12279
12750
  if (nested === name) {
12280
- return [...path39, nested];
12751
+ return [...path40, nested];
12281
12752
  }
12282
- if (path39.includes(nested)) {
12753
+ if (path40.includes(nested)) {
12283
12754
  continue;
12284
12755
  }
12285
- const found = walk(nested, [...path39, nested]);
12756
+ const found = walk(nested, [...path40, nested]);
12286
12757
  if (found !== void 0) {
12287
12758
  return found;
12288
12759
  }
@@ -12381,7 +12852,7 @@ init_paths();
12381
12852
  init_realCredentialCache();
12382
12853
  init_providersStore();
12383
12854
  init_realPorts();
12384
- var import_node_path25 = __toESM(require("node:path"), 1);
12855
+ var import_node_path26 = __toESM(require("node:path"), 1);
12385
12856
  var import_zod15 = require("zod");
12386
12857
  init_envBool();
12387
12858
  init_load();
@@ -12730,10 +13201,10 @@ function collectCheckReport(params) {
12730
13201
  }).input;
12731
13202
  const providerName = cascadeProviderName(cascade);
12732
13203
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
12733
- const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path25.default.join(paths.identitiesDir, identityDecision.name);
13204
+ const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path26.default.join(paths.identitiesDir, identityDecision.name);
12734
13205
  const settingsFiles = {
12735
- "settings.json": realFsPort.readFileUtf8(import_node_path25.default.join(claudeHome, "settings.json")),
12736
- "settings.local.json": realFsPort.readFileUtf8(import_node_path25.default.join(claudeHome, "settings.local.json"))
13206
+ "settings.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.json")),
13207
+ "settings.local.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.local.json"))
12737
13208
  };
12738
13209
  const report = runCheck({
12739
13210
  cwd,
@@ -13025,7 +13496,7 @@ var ResetRowSchema = import_zod18.z.strictObject({
13025
13496
  var ResetScheduleSchema = import_zod18.z.strictObject({ resets: import_zod18.z.readonly(import_zod18.z.array(ResetRowSchema)) });
13026
13497
 
13027
13498
  // src/frontdoor/controlSchemas.ts
13028
- var import_node_path30 = __toESM(require("node:path"), 1);
13499
+ var import_node_path31 = __toESM(require("node:path"), 1);
13029
13500
  var import_zod23 = require("zod");
13030
13501
 
13031
13502
  // src/doctorReport.ts
@@ -13034,7 +13505,7 @@ init_store();
13034
13505
 
13035
13506
  // src/identityStore.ts
13036
13507
  var import_node_fs8 = __toESM(require("node:fs"), 1);
13037
- var import_node_path27 = __toESM(require("node:path"), 1);
13508
+ var import_node_path28 = __toESM(require("node:path"), 1);
13038
13509
  init_load();
13039
13510
  init_store();
13040
13511
  init_schema();
@@ -13068,7 +13539,7 @@ var InvalidIdentityNameError = class extends CliError {
13068
13539
  attemptedName;
13069
13540
  };
13070
13541
  function identityJsonPath(paths, name) {
13071
- return import_node_path27.default.join(paths.identitiesDir, name, "identity.json");
13542
+ return import_node_path28.default.join(paths.identitiesDir, name, "identity.json");
13072
13543
  }
13073
13544
  function requireIdentityNames(paths, names) {
13074
13545
  const existing = new Set(listIdentities(paths).map((entry) => entry.name));
@@ -13183,7 +13654,7 @@ function setIdentityCredential(paths, identityName, change) {
13183
13654
  });
13184
13655
  }
13185
13656
  function belongsToIdentity(entry, name) {
13186
- return entry === name || entry === import_node_path27.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
13657
+ return entry === name || entry === import_node_path28.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
13187
13658
  }
13188
13659
  function removeIdentity(paths, name) {
13189
13660
  if (!identityExists(paths, name)) {
@@ -13191,7 +13662,7 @@ function removeIdentity(paths, name) {
13191
13662
  }
13192
13663
  for (const entry of import_node_fs8.default.readdirSync(paths.identitiesDir)) {
13193
13664
  if (belongsToIdentity(entry, name)) {
13194
- import_node_fs8.default.rmSync(import_node_path27.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
13665
+ import_node_fs8.default.rmSync(import_node_path28.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
13195
13666
  }
13196
13667
  }
13197
13668
  if (readActiveIdentity2(paths) === name) {
@@ -13202,10 +13673,10 @@ function removeIdentity(paths, name) {
13202
13673
  // src/doctorReport.ts
13203
13674
  init_realPorts();
13204
13675
  var import_node_fs9 = __toESM(require("node:fs"), 1);
13205
- var import_node_path29 = __toESM(require("node:path"), 1);
13676
+ var import_node_path30 = __toESM(require("node:path"), 1);
13206
13677
 
13207
13678
  // src/usage/signIn.ts
13208
- var import_node_path28 = __toESM(require("node:path"), 1);
13679
+ var import_node_path29 = __toESM(require("node:path"), 1);
13209
13680
  var CREDENTIALS_FILE = ".credentials.json";
13210
13681
  function keychainHasItem(run, account) {
13211
13682
  return run.run("security", ["find-generic-password", "-a", account]).status === 0;
@@ -13223,7 +13694,7 @@ function decideSignIn(facts) {
13223
13694
  return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
13224
13695
  }
13225
13696
  function credentialsFilePath(farmRoot) {
13226
- return import_node_path28.default.join(farmRoot, CREDENTIALS_FILE);
13697
+ return import_node_path29.default.join(farmRoot, CREDENTIALS_FILE);
13227
13698
  }
13228
13699
 
13229
13700
  // src/codex/siwcStore.ts
@@ -13312,17 +13783,75 @@ init_realCredentialCache();
13312
13783
  init_source();
13313
13784
 
13314
13785
  // src/headroom/allowlistDrift.ts
13786
+ init_earlierRelease();
13315
13787
  init_state2();
13316
13788
  function diagnoseAllowlistDrift(params) {
13317
- const { recordedHash, providers, frontDoorOrigin: frontDoorOrigin2 } = params;
13318
- if (recordedHash === void 0 || recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin2)))) {
13789
+ const { allowlist, fileContent, recordedHash, earlierRelease } = params;
13790
+ if (recordedHash === void 0) {
13791
+ return void 0;
13792
+ }
13793
+ if (earlierRelease !== void 0) {
13794
+ return earlierRelease.admitsServingDoor ? void 0 : { startedByEarlierRelease: true };
13795
+ }
13796
+ const served = fileContent === void 0 ? [] : parseAllowlistFile(fileContent);
13797
+ const listed = new Set(served);
13798
+ const computed = new Set(allowlist);
13799
+ const missingFromFile = allowlist.filter((entry) => !listed.has(entry));
13800
+ const staleInFile = served.filter((entry) => !computed.has(entry)).sort();
13801
+ const hashLags = recordedHash !== (fileContent === void 0 ? void 0 : hashAllowlistFile(fileContent));
13802
+ if (missingFromFile.length === 0 && staleInFile.length === 0 && !hashLags) {
13319
13803
  return void 0;
13320
13804
  }
13321
- const originIsInput = providers.length > 0 && frontDoorOrigin2 !== void 0;
13322
- if (!originIsInput) {
13323
- return ["provider-files"];
13805
+ return { missingFromFile, staleInFile, hashLags };
13806
+ }
13807
+ function describeAllowlistDrift(params) {
13808
+ const { drift, allowlistFile, liveSupervisorPid } = params;
13809
+ if (drift.startedByEarlierRelease === true) {
13810
+ return `the daemon was ${EARLIER_RELEASE_ALLOWLIST}, its allowlist cannot be shown to admit the serving front door (the door moved, or a provider changed, since it started), and until then provider launches are refused`;
13811
+ }
13812
+ const parts = [];
13813
+ if (drift.missingFromFile.length > 0) {
13814
+ parts.push(`${allowlistFile} lacks ${drift.missingFromFile.join(", ")} (live front doors' direct origins, so the daemon refuses every request a provider launch sends back through those doors)`);
13815
+ }
13816
+ if (drift.staleInFile.length > 0) {
13817
+ parts.push(`${allowlistFile} still lists ${drift.staleInFile.join(", ")}`);
13818
+ }
13819
+ if (drift.hashLags) {
13820
+ parts.push("the supervisor has not yet recorded the file's allowlist as served, and provider launches through headroom wait until it does");
13821
+ }
13822
+ const healing = liveSupervisorPid === void 0 ? "the supervisor is not running, so nothing rewrites the file until the next launch through headroom starts one" : `supervisor ${String(liveSupervisorPid)} rewrites the file on its next tick, so drift that persists means it cannot write it (see ${params.logPath})`;
13823
+ return `${parts.join("; ")}; ${healing}`;
13824
+ }
13825
+
13826
+ // src/doctorReport.ts
13827
+ init_earlierRelease();
13828
+ init_socket();
13829
+
13830
+ // src/doctorHeadroomAllowlist.ts
13831
+ function pushRefusedAllowlistFile(push, allowlist) {
13832
+ const problem = allowlist.fileProblem;
13833
+ if (problem?.repairable === false) {
13834
+ push("headroom", "fail", `Headroom refuses its allowlist file, so it admits nothing and every provider request through headroom fails: ${problem.message}.`, allowlist.file);
13835
+ }
13836
+ }
13837
+ function pushHeadroomAllowlist(push, allowlist, daemon) {
13838
+ const { drift } = allowlist;
13839
+ const problem = allowlist.fileProblem;
13840
+ if (problem?.repairable === true) {
13841
+ push("headroom", "warn", `Headroom's allowlist file breaks agent-shim's owner-only rule for it: ${problem.message}. Its supervisor repairs this on its next tick, and stops the daemon if it cannot.`, allowlist.file);
13842
+ }
13843
+ if (drift !== void 0) {
13844
+ const blocking = drift.startedByEarlierRelease === true || drift.missingFromFile.length > 0 || drift.hashLags;
13845
+ push(
13846
+ "headroom",
13847
+ blocking ? "fail" : "warn",
13848
+ `Headroom daemon ${String(daemon.headroomPid)}'s allowlist lags the current one: ` + describeAllowlistDrift({ drift, allowlistFile: allowlist.file, liveSupervisorPid: daemon.liveSupervisorPid, logPath: allowlist.logPath }) + ". `--no-headroom` launches are unaffected.",
13849
+ String(daemon.headroomPid)
13850
+ );
13851
+ }
13852
+ for (const door of allowlist.undeterminedFrontDoors) {
13853
+ push("headroom", "warn", `Could not tell whether front door ${String(door.pid)} is still running (${door.reason}), so headroom keeps admitting its direct origin ${door.origin} until a later read can.`, String(door.pid));
13324
13854
  }
13325
- return recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, void 0))) ? ["front-door-origin"] : ["provider-files", "front-door-origin"];
13326
13855
  }
13327
13856
 
13328
13857
  // src/doctorReport.ts
@@ -13331,7 +13860,7 @@ init_supervisor();
13331
13860
  init_state();
13332
13861
 
13333
13862
  // src/doctorFrontDoor.ts
13334
- function pushFrontDoor(push, supervisors, registeredPid) {
13863
+ function pushFrontDoor(push, supervisors, registeredPid, liveSessions) {
13335
13864
  if (!supervisors.ok) {
13336
13865
  push("frontdoor", "warn", `Could not list processes to look for duplicate front door supervisors: ${supervisors.message}.`);
13337
13866
  return;
@@ -13348,6 +13877,16 @@ function pushFrontDoor(push, supervisors, registeredPid) {
13348
13877
  }
13349
13878
  const serving = registeredPid !== void 0 && pids.includes(registeredPid) ? `The front door state file names pid ${String(registeredPid)} as the serving supervisor.` : "The front door state file names no running supervisor.";
13350
13879
  for (const pid of pids.filter((candidate) => candidate !== registeredPid)) {
13880
+ const served = liveSessions.filter((session) => session.supervisorPid === pid).length;
13881
+ if (registeredPid !== void 0 && pids.includes(registeredPid) && served > 0) {
13882
+ push(
13883
+ "frontdoor",
13884
+ "warn",
13885
+ `Front door supervisor pid ${String(pid)} has been superseded by pid ${String(registeredPid)} and still serves ${String(served)} launch${served === 1 ? "" : "es"} registered against it; it exits once they end.`,
13886
+ String(pid)
13887
+ );
13888
+ continue;
13889
+ }
13351
13890
  push(
13352
13891
  "frontdoor",
13353
13892
  "fail",
@@ -13417,7 +13956,7 @@ function tcpPortEraRecord(raw) {
13417
13956
  return (has("port") || has("lastPort")) && !has("socketPath");
13418
13957
  }
13419
13958
  function pushPathResolution(push, resolution) {
13420
- const ownDir = import_node_path29.default.dirname(resolution.ownExecutablePath);
13959
+ const ownDir = import_node_path30.default.dirname(resolution.ownExecutablePath);
13421
13960
  switch (resolution.agentShim.status) {
13422
13961
  case "ok":
13423
13962
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -13516,14 +14055,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
13516
14055
  }
13517
14056
  function pushLegacyName(push, params) {
13518
14057
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
13519
- if (legacyVariables.length === 0 && import_node_path29.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
14058
+ if (legacyVariables.length === 0 && import_node_path30.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
13520
14059
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
13521
14060
  return;
13522
14061
  }
13523
14062
  for (const name of legacyVariables) {
13524
14063
  push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
13525
14064
  }
13526
- if (import_node_path29.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
14065
+ if (import_node_path30.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
13527
14066
  push(
13528
14067
  "legacy-name",
13529
14068
  "warn",
@@ -13779,15 +14318,11 @@ function runDoctor(params) {
13779
14318
  );
13780
14319
  }
13781
14320
  const allowlist = params.headroom.allowlist;
13782
- if (supervisorAlive && headroomAlive && state.socketPath !== void 0 && allowlist?.driftInputs?.includes("front-door-origin") === true) {
13783
- const origin = allowlist.frontDoorOrigin ?? "";
13784
- const certainty = allowlist.driftInputs.includes("provider-files") ? "may exclude" : "excludes";
13785
- push(
13786
- "headroom",
13787
- "fail",
13788
- `Headroom daemon ${String(state.headroomPid)} was started with an allowlist that ${certainty} the serving front door's direct origin ${origin}, so it refuses every request a provider launch sends back through the door. Its supervisor restarts it once no launch is registered against it; \`agent-shim headroom status\` lists the registered launches, and \`--no-headroom\` launches are unaffected.`,
13789
- String(state.headroomPid)
13790
- );
14321
+ if (allowlist !== void 0) {
14322
+ pushRefusedAllowlistFile(push, allowlist);
14323
+ }
14324
+ if (allowlist !== void 0 && headroomAlive && state.headroomPid !== void 0) {
14325
+ pushHeadroomAllowlist(push, allowlist, { headroomPid: state.headroomPid, liveSupervisorPid: supervisorAlive ? state.supervisorPid : void 0 });
13791
14326
  }
13792
14327
  if (state.lastError !== void 0 && supervisorAlive) {
13793
14328
  push("headroom", "warn", `Headroom recorded a previous error: ${state.lastError}`);
@@ -13803,7 +14338,7 @@ function runDoctor(params) {
13803
14338
  }
13804
14339
  if (params.frontDoor !== void 0) {
13805
14340
  const validated3 = params.frontDoor.state.raw === void 0 ? void 0 : validateJson(FrontDoorStateSchema, params.frontDoor.state);
13806
- pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0);
14341
+ pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0, params.frontDoor.liveSessions);
13807
14342
  }
13808
14343
  if (params.activeIdentity.raw === void 0) {
13809
14344
  push("active-identity", "pass", "No active identity set.");
@@ -13896,18 +14431,18 @@ function collectDoctorReport(params) {
13896
14431
  const { paths } = params;
13897
14432
  const identityNames = import_node_fs9.default.existsSync(paths.identitiesDir) ? import_node_fs9.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
13898
14433
  const identities = identityNames.map((name) => {
13899
- const farmRoot = import_node_path29.default.join(paths.identitiesDir, name);
13900
- const identityPath = import_node_path29.default.join(farmRoot, "identity.json");
14434
+ const farmRoot = import_node_path30.default.join(paths.identitiesDir, name);
14435
+ const identityPath = import_node_path30.default.join(farmRoot, "identity.json");
13901
14436
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs9.default.existsSync(credentialsFilePath(farmRoot)) };
13902
14437
  });
13903
14438
  const profileNames = import_node_fs9.default.existsSync(paths.configProfilesDir) ? import_node_fs9.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
13904
14439
  const configProfiles = profileNames.map((name) => {
13905
- const profilePath = import_node_path29.default.join(paths.configProfilesDir, `${name}.json`);
14440
+ const profilePath = import_node_path30.default.join(paths.configProfilesDir, `${name}.json`);
13906
14441
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
13907
14442
  });
13908
14443
  const providerNames = import_node_fs9.default.existsSync(paths.providersDir) ? import_node_fs9.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
13909
14444
  const providers = providerNames.map((name) => {
13910
- const providerPath = import_node_path29.default.join(paths.providersDir, `${name}.json`);
14445
+ const providerPath = import_node_path30.default.join(paths.providersDir, `${name}.json`);
13911
14446
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
13912
14447
  });
13913
14448
  const ownExecutablePath = realOwnExecutablePath();
@@ -13919,20 +14454,24 @@ function collectDoctorReport(params) {
13919
14454
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
13920
14455
  }
13921
14456
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
13922
- const pathDirs = (params.env.PATH ?? "").split(import_node_path29.default.delimiter).filter((dir) => dir !== "");
14457
+ const pathDirs = (params.env.PATH ?? "").split(import_node_path30.default.delimiter).filter((dir) => dir !== "");
13923
14458
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
13924
14459
  findPathShadow({
13925
14460
  pathDirs,
13926
- targetDir: import_node_path29.default.dirname(shimState.targetPath),
13927
- targetFilename: import_node_path29.default.basename(shimState.targetPath),
14461
+ targetDir: import_node_path30.default.dirname(shimState.targetPath),
14462
+ targetFilename: import_node_path30.default.basename(shimState.targetPath),
13928
14463
  findExecutableInDir
13929
14464
  }),
13930
14465
  shimState.targetPath,
13931
14466
  realpathOrSelf
13932
14467
  );
13933
14468
  const uid = process.getuid?.();
13934
- const allowlistInputs = currentHeadroomAllowlistInputs(realFarmFs, paths);
14469
+ const allowlistContent = realFarmFs.readFileUtf8(paths.headroomAllowlistFile);
14470
+ const allowlistInputs = currentHeadroomAllowlistInputs(realFarmFs, paths, realFrontDoorLiveness);
13935
14471
  const servingHeadroom = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
14472
+ const servingState = servingHeadroom?.state;
14473
+ const servingDaemon = servingState?.headroomPid !== void 0 && servingState.socketPath !== void 0 && realIsProcessRunning(servingState.headroomPid) ? { pid: servingState.headroomPid, socketPath: servingState.socketPath } : void 0;
14474
+ const servingEarlierRelease = servingDaemon === void 0 ? void 0 : earlierReleaseDaemon(realFarmFs, paths, { commandLine: realProcessCommandLine(servingDaemon.pid), socketPath: servingDaemon.socketPath, recordedHash: servingState?.allowlistHash });
13936
14475
  const report = runDoctor({
13937
14476
  env: params.env,
13938
14477
  credentialCache: realCredentialCacheEnv(paths),
@@ -13953,7 +14492,7 @@ function collectDoctorReport(params) {
13953
14492
  agentShim: refinePathShadow(
13954
14493
  findPathShadow({
13955
14494
  pathDirs,
13956
- targetDir: import_node_path29.default.dirname(ownExecutablePath),
14495
+ targetDir: import_node_path30.default.dirname(ownExecutablePath),
13957
14496
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
13958
14497
  findExecutableInDir
13959
14498
  }),
@@ -13973,11 +14512,20 @@ function collectDoctorReport(params) {
13973
14512
  })(),
13974
14513
  isRunning: realIsProcessRunning,
13975
14514
  allowlist: {
13976
- driftInputs: diagnoseAllowlistDrift({ recordedHash: servingHeadroom?.state.allowlistHash, ...allowlistInputs }),
13977
- frontDoorOrigin: allowlistInputs.frontDoorOrigin
14515
+ drift: diagnoseAllowlistDrift({
14516
+ allowlist: allowlistInputs.frontDoorOrigins,
14517
+ fileContent: allowlistContent,
14518
+ recordedHash: servingHeadroom?.state.allowlistHash,
14519
+ earlierRelease: servingEarlierRelease
14520
+ }),
14521
+ file: paths.headroomAllowlistFile,
14522
+ undeterminedFrontDoors: undeterminedFrontDoors(allowlistInputs),
14523
+ // An earlier release's daemon reads no allowlist file, so there is nothing to check while one serves.
14524
+ fileProblem: servingEarlierRelease === void 0 ? reportableAllowlistFileProblem(paths.headroomAllowlistFile, realHeadroomSocketTrust, servingHeadroom?.state.allowlistHash !== void 0) : void 0,
14525
+ logPath: paths.headroomLogPath
13978
14526
  }
13979
14527
  },
13980
- ...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid) } }
14528
+ ...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid), liveSessions: listFrontDoorSessions(realFarmFs, paths.frontdoorSessionsDir).filter((session) => realIsProcessRunning(session.pid)) } }
13981
14529
  });
13982
14530
  return report;
13983
14531
  }
@@ -14032,11 +14580,11 @@ var FrontDoorSessionsOutputSchema = import_zod23.z.strictObject({ sessions: impo
14032
14580
  var CheckRunInputSchema = import_zod23.z.strictObject({
14033
14581
  path: import_zod23.z.string().min(1),
14034
14582
  identity: import_zod23.z.string().min(1).optional()
14035
- }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
14583
+ }).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
14036
14584
  var PoolPickInputSchema = import_zod23.z.strictObject({
14037
14585
  pool: import_zod23.z.string().min(1),
14038
14586
  path: import_zod23.z.string().min(1)
14039
- }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
14587
+ }).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
14040
14588
  var DoctorFindingSchema = import_zod23.z.strictObject({
14041
14589
  section: import_zod23.z.enum(DOCTOR_SECTIONS),
14042
14590
  subject: import_zod23.z.string().optional(),
@@ -14416,7 +14964,7 @@ function profileValue(name, paths) {
14416
14964
  function createConfigApiRouter(deps) {
14417
14965
  const authed = doorApiAuth(deps.expectedToken);
14418
14966
  const { paths } = deps;
14419
- const route = (path39, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path39, summary, tags: [CONFIG_API_TAG] }));
14967
+ const route = (path40, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path40, summary, tags: [CONFIG_API_TAG] }));
14420
14968
  return {
14421
14969
  config: {
14422
14970
  identity: {
@@ -14780,7 +15328,7 @@ var import_openapi6 = require("@orpc/openapi");
14780
15328
  init_cliError();
14781
15329
 
14782
15330
  // src/frontdoor/launchSchemas.ts
14783
- var import_node_path31 = __toESM(require("node:path"), 1);
15331
+ var import_node_path32 = __toESM(require("node:path"), 1);
14784
15332
  var import_zod26 = require("zod");
14785
15333
  init_claudeVersion();
14786
15334
  init_identity();
@@ -14790,7 +15338,7 @@ var LaunchResolveInputSchema = import_zod26.z.strictObject({
14790
15338
  argv: import_zod26.z.readonly(import_zod26.z.array(import_zod26.z.string())).optional(),
14791
15339
  /** The launch's inherited environment. Absent means an empty one: the door's own environment is never a substitute for the caller's, so a caller that wants `AGENT_SHIM_*` switches or a `CLAUDE_CONFIG_DIR` considered names them here. Values are read, never reported. */
14792
15340
  env: import_zod26.z.record(import_zod26.z.string(), import_zod26.z.string()).optional()
14793
- }).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
15341
+ }).refine((input) => import_node_path32.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
14794
15342
  var LaunchPoolDecisionSchema = import_zod26.z.strictObject({
14795
15343
  name: import_zod26.z.string(),
14796
15344
  reasons: import_zod26.z.readonly(import_zod26.z.array(import_zod26.z.string())),
@@ -16957,7 +17505,7 @@ data: ${JSON.stringify(envelope)}
16957
17505
  }
16958
17506
 
16959
17507
  // src/frontdoor/rcSelfHostMint.ts
16960
- var import_node_path32 = __toESM(require("node:path"), 1);
17508
+ var import_node_path33 = __toESM(require("node:path"), 1);
16961
17509
  init_account();
16962
17510
  var CREDENTIALS_FILE2 = ".credentials.json";
16963
17511
  var CLAUDE_JSON2 = ".claude.json";
@@ -16982,7 +17530,7 @@ function readJsonObject(fs12, file) {
16982
17530
  return isRecord12(parsed) ? parsed : void 0;
16983
17531
  }
16984
17532
  function readRcSelfHostRecord(fs12, frontdoorDir) {
16985
- const parsed = readJsonObject(fs12, import_node_path32.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
17533
+ const parsed = readJsonObject(fs12, import_node_path33.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
16986
17534
  if (parsed === void 0) {
16987
17535
  return void 0;
16988
17536
  }
@@ -16996,11 +17544,11 @@ function mintRcSelfHostCredential(deps) {
16996
17544
  if (!isIdentityName(deps.identity)) {
16997
17545
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
16998
17546
  }
16999
- const identityDir = import_node_path32.default.join(deps.identitiesDir, deps.identity);
17000
- const credentialsFile = import_node_path32.default.join(identityDir, CREDENTIALS_FILE2);
17001
- const claudeJsonFile = import_node_path32.default.join(identityDir, CLAUDE_JSON2);
17002
- const recordDir = import_node_path32.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
17003
- const recordFile = import_node_path32.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
17547
+ const identityDir = import_node_path33.default.join(deps.identitiesDir, deps.identity);
17548
+ const credentialsFile = import_node_path33.default.join(identityDir, CREDENTIALS_FILE2);
17549
+ const claudeJsonFile = import_node_path33.default.join(identityDir, CLAUDE_JSON2);
17550
+ const recordDir = import_node_path33.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
17551
+ const recordFile = import_node_path33.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
17004
17552
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
17005
17553
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
17006
17554
  const existingOauth = isRecord12(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -17016,7 +17564,7 @@ function mintRcSelfHostCredential(deps) {
17016
17564
  const organizationUuid = deps.newUuid();
17017
17565
  const accountUuid = deps.newUuid();
17018
17566
  const mintedAt = new Date(deps.now()).toISOString();
17019
- deps.fs.mkdirPrivate(import_node_path32.default.dirname(credentialsFile));
17567
+ deps.fs.mkdirPrivate(import_node_path33.default.dirname(credentialsFile));
17020
17568
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
17021
17569
  `);
17022
17570
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
@@ -17058,7 +17606,7 @@ init_plan2();
17058
17606
  init_poolPick();
17059
17607
 
17060
17608
  // src/agents/read.ts
17061
- var import_node_path33 = __toESM(require("node:path"), 1);
17609
+ var import_node_path34 = __toESM(require("node:path"), 1);
17062
17610
  var import_zod28 = require("zod");
17063
17611
  var PROJECTS_DIR = "projects";
17064
17612
  var TASKS_DIR = "tasks";
@@ -17084,15 +17632,15 @@ function parseEntry2(project, entry) {
17084
17632
  }
17085
17633
  function listSessions2(fs12, configDir) {
17086
17634
  const found = [];
17087
- for (const project of fs12.readdir(import_node_path33.default.join(configDir, PROJECTS_DIR))) {
17088
- const projectDir = import_node_path33.default.join(configDir, PROJECTS_DIR, project);
17635
+ for (const project of fs12.readdir(import_node_path34.default.join(configDir, PROJECTS_DIR))) {
17636
+ const projectDir = import_node_path34.default.join(configDir, PROJECTS_DIR, project);
17089
17637
  const entries = /* @__PURE__ */ new Set();
17090
17638
  for (const name of fs12.readdir(projectDir)) {
17091
17639
  if (name.endsWith(TRANSCRIPT_SUFFIX)) {
17092
17640
  entries.add(name.slice(0, -TRANSCRIPT_SUFFIX.length));
17093
17641
  continue;
17094
17642
  }
17095
- const children = fs12.readdir(import_node_path33.default.join(projectDir, name));
17643
+ const children = fs12.readdir(import_node_path34.default.join(projectDir, name));
17096
17644
  if (children.includes(SUBAGENTS_DIR) || children.includes(WORKFLOWS_DIR)) {
17097
17645
  entries.add(name);
17098
17646
  }
@@ -17112,8 +17660,8 @@ function locateAgents(fs12, configDir, relativeDir, workflowRunId, report) {
17112
17660
  const id = name.slice(AGENT_FILE_PREFIX.length, -META_SUFFIX.length);
17113
17661
  located.push({
17114
17662
  id,
17115
- metaPath: import_node_path33.default.join(relativeDir, name),
17116
- transcriptPath: import_node_path33.default.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
17663
+ metaPath: import_node_path34.default.join(relativeDir, name),
17664
+ transcriptPath: import_node_path34.default.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
17117
17665
  workflowRunId
17118
17666
  });
17119
17667
  }
@@ -17156,7 +17704,7 @@ function describeFailure(error) {
17156
17704
  }
17157
17705
  function readFileOrReport(fs12, configDir, relative, report) {
17158
17706
  try {
17159
- return fs12.readFileUtf8(import_node_path33.default.join(configDir, relative));
17707
+ return fs12.readFileUtf8(import_node_path34.default.join(configDir, relative));
17160
17708
  } catch (error) {
17161
17709
  report({ path: relative, reason: `could not be read: ${describeFailure(error)}` });
17162
17710
  return void 0;
@@ -17164,7 +17712,7 @@ function readFileOrReport(fs12, configDir, relative, report) {
17164
17712
  }
17165
17713
  function listDirOrReport(fs12, configDir, relative, report) {
17166
17714
  try {
17167
- return fs12.readdir(import_node_path33.default.join(configDir, relative));
17715
+ return fs12.readdir(import_node_path34.default.join(configDir, relative));
17168
17716
  } catch (error) {
17169
17717
  report({ path: relative, reason: `could not be listed: ${describeFailure(error)}` });
17170
17718
  return [];
@@ -17188,18 +17736,18 @@ var WorkflowRunFileSchema = import_zod28.z.object({
17188
17736
  summary: import_zod28.z.string().optional()
17189
17737
  });
17190
17738
  function summariseSession(fs12, configDir, ref) {
17191
- const sessionRelative = import_node_path33.default.join(PROJECTS_DIR, ref.project, ref.entry);
17192
- const subagentsRelative = import_node_path33.default.join(sessionRelative, SUBAGENTS_DIR);
17193
- const workflowsUnderSubagents = import_node_path33.default.join(subagentsRelative, WORKFLOWS_DIR);
17739
+ const sessionRelative = import_node_path34.default.join(PROJECTS_DIR, ref.project, ref.entry);
17740
+ const subagentsRelative = import_node_path34.default.join(sessionRelative, SUBAGENTS_DIR);
17741
+ const workflowsUnderSubagents = import_node_path34.default.join(subagentsRelative, WORKFLOWS_DIR);
17194
17742
  const isMeta = (name) => name.startsWith(AGENT_FILE_PREFIX) && name.endsWith(META_SUFFIX);
17195
- let agentCount = fs12.readdir(import_node_path33.default.join(configDir, subagentsRelative)).filter(isMeta).length;
17196
- for (const runDir of fs12.readdir(import_node_path33.default.join(configDir, workflowsUnderSubagents))) {
17743
+ let agentCount = fs12.readdir(import_node_path34.default.join(configDir, subagentsRelative)).filter(isMeta).length;
17744
+ for (const runDir of fs12.readdir(import_node_path34.default.join(configDir, workflowsUnderSubagents))) {
17197
17745
  if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
17198
- agentCount += fs12.readdir(import_node_path33.default.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
17746
+ agentCount += fs12.readdir(import_node_path34.default.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
17199
17747
  }
17200
17748
  }
17201
- const workflowRunCount = fs12.readdir(import_node_path33.default.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
17202
- const transcript = fs12.lstat(import_node_path33.default.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
17749
+ const workflowRunCount = fs12.readdir(import_node_path34.default.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
17750
+ const transcript = fs12.lstat(import_node_path34.default.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
17203
17751
  return { ...ref, agentCount, workflowRunCount, ...transcript === void 0 ? {} : { updatedAt: new Date(transcript.mtimeMs).toISOString() } };
17204
17752
  }
17205
17753
  function readSessionAgentTree(fs12, configDir, ref, options = {}) {
@@ -17207,13 +17755,13 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
17207
17755
  const report = (problem) => {
17208
17756
  problems.push(problem);
17209
17757
  };
17210
- const sessionRelative = import_node_path33.default.join(PROJECTS_DIR, ref.project, ref.entry);
17211
- const subagentsRelative = import_node_path33.default.join(sessionRelative, SUBAGENTS_DIR);
17212
- const workflowsUnderSubagents = import_node_path33.default.join(subagentsRelative, WORKFLOWS_DIR);
17758
+ const sessionRelative = import_node_path34.default.join(PROJECTS_DIR, ref.project, ref.entry);
17759
+ const subagentsRelative = import_node_path34.default.join(sessionRelative, SUBAGENTS_DIR);
17760
+ const workflowsUnderSubagents = import_node_path34.default.join(subagentsRelative, WORKFLOWS_DIR);
17213
17761
  const located = locateAgents(fs12, configDir, subagentsRelative, void 0, report);
17214
17762
  for (const runDir of listDirOrReport(fs12, configDir, workflowsUnderSubagents, report)) {
17215
17763
  if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
17216
- located.push(...locateAgents(fs12, configDir, import_node_path33.default.join(workflowsUnderSubagents, runDir), runDir, report));
17764
+ located.push(...locateAgents(fs12, configDir, import_node_path34.default.join(workflowsUnderSubagents, runDir), runDir, report));
17217
17765
  }
17218
17766
  }
17219
17767
  const agents = /* @__PURE__ */ new Map();
@@ -17254,7 +17802,7 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
17254
17802
  superseded: ref.superseded,
17255
17803
  agents: roots.sort().map(build),
17256
17804
  tasks: readTasks(fs12, configDir, ownTaskLists(ref.sessionId), [.../* @__PURE__ */ new Set([...teamNames, ...options.taskListIds ?? []])].filter((id) => !ownTaskLists(ref.sessionId).includes(id)), report),
17257
- workflowRuns: readWorkflowRuns(fs12, configDir, import_node_path33.default.join(sessionRelative, WORKFLOWS_DIR), report),
17805
+ workflowRuns: readWorkflowRuns(fs12, configDir, import_node_path34.default.join(sessionRelative, WORKFLOWS_DIR), report),
17258
17806
  problems
17259
17807
  };
17260
17808
  }
@@ -17319,12 +17867,12 @@ function ownTaskLists(sessionId) {
17319
17867
  function readTasks(fs12, configDir, ownLists, sharedLists, report) {
17320
17868
  const tasks = [];
17321
17869
  [...ownLists, ...sharedLists].forEach((scope, index) => {
17322
- const relativeDir = import_node_path33.default.join(TASKS_DIR, scope);
17870
+ const relativeDir = import_node_path34.default.join(TASKS_DIR, scope);
17323
17871
  for (const name of [...listDirOrReport(fs12, configDir, relativeDir, report)].sort()) {
17324
17872
  if (name.startsWith(".") || !name.endsWith(JSON_SUFFIX)) {
17325
17873
  continue;
17326
17874
  }
17327
- const relative = import_node_path33.default.join(relativeDir, name);
17875
+ const relative = import_node_path34.default.join(relativeDir, name);
17328
17876
  const text = readFileOrReport(fs12, configDir, relative, report);
17329
17877
  const parsed = TaskFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
17330
17878
  if (parsed.success) {
@@ -17342,7 +17890,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
17342
17890
  if (!name.startsWith(WORKFLOW_RUN_PREFIX) || !name.endsWith(JSON_SUFFIX)) {
17343
17891
  continue;
17344
17892
  }
17345
- const relative = import_node_path33.default.join(relativeDir, name);
17893
+ const relative = import_node_path34.default.join(relativeDir, name);
17346
17894
  const text = readFileOrReport(fs12, configDir, relative, report);
17347
17895
  const parsed = WorkflowRunFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
17348
17896
  if (!parsed.success) {
@@ -17358,7 +17906,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
17358
17906
  }
17359
17907
 
17360
17908
  // src/agents/sessions.ts
17361
- var import_node_path34 = __toESM(require("node:path"), 1);
17909
+ var import_node_path35 = __toESM(require("node:path"), 1);
17362
17910
  init_cliError();
17363
17911
  var SessionLookupError = class extends CliError {
17364
17912
  constructor(message) {
@@ -17367,13 +17915,13 @@ var SessionLookupError = class extends CliError {
17367
17915
  }
17368
17916
  };
17369
17917
  function identityConfigDir(identitiesDir, identity) {
17370
- return import_node_path34.default.join(identitiesDir, identity);
17918
+ return import_node_path35.default.join(identitiesDir, identity);
17371
17919
  }
17372
17920
  function historyStores(fs12, identitiesDir, identities) {
17373
17921
  const byRealPath = /* @__PURE__ */ new Map();
17374
17922
  for (const identity of identities) {
17375
17923
  const configDir = identityConfigDir(identitiesDir, identity);
17376
- const real = fs12.realpath(import_node_path34.default.join(configDir, "projects"));
17924
+ const real = fs12.realpath(import_node_path35.default.join(configDir, "projects"));
17377
17925
  if (real === void 0) {
17378
17926
  continue;
17379
17927
  }
@@ -17826,6 +18374,7 @@ init_ownCli();
17826
18374
  isRcReadFileEncoding,
17827
18375
  lateRcEventDial,
17828
18376
  lateRcStreamDial,
18377
+ launchRequiredUpstreams,
17829
18378
  listDirectoryRules,
17830
18379
  listIdentities,
17831
18380
  listProfiles,