agent-shim 11.5.1 → 11.6.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/cli.cjs CHANGED
@@ -24697,6 +24697,35 @@ var init_store = __esm({
24697
24697
  }
24698
24698
  });
24699
24699
 
24700
+ // src/processRole.ts
24701
+ function enterProcessRole(role) {
24702
+ const previous = currentRole;
24703
+ currentRole = role;
24704
+ return () => {
24705
+ currentRole = previous;
24706
+ };
24707
+ }
24708
+ function refuseToBlockInRole(operation) {
24709
+ if (currentRole !== void 0) {
24710
+ throw new BlockingInEventLoopError(operation, currentRole);
24711
+ }
24712
+ }
24713
+ var currentRole, BlockingInEventLoopError;
24714
+ var init_processRole = __esm({
24715
+ "src/processRole.ts"() {
24716
+ "use strict";
24717
+ init_cliError();
24718
+ BlockingInEventLoopError = class extends CliError {
24719
+ constructor(operation, role) {
24720
+ super(
24721
+ `${operation} blocks the calling thread, which in the ${role} is the event loop that answers every session; it must not run there (a launch planned inside the door reaches it through its own addresses, never through the launcher's synchronous coordination)`
24722
+ );
24723
+ this.name = "BlockingInEventLoopError";
24724
+ }
24725
+ };
24726
+ }
24727
+ });
24728
+
24700
24729
  // src/versionDiscovery.ts
24701
24730
  function defaultVersionsDir() {
24702
24731
  return import_node_path3.default.join(import_node_os.default.homedir(), ".local", "share", "claude", "versions");
@@ -28498,6 +28527,7 @@ function isErrorWithCode(error63, code) {
28498
28527
  return typeof error63 === "object" && error63 !== null && "code" in error63 && error63.code === code;
28499
28528
  }
28500
28529
  function realSleepSync(ms2) {
28530
+ refuseToBlockInRole("a synchronous sleep");
28501
28531
  Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms2);
28502
28532
  }
28503
28533
  function realIsProcessAlive(pid) {
@@ -28786,6 +28816,7 @@ var import_node_child_process2, import_node_crypto4, import_node_fs3, import_nod
28786
28816
  var init_realPorts = __esm({
28787
28817
  "src/realPorts.ts"() {
28788
28818
  "use strict";
28819
+ init_processRole();
28789
28820
  import_node_child_process2 = require("node:child_process");
28790
28821
  import_node_crypto4 = require("node:crypto");
28791
28822
  import_node_fs3 = __toESM(require("node:fs"), 1);
@@ -33976,7 +34007,7 @@ var init_package = __esm({
33976
34007
  "package.json"() {
33977
34008
  package_default = {
33978
34009
  name: "agent-shim",
33979
- version: "11.5.1",
34010
+ version: "11.6.0",
33980
34011
  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.",
33981
34012
  license: "MIT",
33982
34013
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -61821,7 +61852,13 @@ function ensureFrontDoor(params) {
61821
61852
  };
61822
61853
  const stopAndAwaitExit = (supervisorPid, failure2) => {
61823
61854
  ports.stopSupervisor(supervisorPid);
61855
+ const graceEnds = ports.now() + FRONTDOOR_EXIT_GRACE_MS;
61856
+ let killed = false;
61824
61857
  while (ports.isRunning(supervisorPid)) {
61858
+ if (!killed && ports.now() >= graceEnds) {
61859
+ ports.killSupervisor(supervisorPid);
61860
+ killed = true;
61861
+ }
61825
61862
  if (ports.now() >= deadline) {
61826
61863
  throw new FrontDoorStartError(`${failure2}. Daemon log: ${paths.frontdoorLogPath}`);
61827
61864
  }
@@ -61833,6 +61870,11 @@ function ensureFrontDoor(params) {
61833
61870
  const supervisorPid = state?.supervisorPid;
61834
61871
  if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
61835
61872
  if (state?.port !== void 0 && state.connectPort !== void 0) {
61873
+ if (supervisorPid === params.launcherPid && params.replace !== true && ports.isFrontDoorSupervisor(supervisorPid)) {
61874
+ const token = (0, import_node_crypto10.randomUUID)();
61875
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
61876
+ return { port: state.port, connectPort: state.connectPort, token };
61877
+ }
61836
61878
  const verdict = verifyWithRetry(state.port);
61837
61879
  if (verdict.ok && !replaced && !spawned && (params.replace === true || (state.protocol ?? 0) < FRONT_DOOR_PROTOCOL)) {
61838
61880
  stopAndAwaitExit(
@@ -61853,6 +61895,11 @@ function ensureFrontDoor(params) {
61853
61895
  }
61854
61896
  if (ports.isFrontDoorSupervisor(supervisorPid)) {
61855
61897
  const stranded = liveSessionsOn(supervisorPid);
61898
+ if (params.replace === true && !replaced) {
61899
+ stopAndAwaitExit(supervisorPid, `the front door (pid ${String(supervisorPid)}) stopped answering and did not exit when asked to`);
61900
+ replaced = true;
61901
+ continue;
61902
+ }
61856
61903
  if (stranded > 0) {
61857
61904
  busyDoor = { pid: supervisorPid, sessions: stranded };
61858
61905
  } else {
@@ -61908,7 +61955,7 @@ function restartFrontDoor(params) {
61908
61955
  }
61909
61956
  return { action: "restarted", previousPid, pid };
61910
61957
  }
61911
- var import_node_crypto10, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FrontDoorStartError;
61958
+ var import_node_crypto10, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FRONTDOOR_EXIT_GRACE_MS, FrontDoorStartError;
61912
61959
  var init_ensure2 = __esm({
61913
61960
  "src/frontdoor/ensure.ts"() {
61914
61961
  "use strict";
@@ -61919,6 +61966,7 @@ var init_ensure2 = __esm({
61919
61966
  FRONTDOOR_START_TIMEOUT_MS = 3e4;
61920
61967
  FRONTDOOR_LAUNCHER_POLL_MS = 100;
61921
61968
  FRONTDOOR_PROBE_ATTEMPTS = 3;
61969
+ FRONTDOOR_EXIT_GRACE_MS = 5e3;
61922
61970
  FrontDoorStartError = class extends CliError {
61923
61971
  constructor(message) {
61924
61972
  super(message);
@@ -61930,6 +61978,7 @@ var init_ensure2 = __esm({
61930
61978
 
61931
61979
  // src/frontdoor/probe.ts
61932
61980
  function probeFrontDoorSync(port, caPem) {
61981
+ refuseToBlockInRole("a synchronous probe of the front door");
61933
61982
  const shared = new SharedArrayBuffer(HEADER_SLOTS * INT32_BYTES + REASON_BYTES);
61934
61983
  const header = new Int32Array(shared, 0, HEADER_SLOTS);
61935
61984
  const worker = new import_node_worker_threads.Worker(PROBE_SOURCE, {
@@ -61956,6 +62005,7 @@ var import_node_worker_threads, PROBE_TIMEOUT_MS, PROBE_WAIT_MARGIN_MS, REASON_B
61956
62005
  var init_probe = __esm({
61957
62006
  "src/frontdoor/probe.ts"() {
61958
62007
  "use strict";
62008
+ init_processRole();
61959
62009
  import_node_worker_threads = require("node:worker_threads");
61960
62010
  PROBE_TIMEOUT_MS = 2e3;
61961
62011
  PROBE_WAIT_MARGIN_MS = 1e3;
@@ -62048,6 +62098,9 @@ function realEnsurePorts(paths, spawnDaemon) {
62048
62098
  stopSupervisor: (pid) => {
62049
62099
  process.kill(pid, "SIGTERM");
62050
62100
  },
62101
+ killSupervisor: (pid) => {
62102
+ process.kill(pid, "SIGKILL");
62103
+ },
62051
62104
  // Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
62052
62105
  verifyListener: (port) => probeFrontDoorSync(port, import_node_fs13.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
62053
62106
  };
@@ -114076,6 +114129,7 @@ init_route();
114076
114129
  init_state();
114077
114130
 
114078
114131
  // src/frontdoor/supervisor.ts
114132
+ init_processRole();
114079
114133
  var import_node_path44 = __toESM(require("node:path"), 1);
114080
114134
  init_state();
114081
114135
  function watchedInstallEntry(resolvedOwnExecutablePath, siblingExists) {
@@ -114090,6 +114144,14 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
114090
114144
  var FRONTDOOR_POLL_MS = 1e3;
114091
114145
  var MS_PER_MINUTE3 = 6e4;
114092
114146
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
114147
+ const leaveRole = enterProcessRole("frontdoor-supervisor");
114148
+ try {
114149
+ return await serveFrontDoor(idleShutdownMinutes, ports, options);
114150
+ } finally {
114151
+ leaveRole();
114152
+ }
114153
+ }
114154
+ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
114093
114155
  const { fs: fs23, paths } = ports;
114094
114156
  const servingBinary = ports.statOwnExecutable();
114095
114157
  const previous = readFrontDoorState(fs23, paths.frontdoorStateFile);
package/dist/index.cjs CHANGED
@@ -2752,13 +2752,42 @@ var init_state = __esm({
2752
2752
  }
2753
2753
  });
2754
2754
 
2755
+ // src/processRole.ts
2756
+ function enterProcessRole(role) {
2757
+ const previous = currentRole;
2758
+ currentRole = role;
2759
+ return () => {
2760
+ currentRole = previous;
2761
+ };
2762
+ }
2763
+ function refuseToBlockInRole(operation) {
2764
+ if (currentRole !== void 0) {
2765
+ throw new BlockingInEventLoopError(operation, currentRole);
2766
+ }
2767
+ }
2768
+ var currentRole, BlockingInEventLoopError;
2769
+ var init_processRole = __esm({
2770
+ "src/processRole.ts"() {
2771
+ "use strict";
2772
+ init_cliError();
2773
+ BlockingInEventLoopError = class extends CliError {
2774
+ constructor(operation, role) {
2775
+ super(
2776
+ `${operation} blocks the calling thread, which in the ${role} is the event loop that answers every session; it must not run there (a launch planned inside the door reaches it through its own addresses, never through the launcher's synchronous coordination)`
2777
+ );
2778
+ this.name = "BlockingInEventLoopError";
2779
+ }
2780
+ };
2781
+ }
2782
+ });
2783
+
2755
2784
  // package.json
2756
2785
  var package_default;
2757
2786
  var init_package = __esm({
2758
2787
  "package.json"() {
2759
2788
  package_default = {
2760
2789
  name: "agent-shim",
2761
- version: "11.5.1",
2790
+ version: "11.6.0",
2762
2791
  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.",
2763
2792
  license: "MIT",
2764
2793
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -3932,6 +3961,7 @@ function isErrorWithCode(error, code) {
3932
3961
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
3933
3962
  }
3934
3963
  function realSleepSync(ms) {
3964
+ refuseToBlockInRole("a synchronous sleep");
3935
3965
  Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
3936
3966
  }
3937
3967
  function realIsProcessAlive(pid) {
@@ -4165,6 +4195,7 @@ var import_node_child_process2, import_node_crypto8, import_node_fs2, import_nod
4165
4195
  var init_realPorts = __esm({
4166
4196
  "src/realPorts.ts"() {
4167
4197
  "use strict";
4198
+ init_processRole();
4168
4199
  import_node_child_process2 = require("node:child_process");
4169
4200
  import_node_crypto8 = require("node:crypto");
4170
4201
  import_node_fs2 = __toESM(require("node:fs"), 1);
@@ -6772,7 +6803,13 @@ function ensureFrontDoor(params) {
6772
6803
  };
6773
6804
  const stopAndAwaitExit = (supervisorPid, failure) => {
6774
6805
  ports.stopSupervisor(supervisorPid);
6806
+ const graceEnds = ports.now() + FRONTDOOR_EXIT_GRACE_MS;
6807
+ let killed = false;
6775
6808
  while (ports.isRunning(supervisorPid)) {
6809
+ if (!killed && ports.now() >= graceEnds) {
6810
+ ports.killSupervisor(supervisorPid);
6811
+ killed = true;
6812
+ }
6776
6813
  if (ports.now() >= deadline) {
6777
6814
  throw new FrontDoorStartError(`${failure}. Daemon log: ${paths.frontdoorLogPath}`);
6778
6815
  }
@@ -6784,6 +6821,11 @@ function ensureFrontDoor(params) {
6784
6821
  const supervisorPid = state?.supervisorPid;
6785
6822
  if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
6786
6823
  if (state?.port !== void 0 && state.connectPort !== void 0) {
6824
+ if (supervisorPid === params.launcherPid && params.replace !== true && ports.isFrontDoorSupervisor(supervisorPid)) {
6825
+ const token = (0, import_node_crypto9.randomUUID)();
6826
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
6827
+ return { port: state.port, connectPort: state.connectPort, token };
6828
+ }
6787
6829
  const verdict = verifyWithRetry(state.port);
6788
6830
  if (verdict.ok && !replaced && !spawned && (params.replace === true || (state.protocol ?? 0) < FRONT_DOOR_PROTOCOL)) {
6789
6831
  stopAndAwaitExit(
@@ -6804,6 +6846,11 @@ function ensureFrontDoor(params) {
6804
6846
  }
6805
6847
  if (ports.isFrontDoorSupervisor(supervisorPid)) {
6806
6848
  const stranded = liveSessionsOn(supervisorPid);
6849
+ if (params.replace === true && !replaced) {
6850
+ stopAndAwaitExit(supervisorPid, `the front door (pid ${String(supervisorPid)}) stopped answering and did not exit when asked to`);
6851
+ replaced = true;
6852
+ continue;
6853
+ }
6807
6854
  if (stranded > 0) {
6808
6855
  busyDoor = { pid: supervisorPid, sessions: stranded };
6809
6856
  } else {
@@ -6842,7 +6889,7 @@ function ensureFrontDoor(params) {
6842
6889
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6843
6890
  }
6844
6891
  }
6845
- var import_node_crypto9, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FrontDoorStartError;
6892
+ var import_node_crypto9, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FRONTDOOR_EXIT_GRACE_MS, FrontDoorStartError;
6846
6893
  var init_ensure2 = __esm({
6847
6894
  "src/frontdoor/ensure.ts"() {
6848
6895
  "use strict";
@@ -6853,6 +6900,7 @@ var init_ensure2 = __esm({
6853
6900
  FRONTDOOR_START_TIMEOUT_MS = 3e4;
6854
6901
  FRONTDOOR_LAUNCHER_POLL_MS = 100;
6855
6902
  FRONTDOOR_PROBE_ATTEMPTS = 3;
6903
+ FRONTDOOR_EXIT_GRACE_MS = 5e3;
6856
6904
  FrontDoorStartError = class extends CliError {
6857
6905
  constructor(message) {
6858
6906
  super(message);
@@ -8022,6 +8070,7 @@ var init_ownCli = __esm({
8022
8070
 
8023
8071
  // src/frontdoor/probe.ts
8024
8072
  function probeFrontDoorSync(port, caPem) {
8073
+ refuseToBlockInRole("a synchronous probe of the front door");
8025
8074
  const shared = new SharedArrayBuffer(HEADER_SLOTS * INT32_BYTES + REASON_BYTES);
8026
8075
  const header = new Int32Array(shared, 0, HEADER_SLOTS);
8027
8076
  const worker = new import_node_worker_threads.Worker(PROBE_SOURCE, {
@@ -8048,6 +8097,7 @@ var import_node_worker_threads, PROBE_TIMEOUT_MS, PROBE_WAIT_MARGIN_MS, REASON_B
8048
8097
  var init_probe = __esm({
8049
8098
  "src/frontdoor/probe.ts"() {
8050
8099
  "use strict";
8100
+ init_processRole();
8051
8101
  import_node_worker_threads = require("node:worker_threads");
8052
8102
  PROBE_TIMEOUT_MS = 2e3;
8053
8103
  PROBE_WAIT_MARGIN_MS = 1e3;
@@ -8140,6 +8190,9 @@ function realEnsurePorts(paths, spawnDaemon) {
8140
8190
  stopSupervisor: (pid) => {
8141
8191
  process.kill(pid, "SIGTERM");
8142
8192
  },
8193
+ killSupervisor: (pid) => {
8194
+ process.kill(pid, "SIGKILL");
8195
+ },
8143
8196
  // Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
8144
8197
  verifyListener: (port) => probeFrontDoorSync(port, import_node_fs11.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
8145
8198
  };
@@ -9361,6 +9414,7 @@ init_route();
9361
9414
  init_state();
9362
9415
 
9363
9416
  // src/frontdoor/supervisor.ts
9417
+ init_processRole();
9364
9418
  var import_node_path9 = __toESM(require("node:path"), 1);
9365
9419
  init_state();
9366
9420
  function watchedInstallEntry(resolvedOwnExecutablePath, siblingExists) {
@@ -9375,6 +9429,14 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
9375
9429
  var FRONTDOOR_POLL_MS = 1e3;
9376
9430
  var MS_PER_MINUTE = 6e4;
9377
9431
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
9432
+ const leaveRole = enterProcessRole("frontdoor-supervisor");
9433
+ try {
9434
+ return await serveFrontDoor(idleShutdownMinutes, ports, options);
9435
+ } finally {
9436
+ leaveRole();
9437
+ }
9438
+ }
9439
+ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9378
9440
  const { fs: fs12, paths } = ports;
9379
9441
  const servingBinary = ports.statOwnExecutable();
9380
9442
  const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
package/dist/index.mjs CHANGED
@@ -2728,13 +2728,42 @@ var init_state = __esm({
2728
2728
  }
2729
2729
  });
2730
2730
 
2731
+ // src/processRole.ts
2732
+ function enterProcessRole(role) {
2733
+ const previous = currentRole;
2734
+ currentRole = role;
2735
+ return () => {
2736
+ currentRole = previous;
2737
+ };
2738
+ }
2739
+ function refuseToBlockInRole(operation) {
2740
+ if (currentRole !== void 0) {
2741
+ throw new BlockingInEventLoopError(operation, currentRole);
2742
+ }
2743
+ }
2744
+ var currentRole, BlockingInEventLoopError;
2745
+ var init_processRole = __esm({
2746
+ "src/processRole.ts"() {
2747
+ "use strict";
2748
+ init_cliError();
2749
+ BlockingInEventLoopError = class extends CliError {
2750
+ constructor(operation, role) {
2751
+ super(
2752
+ `${operation} blocks the calling thread, which in the ${role} is the event loop that answers every session; it must not run there (a launch planned inside the door reaches it through its own addresses, never through the launcher's synchronous coordination)`
2753
+ );
2754
+ this.name = "BlockingInEventLoopError";
2755
+ }
2756
+ };
2757
+ }
2758
+ });
2759
+
2731
2760
  // package.json
2732
2761
  var package_default;
2733
2762
  var init_package = __esm({
2734
2763
  "package.json"() {
2735
2764
  package_default = {
2736
2765
  name: "agent-shim",
2737
- version: "11.5.1",
2766
+ version: "11.6.0",
2738
2767
  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.",
2739
2768
  license: "MIT",
2740
2769
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -3913,6 +3942,7 @@ function isErrorWithCode(error, code) {
3913
3942
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
3914
3943
  }
3915
3944
  function realSleepSync(ms) {
3945
+ refuseToBlockInRole("a synchronous sleep");
3916
3946
  Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
3917
3947
  }
3918
3948
  function realIsProcessAlive(pid) {
@@ -4146,6 +4176,7 @@ var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, real
4146
4176
  var init_realPorts = __esm({
4147
4177
  "src/realPorts.ts"() {
4148
4178
  "use strict";
4179
+ init_processRole();
4149
4180
  init_load();
4150
4181
  init_versionDiscovery();
4151
4182
  init_supervisorProcesses();
@@ -6746,7 +6777,13 @@ function ensureFrontDoor(params) {
6746
6777
  };
6747
6778
  const stopAndAwaitExit = (supervisorPid, failure) => {
6748
6779
  ports.stopSupervisor(supervisorPid);
6780
+ const graceEnds = ports.now() + FRONTDOOR_EXIT_GRACE_MS;
6781
+ let killed = false;
6749
6782
  while (ports.isRunning(supervisorPid)) {
6783
+ if (!killed && ports.now() >= graceEnds) {
6784
+ ports.killSupervisor(supervisorPid);
6785
+ killed = true;
6786
+ }
6750
6787
  if (ports.now() >= deadline) {
6751
6788
  throw new FrontDoorStartError(`${failure}. Daemon log: ${paths.frontdoorLogPath}`);
6752
6789
  }
@@ -6758,6 +6795,11 @@ function ensureFrontDoor(params) {
6758
6795
  const supervisorPid = state?.supervisorPid;
6759
6796
  if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
6760
6797
  if (state?.port !== void 0 && state.connectPort !== void 0) {
6798
+ if (supervisorPid === params.launcherPid && params.replace !== true && ports.isFrontDoorSupervisor(supervisorPid)) {
6799
+ const token = randomUUID3();
6800
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
6801
+ return { port: state.port, connectPort: state.connectPort, token };
6802
+ }
6761
6803
  const verdict = verifyWithRetry(state.port);
6762
6804
  if (verdict.ok && !replaced && !spawned && (params.replace === true || (state.protocol ?? 0) < FRONT_DOOR_PROTOCOL)) {
6763
6805
  stopAndAwaitExit(
@@ -6778,6 +6820,11 @@ function ensureFrontDoor(params) {
6778
6820
  }
6779
6821
  if (ports.isFrontDoorSupervisor(supervisorPid)) {
6780
6822
  const stranded = liveSessionsOn(supervisorPid);
6823
+ if (params.replace === true && !replaced) {
6824
+ stopAndAwaitExit(supervisorPid, `the front door (pid ${String(supervisorPid)}) stopped answering and did not exit when asked to`);
6825
+ replaced = true;
6826
+ continue;
6827
+ }
6781
6828
  if (stranded > 0) {
6782
6829
  busyDoor = { pid: supervisorPid, sessions: stranded };
6783
6830
  } else {
@@ -6816,7 +6863,7 @@ function ensureFrontDoor(params) {
6816
6863
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6817
6864
  }
6818
6865
  }
6819
- var FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FrontDoorStartError;
6866
+ var FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FRONTDOOR_EXIT_GRACE_MS, FrontDoorStartError;
6820
6867
  var init_ensure2 = __esm({
6821
6868
  "src/frontdoor/ensure.ts"() {
6822
6869
  "use strict";
@@ -6826,6 +6873,7 @@ var init_ensure2 = __esm({
6826
6873
  FRONTDOOR_START_TIMEOUT_MS = 3e4;
6827
6874
  FRONTDOOR_LAUNCHER_POLL_MS = 100;
6828
6875
  FRONTDOOR_PROBE_ATTEMPTS = 3;
6876
+ FRONTDOOR_EXIT_GRACE_MS = 5e3;
6829
6877
  FrontDoorStartError = class extends CliError {
6830
6878
  constructor(message) {
6831
6879
  super(message);
@@ -7994,6 +8042,7 @@ var init_ownCli = __esm({
7994
8042
  // src/frontdoor/probe.ts
7995
8043
  import { Worker } from "node:worker_threads";
7996
8044
  function probeFrontDoorSync(port, caPem) {
8045
+ refuseToBlockInRole("a synchronous probe of the front door");
7997
8046
  const shared = new SharedArrayBuffer(HEADER_SLOTS * INT32_BYTES + REASON_BYTES);
7998
8047
  const header = new Int32Array(shared, 0, HEADER_SLOTS);
7999
8048
  const worker = new Worker(PROBE_SOURCE, {
@@ -8020,6 +8069,7 @@ var PROBE_TIMEOUT_MS, PROBE_WAIT_MARGIN_MS, REASON_BYTES, HEADER_SLOTS, INT32_BY
8020
8069
  var init_probe = __esm({
8021
8070
  "src/frontdoor/probe.ts"() {
8022
8071
  "use strict";
8072
+ init_processRole();
8023
8073
  PROBE_TIMEOUT_MS = 2e3;
8024
8074
  PROBE_WAIT_MARGIN_MS = 1e3;
8025
8075
  REASON_BYTES = 1024;
@@ -8112,6 +8162,9 @@ function realEnsurePorts(paths, spawnDaemon) {
8112
8162
  stopSupervisor: (pid) => {
8113
8163
  process.kill(pid, "SIGTERM");
8114
8164
  },
8165
+ killSupervisor: (pid) => {
8166
+ process.kill(pid, "SIGKILL");
8167
+ },
8115
8168
  // Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
8116
8169
  verifyListener: (port) => probeFrontDoorSync(port, fs11.readFileSync(paths.frontdoorCaCertFile, "utf8"))
8117
8170
  };
@@ -8948,6 +9001,7 @@ init_route();
8948
9001
  init_state();
8949
9002
 
8950
9003
  // src/frontdoor/supervisor.ts
9004
+ init_processRole();
8951
9005
  init_state();
8952
9006
  import path9 from "node:path";
8953
9007
  function watchedInstallEntry(resolvedOwnExecutablePath, siblingExists) {
@@ -8962,6 +9016,14 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
8962
9016
  var FRONTDOOR_POLL_MS = 1e3;
8963
9017
  var MS_PER_MINUTE = 6e4;
8964
9018
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
9019
+ const leaveRole = enterProcessRole("frontdoor-supervisor");
9020
+ try {
9021
+ return await serveFrontDoor(idleShutdownMinutes, ports, options);
9022
+ } finally {
9023
+ leaveRole();
9024
+ }
9025
+ }
9026
+ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
8965
9027
  const { fs: fs12, paths } = ports;
8966
9028
  const servingBinary = ports.statOwnExecutable();
8967
9029
  const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
@@ -1332,8 +1332,8 @@ declare const HeadroomGlobalConfigSchema: z.ZodObject<{
1332
1332
  targetRatio: z.ZodOptional<z.ZodNumber>;
1333
1333
  ccr: z.ZodOptional<z.ZodEnum<{
1334
1334
  default: "default";
1335
- lossless: "lossless";
1336
1335
  none: "none";
1336
+ lossless: "lossless";
1337
1337
  }>>;
1338
1338
  rolloutChannel: z.ZodOptional<z.ZodEnum<{
1339
1339
  beta: "beta";
@@ -1460,8 +1460,8 @@ declare const GlobalConfigSchema: z.ZodObject<{
1460
1460
  targetRatio: z.ZodOptional<z.ZodNumber>;
1461
1461
  ccr: z.ZodOptional<z.ZodEnum<{
1462
1462
  default: "default";
1463
- lossless: "lossless";
1464
1463
  none: "none";
1464
+ lossless: "lossless";
1465
1465
  }>>;
1466
1466
  rolloutChannel: z.ZodOptional<z.ZodEnum<{
1467
1467
  beta: "beta";
@@ -4163,12 +4163,12 @@ declare const CheckReportJsonSchema: z.ZodObject<{
4163
4163
  identity: z.ZodObject<{
4164
4164
  name: z.ZodNullable<z.ZodString>;
4165
4165
  source: z.ZodEnum<{
4166
- env: "env";
4167
- none: "none";
4168
4166
  "config-dir-escape-hatch": "config-dir-escape-hatch";
4169
4167
  argv: "argv";
4168
+ env: "env";
4170
4169
  "directory-pin": "directory-pin";
4171
4170
  "active-identity-file": "active-identity-file";
4171
+ none: "none";
4172
4172
  }>;
4173
4173
  }, z.core.$strict>;
4174
4174
  pool: z.ZodOptional<z.ZodObject<{
@@ -4246,11 +4246,11 @@ declare const CheckReportJsonSchema: z.ZodObject<{
4246
4246
  "category-default": "category-default";
4247
4247
  }>;
4248
4248
  category: z.ZodNullable<z.ZodEnum<{
4249
+ secret: "secret";
4249
4250
  runtime: "runtime";
4250
4251
  history: "history";
4251
4252
  knowledge: "knowledge";
4252
4253
  settings: "settings";
4253
- secret: "secret";
4254
4254
  }>>;
4255
4255
  rule: z.ZodOptional<z.ZodObject<{
4256
4256
  key: z.ZodString;
@@ -5656,6 +5656,7 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5656
5656
  kind: zod.ZodLiteral<"profile">;
5657
5657
  name: zod.ZodString;
5658
5658
  value: zod.ZodObject<{
5659
+ description: zod.ZodOptional<zod.ZodString>;
5659
5660
  entries: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnion<readonly [zod.ZodBoolean, zod.ZodObject<{
5660
5661
  value: zod.ZodBoolean;
5661
5662
  when: zod.ZodUnion<readonly [zod.ZodObject<{
@@ -5731,7 +5732,6 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5731
5732
  key: zod.ZodType<trilean.JsonValue, unknown, zod_v4_core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
5732
5733
  }, zod_v4_core.$strip>], "kind">]>;
5733
5734
  }, zod_v4_core.$strict>]>>>;
5734
- description: zod.ZodOptional<zod.ZodString>;
5735
5735
  extends: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
5736
5736
  categories: zod.ZodOptional<zod.ZodPipe<zod.ZodObject<{
5737
5737
  all: zod.ZodOptional<zod.ZodBoolean>;
@@ -5775,6 +5775,7 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5775
5775
  kind: zod.ZodLiteral<"profile">;
5776
5776
  name: zod.ZodString;
5777
5777
  value: zod.ZodObject<{
5778
+ description: zod.ZodOptional<zod.ZodString>;
5778
5779
  entries: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnion<readonly [zod.ZodBoolean, zod.ZodObject<{
5779
5780
  value: zod.ZodBoolean;
5780
5781
  when: zod.ZodUnion<readonly [zod.ZodObject<{
@@ -5850,7 +5851,6 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5850
5851
  key: zod.ZodType<trilean.JsonValue, unknown, zod_v4_core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
5851
5852
  }, zod_v4_core.$strip>], "kind">]>;
5852
5853
  }, zod_v4_core.$strict>]>>>;
5853
- description: zod.ZodOptional<zod.ZodString>;
5854
5854
  extends: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
5855
5855
  categories: zod.ZodOptional<zod.ZodPipe<zod.ZodObject<{
5856
5856
  all: zod.ZodOptional<zod.ZodBoolean>;
@@ -6942,9 +6942,9 @@ declare function createLifecycleApiRouter(deps: LifecycleApiDeps): {
6942
6942
  current: zod.ZodString;
6943
6943
  latest: zod.ZodString;
6944
6944
  action: zod.ZodEnum<{
6945
- updated: "updated";
6946
6945
  current: "current";
6947
6946
  available: "available";
6947
+ updated: "updated";
6948
6948
  }>;
6949
6949
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
6950
6950
  };
@@ -7191,12 +7191,12 @@ declare function createLaunchApiRouter(deps: LaunchApiDeps): {
7191
7191
  decision: zod.ZodObject<{
7192
7192
  identity: zod.ZodOptional<zod.ZodString>;
7193
7193
  identitySource: zod.ZodEnum<{
7194
- env: "env";
7195
- none: "none";
7196
7194
  "config-dir-escape-hatch": "config-dir-escape-hatch";
7197
7195
  argv: "argv";
7196
+ env: "env";
7198
7197
  "directory-pin": "directory-pin";
7199
7198
  "active-identity-file": "active-identity-file";
7199
+ none: "none";
7200
7200
  }>;
7201
7201
  pool: zod.ZodOptional<zod.ZodObject<{
7202
7202
  name: zod.ZodString;
@@ -7791,12 +7791,12 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
7791
7791
  identity: zod.ZodObject<{
7792
7792
  name: zod.ZodNullable<zod.ZodString>;
7793
7793
  source: zod.ZodEnum<{
7794
- env: "env";
7795
- none: "none";
7796
7794
  "config-dir-escape-hatch": "config-dir-escape-hatch";
7797
7795
  argv: "argv";
7796
+ env: "env";
7798
7797
  "directory-pin": "directory-pin";
7799
7798
  "active-identity-file": "active-identity-file";
7799
+ none: "none";
7800
7800
  }>;
7801
7801
  }, zod_v4_core.$strict>;
7802
7802
  pool: zod.ZodOptional<zod.ZodObject<{
@@ -7874,11 +7874,11 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
7874
7874
  "category-default": "category-default";
7875
7875
  }>;
7876
7876
  category: zod.ZodNullable<zod.ZodEnum<{
7877
+ secret: "secret";
7877
7878
  runtime: "runtime";
7878
7879
  history: "history";
7879
7880
  knowledge: "knowledge";
7880
7881
  settings: "settings";
7881
- secret: "secret";
7882
7882
  }>>;
7883
7883
  rule: zod.ZodOptional<zod.ZodObject<{
7884
7884
  key: zod.ZodString;
@@ -8097,11 +8097,10 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
8097
8097
  "global-config": "global-config";
8098
8098
  "config-profile": "config-profile";
8099
8099
  identity: "identity";
8100
- keychain: "keychain";
8101
8100
  provider: "provider";
8102
- headroom: "headroom";
8103
8101
  frontdoor: "frontdoor";
8104
8102
  pool: "pool";
8103
+ keychain: "keychain";
8105
8104
  "ambient-credential": "ambient-credential";
8106
8105
  "binary-discovery": "binary-discovery";
8107
8106
  "claude-shim": "claude-shim";
@@ -8111,6 +8110,7 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
8111
8110
  "directory-rules": "directory-rules";
8112
8111
  "categories-local": "categories-local";
8113
8112
  "active-identity": "active-identity";
8113
+ headroom: "headroom";
8114
8114
  }>;
8115
8115
  subject: zod.ZodOptional<zod.ZodString>;
8116
8116
  severity: zod.ZodEnum<{
@@ -8303,12 +8303,12 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8303
8303
  decision: zod.ZodObject<{
8304
8304
  identity: zod.ZodOptional<zod.ZodString>;
8305
8305
  identitySource: zod.ZodEnum<{
8306
- env: "env";
8307
- none: "none";
8308
8306
  "config-dir-escape-hatch": "config-dir-escape-hatch";
8309
8307
  argv: "argv";
8308
+ env: "env";
8310
8309
  "directory-pin": "directory-pin";
8311
8310
  "active-identity-file": "active-identity-file";
8311
+ none: "none";
8312
8312
  }>;
8313
8313
  pool: zod.ZodOptional<zod.ZodObject<{
8314
8314
  name: zod.ZodString;
@@ -8606,6 +8606,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8606
8606
  kind: zod.ZodLiteral<"profile">;
8607
8607
  name: zod.ZodString;
8608
8608
  value: zod.ZodObject<{
8609
+ description: zod.ZodOptional<zod.ZodString>;
8609
8610
  entries: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnion<readonly [zod.ZodBoolean, zod.ZodObject<{
8610
8611
  value: zod.ZodBoolean;
8611
8612
  when: zod.ZodUnion<readonly [zod.ZodObject<{
@@ -8681,7 +8682,6 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8681
8682
  key: zod.ZodType<trilean.JsonValue, unknown, zod_v4_core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
8682
8683
  }, zod_v4_core.$strip>], "kind">]>;
8683
8684
  }, zod_v4_core.$strict>]>>>;
8684
- description: zod.ZodOptional<zod.ZodString>;
8685
8685
  extends: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
8686
8686
  categories: zod.ZodOptional<zod.ZodPipe<zod.ZodObject<{
8687
8687
  all: zod.ZodOptional<zod.ZodBoolean>;
@@ -8725,6 +8725,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8725
8725
  kind: zod.ZodLiteral<"profile">;
8726
8726
  name: zod.ZodString;
8727
8727
  value: zod.ZodObject<{
8728
+ description: zod.ZodOptional<zod.ZodString>;
8728
8729
  entries: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnion<readonly [zod.ZodBoolean, zod.ZodObject<{
8729
8730
  value: zod.ZodBoolean;
8730
8731
  when: zod.ZodUnion<readonly [zod.ZodObject<{
@@ -8800,7 +8801,6 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8800
8801
  key: zod.ZodType<trilean.JsonValue, unknown, zod_v4_core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
8801
8802
  }, zod_v4_core.$strip>], "kind">]>;
8802
8803
  }, zod_v4_core.$strict>]>>>;
8803
- description: zod.ZodOptional<zod.ZodString>;
8804
8804
  extends: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
8805
8805
  categories: zod.ZodOptional<zod.ZodPipe<zod.ZodObject<{
8806
8806
  all: zod.ZodOptional<zod.ZodBoolean>;
@@ -9684,9 +9684,9 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9684
9684
  current: zod.ZodString;
9685
9685
  latest: zod.ZodString;
9686
9686
  action: zod.ZodEnum<{
9687
- updated: "updated";
9688
9687
  current: "current";
9689
9688
  available: "available";
9689
+ updated: "updated";
9690
9690
  }>;
9691
9691
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
9692
9692
  };
@@ -9885,12 +9885,12 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9885
9885
  identity: zod.ZodObject<{
9886
9886
  name: zod.ZodNullable<zod.ZodString>;
9887
9887
  source: zod.ZodEnum<{
9888
- env: "env";
9889
- none: "none";
9890
9888
  "config-dir-escape-hatch": "config-dir-escape-hatch";
9891
9889
  argv: "argv";
9890
+ env: "env";
9892
9891
  "directory-pin": "directory-pin";
9893
9892
  "active-identity-file": "active-identity-file";
9893
+ none: "none";
9894
9894
  }>;
9895
9895
  }, zod_v4_core.$strict>;
9896
9896
  pool: zod.ZodOptional<zod.ZodObject<{
@@ -9968,11 +9968,11 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9968
9968
  "category-default": "category-default";
9969
9969
  }>;
9970
9970
  category: zod.ZodNullable<zod.ZodEnum<{
9971
+ secret: "secret";
9971
9972
  runtime: "runtime";
9972
9973
  history: "history";
9973
9974
  knowledge: "knowledge";
9974
9975
  settings: "settings";
9975
- secret: "secret";
9976
9976
  }>>;
9977
9977
  rule: zod.ZodOptional<zod.ZodObject<{
9978
9978
  key: zod.ZodString;
@@ -10191,11 +10191,10 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
10191
10191
  "global-config": "global-config";
10192
10192
  "config-profile": "config-profile";
10193
10193
  identity: "identity";
10194
- keychain: "keychain";
10195
10194
  provider: "provider";
10196
- headroom: "headroom";
10197
10195
  frontdoor: "frontdoor";
10198
10196
  pool: "pool";
10197
+ keychain: "keychain";
10199
10198
  "ambient-credential": "ambient-credential";
10200
10199
  "binary-discovery": "binary-discovery";
10201
10200
  "claude-shim": "claude-shim";
@@ -10205,6 +10204,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
10205
10204
  "directory-rules": "directory-rules";
10206
10205
  "categories-local": "categories-local";
10207
10206
  "active-identity": "active-identity";
10207
+ headroom: "headroom";
10208
10208
  }>;
10209
10209
  subject: zod.ZodOptional<zod.ZodString>;
10210
10210
  severity: zod.ZodEnum<{
@@ -10714,6 +10714,7 @@ declare const ConfigProfileAddOutputSchema: z.ZodObject<{
10714
10714
  kind: z.ZodLiteral<"profile">;
10715
10715
  name: z.ZodString;
10716
10716
  value: z.ZodObject<{
10717
+ description: z.ZodOptional<z.ZodString>;
10717
10718
  entries: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
10718
10719
  value: z.ZodBoolean;
10719
10720
  when: z.ZodUnion<readonly [z.ZodObject<{
@@ -10789,7 +10790,6 @@ declare const ConfigProfileAddOutputSchema: z.ZodObject<{
10789
10790
  key: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
10790
10791
  }, z.core.$strip>], "kind">]>;
10791
10792
  }, z.core.$strict>]>>>;
10792
- description: z.ZodOptional<z.ZodString>;
10793
10793
  extends: z.ZodOptional<z.ZodArray<z.ZodString>>;
10794
10794
  categories: z.ZodOptional<z.ZodPipe<z.ZodObject<{
10795
10795
  all: z.ZodOptional<z.ZodBoolean>;
@@ -10835,6 +10835,7 @@ declare const ConfigProfileSetOutputSchema: z.ZodObject<{
10835
10835
  kind: z.ZodLiteral<"profile">;
10836
10836
  name: z.ZodString;
10837
10837
  value: z.ZodObject<{
10838
+ description: z.ZodOptional<z.ZodString>;
10838
10839
  entries: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
10839
10840
  value: z.ZodBoolean;
10840
10841
  when: z.ZodUnion<readonly [z.ZodObject<{
@@ -10910,7 +10911,6 @@ declare const ConfigProfileSetOutputSchema: z.ZodObject<{
10910
10911
  key: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
10911
10912
  }, z.core.$strip>], "kind">]>;
10912
10913
  }, z.core.$strict>]>>>;
10913
- description: z.ZodOptional<z.ZodString>;
10914
10914
  extends: z.ZodOptional<z.ZodArray<z.ZodString>>;
10915
10915
  categories: z.ZodOptional<z.ZodPipe<z.ZodObject<{
10916
10916
  all: z.ZodOptional<z.ZodBoolean>;
@@ -12037,11 +12037,10 @@ declare const DoctorFindingSchema: z.ZodObject<{
12037
12037
  "global-config": "global-config";
12038
12038
  "config-profile": "config-profile";
12039
12039
  identity: "identity";
12040
- keychain: "keychain";
12041
12040
  provider: "provider";
12042
- headroom: "headroom";
12043
12041
  frontdoor: "frontdoor";
12044
12042
  pool: "pool";
12043
+ keychain: "keychain";
12045
12044
  "ambient-credential": "ambient-credential";
12046
12045
  "binary-discovery": "binary-discovery";
12047
12046
  "claude-shim": "claude-shim";
@@ -12051,6 +12050,7 @@ declare const DoctorFindingSchema: z.ZodObject<{
12051
12050
  "directory-rules": "directory-rules";
12052
12051
  "categories-local": "categories-local";
12053
12052
  "active-identity": "active-identity";
12053
+ headroom: "headroom";
12054
12054
  }>;
12055
12055
  subject: z.ZodOptional<z.ZodString>;
12056
12056
  severity: z.ZodEnum<{
@@ -12068,11 +12068,10 @@ declare const DoctorRunOutputSchema: z.ZodObject<{
12068
12068
  "global-config": "global-config";
12069
12069
  "config-profile": "config-profile";
12070
12070
  identity: "identity";
12071
- keychain: "keychain";
12072
12071
  provider: "provider";
12073
- headroom: "headroom";
12074
12072
  frontdoor: "frontdoor";
12075
12073
  pool: "pool";
12074
+ keychain: "keychain";
12076
12075
  "ambient-credential": "ambient-credential";
12077
12076
  "binary-discovery": "binary-discovery";
12078
12077
  "claude-shim": "claude-shim";
@@ -12082,6 +12081,7 @@ declare const DoctorRunOutputSchema: z.ZodObject<{
12082
12081
  "directory-rules": "directory-rules";
12083
12082
  "categories-local": "categories-local";
12084
12083
  "active-identity": "active-identity";
12084
+ headroom: "headroom";
12085
12085
  }>;
12086
12086
  subject: z.ZodOptional<z.ZodString>;
12087
12087
  severity: z.ZodEnum<{
@@ -12102,9 +12102,9 @@ declare const UpdateCheckOutputSchema: z.ZodObject<{
12102
12102
  current: z.ZodString;
12103
12103
  latest: z.ZodString;
12104
12104
  action: z.ZodEnum<{
12105
- updated: "updated";
12106
12105
  current: "current";
12107
12106
  available: "available";
12107
+ updated: "updated";
12108
12108
  }>;
12109
12109
  }, z.core.$strict>;
12110
12110
  /** The Sign in with ChatGPT login's state as `codex status` reports it: no sign-in yet, signed in (with who, whether the plan scope was granted, and when the access token lapses), or a file that cannot be read. */
@@ -12154,12 +12154,12 @@ declare const LaunchResolveOutputSchema: z.ZodObject<{
12154
12154
  decision: z.ZodObject<{
12155
12155
  identity: z.ZodOptional<z.ZodString>;
12156
12156
  identitySource: z.ZodEnum<{
12157
- env: "env";
12158
- none: "none";
12159
12157
  "config-dir-escape-hatch": "config-dir-escape-hatch";
12160
12158
  argv: "argv";
12159
+ env: "env";
12161
12160
  "directory-pin": "directory-pin";
12162
12161
  "active-identity-file": "active-identity-file";
12162
+ none: "none";
12163
12163
  }>;
12164
12164
  pool: z.ZodOptional<z.ZodObject<{
12165
12165
  name: z.ZodString;
@@ -12533,6 +12533,8 @@ interface EnsureFrontDoorPorts {
12533
12533
  readonly verifyListener: (port: number) => ListenerVerdict;
12534
12534
  /** Asks a running front-door supervisor to exit, without waiting for it to: the caller polls `isRunning`. Only ever called for a pid whose recorded listener has just authenticated as agent-shim's own, or whose process is agent-shim's front-door supervisor (`isFrontDoorSupervisor`). */
12535
12535
  readonly stopSupervisor: (pid: number) => void;
12536
+ /** Ends a supervisor that did not exit when asked to, without giving it the chance to refuse: a door whose event loop is blocked never runs its signal handler. Called only for a pid `isFrontDoorSupervisor` has just confirmed, after `stopSupervisor` and a grace period. */
12537
+ readonly killSupervisor: (pid: number) => void;
12536
12538
  /** Whether `pid` is a live agent-shim front-door supervisor process, read from the process's own command line. This is what separates a wedged door of this tool, which a replacement must retire so the two never coexist, from an unrelated process that reuses the recorded pid, which must never be signalled. */
12537
12539
  readonly isFrontDoorSupervisor: (pid: number) => boolean;
12538
12540
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "11.5.1",
3
+ "version": "11.6.0",
4
4
  "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.",
5
5
  "license": "MIT",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",