@modootoday/pmcp 0.16.1 → 0.17.1

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.js CHANGED
@@ -1940,45 +1940,45 @@ var init_validation2 = __esm({
1940
1940
  // src/harness/groups/store.ts
1941
1941
  import { randomUUID as randomUUID5 } from "crypto";
1942
1942
  import {
1943
- closeSync as closeSync4,
1943
+ closeSync as closeSync5,
1944
1944
  constants as constants3,
1945
1945
  fstatSync as fstatSync2,
1946
1946
  fsyncSync as fsyncSync2,
1947
- openSync as openSync4,
1948
- readFileSync as readFileSync34,
1949
- realpathSync as realpathSync6,
1947
+ openSync as openSync5,
1948
+ readFileSync as readFileSync35,
1949
+ realpathSync as realpathSync7,
1950
1950
  renameSync as renameSync4,
1951
1951
  writeFileSync as writeFileSync9
1952
1952
  } from "fs";
1953
- import { dirname as dirname21, join as join29 } from "path";
1953
+ import { dirname as dirname21, join as join32 } from "path";
1954
1954
  function privateJson(path, value) {
1955
1955
  const temporary = `${path}.${randomUUID5()}.new`;
1956
- const descriptor = openSync4(temporary, "wx", 384);
1956
+ const descriptor = openSync5(temporary, "wx", 384);
1957
1957
  try {
1958
1958
  writeFileSync9(descriptor, `${JSON.stringify(value, null, 2)}
1959
1959
  `);
1960
1960
  fsyncSync2(descriptor);
1961
1961
  } finally {
1962
- closeSync4(descriptor);
1962
+ closeSync5(descriptor);
1963
1963
  }
1964
1964
  renameSync4(temporary, path);
1965
- const directory = openSync4(dirname21(path), "r");
1965
+ const directory = openSync5(dirname21(path), "r");
1966
1966
  try {
1967
1967
  fsyncSync2(directory);
1968
1968
  } finally {
1969
- closeSync4(directory);
1969
+ closeSync5(directory);
1970
1970
  }
1971
1971
  }
1972
1972
  function readPrivateJson2(path) {
1973
- const descriptor = openSync4(path, constants3.O_RDONLY | constants3.O_NOFOLLOW);
1973
+ const descriptor = openSync5(path, constants3.O_RDONLY | constants3.O_NOFOLLOW);
1974
1974
  try {
1975
1975
  const stat = fstatSync2(descriptor);
1976
1976
  if (!stat.isFile() || (stat.mode & 63) !== 0 || stat.size > 2097152)
1977
1977
  throw new Error("unsafe_state_file");
1978
1978
  if (stat.uid !== process.getuid?.()) throw new Error("foreign_state_file");
1979
- return JSON.parse(readFileSync34(descriptor, "utf8"));
1979
+ return JSON.parse(readFileSync35(descriptor, "utf8"));
1980
1980
  } finally {
1981
- closeSync4(descriptor);
1981
+ closeSync5(descriptor);
1982
1982
  }
1983
1983
  }
1984
1984
  var GroupStore;
@@ -1991,10 +1991,10 @@ var init_store2 = __esm({
1991
1991
  path;
1992
1992
  state;
1993
1993
  constructor(path) {
1994
- this.path = realpathSync6(path);
1994
+ this.path = realpathSync7(path);
1995
1995
  this.state = validateState(readPrivateJson2(path));
1996
1996
  const metadata2 = object8(
1997
- readPrivateJson2(join29(dirname21(this.path), "harness.json"))
1997
+ readPrivateJson2(join32(dirname21(this.path), "harness.json"))
1998
1998
  );
1999
1999
  if (this.state.group.schemaVersion !== 1 || this.state.group.owner !== metadata2.owner) {
2000
2000
  throw new Error("foreign_group");
@@ -2014,18 +2014,18 @@ var init_store2 = __esm({
2014
2014
  });
2015
2015
 
2016
2016
  // src/harness/adapters/process/serialized.ts
2017
- import { spawnSync as spawnSync4 } from "child_process";
2017
+ import { spawnSync as spawnSync5 } from "child_process";
2018
2018
  import { randomUUID as randomUUID6 } from "crypto";
2019
- import { existsSync as existsSync25, unlinkSync as unlinkSync2 } from "fs";
2020
- import { dirname as dirname22, join as join30 } from "path";
2019
+ import { existsSync as existsSync26, unlinkSync as unlinkSync2 } from "fs";
2020
+ import { dirname as dirname22, join as join33 } from "path";
2021
2021
  function serialized(operation) {
2022
2022
  const store = new GroupStore(text(operation.groupFile, "group_file"));
2023
2023
  const directory = dirname22(store.path);
2024
- const operationFile = join30(directory, `operation-${randomUUID6()}.json`);
2024
+ const operationFile = join33(directory, `operation-${randomUUID6()}.json`);
2025
2025
  privateJson(operationFile, operation);
2026
2026
  const worker = artifact("worker");
2027
2027
  try {
2028
- const result = spawnSync4(
2028
+ const result = spawnSync5(
2029
2029
  "flock",
2030
2030
  [
2031
2031
  "--exclusive",
@@ -2033,7 +2033,7 @@ function serialized(operation) {
2033
2033
  "--no-fork",
2034
2034
  "--conflict-exit-code",
2035
2035
  "73",
2036
- join30(directory, "group-control.lock"),
2036
+ join33(directory, "group-control.lock"),
2037
2037
  process.execPath,
2038
2038
  worker,
2039
2039
  operationFile
@@ -2049,7 +2049,7 @@ function serialized(operation) {
2049
2049
  if (!result.stdout.trim()) throw new Error("worker_receipt_missing");
2050
2050
  return JSON.parse(result.stdout);
2051
2051
  } finally {
2052
- if (existsSync25(operationFile)) unlinkSync2(operationFile);
2052
+ if (existsSync26(operationFile)) unlinkSync2(operationFile);
2053
2053
  }
2054
2054
  }
2055
2055
  var init_serialized = __esm({
@@ -2129,11 +2129,11 @@ var init_command = __esm({
2129
2129
  });
2130
2130
 
2131
2131
  // src/harness/adapters/process/identity.ts
2132
- import { readFileSync as readFileSync35 } from "fs";
2132
+ import { readFileSync as readFileSync36 } from "fs";
2133
2133
  function processIdentity(pid) {
2134
2134
  if (!Number.isSafeInteger(pid) || pid < 1)
2135
2135
  throw new Error("invalid_process_id");
2136
- const stat = readFileSync35(`/proc/${pid}/stat`, "utf8");
2136
+ const stat = readFileSync36(`/proc/${pid}/stat`, "utf8");
2137
2137
  const fields = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
2138
2138
  if (!/^\d+$/.test(fields[19] ?? ""))
2139
2139
  throw new Error("process_identity_unknown");
@@ -2368,14 +2368,14 @@ import {
2368
2368
  lstatSync as lstatSync6,
2369
2369
  mkdirSync as mkdirSync9,
2370
2370
  readdirSync as readdirSync10,
2371
- realpathSync as realpathSync7,
2371
+ realpathSync as realpathSync8,
2372
2372
  writeFileSync as writeFileSync10
2373
2373
  } from "fs";
2374
2374
  import { homedir as homedir7 } from "os";
2375
- import { join as join31 } from "path";
2375
+ import { join as join34 } from "path";
2376
2376
  function stateDirectory() {
2377
- return join31(
2378
- process.env.XDG_STATE_HOME ?? join31(homedir7(), ".local/state"),
2377
+ return join34(
2378
+ process.env.XDG_STATE_HOME ?? join34(homedir7(), ".local/state"),
2379
2379
  "pmcp/harness"
2380
2380
  );
2381
2381
  }
@@ -2405,12 +2405,12 @@ var init_records = __esm({
2405
2405
  const stat = lstatSync6(directory);
2406
2406
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
2407
2407
  throw new Error("unsafe_group_directory");
2408
- this.directory = realpathSync7(directory);
2409
- this.socket = join31(this.directory, "s");
2408
+ this.directory = realpathSync8(directory);
2409
+ this.socket = join34(this.directory, "s");
2410
2410
  if (Buffer.byteLength(this.socket) > 100)
2411
2411
  throw new Error("socket_path_too_long");
2412
- this.metadataPath = join31(this.directory, "harness.json");
2413
- this.configPath = join31(this.directory, "tmux.conf");
2412
+ this.metadataPath = join34(this.directory, "harness.json");
2413
+ this.configPath = join34(this.directory, "tmux.conf");
2414
2414
  this.owner = text(
2415
2415
  object8(readPrivateJson2(this.metadataPath)).owner,
2416
2416
  "owner"
@@ -2420,17 +2420,17 @@ var init_records = __esm({
2420
2420
  static create() {
2421
2421
  const root = stateDirectory();
2422
2422
  mkdirSync9(root, { recursive: true, mode: 448 });
2423
- const directory = join31(root, randomUUID7().slice(0, 16));
2424
- if (Buffer.byteLength(join31(directory, "s")) > 100)
2423
+ const directory = join34(root, randomUUID7().slice(0, 16));
2424
+ if (Buffer.byteLength(join34(directory, "s")) > 100)
2425
2425
  throw new Error("socket_path_too_long");
2426
2426
  mkdirSync9(directory, { mode: 448 });
2427
- mkdirSync9(join31(directory, "sessions"), { mode: 448 });
2428
- privateJson(join31(directory, "harness.json"), {
2427
+ mkdirSync9(join34(directory, "sessions"), { mode: 448 });
2428
+ privateJson(join34(directory, "harness.json"), {
2429
2429
  owner: randomUUID7(),
2430
2430
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
2431
2431
  });
2432
2432
  writeFileSync10(
2433
- join31(directory, "tmux.conf"),
2433
+ join34(directory, "tmux.conf"),
2434
2434
  [
2435
2435
  "set -g remain-on-exit on",
2436
2436
  "set -g history-limit 2000",
@@ -2446,7 +2446,7 @@ var init_records = __esm({
2446
2446
  }
2447
2447
  path(id2) {
2448
2448
  runtimeUnit(id2);
2449
- return join31(this.directory, "sessions", `${id2}.json`);
2449
+ return join34(this.directory, "sessions", `${id2}.json`);
2450
2450
  }
2451
2451
  read(id2) {
2452
2452
  const record = object8(readPrivateJson2(this.path(id2)));
@@ -2468,7 +2468,7 @@ var init_records = __esm({
2468
2468
  return record;
2469
2469
  }
2470
2470
  all() {
2471
- return readdirSync10(join31(this.directory, "sessions")).filter((name) => name.endsWith(".json")).map((name) => this.read(name.slice(0, -5)));
2471
+ return readdirSync10(join34(this.directory, "sessions")).filter((name) => name.endsWith(".json")).map((name) => this.read(name.slice(0, -5)));
2472
2472
  }
2473
2473
  save(record) {
2474
2474
  privateJson(this.path(record.id), record);
@@ -2550,8 +2550,8 @@ var init_launch_identity = __esm({
2550
2550
 
2551
2551
  // src/harness/launch/journal.ts
2552
2552
  import { createHash as createHash16 } from "crypto";
2553
- import { existsSync as existsSync26, readdirSync as readdirSync11 } from "fs";
2554
- import { join as join32 } from "path";
2553
+ import { existsSync as existsSync27, readdirSync as readdirSync11 } from "fs";
2554
+ import { join as join35 } from "path";
2555
2555
  function launchJournals(records2) {
2556
2556
  return readdirSync11(records2.directory).filter((name) => name.endsWith(".intent.json")).map((name) => new LaunchJournal(records2, name.slice(0, -12)));
2557
2557
  }
@@ -2559,7 +2559,7 @@ function pendingLaunches(records2) {
2559
2559
  return launchJournals(records2).filter((journal) => {
2560
2560
  const aborted = journal.abortRecord();
2561
2561
  if (aborted) return aborted.state !== "stopped";
2562
- if (!existsSync26(journal.path("committed"))) return true;
2562
+ if (!existsSync27(journal.path("committed"))) return true;
2563
2563
  journal.assertCommitted();
2564
2564
  return false;
2565
2565
  });
@@ -2586,7 +2586,7 @@ var init_journal = __esm({
2586
2586
  path(kind2) {
2587
2587
  if (!["intent", "proof", "grant", "committed", "aborted"].includes(kind2))
2588
2588
  throw new Error("invalid_launch_artifact");
2589
- return join32(this.records.directory, `${this.id}.${kind2}.json`);
2589
+ return join35(this.records.directory, `${this.id}.${kind2}.json`);
2590
2590
  }
2591
2591
  intent() {
2592
2592
  const value = object8(readPrivateJson2(this.path("intent")));
@@ -2615,13 +2615,13 @@ var init_journal = __esm({
2615
2615
  throw new Error("invalid_docker_bridge_digest");
2616
2616
  if (!bridge && creation.bridgeSha256 !== void 0)
2617
2617
  throw new Error("ungranted_docker_bridge_digest");
2618
- const policy = new GroupStore(join32(this.records.directory, "group.json")).state.group.dockerPolicy;
2618
+ const policy = new GroupStore(join35(this.records.directory, "group.json")).state.group.dockerPolicy;
2619
2619
  const profile = selectedProfile(
2620
2620
  policy,
2621
2621
  creation.privateProfile,
2622
2622
  text(value.runtime, "runtime")
2623
2623
  );
2624
- const expectedState = profile?.directory ?? join32(
2624
+ const expectedState = profile?.directory ?? join35(
2625
2625
  this.records.directory,
2626
2626
  "containers",
2627
2627
  text(value.nonce, "nonce"),
@@ -2667,7 +2667,7 @@ var init_journal = __esm({
2667
2667
  }
2668
2668
  assertRegistered() {
2669
2669
  const intent = this.intent();
2670
- const group = new GroupStore(join32(this.records.directory, "group.json")).state.group;
2670
+ const group = new GroupStore(join35(this.records.directory, "group.json")).state.group;
2671
2671
  if (group.id !== intent.groupId || group.generation !== intent.generation)
2672
2672
  throw new Error("launch_group_generation_mismatch");
2673
2673
  if (intent.dockerCreation && JSON.stringify(intent.dockerCreation.egress) !== JSON.stringify(group.dockerPolicy?.egress))
@@ -2683,12 +2683,12 @@ var init_journal = __esm({
2683
2683
  throw new Error("launch_record_mismatch");
2684
2684
  }
2685
2685
  authorize() {
2686
- if (existsSync26(this.path("aborted"))) throw new Error("launch_was_aborted");
2686
+ if (existsSync27(this.path("aborted"))) throw new Error("launch_was_aborted");
2687
2687
  this.assertRegistered();
2688
2688
  privateJson(this.path("grant"), this.grant());
2689
2689
  }
2690
2690
  assertGrant() {
2691
- if (existsSync26(this.path("aborted"))) throw new Error("launch_was_aborted");
2691
+ if (existsSync27(this.path("aborted"))) throw new Error("launch_was_aborted");
2692
2692
  const grant = object8(readPrivateJson2(this.path("grant")));
2693
2693
  if (JSON.stringify(grant) !== JSON.stringify(this.grant()))
2694
2694
  throw new Error("launch_grant_mismatch");
@@ -2705,7 +2705,7 @@ var init_journal = __esm({
2705
2705
  throw new Error("launch_commit_mismatch");
2706
2706
  }
2707
2707
  abortRecord() {
2708
- if (!existsSync26(this.path("aborted"))) return;
2708
+ if (!existsSync27(this.path("aborted"))) return;
2709
2709
  const value = object8(readPrivateJson2(this.path("aborted")));
2710
2710
  if (value.id !== this.id || value.owner !== this.records.owner || !["stopping", "stopped"].includes(String(value.state)))
2711
2711
  throw new Error("foreign_launch_abort");
@@ -2752,30 +2752,30 @@ var init_lifecycle = __esm({
2752
2752
  // src/harness/adapters/docker/private-profile.ts
2753
2753
  import { homedir as homedir8 } from "os";
2754
2754
  import {
2755
- closeSync as closeSync5,
2755
+ closeSync as closeSync6,
2756
2756
  constants as constants4,
2757
- existsSync as existsSync27,
2757
+ existsSync as existsSync28,
2758
2758
  fstatSync as fstatSync3,
2759
2759
  lstatSync as lstatSync7,
2760
- openSync as openSync5,
2761
- realpathSync as realpathSync8,
2760
+ openSync as openSync6,
2761
+ realpathSync as realpathSync9,
2762
2762
  statfsSync
2763
2763
  } from "fs";
2764
- import { join as join33, relative as relative11 } from "path";
2764
+ import { join as join36, relative as relative11 } from "path";
2765
2765
  function overlap(left, right) {
2766
2766
  const scope = relative11(left, right);
2767
2767
  return scope === "" || scope !== ".." && !scope.startsWith("../");
2768
2768
  }
2769
2769
  function profileIdentity(directory, projectRoot) {
2770
- if (directory === "/" || directory === realpathSync8(homedir8()) || overlap(directory, projectRoot) || overlap(projectRoot, directory) || realpathSync8(directory) !== directory)
2770
+ if (directory === "/" || directory === realpathSync9(homedir8()) || overlap(directory, projectRoot) || overlap(projectRoot, directory) || realpathSync9(directory) !== directory)
2771
2771
  throw new Error("private_profile_scope_not_admitted");
2772
2772
  const stat = lstatSync7(directory);
2773
2773
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 511) !== 448)
2774
2774
  throw new Error("unsafe_private_profile_directory");
2775
2775
  if ([26985, 4283649346, 4266872130].includes(statfsSync(directory).type))
2776
2776
  throw new Error("remote_private_profile_not_admitted");
2777
- const lock = openSync5(
2778
- join33(directory, privateProfileLock),
2777
+ const lock = openSync6(
2778
+ join36(directory, privateProfileLock),
2779
2779
  constants4.O_RDONLY | constants4.O_NOFOLLOW
2780
2780
  );
2781
2781
  try {
@@ -2784,18 +2784,18 @@ function profileIdentity(directory, projectRoot) {
2784
2784
  throw new Error("unsafe_private_profile_lock");
2785
2785
  return `${stat.dev}:${stat.ino}:${value.dev}:${value.ino}`;
2786
2786
  } finally {
2787
- closeSync5(lock);
2787
+ closeSync6(lock);
2788
2788
  }
2789
2789
  }
2790
2790
  function captureProfile(grant, projectRoot) {
2791
- const directory = realpathSync8(grant.directory);
2792
- if (directory !== grant.directory || overlap(directory, projectRoot) || overlap(projectRoot, directory) || directory === "/" || directory === realpathSync8(homedir8()))
2791
+ const directory = realpathSync9(grant.directory);
2792
+ if (directory !== grant.directory || overlap(directory, projectRoot) || overlap(projectRoot, directory) || directory === "/" || directory === realpathSync9(homedir8()))
2793
2793
  throw new Error("private_profile_scope_not_admitted");
2794
2794
  const stat = lstatSync7(directory);
2795
2795
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 511) !== 448)
2796
2796
  throw new Error("unsafe_private_profile_directory");
2797
- const lock = join33(directory, privateProfileLock);
2798
- if (!existsSync27(lock)) closeSync5(openSync5(lock, "wx", 384));
2797
+ const lock = join36(directory, privateProfileLock);
2798
+ if (!existsSync28(lock)) closeSync6(openSync6(lock, "wx", 384));
2799
2799
  const identity = profileIdentity(directory, projectRoot);
2800
2800
  if (grant.identity && grant.identity !== identity)
2801
2801
  throw new Error("private_profile_identity_changed");
@@ -2813,7 +2813,7 @@ function assertProfileAvailable(grant, projectRoot) {
2813
2813
  "--nonblock",
2814
2814
  "--conflict-exit-code",
2815
2815
  "73",
2816
- join33(grant.directory, privateProfileLock),
2816
+ join36(grant.directory, privateProfileLock),
2817
2817
  "true"
2818
2818
  ]);
2819
2819
  } catch (error) {
@@ -2833,7 +2833,7 @@ var init_private_profile = __esm({
2833
2833
 
2834
2834
  // src/harness/adapters/docker/profile.ts
2835
2835
  import { homedir as homedir9 } from "os";
2836
- import { lstatSync as lstatSync8, realpathSync as realpathSync9 } from "fs";
2836
+ import { lstatSync as lstatSync8, realpathSync as realpathSync10 } from "fs";
2837
2837
  import { relative as relative12 } from "path";
2838
2838
  function assertLocalDocker() {
2839
2839
  if (process.env.DOCKER_HOST)
@@ -2850,12 +2850,12 @@ function assertLocalDocker() {
2850
2850
  throw new Error("remote_docker_context_not_admitted");
2851
2851
  }
2852
2852
  function loadDockerPolicy(path, projectRoot, runtimes) {
2853
- if (projectRoot === "/" || projectRoot === realpathSync9(homedir9()))
2853
+ if (projectRoot === "/" || projectRoot === realpathSync10(homedir9()))
2854
2854
  throw new Error("docker_project_root_too_broad");
2855
2855
  const inputPath = text(path, "docker_policy_file");
2856
2856
  if (lstatSync8(inputPath).isSymbolicLink())
2857
2857
  throw new Error("symlink_docker_policy_not_admitted");
2858
- const source2 = realpathSync9(inputPath);
2858
+ const source2 = realpathSync10(inputPath);
2859
2859
  const scope = relative12(projectRoot, source2);
2860
2860
  if (scope === ".." || scope.startsWith("../"))
2861
2861
  throw new Error("docker_policy_outside_project");
@@ -2889,14 +2889,14 @@ var init_profile = __esm({
2889
2889
  });
2890
2890
 
2891
2891
  // src/harness/adapters/docker/mounts.ts
2892
- import { lstatSync as lstatSync9, realpathSync as realpathSync10 } from "fs";
2893
- import { join as join34 } from "path";
2892
+ import { lstatSync as lstatSync9, realpathSync as realpathSync11 } from "fs";
2893
+ import { join as join37 } from "path";
2894
2894
  function assertContainerMounts(actual, statePath, projectRoot, directory, nonce, policy, privateProfile, runtime2) {
2895
2895
  const state = text(statePath, "container_state_directory");
2896
2896
  const profile = selectedProfile(policy, privateProfile, runtime2 ?? "");
2897
2897
  if (profile) assertProfileIdentity(profile, projectRoot);
2898
- const expected = profile?.directory ?? join34(directory, "containers", nonce, "profile");
2899
- if (state !== expected || realpathSync10(state) !== expected)
2898
+ const expected = profile?.directory ?? join37(directory, "containers", nonce, "profile");
2899
+ if (state !== expected || realpathSync11(state) !== expected)
2900
2900
  throw new Error("foreign_container_state_directory");
2901
2901
  const stat = lstatSync9(state);
2902
2902
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
@@ -2990,8 +2990,8 @@ var init_entrypoint = __esm({
2990
2990
  });
2991
2991
 
2992
2992
  // src/harness/adapters/docker/admission.ts
2993
- import { lstatSync as lstatSync10, realpathSync as realpathSync11 } from "fs";
2994
- import { join as join35, relative as relative13 } from "path";
2993
+ import { lstatSync as lstatSync10, realpathSync as realpathSync12 } from "fs";
2994
+ import { join as join38, relative as relative13 } from "path";
2995
2995
  function admitResource(path, group, role, directory, memoryMb, runtime2) {
2996
2996
  if (group.profile !== "docker" || !group.dockerPolicy)
2997
2997
  throw new Error("container_requires_docker_profile");
@@ -3000,7 +3000,7 @@ function admitResource(path, group, role, directory, memoryMb, runtime2) {
3000
3000
  const inputPath = text(path, "container_file");
3001
3001
  if (lstatSync10(inputPath).isSymbolicLink())
3002
3002
  throw new Error("symlink_container_file_not_admitted");
3003
- const source2 = realpathSync11(inputPath);
3003
+ const source2 = realpathSync12(inputPath);
3004
3004
  const scope = relative13(projectRoot, source2);
3005
3005
  if (scope === ".." || scope.startsWith("../"))
3006
3006
  throw new Error("container_file_outside_project");
@@ -3047,7 +3047,7 @@ function admitClaim(value, group, role, directory, memoryMb, runtime2, cwd = gro
3047
3047
  )
3048
3048
  ))
3049
3049
  throw new Error("container_runtime_image_not_granted");
3050
- if (config.WorkingDir !== join35("/workspace", relative13(projectRoot, cwd)))
3050
+ if (config.WorkingDir !== join38("/workspace", relative13(projectRoot, cwd)))
3051
3051
  throw new Error("container_cwd_not_granted");
3052
3052
  assertContainerMounts(
3053
3053
  actual,
@@ -3183,20 +3183,20 @@ var init_engine = __esm({
3183
3183
  // src/harness/adapters/docker/bridge-artifact.ts
3184
3184
  import { createHash as createHash17 } from "crypto";
3185
3185
  import {
3186
- closeSync as closeSync6,
3186
+ closeSync as closeSync7,
3187
3187
  constants as constants5,
3188
3188
  fstatSync as fstatSync4,
3189
3189
  fsyncSync as fsyncSync3,
3190
- openSync as openSync6,
3191
- readFileSync as readFileSync36,
3190
+ openSync as openSync7,
3191
+ readFileSync as readFileSync37,
3192
3192
  writeFileSync as writeFileSync11
3193
3193
  } from "fs";
3194
- import { join as join36 } from "path";
3194
+ import { join as join39 } from "path";
3195
3195
  function source() {
3196
3196
  const path = artifact("egress-bridge");
3197
3197
  if (!path.endsWith(".js"))
3198
3198
  throw new Error("docker_bridge_requires_compiled_cli");
3199
- return readFileSync36(path);
3199
+ return readFileSync37(path);
3200
3200
  }
3201
3201
  function digest(value) {
3202
3202
  return createHash17("sha256").update(value).digest("hex");
@@ -3209,8 +3209,8 @@ function prepareBridge(creation) {
3209
3209
  const content = source();
3210
3210
  if (digest(content) !== creation.bridgeSha256)
3211
3211
  throw new Error("docker_bridge_source_changed");
3212
- const descriptor = openSync6(
3213
- join36(creation.state, bridgeName(creation.nonce)),
3212
+ const descriptor = openSync7(
3213
+ join39(creation.state, bridgeName(creation.nonce)),
3214
3214
  "wx",
3215
3215
  384
3216
3216
  );
@@ -3218,21 +3218,21 @@ function prepareBridge(creation) {
3218
3218
  writeFileSync11(descriptor, content);
3219
3219
  fsyncSync3(descriptor);
3220
3220
  } finally {
3221
- closeSync6(descriptor);
3221
+ closeSync7(descriptor);
3222
3222
  }
3223
3223
  }
3224
3224
  function assertBridge(creation) {
3225
3225
  if (!creation.egress?.bridgeExecutable) return;
3226
- const descriptor = openSync6(
3227
- join36(creation.state, bridgeName(creation.nonce)),
3226
+ const descriptor = openSync7(
3227
+ join39(creation.state, bridgeName(creation.nonce)),
3228
3228
  constants5.O_RDONLY | constants5.O_NOFOLLOW
3229
3229
  );
3230
3230
  try {
3231
3231
  const stat = fstatSync4(descriptor);
3232
- if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.nlink !== 1 || (stat.mode & 63) !== 0 || stat.size > 2097152 || digest(readFileSync36(descriptor)) !== creation.bridgeSha256)
3232
+ if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.nlink !== 1 || (stat.mode & 63) !== 0 || stat.size > 2097152 || digest(readFileSync37(descriptor)) !== creation.bridgeSha256)
3233
3233
  throw new Error("docker_bridge_artifact_changed");
3234
3234
  } finally {
3235
- closeSync6(descriptor);
3235
+ closeSync7(descriptor);
3236
3236
  }
3237
3237
  }
3238
3238
  var init_bridge_artifact = __esm({
@@ -3244,7 +3244,7 @@ var init_bridge_artifact = __esm({
3244
3244
  });
3245
3245
 
3246
3246
  // src/harness/adapters/docker/creation-plan.ts
3247
- import { join as join37, relative as relative14 } from "path";
3247
+ import { join as join40, relative as relative14 } from "path";
3248
3248
  function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, preparation) {
3249
3249
  if (group.profile !== "docker" || !group.dockerPolicy)
3250
3250
  throw new Error("container_requires_docker_profile");
@@ -3261,7 +3261,7 @@ function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, prepara
3261
3261
  throw new Error("invalid_container_image_environment");
3262
3262
  const profile = selectedProfile(policy, preparation.privateProfile, runtime2);
3263
3263
  if (profile) assertProfileAvailable(profile, group.projectRoot);
3264
- const state = profile?.directory ?? join37(directory, "containers", nonce, "profile");
3264
+ const state = profile?.directory ?? join40(directory, "containers", nonce, "profile");
3265
3265
  return {
3266
3266
  name: containerName(group.owner, id2),
3267
3267
  nonce,
@@ -3278,7 +3278,7 @@ function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, prepara
3278
3278
  preparation.privateProfile
3279
3279
  ),
3280
3280
  Cmd: preparation.args.length ? preparation.args : null,
3281
- WorkingDir: join37("/workspace", relative14(group.projectRoot, cwd)),
3281
+ WorkingDir: join40("/workspace", relative14(group.projectRoot, cwd)),
3282
3282
  User: `${process.getuid?.()}:${process.getgid?.()}`,
3283
3283
  Env: [
3284
3284
  ...environment2.filter(
@@ -3377,12 +3377,12 @@ var init_creation_plan = __esm({
3377
3377
 
3378
3378
  // src/harness/adapters/docker/creation.ts
3379
3379
  import { mkdirSync as mkdirSync10 } from "fs";
3380
- import { join as join38 } from "path";
3380
+ import { join as join41 } from "path";
3381
3381
  async function prepareCreation(journal) {
3382
3382
  const intent = journal.intent();
3383
3383
  const creation = intent.dockerCreation;
3384
3384
  if (!creation) throw new Error("container_creation_missing");
3385
- const group = new GroupStore(join38(journal.records.directory, "group.json")).state.group;
3385
+ const group = new GroupStore(join41(journal.records.directory, "group.json")).state.group;
3386
3386
  const profile = selectedProfile(
3387
3387
  group.dockerPolicy,
3388
3388
  creation.privateProfile,
@@ -3396,7 +3396,7 @@ async function prepareCreation(journal) {
3396
3396
  creation.name,
3397
3397
  creation.configuration
3398
3398
  );
3399
- const current = new GroupStore(join38(journal.records.directory, "group.json")).state.group;
3399
+ const current = new GroupStore(join41(journal.records.directory, "group.json")).state.group;
3400
3400
  if (current.id !== intent.groupId || current.generation !== intent.generation)
3401
3401
  throw new Error("launch_group_generation_mismatch");
3402
3402
  const resource = {
@@ -3464,7 +3464,7 @@ function findCreation(journal) {
3464
3464
  assertResourceOwner(resource, actual);
3465
3465
  assertCreationConfiguration(actual, creation);
3466
3466
  if (!intent.resource) {
3467
- const group = new GroupStore(join38(journal.records.directory, "group.json")).state.group;
3467
+ const group = new GroupStore(join41(journal.records.directory, "group.json")).state.group;
3468
3468
  return {
3469
3469
  ...admitClaim(
3470
3470
  { ...resource, runtime: intent.runtime, state: creation.state },
@@ -3501,7 +3501,7 @@ var init_creation = __esm({
3501
3501
  });
3502
3502
 
3503
3503
  // src/harness/launch/recovery.ts
3504
- import { existsSync as existsSync28 } from "fs";
3504
+ import { existsSync as existsSync29 } from "fs";
3505
3505
  function abortLaunch(connection, journal) {
3506
3506
  const intent = journal.intent();
3507
3507
  if (!controllerExited(intent.controllerIdentity))
@@ -3518,7 +3518,7 @@ function abortLaunch(connection, journal) {
3518
3518
  inputReplayed: false
3519
3519
  };
3520
3520
  }
3521
- if (!existsSync28(journal.path("proof"))) {
3521
+ if (!existsSync29(journal.path("proof"))) {
3522
3522
  const paneUnknown = connection.alive() && (!intent.dockerCreation || connection.tmux(["list-sessions", "-F", "#{session_name}"]).trim().split("\n").includes(`pmcp-${intent.id}`));
3523
3523
  if (paneUnknown || unitActive(intent.unit))
3524
3524
  throw new Error("launch_identity_unknown");
@@ -3545,7 +3545,7 @@ function abortLaunch(connection, journal) {
3545
3545
  assertProof(connection, proof);
3546
3546
  connection.tmux(["kill-pane", "-t", proof.session.paneId]);
3547
3547
  }
3548
- if (existsSync28(journal.records.path(intent.id)))
3548
+ if (existsSync29(journal.records.path(intent.id)))
3549
3549
  journal.records.save({
3550
3550
  ...proof.session,
3551
3551
  stoppedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -3572,9 +3572,9 @@ var init_recovery = __esm({
3572
3572
 
3573
3573
  // src/harness/adapters/tmux/lifecycle.ts
3574
3574
  import { randomUUID as randomUUID8 } from "crypto";
3575
- import { existsSync as existsSync29 } from "fs";
3575
+ import { existsSync as existsSync30 } from "fs";
3576
3576
  import { setTimeout as setTimeout2 } from "timers/promises";
3577
- import { join as join39 } from "path";
3577
+ import { join as join42 } from "path";
3578
3578
  async function start(connection, spec) {
3579
3579
  const records2 = connection.records;
3580
3580
  if (spec.budgetSlice !== budgetSlice(records2.owner))
@@ -3588,7 +3588,7 @@ async function start(connection, spec) {
3588
3588
  const nonce = randomUUID8();
3589
3589
  const journal = new LaunchJournal(records2, id2);
3590
3590
  const dockerCreation = spec.dockerPreparation ? creationPlan(
3591
- new GroupStore(join39(records2.directory, "group.json")).state.group,
3591
+ new GroupStore(join42(records2.directory, "group.json")).state.group,
3592
3592
  records2.directory,
3593
3593
  id2,
3594
3594
  nonce,
@@ -3648,7 +3648,7 @@ async function start(connection, spec) {
3648
3648
  `exec ${argv.map(quote2).join(" ")}`
3649
3649
  ]);
3650
3650
  const deadline = Date.now() + 5e3;
3651
- while (!existsSync29(journal.path("proof"))) {
3651
+ while (!existsSync30(journal.path("proof"))) {
3652
3652
  if (Date.now() >= deadline) throw new Error("launch_proof_timeout");
3653
3653
  await setTimeout2(25);
3654
3654
  }
@@ -3659,7 +3659,7 @@ async function start(connection, spec) {
3659
3659
  }
3660
3660
  function stop(connection, id2) {
3661
3661
  const journal = new LaunchJournal(connection.records, id2);
3662
- if (existsSync29(journal.path("intent"))) {
3662
+ if (existsSync30(journal.path("intent"))) {
3663
3663
  abortLaunch(connection, journal);
3664
3664
  return;
3665
3665
  }
@@ -3686,7 +3686,7 @@ function cleanup(connection) {
3686
3686
  }
3687
3687
  for (const record of records2) {
3688
3688
  if (record.resource) stopResource(record.resource);
3689
- if (record.stoppedAt || !existsSync29(
3689
+ if (record.stoppedAt || !existsSync30(
3690
3690
  new LaunchJournal(connection.records, record.id).path("intent")
3691
3691
  )) {
3692
3692
  stopUnit(record.unit);
@@ -3717,8 +3717,8 @@ var init_lifecycle2 = __esm({
3717
3717
 
3718
3718
  // src/harness/adapters/tmux/input.ts
3719
3719
  import { randomUUID as randomUUID9 } from "crypto";
3720
- import { closeSync as closeSync7, openSync as openSync7, unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
3721
- import { join as join40 } from "path";
3720
+ import { closeSync as closeSync8, openSync as openSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
3721
+ import { join as join43 } from "path";
3722
3722
  function validateText(text3) {
3723
3723
  if (typeof text3 !== "string" || Buffer.byteLength(text3) > 16384)
3724
3724
  throw new Error("invalid_text");
@@ -3749,8 +3749,8 @@ function write(connection, id2, text3, submit) {
3749
3749
  validateText(text3);
3750
3750
  const session = connection.inspect(id2);
3751
3751
  if (!session.alive) throw new Error("runtime_exited");
3752
- const lock = join40(connection.records.directory, `${id2}.input.lock`);
3753
- const descriptor = openSync7(lock, "wx", 384);
3752
+ const lock = join43(connection.records.directory, `${id2}.input.lock`);
3753
+ const descriptor = openSync8(lock, "wx", 384);
3754
3754
  const buffer = `pmcp-${randomUUID9()}`;
3755
3755
  try {
3756
3756
  writeFileSync12(
@@ -3791,7 +3791,7 @@ function write(connection, id2, text3, submit) {
3791
3791
  connection.tmux(["delete-buffer", "-b", buffer]);
3792
3792
  } catch {
3793
3793
  }
3794
- closeSync7(descriptor);
3794
+ closeSync8(descriptor);
3795
3795
  unlinkSync3(lock);
3796
3796
  }
3797
3797
  }
@@ -3908,10 +3908,10 @@ var init_backend = __esm({
3908
3908
  });
3909
3909
 
3910
3910
  // src/harness/adapters/systemd/budget.ts
3911
- import { join as join41 } from "path";
3911
+ import { join as join44 } from "path";
3912
3912
  async function budgetOperation(directory, operation) {
3913
3913
  const backend = openBackend(directory);
3914
- const path = join41(directory, "runtime-policy.json");
3914
+ const path = join44(directory, "runtime-policy.json");
3915
3915
  const metadata2 = object8(readPrivateJson2(backend.metadataPath));
3916
3916
  const slice = budgetSlice(backend.owner);
3917
3917
  if (operation.action === "configure") {
@@ -4012,7 +4012,7 @@ var init_budget = __esm({
4012
4012
 
4013
4013
  // src/harness/adapters/systemd/configure.ts
4014
4014
  import { execFileSync as execFileSync3 } from "child_process";
4015
- import { join as join42 } from "path";
4015
+ import { join as join45 } from "path";
4016
4016
  function configureBudget(context, input) {
4017
4017
  const { store, backend } = context;
4018
4018
  assertOwnedRecords(backend);
@@ -4034,7 +4034,7 @@ function configureBudget(context, input) {
4034
4034
  throw new Error("capacity_below_active_sessions");
4035
4035
  if (active.reduce((total, session) => total + session.memoryMb, 0) > memoryMb)
4036
4036
  throw new Error("budget_below_reserved_memory");
4037
- const path = join42(backend.runDirectory, "runtime-policy.json");
4037
+ const path = join45(backend.runDirectory, "runtime-policy.json");
4038
4038
  const policy = object8(readPrivateJson2(path));
4039
4039
  const metadata2 = object8(readPrivateJson2(backend.metadataPath));
4040
4040
  const slice = budgetSlice(backend.owner);
@@ -4071,14 +4071,14 @@ var init_configure = __esm({
4071
4071
  });
4072
4072
 
4073
4073
  // src/harness/adapters/process/executable.ts
4074
- import { accessSync, constants as constants6, statSync as statSync16 } from "fs";
4074
+ import { accessSync, constants as constants6, statSync as statSync17 } from "fs";
4075
4075
  import { delimiter, resolve as resolve18 } from "path";
4076
4076
  function locateExecutable(binary, cwd = process.cwd()) {
4077
4077
  for (const directory of (process.env.PATH ?? "").split(delimiter)) {
4078
4078
  if (!directory) continue;
4079
4079
  const path = resolve18(cwd, directory, binary);
4080
4080
  try {
4081
- if (!statSync16(path).isFile()) continue;
4081
+ if (!statSync17(path).isFile()) continue;
4082
4082
  accessSync(path, constants6.X_OK);
4083
4083
  return path;
4084
4084
  } catch {
@@ -4129,11 +4129,11 @@ var init_admission2 = __esm({
4129
4129
 
4130
4130
  // src/harness/groups/service.ts
4131
4131
  import { randomUUID as randomUUID10 } from "crypto";
4132
- import { realpathSync as realpathSync12, statSync as statSync17, unlinkSync as unlinkSync4 } from "fs";
4133
- import { join as join43 } from "path";
4132
+ import { realpathSync as realpathSync13, statSync as statSync18, unlinkSync as unlinkSync4 } from "fs";
4133
+ import { join as join46 } from "path";
4134
4134
  async function createGroup(input) {
4135
- const projectRoot = realpathSync12(text(input.projectRoot, "project_root"));
4136
- if (!statSync17(projectRoot).isDirectory())
4135
+ const projectRoot = realpathSync13(text(input.projectRoot, "project_root"));
4136
+ if (!statSync18(projectRoot).isDirectory())
4137
4137
  throw new Error("invalid_project_root");
4138
4138
  const allowedRuntimes = strings2(input.allowedRuntimes, "allowed_runtimes");
4139
4139
  const profile = input.profile ?? "native";
@@ -4163,7 +4163,7 @@ async function createGroup(input) {
4163
4163
  sessions: [],
4164
4164
  ...dockerPolicy2 ? { dockerPolicy: dockerPolicy2 } : {}
4165
4165
  };
4166
- const groupFile = join43(backend.runDirectory, "group.json");
4166
+ const groupFile = join46(backend.runDirectory, "group.json");
4167
4167
  privateJson(groupFile, { group, leases: [], deliveries: [] });
4168
4168
  try {
4169
4169
  await budgetOperation(backend.runDirectory, {
@@ -4176,7 +4176,7 @@ async function createGroup(input) {
4176
4176
  await budgetOperation(backend.runDirectory, { action: "cleanup" });
4177
4177
  unlinkSync4(groupFile);
4178
4178
  } catch (cleanupError) {
4179
- privateJson(join43(backend.runDirectory, "initialization-failure.json"), {
4179
+ privateJson(join46(backend.runDirectory, "initialization-failure.json"), {
4180
4180
  error: String(error),
4181
4181
  cleanupError: String(cleanupError),
4182
4182
  recoveryRequired: true
@@ -4238,16 +4238,16 @@ var init_service2 = __esm({
4238
4238
  });
4239
4239
 
4240
4240
  // src/harness/groups/catalog.ts
4241
- import { existsSync as existsSync30, readdirSync as readdirSync12 } from "fs";
4242
- import { join as join44 } from "path";
4241
+ import { existsSync as existsSync31, readdirSync as readdirSync12 } from "fs";
4242
+ import { join as join47 } from "path";
4243
4243
  function listGroups() {
4244
4244
  const directory = stateDirectory();
4245
- if (!existsSync30(directory)) return { groups: [] };
4245
+ if (!existsSync31(directory)) return { groups: [] };
4246
4246
  const groups2 = [];
4247
4247
  for (const entry2 of readdirSync12(directory, { withFileTypes: true })) {
4248
4248
  if (!entry2.isDirectory()) continue;
4249
- const path = join44(directory, entry2.name, "group.json");
4250
- if (!existsSync30(path)) continue;
4249
+ const path = join47(directory, entry2.name, "group.json");
4250
+ if (!existsSync31(path)) continue;
4251
4251
  try {
4252
4252
  const store = new GroupStore(path);
4253
4253
  groups2.push({ groupFile: store.path, group: store.state.group });
@@ -4444,7 +4444,7 @@ var init_watch = __esm({
4444
4444
 
4445
4445
  // src/harness/control/leases.ts
4446
4446
  import { randomUUID as randomUUID11 } from "crypto";
4447
- import { join as join45 } from "path";
4447
+ import { join as join48 } from "path";
4448
4448
  function resolveLease(context, file2, allowExpired = false) {
4449
4449
  const credential2 = object8(readPrivateJson2(file2));
4450
4450
  const lease = context.store.state.leases.find(
@@ -4488,7 +4488,7 @@ function acquireControl(context, sessionId, controller, mode) {
4488
4488
  );
4489
4489
  store.state.leases.push(lease);
4490
4490
  store.save();
4491
- const leaseFile = join45(backend.runDirectory, `lease-${randomUUID11()}.json`);
4491
+ const leaseFile = join48(backend.runDirectory, `lease-${randomUUID11()}.json`);
4492
4492
  privateJson(leaseFile, { token: lease.token });
4493
4493
  return { sessionId, controller, mode, expiresAt: lease.expiresAt, leaseFile };
4494
4494
  }
@@ -4635,12 +4635,12 @@ var init_service5 = __esm({
4635
4635
  });
4636
4636
 
4637
4637
  // src/harness/adapters/process/recover-lock.ts
4638
- import { existsSync as existsSync31, lstatSync as lstatSync11, unlinkSync as unlinkSync5 } from "fs";
4639
- import { join as join46 } from "path";
4638
+ import { existsSync as existsSync32, lstatSync as lstatSync11, unlinkSync as unlinkSync5 } from "fs";
4639
+ import { join as join49 } from "path";
4640
4640
  function recoverInputLock(backend, sessionId) {
4641
4641
  backend.inspect(sessionId);
4642
- const path = join46(backend.runDirectory, `${sessionId}.input.lock`);
4643
- if (!existsSync31(path)) return;
4642
+ const path = join49(backend.runDirectory, `${sessionId}.input.lock`);
4643
+ if (!existsSync32(path)) return;
4644
4644
  const before = lstatSync11(path);
4645
4645
  const record = object8(readPrivateJson2(path));
4646
4646
  if (record.id !== sessionId) throw new Error("foreign_writer_lock");
@@ -4660,7 +4660,7 @@ var init_recover_lock = __esm({
4660
4660
  });
4661
4661
 
4662
4662
  // src/harness/launch/service.ts
4663
- import { existsSync as existsSync32 } from "fs";
4663
+ import { existsSync as existsSync33 } from "fs";
4664
4664
  function assertLaunchAdmission(records2) {
4665
4665
  for (const journal of launchJournals(records2)) {
4666
4666
  if (journal.abortRecord()?.state === "stopped" && unitActive(journal.intent().unit))
@@ -4685,12 +4685,12 @@ function inspectPendingStarts(context) {
4685
4685
  role: journal.intent().role,
4686
4686
  runtime: journal.intent().runtime,
4687
4687
  controllerExited: controllerExited(journal.intent().controllerIdentity),
4688
- proofPresent: existsSync32(journal.path("proof")),
4689
- recordPresent: existsSync32(journal.records.path(journal.id)),
4688
+ proofPresent: existsSync33(journal.path("proof")),
4689
+ recordPresent: existsSync33(journal.records.path(journal.id)),
4690
4690
  registered: context.store.state.group.sessions.some(
4691
4691
  (session) => session.id === journal.id
4692
4692
  ),
4693
- authorizationPresent: existsSync32(journal.path("grant")),
4693
+ authorizationPresent: existsSync33(journal.path("grant")),
4694
4694
  processingConfirmed: false,
4695
4695
  inputReplayed: false
4696
4696
  }));
@@ -4708,7 +4708,7 @@ var init_service6 = __esm({
4708
4708
  });
4709
4709
 
4710
4710
  // src/harness/sessions/service.ts
4711
- import { realpathSync as realpathSync13 } from "fs";
4711
+ import { realpathSync as realpathSync14 } from "fs";
4712
4712
  import { relative as relative15 } from "path";
4713
4713
  async function startSession(context, input) {
4714
4714
  const { store, backend } = context;
@@ -4742,7 +4742,7 @@ async function startSession(context, input) {
4742
4742
  );
4743
4743
  if (!backend.inspect(main2.id).alive) throw new Error("main_unavailable");
4744
4744
  }
4745
- const cwd = realpathSync13(text(input.cwd ?? group.projectRoot, "cwd"));
4745
+ const cwd = realpathSync14(text(input.cwd ?? group.projectRoot, "cwd"));
4746
4746
  const scope = relative15(group.projectRoot, cwd);
4747
4747
  if (scope === ".." || scope.startsWith("../"))
4748
4748
  throw new Error("cwd_outside_project");
@@ -5205,9 +5205,9 @@ var init_invoke = __esm({
5205
5205
  });
5206
5206
 
5207
5207
  // src/tui/adapters/process/runtime.ts
5208
- import { dirname as dirname24, join as join47 } from "path";
5208
+ import { dirname as dirname24, join as join50 } from "path";
5209
5209
  import { fileURLToPath as fileURLToPath4 } from "url";
5210
- import { existsSync as existsSync33, realpathSync as realpathSync14 } from "fs";
5210
+ import { existsSync as existsSync34, realpathSync as realpathSync15 } from "fs";
5211
5211
  function dependencies() {
5212
5212
  const tmux = locateExecutable("tmux");
5213
5213
  const flock = locateExecutable("flock");
@@ -5241,9 +5241,9 @@ function runtime() {
5241
5241
  throw new Error("tui_dependencies_unavailable");
5242
5242
  const current = fileURLToPath4(import.meta.url);
5243
5243
  const directory = dirname24(current);
5244
- const bundled = join47(directory, "tui-worker.js");
5245
- if (!existsSync33(bundled)) throw new Error("tui_build_required");
5246
- return { node: realpathSync14(available.node), worker: bundled };
5244
+ const bundled = join50(directory, "tui-worker.js");
5245
+ if (!existsSync34(bundled)) throw new Error("tui_build_required");
5246
+ return { node: realpathSync15(available.node), worker: bundled };
5247
5247
  }
5248
5248
  var init_runtime2 = __esm({
5249
5249
  "src/tui/adapters/process/runtime.ts"() {
@@ -5330,32 +5330,32 @@ var init_diagnostics = __esm({
5330
5330
  // src/tui/state/store.ts
5331
5331
  import { randomUUID as randomUUID13 } from "crypto";
5332
5332
  import {
5333
- existsSync as existsSync34,
5333
+ existsSync as existsSync35,
5334
5334
  lstatSync as lstatSync12,
5335
5335
  mkdirSync as mkdirSync11,
5336
- realpathSync as realpathSync15,
5336
+ realpathSync as realpathSync16,
5337
5337
  unlinkSync as unlinkSync6,
5338
5338
  writeFileSync as writeFileSync13
5339
5339
  } from "fs";
5340
5340
  import { homedir as homedir10 } from "os";
5341
- import { dirname as dirname25, join as join48 } from "path";
5341
+ import { dirname as dirname25, join as join51 } from "path";
5342
5342
  function createDirectory() {
5343
- const root = join48(
5344
- process.env.XDG_STATE_HOME ?? join48(homedir10(), ".local/state"),
5343
+ const root = join51(
5344
+ process.env.XDG_STATE_HOME ?? join51(homedir10(), ".local/state"),
5345
5345
  "pmcp/tui"
5346
5346
  );
5347
5347
  mkdirSync11(root, { recursive: true, mode: 448 });
5348
- const directory = join48(realpathSync15(root), randomUUID13().slice(0, 16));
5349
- if (Buffer.byteLength(join48(directory, "s")) > 100)
5348
+ const directory = join51(realpathSync16(root), randomUUID13().slice(0, 16));
5349
+ if (Buffer.byteLength(join51(directory, "s")) > 100)
5350
5350
  throw new Error("socket_path_too_long");
5351
5351
  mkdirSync11(directory, { mode: 448 });
5352
5352
  const owner = randomUUID13();
5353
- privateJson(join48(directory, "owner.json"), {
5353
+ privateJson(join51(directory, "owner.json"), {
5354
5354
  owner,
5355
5355
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
5356
5356
  });
5357
5357
  writeFileSync13(
5358
- join48(directory, "tmux.conf"),
5358
+ join51(directory, "tmux.conf"),
5359
5359
  [
5360
5360
  "set -g remain-on-exit on",
5361
5361
  "set -g history-limit 2000",
@@ -5370,13 +5370,13 @@ function createDirectory() {
5370
5370
  return { directory, owner };
5371
5371
  }
5372
5372
  function readView(path) {
5373
- const file2 = realpathSync15(path);
5373
+ const file2 = realpathSync16(path);
5374
5374
  const directory = dirname25(file2);
5375
5375
  const stat = lstatSync12(directory);
5376
5376
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
5377
5377
  throw new Error("unsafe_view_directory");
5378
5378
  const value = object8(readPrivateJson2(file2));
5379
- const metadata2 = object8(readPrivateJson2(join48(directory, "owner.json")));
5379
+ const metadata2 = object8(readPrivateJson2(join51(directory, "owner.json")));
5380
5380
  if (value.schemaVersion !== 1 || value.directory !== directory || value.owner !== metadata2.owner)
5381
5381
  throw new Error("foreign_view_owner");
5382
5382
  for (const key of [
@@ -5413,8 +5413,8 @@ function readView(path) {
5413
5413
  throw new Error("invalid_view_identity");
5414
5414
  }
5415
5415
  const view = value;
5416
- const fallback = join48(directory, "callback-failure.json");
5417
- if (existsSync34(fallback)) {
5416
+ const fallback = join51(directory, "callback-failure.json");
5417
+ if (existsSync35(fallback)) {
5418
5418
  const recorded = object8(readPrivateJson2(fallback));
5419
5419
  const failure2 = object8(recorded.failure);
5420
5420
  if (recorded.owner !== view.owner || typeof failure2.code !== "string" || !/^[a-z][a-z0-9_]{0,79}$/.test(failure2.code))
@@ -5425,8 +5425,8 @@ function readView(path) {
5425
5425
  return { file: file2, view };
5426
5426
  }
5427
5427
  function dismissFailure(file2, view) {
5428
- const fallback = join48(view.directory, "callback-failure.json");
5429
- if (existsSync34(fallback)) unlinkSync6(fallback);
5428
+ const fallback = join51(view.directory, "callback-failure.json");
5429
+ if (existsSync35(fallback)) unlinkSync6(fallback);
5430
5430
  delete view.failure;
5431
5431
  saveView(file2, view);
5432
5432
  }
@@ -5443,7 +5443,7 @@ var init_store3 = __esm({
5443
5443
  });
5444
5444
 
5445
5445
  // src/tui/adapters/process/lock.ts
5446
- import { spawnSync as spawnSync5 } from "child_process";
5446
+ import { spawnSync as spawnSync6 } from "child_process";
5447
5447
  function serializedView(invocation2) {
5448
5448
  const { file: file2, view } = readView(invocation2.viewFile);
5449
5449
  const args = ["locked", invocation2.action, "--view", file2];
@@ -5454,7 +5454,7 @@ function serializedView(invocation2) {
5454
5454
  ["confirm-session", invocation2.input.confirmSession]
5455
5455
  ])
5456
5456
  if (value !== void 0) args.push(`--${name}`, String(value));
5457
- const child = spawnSync5(
5457
+ const child = spawnSync6(
5458
5458
  "flock",
5459
5459
  [
5460
5460
  "--wait",
@@ -5488,7 +5488,7 @@ var init_lock = __esm({
5488
5488
  });
5489
5489
 
5490
5490
  // src/tui/adapters/process/budget.ts
5491
- import { readFileSync as readFileSync37 } from "fs";
5491
+ import { readFileSync as readFileSync38 } from "fs";
5492
5492
  function viewUnit(owner) {
5493
5493
  if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/.test(owner))
5494
5494
  throw new Error("invalid_view_owner");
@@ -5516,7 +5516,7 @@ function startPresentation(owner, args, env) {
5516
5516
  );
5517
5517
  }
5518
5518
  function assertPresentationBudget(owner, pid) {
5519
- if (!readFileSync37(`/proc/${pid}/cgroup`, "utf8").includes(
5519
+ if (!readFileSync38(`/proc/${pid}/cgroup`, "utf8").includes(
5520
5520
  `/${viewUnit(owner)}
5521
5521
  `
5522
5522
  ))
@@ -5531,7 +5531,7 @@ var init_budget2 = __esm({
5531
5531
 
5532
5532
  // src/tui/adapters/tmux/connection.ts
5533
5533
  import { spawn as spawn3 } from "child_process";
5534
- import { join as join49 } from "path";
5534
+ import { join as join52 } from "path";
5535
5535
  var ViewConnection;
5536
5536
  var init_connection2 = __esm({
5537
5537
  "src/tui/adapters/tmux/connection.ts"() {
@@ -5544,7 +5544,7 @@ var init_connection2 = __esm({
5544
5544
  this.directory = directory;
5545
5545
  this.owner = owner;
5546
5546
  this.identity = identity;
5547
- this.socket = join49(directory, "s");
5547
+ this.socket = join52(directory, "s");
5548
5548
  }
5549
5549
  directory;
5550
5550
  owner;
@@ -5557,14 +5557,14 @@ var init_connection2 = __esm({
5557
5557
  "-S",
5558
5558
  this.socket,
5559
5559
  "-f",
5560
- join49(this.directory, "tmux.conf"),
5560
+ join52(this.directory, "tmux.conf"),
5561
5561
  ...args
5562
5562
  ];
5563
5563
  if (args[0] === "new-session" && !this.identity)
5564
5564
  return startPresentation(this.owner, options2, env).trim();
5565
5565
  return command(
5566
5566
  "tmux",
5567
- ["-S", this.socket, "-f", join49(this.directory, "tmux.conf"), ...args],
5567
+ ["-S", this.socket, "-f", join52(this.directory, "tmux.conf"), ...args],
5568
5568
  { env }
5569
5569
  ).trim();
5570
5570
  }
@@ -5628,7 +5628,7 @@ var init_connection2 = __esm({
5628
5628
  });
5629
5629
 
5630
5630
  // src/tui/application/feedback.ts
5631
- import { join as join50 } from "path";
5631
+ import { join as join53 } from "path";
5632
5632
  function describeFailure(action, error) {
5633
5633
  const message = error instanceof Error ? error.message : "view_action_failed";
5634
5634
  const code = error instanceof RangeError ? "terminal_size_invalid" : failureCode(message);
@@ -6080,16 +6080,16 @@ var init_common = __esm({
6080
6080
  });
6081
6081
 
6082
6082
  // src/tui/application/create.ts
6083
- import { join as join51 } from "path";
6084
- import { realpathSync as realpathSync16 } from "fs";
6083
+ import { join as join54 } from "path";
6084
+ import { realpathSync as realpathSync17 } from "fs";
6085
6085
  async function createView(input) {
6086
6086
  const plan2 = planLayout(input.columns, input.rows);
6087
6087
  const helpers = runtime();
6088
6088
  const mailbox = input.mailbox ? {
6089
- config: realpathSync16(input.mailbox.config),
6090
- actorFile: realpathSync16(input.mailbox.actorFile)
6089
+ config: realpathSync17(input.mailbox.config),
6090
+ actorFile: realpathSync17(input.mailbox.actorFile)
6091
6091
  } : void 0;
6092
- const groupFile = realpathSync16(input.groupFile);
6092
+ const groupFile = realpathSync17(input.groupFile);
6093
6093
  const group = new GroupStore(groupFile).state.group;
6094
6094
  const common2 = new CommonHarness({
6095
6095
  groupFile,
@@ -6102,7 +6102,7 @@ async function createView(input) {
6102
6102
  );
6103
6103
  if (!main2) throw new Error("view_requires_live_main");
6104
6104
  const { directory, owner } = createDirectory();
6105
- const file2 = join51(directory, "view.json");
6105
+ const file2 = join54(directory, "view.json");
6106
6106
  const connection = new ViewConnection(directory, owner);
6107
6107
  const argv = [helpers.node, helpers.worker, "attach", file2, main2.id];
6108
6108
  const result = connection.raw([
@@ -6330,7 +6330,7 @@ var init_navigation = __esm({
6330
6330
  });
6331
6331
 
6332
6332
  // src/tui/application/history.ts
6333
- import { join as join52 } from "path";
6333
+ import { join as join55 } from "path";
6334
6334
  async function observeHistory(context) {
6335
6335
  const { view, renderer, common: common2, file: file2 } = context;
6336
6336
  await releaseControl(context);
@@ -6338,7 +6338,7 @@ async function observeHistory(context) {
6338
6338
  sessionId: view.target,
6339
6339
  input: { lines: 2e3, maxBytes: 65536 }
6340
6340
  });
6341
- privateJson(join52(view.directory, "history.json"), {
6341
+ privateJson(join55(view.directory, "history.json"), {
6342
6342
  sessionId: view.target,
6343
6343
  content: history.content,
6344
6344
  truncated: history.truncated
@@ -6414,8 +6414,8 @@ var init_mailbox = __esm({
6414
6414
  });
6415
6415
 
6416
6416
  // src/tui/application/lifecycle.ts
6417
- import { existsSync as existsSync35, unlinkSync as unlinkSync7 } from "fs";
6418
- import { join as join53 } from "path";
6417
+ import { existsSync as existsSync36, unlinkSync as unlinkSync7 } from "fs";
6418
+ import { join as join56 } from "path";
6419
6419
  function resizeView({ view, renderer, input }) {
6420
6420
  renderer.resize(view, planLayout(input.columns, input.rows));
6421
6421
  }
@@ -6430,8 +6430,8 @@ async function stopTarget(context) {
6430
6430
  async function closeView(context) {
6431
6431
  await returnToMain(context);
6432
6432
  context.renderer.connection.cleanup();
6433
- const history = join53(context.view.directory, "history.json");
6434
- if (existsSync35(history)) unlinkSync7(history);
6433
+ const history = join56(context.view.directory, "history.json");
6434
+ if (existsSync36(history)) unlinkSync7(history);
6435
6435
  context.view.state = "closed";
6436
6436
  saveView(context.file, context.view);
6437
6437
  }
@@ -6688,7 +6688,7 @@ var init_worker_start = __esm({
6688
6688
  });
6689
6689
 
6690
6690
  // src/tui/startup/config.ts
6691
- import { realpathSync as realpathSync17 } from "fs";
6691
+ import { realpathSync as realpathSync18 } from "fs";
6692
6692
  import { resolve as resolve19 } from "path";
6693
6693
  function startupSettings(request3) {
6694
6694
  const path = request3.config ? resolve19(request3.cwd, request3.config) : findConfig(request3.cwd);
@@ -6741,7 +6741,7 @@ function startupSettings(request3) {
6741
6741
  fail2("session memory exceeds the group budget");
6742
6742
  const groupFile = string("group_file");
6743
6743
  return {
6744
- projectRoot: realpathSync17(config?.dir ?? request3.cwd),
6744
+ projectRoot: realpathSync18(config?.dir ?? request3.cwd),
6745
6745
  ...config ? { configFile: config.path } : {},
6746
6746
  runtime: runtime2,
6747
6747
  allowedRuntimes: [.../* @__PURE__ */ new Set([...available, runtime2])],
@@ -6770,16 +6770,16 @@ var init_config3 = __esm({
6770
6770
 
6771
6771
  // src/tui/startup/state.ts
6772
6772
  import { createHash as createHash19 } from "crypto";
6773
- import { existsSync as existsSync36, lstatSync as lstatSync13, mkdirSync as mkdirSync12 } from "fs";
6773
+ import { existsSync as existsSync37, lstatSync as lstatSync13, mkdirSync as mkdirSync12 } from "fs";
6774
6774
  import { homedir as homedir11 } from "os";
6775
- import { dirname as dirname26, join as join54 } from "path";
6775
+ import { dirname as dirname26, join as join57 } from "path";
6776
6776
  function startupFile(projectRoot) {
6777
- const root = join54(
6778
- process.env.XDG_STATE_HOME ?? join54(homedir11(), ".local/state"),
6777
+ const root = join57(
6778
+ process.env.XDG_STATE_HOME ?? join57(homedir11(), ".local/state"),
6779
6779
  "pmcp/launcher"
6780
6780
  );
6781
6781
  const key = createHash19("sha256").update(projectRoot).digest("hex");
6782
- return join54(root, `${key}.json`);
6782
+ return join57(root, `${key}.json`);
6783
6783
  }
6784
6784
  function ensureStartupDirectory(file2) {
6785
6785
  const directory = dirname26(file2);
@@ -6789,7 +6789,7 @@ function ensureStartupDirectory(file2) {
6789
6789
  throw new Error("unsafe_startup_directory");
6790
6790
  }
6791
6791
  function readStartup(file2, projectRoot) {
6792
- if (!existsSync36(file2)) return null;
6792
+ if (!existsSync37(file2)) return null;
6793
6793
  const value = object8(readPrivateJson2(file2));
6794
6794
  if (value.schemaVersion !== 1 || value.projectRoot !== projectRoot)
6795
6795
  throw new Error("foreign_startup_state");
@@ -7009,14 +7009,14 @@ var init_host = __esm({
7009
7009
  });
7010
7010
 
7011
7011
  // src/tui/startup/lock.ts
7012
- import { spawnSync as spawnSync6 } from "child_process";
7013
- import { closeSync as closeSync8, constants as constants7, fstatSync as fstatSync5, openSync as openSync8 } from "fs";
7012
+ import { spawnSync as spawnSync7 } from "child_process";
7013
+ import { closeSync as closeSync9, constants as constants7, fstatSync as fstatSync5, openSync as openSync9 } from "fs";
7014
7014
  function serializedStartup(request3) {
7015
7015
  const settings2 = startupSettings(request3);
7016
7016
  const file2 = startupFile(settings2.projectRoot);
7017
7017
  ensureStartupDirectory(file2);
7018
7018
  const lock = `${file2}.lock`;
7019
- const descriptor = openSync8(
7019
+ const descriptor = openSync9(
7020
7020
  lock,
7021
7021
  constants7.O_CREAT | constants7.O_WRONLY | constants7.O_NOFOLLOW,
7022
7022
  384
@@ -7026,11 +7026,11 @@ function serializedStartup(request3) {
7026
7026
  if (!stat.isFile() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
7027
7027
  throw new Error("unsafe_startup_lock");
7028
7028
  } finally {
7029
- closeSync8(descriptor);
7029
+ closeSync9(descriptor);
7030
7030
  }
7031
7031
  const helpers = runtime();
7032
7032
  const encoded = Buffer.from(JSON.stringify(request3)).toString("base64url");
7033
- const child = spawnSync6(
7033
+ const child = spawnSync7(
7034
7034
  "flock",
7035
7035
  [
7036
7036
  "--wait",
@@ -9859,7 +9859,7 @@ function registerMailboxTools(server, service) {
9859
9859
 
9860
9860
  // src/mcp.ts
9861
9861
  var SERVER_NAME = "pmcp";
9862
- var SERVER_VERSION = "0.16.1";
9862
+ var SERVER_VERSION = "0.17.1";
9863
9863
  function registerSkillTools(server, tools) {
9864
9864
  registerCatalogTool(server, tools);
9865
9865
  registerFindTool(server, tools);
@@ -12002,7 +12002,7 @@ import { homedir as homedir6 } from "os";
12002
12002
  // src/project/apply.ts
12003
12003
  import { createHash as createHash13 } from "crypto";
12004
12004
  import {
12005
- existsSync as existsSync20,
12005
+ existsSync as existsSync21,
12006
12006
  lstatSync as lstatSync5,
12007
12007
  mkdirSync as mkdirSync7,
12008
12008
  readFileSync as readFileSync25,
@@ -12010,7 +12010,7 @@ import {
12010
12010
  readlinkSync as readlinkSync2,
12011
12011
  rmSync as rmSync5
12012
12012
  } from "fs";
12013
- import { dirname as dirname18, join as join24, posix as posix2 } from "path";
12013
+ import { dirname as dirname18, join as join25, posix as posix2 } from "path";
12014
12014
  import { parse as parse5 } from "smol-toml";
12015
12015
 
12016
12016
  // src/project/backup.ts
@@ -12202,6 +12202,56 @@ function splitKeyed(path) {
12202
12202
 
12203
12203
  // src/project/mcp.ts
12204
12204
  import { isAbsolute as isAbsolute5, relative as relative9 } from "path";
12205
+
12206
+ // src/project/adapters/opencode.ts
12207
+ import { existsSync as existsSync17 } from "fs";
12208
+ import { join as join22 } from "path";
12209
+ var OPENCODE_CONFIG = "opencode.json";
12210
+ function checkOpenCodeConfig(root) {
12211
+ if (existsSync17(join22(root, "opencode.jsonc"))) {
12212
+ throw new ProjectError(
12213
+ "OpenCode JSONC projection is not supported; reconcile opencode.jsonc before projecting opencode.json"
12214
+ );
12215
+ }
12216
+ }
12217
+ function opencodeMcpEntry(server, started) {
12218
+ if (server.tools !== void 0) {
12219
+ throw new ProjectError(
12220
+ "OpenCode per-server tool filtering is not qualified; limit this server's targets"
12221
+ );
12222
+ }
12223
+ const timeout = server.native?.opencode;
12224
+ if (server.url !== void 0) {
12225
+ const headers = { ...server.headers };
12226
+ for (const [key, name] of Object.entries(server.headerEnv ?? {})) {
12227
+ headers[key] = `{env:${name}}`;
12228
+ }
12229
+ if (server.bearerTokenEnvVar) {
12230
+ headers["Authorization"] = `Bearer {env:${server.bearerTokenEnvVar}}`;
12231
+ }
12232
+ return {
12233
+ type: "remote",
12234
+ url: server.url,
12235
+ enabled: true,
12236
+ ...Object.keys(headers).length > 0 ? { headers } : {},
12237
+ ...timeout
12238
+ };
12239
+ }
12240
+ if (!started) {
12241
+ throw new ProjectError(
12242
+ "OpenCode local MCP projection requires a launch specification"
12243
+ );
12244
+ }
12245
+ return {
12246
+ type: "local",
12247
+ command: [started.command, ...started.args],
12248
+ enabled: true,
12249
+ ...Object.keys(started.env).length > 0 ? { environment: { ...started.env } } : {},
12250
+ ...timeout
12251
+ };
12252
+ }
12253
+
12254
+ // src/project/mcp.ts
12205
12255
  var runtimeByTool = {
12206
12256
  claude: "claude-code",
12207
12257
  codex: "codex-cli",
@@ -12209,6 +12259,15 @@ var runtimeByTool = {
12209
12259
  grok: "grok-cli",
12210
12260
  antigravity: "antigravity"
12211
12261
  };
12262
+ function mailboxRuntime(tool) {
12263
+ const runtime2 = runtimeByTool[tool];
12264
+ if (!runtime2) {
12265
+ throw new ProjectError(
12266
+ "OpenCode mailbox runtime binding is not qualified; limit this server's targets"
12267
+ );
12268
+ }
12269
+ return runtime2;
12270
+ }
12212
12271
  var ROOT_VAR = "${PROJECT_ROOT}";
12213
12272
  var ANTIGRAVITY_MCP_PLUGIN = ".agents/plugins/pmcp-mcp";
12214
12273
  var VARIABLE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/gu;
@@ -12344,18 +12403,19 @@ function httpEntry(server, tool) {
12344
12403
  function nativeEntry(spec, alias, server, tool) {
12345
12404
  let result;
12346
12405
  if (server.url !== void 0) {
12406
+ if (tool === "opencode") return opencodeMcpEntry(server);
12347
12407
  result = httpEntry(server, tool);
12348
12408
  } else {
12349
12409
  const env = { ...server.env };
12350
12410
  if (server.mailbox) {
12351
- env["PMCP_MAILBOX_RUNTIME"] = runtimeByTool[tool];
12411
+ env["PMCP_MAILBOX_RUNTIME"] = mailboxRuntime(tool);
12352
12412
  }
12353
12413
  let started;
12354
12414
  if (Object.keys(server.envFrom ?? {}).length > 0) {
12355
12415
  const entry2 = relative9(spec.root, process.argv[1] ?? "");
12356
12416
  const driverEnv = {};
12357
12417
  if (server.mailbox) {
12358
- driverEnv["PMCP_MAILBOX_RUNTIME"] = runtimeByTool[tool];
12418
+ driverEnv["PMCP_MAILBOX_RUNTIME"] = mailboxRuntime(tool);
12359
12419
  }
12360
12420
  if (!isAbsolute5(entry2) && !entry2.startsWith("..")) {
12361
12421
  started = launch({
@@ -12373,6 +12433,7 @@ function nativeEntry(spec, alias, server, tool) {
12373
12433
  } else {
12374
12434
  started = launch({ ...server, env });
12375
12435
  }
12436
+ if (tool === "opencode") return opencodeMcpEntry(server, started);
12376
12437
  result = { command: started.command, args: [...started.args] };
12377
12438
  if (Object.keys(started.env).length > 0) {
12378
12439
  result["env"] = { ...started.env };
@@ -12429,9 +12490,11 @@ function mcpOutputs(spec) {
12429
12490
  const jsonFiles = {
12430
12491
  claude: ".mcp.json",
12431
12492
  gemini: ".gemini/settings.json",
12432
- antigravity: `${ANTIGRAVITY_MCP_PLUGIN}/mcp_config.json`
12493
+ antigravity: `${ANTIGRAVITY_MCP_PLUGIN}/mcp_config.json`,
12494
+ opencode: OPENCODE_CONFIG
12433
12495
  };
12434
12496
  for (const tool of spec.tools) {
12497
+ if (tool === "opencode") checkOpenCodeConfig(spec.root);
12435
12498
  const servers = serversForTool(spec, tool);
12436
12499
  if (servers.length === 0) {
12437
12500
  continue;
@@ -12450,7 +12513,7 @@ function mcpOutputs(spec) {
12450
12513
  outputs.push(
12451
12514
  jsonOutput(
12452
12515
  file2,
12453
- ["mcpServers", alias],
12516
+ [tool === "opencode" ? "mcp" : "mcpServers", alias],
12454
12517
  nativeEntry(spec, alias, server, tool)
12455
12518
  )
12456
12519
  );
@@ -12466,14 +12529,14 @@ function mcpOutputs(spec) {
12466
12529
 
12467
12530
  // src/project/hooks.ts
12468
12531
  import { createHash as createHash12 } from "crypto";
12469
- import { existsSync as existsSync18, readFileSync as readFileSync23 } from "fs";
12470
- import { join as join22 } from "path";
12532
+ import { existsSync as existsSync19, readFileSync as readFileSync23 } from "fs";
12533
+ import { join as join23 } from "path";
12471
12534
  import { fileURLToPath as fileURLToPath2 } from "url";
12472
12535
 
12473
12536
  // src/project/hook-adapter.ts
12474
12537
  import { spawnSync as spawnSync2 } from "child_process";
12475
12538
  import { createHash as createHash11 } from "crypto";
12476
- import { existsSync as existsSync17, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync10 } from "fs";
12539
+ import { existsSync as existsSync18, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync10 } from "fs";
12477
12540
  import { dirname as dirname16, isAbsolute as isAbsolute6, relative as relative10, resolve as resolve12 } from "path";
12478
12541
  var denied = () => ({
12479
12542
  decision: "deny",
@@ -12490,7 +12553,7 @@ function guardPath(root, command3) {
12490
12553
  if (isAbsolute6(inside) || inside === ".." || inside.startsWith("../") || inside.startsWith("..\\")) {
12491
12554
  throw new Error("Hook guard must stay under .agents/guards/");
12492
12555
  }
12493
- if (!existsSync17(absolute2) || !statSync10(absolute2).isFile()) {
12556
+ if (!existsSync18(absolute2) || !statSync10(absolute2).isFile()) {
12494
12557
  throw new Error("Hook guard script must exist");
12495
12558
  }
12496
12559
  const actual = relative10(base, realpathSync5(absolute2));
@@ -12685,8 +12748,8 @@ function object4(value) {
12685
12748
  return value;
12686
12749
  }
12687
12750
  function groups(root, file2, key) {
12688
- const absolute2 = join22(root, file2);
12689
- if (!existsSync18(absolute2)) {
12751
+ const absolute2 = join23(root, file2);
12752
+ if (!existsSync19(absolute2)) {
12690
12753
  return [];
12691
12754
  }
12692
12755
  let value;
@@ -12715,15 +12778,15 @@ function adapterSource() {
12715
12778
  const sourceBuild = fileURLToPath2(
12716
12779
  new URL("../../dist/project/hook-adapter.js", import.meta.url)
12717
12780
  );
12718
- const file2 = existsSync18(published) ? published : sourceBuild;
12719
- if (!existsSync18(file2)) {
12781
+ const file2 = existsSync19(published) ? published : sourceBuild;
12782
+ if (!existsSync19(file2)) {
12720
12783
  throw new ProjectError("Build pmcp before projecting shell hook adapters");
12721
12784
  }
12722
12785
  return readFileSync23(file2, "utf8");
12723
12786
  }
12724
12787
  function hookOutputs(spec) {
12725
- const lockFile = join22(spec.root, "pmcp.lock");
12726
- const lock = existsSync18(lockFile) ? JSON.parse(readFileSync23(lockFile, "utf8")) : {};
12788
+ const lockFile = join23(spec.root, "pmcp.lock");
12789
+ const lock = existsSync19(lockFile) ? JSON.parse(readFileSync23(lockFile, "utf8")) : {};
12727
12790
  const previous = new Map(
12728
12791
  (lock.outputs ?? []).filter((entry2) => entry2.managed !== void 0).map((entry2) => [entry2.path, entry2.managed])
12729
12792
  );
@@ -12838,33 +12901,44 @@ ${lines2.join("\n")}
12838
12901
  }
12839
12902
 
12840
12903
  // src/project/plan.ts
12841
- import { existsSync as existsSync19, readFileSync as readFileSync24, readdirSync as readdirSync8 } from "fs";
12842
- import { join as join23 } from "path";
12904
+ import { existsSync as existsSync20, readFileSync as readFileSync24, readdirSync as readdirSync8 } from "fs";
12905
+ import { join as join24 } from "path";
12906
+
12907
+ // src/project/adapters/opencode-skills.ts
12908
+ function opencodeSkillOutputs(spec, names) {
12909
+ if (!spec.tools.has("opencode")) return [];
12910
+ return names.filter((name) => spec.skills[name]?.invocation === "user").map(
12911
+ (name) => jsonOutput(OPENCODE_CONFIG, ["permission", "skill", name], "deny")
12912
+ );
12913
+ }
12914
+
12915
+ // src/project/plan.ts
12843
12916
  var AGENT_FIELDS = {
12844
12917
  claude: ["name", "description", "tools", "model", "effort"],
12845
12918
  gemini: ["name", "description"]
12846
12919
  };
12847
12920
  var SETTINGS = ".claude/settings.json";
12848
12921
  function listDirs(dir) {
12849
- if (!existsSync19(dir)) return [];
12922
+ if (!existsSync20(dir)) return [];
12850
12923
  return readdirSync8(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
12851
12924
  }
12852
12925
  var tomlString = (value) => JSON.stringify(typeof value === "string" ? value : String(value ?? ""));
12853
12926
  function skillNames(root) {
12854
- const dir = join23(root, ".agents/skills");
12927
+ const dir = join24(root, ".agents/skills");
12855
12928
  return listDirs(dir).filter(
12856
- (name) => existsSync19(join23(dir, name, "SKILL.md"))
12929
+ (name) => existsSync20(join24(dir, name, "SKILL.md"))
12857
12930
  );
12858
12931
  }
12859
12932
  function agentNames(root) {
12860
- const dir = join23(root, ".agents/agents");
12933
+ const dir = join24(root, ".agents/agents");
12861
12934
  return listDirs(dir).filter(
12862
- (name) => existsSync19(join23(dir, name, "agent.md"))
12935
+ (name) => existsSync20(join24(dir, name, "agent.md"))
12863
12936
  );
12864
12937
  }
12865
12938
  function skillOutputs(spec) {
12866
- const outputs = [];
12867
- for (const name of skillNames(spec.root)) {
12939
+ const names = skillNames(spec.root);
12940
+ const outputs = opencodeSkillOutputs(spec, names);
12941
+ for (const name of names) {
12868
12942
  const target2 = `../../.agents/skills/${name}`;
12869
12943
  if (spec.tools.has("claude")) {
12870
12944
  outputs.push({ kind: "link", path: `.claude/skills/${name}`, target: target2 });
@@ -12893,13 +12967,13 @@ policy:
12893
12967
  }
12894
12968
  function ruleOutputs(spec) {
12895
12969
  if (!spec.tools.has("claude")) return [];
12896
- const dir = join23(spec.root, ".agents/rules");
12897
- if (!existsSync19(dir)) return [];
12970
+ const dir = join24(spec.root, ".agents/rules");
12971
+ if (!existsSync20(dir)) return [];
12898
12972
  const outputs = [];
12899
12973
  for (const file2 of readdirSync8(dir).filter((f) => f.endsWith(".md")).sort()) {
12900
12974
  const rel = `.agents/rules/${file2}`;
12901
12975
  const { meta, body } = splitFrontmatter(
12902
- readFileSync24(join23(spec.root, rel), "utf8")
12976
+ readFileSync24(join24(spec.root, rel), "utf8")
12903
12977
  );
12904
12978
  const globs = [meta["globs"] ?? []].flat().filter((g) => typeof g === "string" && g !== "");
12905
12979
  const head = globs.length > 0 ? renderFrontmatter({ paths: globs }) : "";
@@ -12918,7 +12992,7 @@ function agentOutputs(spec) {
12918
12992
  for (const name of agentNames(spec.root)) {
12919
12993
  const rel = `.agents/agents/${name}/agent.md`;
12920
12994
  const { meta, body } = splitFrontmatter(
12921
- readFileSync24(join23(spec.root, rel), "utf8")
12995
+ readFileSync24(join24(spec.root, rel), "utf8")
12922
12996
  );
12923
12997
  const overrides = spec.agents[name] ?? {};
12924
12998
  const note = `<!-- ${MARK} from ${rel} -->
@@ -13058,8 +13132,8 @@ var PREDECESSORS = [
13058
13132
  ];
13059
13133
  var sha = (text3) => createHash13("sha256").update(text3).digest("hex");
13060
13134
  function readLock(root) {
13061
- const path = join24(root, LOCK_FILE);
13062
- if (!existsSync20(path)) return [];
13135
+ const path = join25(root, LOCK_FILE);
13136
+ if (!existsSync21(path)) return [];
13063
13137
  const lock = JSON.parse(readFileSync25(path, "utf8"));
13064
13138
  return lock.outputs ?? [];
13065
13139
  }
@@ -13070,9 +13144,9 @@ function linkOf(abs) {
13070
13144
  return null;
13071
13145
  }
13072
13146
  }
13073
- var exists = (abs) => existsSync20(abs) || linkOf(abs) !== null;
13147
+ var exists = (abs) => existsSync21(abs) || linkOf(abs) !== null;
13074
13148
  function readJson2(abs) {
13075
- if (!existsSync20(abs)) return {};
13149
+ if (!existsSync21(abs)) return {};
13076
13150
  let value;
13077
13151
  try {
13078
13152
  value = JSON.parse(readFileSync25(abs, "utf8"));
@@ -13127,32 +13201,44 @@ function withoutBlock(text3) {
13127
13201
  return `${text3.slice(0, start2).replace(/\n+$/u, "\n")}${after}`;
13128
13202
  }
13129
13203
  function present(root, output) {
13130
- const abs = join24(root, "file" in output ? output.file : output.path);
13204
+ const abs = join25(root, "file" in output ? output.file : output.path);
13131
13205
  switch (output.kind) {
13132
13206
  case "link":
13133
13207
  return linkOf(abs) === output.target;
13134
13208
  case "file":
13135
- return existsSync20(abs) && linkOf(abs) === null && readFileSync25(abs, "utf8") === output.content;
13209
+ return existsSync21(abs) && linkOf(abs) === null && readFileSync25(abs, "utf8") === output.content;
13136
13210
  case "json":
13137
13211
  if (output.managed && Array.isArray(output.value) && output.value.length === 0) {
13138
13212
  return getKey(readJson2(abs), output.key) === void 0;
13139
13213
  }
13140
13214
  return same(getKey(readJson2(abs), output.key), output.value);
13141
13215
  case "block":
13142
- return existsSync20(abs) && readFileSync25(abs, "utf8").includes(block(output.content));
13216
+ return existsSync21(abs) && readFileSync25(abs, "utf8").includes(block(output.content));
13143
13217
  }
13144
13218
  }
13145
13219
  function replaceable(root, output, owned) {
13146
13220
  if (output.kind === "json") {
13147
- if (output.key[0] !== "mcpServers" || owned.has(output.path)) {
13221
+ if (output.file === "opencode.json") {
13222
+ let parent = readJson2(join25(root, output.file));
13223
+ for (const part of output.key.slice(0, -1)) {
13224
+ if (parent === void 0) break;
13225
+ if (parent === null || typeof parent !== "object" || Array.isArray(parent))
13226
+ return false;
13227
+ parent = parent[part];
13228
+ }
13229
+ if (parent !== void 0 && (parent === null || typeof parent !== "object" || Array.isArray(parent)))
13230
+ return false;
13231
+ }
13232
+ const guarded2 = output.key[0] === "mcpServers" || output.file === "opencode.json";
13233
+ if (!guarded2 || owned.has(output.path)) {
13148
13234
  return true;
13149
13235
  }
13150
- const existing = getKey(readJson2(join24(root, output.file)), output.key);
13236
+ const existing = getKey(readJson2(join25(root, output.file)), output.key);
13151
13237
  return existing === void 0 || same(existing, output.value);
13152
13238
  }
13153
13239
  if (output.kind === "block") {
13154
- const absolute2 = join24(root, output.file);
13155
- const text4 = existsSync20(absolute2) ? readFileSync25(absolute2, "utf8") : "";
13240
+ const absolute2 = join25(root, output.file);
13241
+ const text4 = existsSync21(absolute2) ? readFileSync25(absolute2, "utf8") : "";
13156
13242
  const outside = parse5(withoutBlock(text4));
13157
13243
  const proposed = parse5(output.content);
13158
13244
  const existing = objectKeys(outside["mcp_servers"]);
@@ -13161,7 +13247,7 @@ function replaceable(root, output, owned) {
13161
13247
  );
13162
13248
  }
13163
13249
  if (owned.has(output.path)) return true;
13164
- const abs = join24(root, output.path);
13250
+ const abs = join25(root, output.path);
13165
13251
  if (!exists(abs)) return true;
13166
13252
  const target2 = linkOf(abs);
13167
13253
  if (target2 !== null) {
@@ -13182,15 +13268,15 @@ function undeclared(spec, outputs) {
13182
13268
  const declared = new Set(outputs.map((o) => o.path));
13183
13269
  const found = [];
13184
13270
  for (const dir of censusDirs(spec)) {
13185
- const abs = join24(spec.root, dir);
13186
- if (!existsSync20(abs)) continue;
13271
+ const abs = join25(spec.root, dir);
13272
+ if (!existsSync21(abs)) continue;
13187
13273
  for (const entry2 of readdirSync9(abs)) {
13188
13274
  const path = `${dir}/${entry2}`;
13189
13275
  if (!declared.has(path)) found.push(path);
13190
13276
  }
13191
13277
  }
13192
- const rules = join24(spec.root, RULES_DIR);
13193
- if (spec.tools.has("grok") && existsSync20(rules)) {
13278
+ const rules = join25(spec.root, RULES_DIR);
13279
+ if (spec.tools.has("grok") && existsSync21(rules)) {
13194
13280
  for (const entry2 of readdirSync9(rules, { withFileTypes: true })) {
13195
13281
  if (entry2.isDirectory()) continue;
13196
13282
  found.push(`${RULES_DIR}/${entry2.name}`);
@@ -13217,8 +13303,8 @@ function deadGlobs(root, outputs) {
13217
13303
  if (rule.kind === "file") {
13218
13304
  text3 = rule.content;
13219
13305
  } else if (rule.kind === "link") {
13220
- const abs = join24(root, posix2.join(posix2.dirname(rule.path), rule.target));
13221
- if (!existsSync20(abs)) continue;
13306
+ const abs = join25(root, posix2.join(posix2.dirname(rule.path), rule.target));
13307
+ if (!existsSync21(abs)) continue;
13222
13308
  text3 = readFileSync25(abs, "utf8");
13223
13309
  } else {
13224
13310
  continue;
@@ -13269,7 +13355,7 @@ function project(spec, options2) {
13269
13355
  }
13270
13356
  }
13271
13357
  for (const path of jsonPaths) {
13272
- readJson2(join24(spec.root, path));
13358
+ readJson2(join25(spec.root, path));
13273
13359
  }
13274
13360
  if (options2.check) {
13275
13361
  const problems = [
@@ -13290,6 +13376,7 @@ function project(spec, options2) {
13290
13376
  return { code: 3, problems: refused, outputs: outputs.length, pruned: 0 };
13291
13377
  }
13292
13378
  const mcpPaths = [
13379
+ "opencode.json",
13293
13380
  ".mcp.json",
13294
13381
  ".gemini/settings.json",
13295
13382
  ".agents/mcp_config.json",
@@ -13331,7 +13418,7 @@ function project(spec, options2) {
13331
13418
  for (const output of outputs) {
13332
13419
  if (output.kind !== "link" && output.kind !== "file") continue;
13333
13420
  if (present(spec.root, output)) continue;
13334
- const abs = join24(spec.root, output.path);
13421
+ const abs = join25(spec.root, output.path);
13335
13422
  mkdirSync7(dirname18(abs), { recursive: true });
13336
13423
  if (output.kind === "link") {
13337
13424
  replaceLink(abs, output.target);
@@ -13359,12 +13446,12 @@ function project(spec, options2) {
13359
13446
  group.drops.push(keyed.key);
13360
13447
  jsonFiles.set(keyed.file, group);
13361
13448
  } else {
13362
- rmSync5(join24(spec.root, entry2.path), { force: true, recursive: true });
13449
+ rmSync5(join25(spec.root, entry2.path), { force: true, recursive: true });
13363
13450
  }
13364
13451
  pruned += 1;
13365
13452
  }
13366
13453
  for (const [file2, { sets, drops }] of jsonFiles) {
13367
- const abs = join24(spec.root, file2);
13454
+ const abs = join25(spec.root, file2);
13368
13455
  const before = readJson2(abs);
13369
13456
  const after = structuredClone(before);
13370
13457
  for (const key of drops) deleteKey(after, key);
@@ -13379,14 +13466,14 @@ function project(spec, options2) {
13379
13466
  }
13380
13467
  }
13381
13468
  if (same(before, after)) continue;
13382
- if (!existsSync20(abs) && Object.keys(after).length === 0) continue;
13469
+ if (!existsSync21(abs) && Object.keys(after).length === 0) continue;
13383
13470
  mkdirSync7(dirname18(abs), { recursive: true });
13384
13471
  replaceFile(abs, `${JSON.stringify(after, null, 2)}
13385
13472
  `);
13386
13473
  }
13387
13474
  for (const [file2, content] of blockFiles) {
13388
- const abs = join24(spec.root, file2);
13389
- const before = existsSync20(abs) ? readFileSync25(abs, "utf8") : "";
13475
+ const abs = join25(spec.root, file2);
13476
+ const before = existsSync21(abs) ? readFileSync25(abs, "utf8") : "";
13390
13477
  let after = withoutBlock(before);
13391
13478
  if (content !== null) {
13392
13479
  const sep7 = after === "" || after.endsWith("\n\n") ? "" : after.endsWith("\n") ? "\n" : "\n\n";
@@ -13405,15 +13492,15 @@ function project(spec, options2) {
13405
13492
  )
13406
13493
  );
13407
13494
  for (const [name, target2] of legacyLinks(spec.root)) {
13408
- const abs = join24(spec.root, RULES_DIR, `${name}.md`);
13409
- const broken = !existsSync20(abs);
13495
+ const abs = join25(spec.root, RULES_DIR, `${name}.md`);
13496
+ const broken = !existsSync21(abs);
13410
13497
  if (!broken && !linkedDirs.has(posix2.dirname(target2))) continue;
13411
13498
  rmSync5(abs, { force: true });
13412
13499
  pruned += 1;
13413
13500
  }
13414
13501
  }
13415
13502
  replaceFile(
13416
- join24(spec.root, LOCK_FILE),
13503
+ join25(spec.root, LOCK_FILE),
13417
13504
  `${JSON.stringify({ version: 1, outputs: outputs.filter((output) => output.kind !== "json" || output.managed === void 0 || output.managed.length > 0).map(lockEntry) }, null, 2)}
13418
13505
  `
13419
13506
  );
@@ -13510,7 +13597,8 @@ var TOOLS = [
13510
13597
  "codex",
13511
13598
  "gemini",
13512
13599
  "grok",
13513
- "antigravity"
13600
+ "antigravity",
13601
+ "opencode"
13514
13602
  ];
13515
13603
  var NAME = /^[a-z0-9][a-z0-9-]*$/u;
13516
13604
  function table(path, where, value) {
@@ -13666,7 +13754,8 @@ function nativeOptions(path, where, value) {
13666
13754
  codex: ["startup_timeout_sec", "tool_timeout_sec"],
13667
13755
  gemini: ["timeout"],
13668
13756
  grok: ["startup_timeout_sec", "tool_timeout_sec"],
13669
- antigravity: []
13757
+ antigravity: [],
13758
+ opencode: ["timeout"]
13670
13759
  };
13671
13760
  const result = {};
13672
13761
  for (const [tool, raw] of Object.entries(
@@ -13860,6 +13949,11 @@ function sourceServers(source2, root) {
13860
13949
  );
13861
13950
  }
13862
13951
  const path = resolve13(root, source2.slice(split + 1));
13952
+ if (tool === "opencode") {
13953
+ throw new ProjectError(
13954
+ "OpenCode MCP import is not qualified; define the server in pmcp.toml"
13955
+ );
13956
+ }
13863
13957
  if (statSync11(path).size > 2 * 1024 * 1024) {
13864
13958
  throw new ProjectError("MCP source exceeds the 2 MiB limit");
13865
13959
  }
@@ -14223,12 +14317,125 @@ async function execMcp(spec, alias, env) {
14223
14317
  }
14224
14318
 
14225
14319
  // src/project/doctor.ts
14226
- import { spawnSync as spawnSync3 } from "child_process";
14227
- import { existsSync as existsSync21, readFileSync as readFileSync28 } from "fs";
14228
- import { join as join25 } from "path";
14320
+ import { spawnSync as spawnSync4 } from "child_process";
14321
+ import { existsSync as existsSync22, readFileSync as readFileSync29 } from "fs";
14322
+ import { join as join28 } from "path";
14229
14323
  import { parse as parse8 } from "smol-toml";
14324
+
14325
+ // src/project/adapters/opencode-doctor.ts
14326
+ import { realpathSync as realpathSync6 } from "fs";
14327
+ import { join as join26 } from "path";
14328
+ function isOpenCodeInventory(command3, args) {
14329
+ return command3 === "opencode" && args.length === 2 && args[0] === "debug" && args[1] === "skill";
14330
+ }
14331
+ function connected(out, alias) {
14332
+ const ansi = new RegExp(
14333
+ `${String.fromCharCode(27)}\\[[0-?]*[ -/]*[@-~]`,
14334
+ "gu"
14335
+ );
14336
+ const pattern = new RegExp(
14337
+ `^[^a-zA-Z0-9]*${alias}\\s+connected(?:\\s|$)`,
14338
+ "u"
14339
+ );
14340
+ return out.replace(ansi, "").split("\n").some((line) => pattern.test(line.trim()));
14341
+ }
14342
+ function projectSkill(out, root, name) {
14343
+ try {
14344
+ const entries = JSON.parse(out);
14345
+ if (!Array.isArray(entries)) return false;
14346
+ const expected = realpathSync6(
14347
+ join26(root, ".agents/skills", name, "SKILL.md")
14348
+ );
14349
+ return entries.some(
14350
+ (entry2) => entry2?.name === name && typeof entry2.location === "string" && realpathSync6(entry2.location) === expected
14351
+ );
14352
+ } catch {
14353
+ return false;
14354
+ }
14355
+ }
14356
+ function opencodeDoctor(spec, options2, listed2) {
14357
+ const findings = [];
14358
+ const names = skillNames(spec.root);
14359
+ if (names.length > 0) {
14360
+ findings.push(
14361
+ listed2(
14362
+ "opencode",
14363
+ "project skills discovered",
14364
+ options2.run("opencode", ["debug", "skill"], spec.root, options2.env),
14365
+ names,
14366
+ (out, name) => projectSkill(out, spec.root, name)
14367
+ )
14368
+ );
14369
+ }
14370
+ const aliases = serversForTool(spec, "opencode").map(([alias]) => alias);
14371
+ if (aliases.length > 0) {
14372
+ findings.push(
14373
+ listed2(
14374
+ "opencode",
14375
+ "mcp servers connected",
14376
+ options2.run("opencode", ["mcp", "list"], spec.root, options2.env),
14377
+ aliases,
14378
+ connected
14379
+ )
14380
+ );
14381
+ }
14382
+ return findings;
14383
+ }
14384
+
14385
+ // src/project/diagnostics/native-json.ts
14386
+ import { spawnSync as spawnSync3 } from "child_process";
14387
+ import {
14388
+ closeSync as closeSync4,
14389
+ mkdtempSync as mkdtempSync3,
14390
+ openSync as openSync4,
14391
+ readFileSync as readFileSync28,
14392
+ rmSync as rmSync6,
14393
+ statSync as statSync13
14394
+ } from "fs";
14395
+ import { tmpdir as tmpdir2 } from "os";
14396
+ import { join as join27 } from "path";
14397
+ var MAX_OUTPUT = 1 << 26;
14398
+ var nativeJsonRunner = (command3, args, cwd, env) => {
14399
+ const directory = mkdtempSync3(join27(tmpdir2(), "pmcp-native-json-"));
14400
+ let descriptor;
14401
+ try {
14402
+ const file2 = join27(directory, "stdout.json");
14403
+ descriptor = openSync4(file2, "wx", 384);
14404
+ const result = spawnSync3(command3, [...args], {
14405
+ cwd,
14406
+ ...env ? { env: { ...process.env, ...env } } : {},
14407
+ encoding: "utf8",
14408
+ timeout: 18e4,
14409
+ maxBuffer: MAX_OUTPUT,
14410
+ stdio: ["ignore", descriptor, "pipe"]
14411
+ });
14412
+ const code = result.error?.code;
14413
+ if (result.status !== 0 || result.error) {
14414
+ return {
14415
+ missing: code === "ENOENT",
14416
+ status: result.status,
14417
+ stdout: result.stderr || result.error?.message || "Native inventory failed"
14418
+ };
14419
+ }
14420
+ if (statSync13(file2).size > MAX_OUTPUT) {
14421
+ return {
14422
+ missing: false,
14423
+ status: null,
14424
+ stdout: "Native JSON output exceeds 64 MiB"
14425
+ };
14426
+ }
14427
+ return { missing: false, status: 0, stdout: readFileSync28(file2, "utf8") };
14428
+ } finally {
14429
+ if (descriptor !== void 0) closeSync4(descriptor);
14430
+ rmSync6(directory, { recursive: true, force: true });
14431
+ }
14432
+ };
14433
+
14434
+ // src/project/doctor.ts
14230
14435
  var spawnRunner = (command3, args, cwd, env) => {
14231
- const result = spawnSync3(command3, [...args], {
14436
+ if (isOpenCodeInventory(command3, args))
14437
+ return nativeJsonRunner(command3, args, cwd, env);
14438
+ const result = spawnSync4(command3, [...args], {
14232
14439
  cwd,
14233
14440
  ...env ? { env: { ...process.env, ...env } } : {},
14234
14441
  encoding: "utf8",
@@ -14302,10 +14509,10 @@ function claude(spec, o) {
14302
14509
  }
14303
14510
  function codex(spec, o) {
14304
14511
  const findings = [];
14305
- const config = join25(o.home, ".codex/config.toml");
14512
+ const config = join28(o.home, ".codex/config.toml");
14306
14513
  let trusted = false;
14307
- if (existsSync21(config)) {
14308
- const projects = parse8(readFileSync28(config, "utf8")).projects ?? {};
14514
+ if (existsSync22(config)) {
14515
+ const projects = parse8(readFileSync29(config, "utf8")).projects ?? {};
14309
14516
  const root = spec.root.replace(/\/$/u, "");
14310
14517
  trusted = projects[root]?.trust_level === "trusted" || projects[`${root}/`]?.trust_level === "trusted";
14311
14518
  }
@@ -14431,8 +14638,8 @@ function grok(spec, o) {
14431
14638
  }
14432
14639
  function antigravity(spec, options2) {
14433
14640
  const foreign = agentNames(spec.root).filter((name) => {
14434
- const text3 = readFileSync28(
14435
- join25(spec.root, ".agents/agents", name, "agent.md"),
14641
+ const text3 = readFileSync29(
14642
+ join28(spec.root, ".agents/agents", name, "agent.md"),
14436
14643
  "utf8"
14437
14644
  );
14438
14645
  return splitFrontmatter(text3).meta["tools"] !== void 0;
@@ -14452,7 +14659,7 @@ function antigravity(spec, options2) {
14452
14659
  if (serversForTool(spec, "antigravity").length > 0) {
14453
14660
  const result = options2.run(
14454
14661
  "agy",
14455
- ["plugin", "validate", join25(spec.root, ANTIGRAVITY_MCP_PLUGIN)],
14662
+ ["plugin", "validate", join28(spec.root, ANTIGRAVITY_MCP_PLUGIN)],
14456
14663
  spec.root
14457
14664
  );
14458
14665
  findings.push(
@@ -14476,6 +14683,8 @@ function doctor(spec, options2) {
14476
14683
  if (wanted("codex")) findings.push(...codex(spec, options2));
14477
14684
  if (wanted("gemini")) findings.push(...gemini(spec, options2));
14478
14685
  if (wanted("grok")) findings.push(...grok(spec, options2));
14686
+ if (wanted("opencode"))
14687
+ findings.push(...opencodeDoctor(spec, options2, listed));
14479
14688
  if (wanted("antigravity")) {
14480
14689
  findings.push(...antigravity(spec, options2));
14481
14690
  }
@@ -14483,8 +14692,8 @@ function doctor(spec, options2) {
14483
14692
  }
14484
14693
 
14485
14694
  // src/project/memory.ts
14486
- import { existsSync as existsSync22, readFileSync as readFileSync29 } from "fs";
14487
- import { isAbsolute as isAbsolute7, join as join26, resolve as resolve15 } from "path";
14695
+ import { existsSync as existsSync23, readFileSync as readFileSync30 } from "fs";
14696
+ import { isAbsolute as isAbsolute7, join as join29, resolve as resolve15 } from "path";
14488
14697
  import { parse as parse9 } from "smol-toml";
14489
14698
  function object7(value) {
14490
14699
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
@@ -14493,10 +14702,10 @@ function object7(value) {
14493
14702
  return value;
14494
14703
  }
14495
14704
  function settings(file2, toml = false) {
14496
- if (!existsSync22(file2)) {
14705
+ if (!existsSync23(file2)) {
14497
14706
  return {};
14498
14707
  }
14499
- const text3 = readFileSync29(file2, "utf8");
14708
+ const text3 = readFileSync30(file2, "utf8");
14500
14709
  return object7(toml ? parse9(text3) : JSON.parse(text3));
14501
14710
  }
14502
14711
  function configuredState(value) {
@@ -14509,11 +14718,17 @@ function configuredState(value) {
14509
14718
  return "unknown";
14510
14719
  }
14511
14720
  function located(metadata2, path, pathScope) {
14512
- return { ...metadata2, path, pathScope, exists: existsSync22(path) };
14721
+ return { ...metadata2, path, pathScope, exists: existsSync23(path) };
14513
14722
  }
14514
14723
  function metadata(tool, spec, options2) {
14515
14724
  const env = options2.env ?? {};
14516
- const directory = (name, fallback) => resolve15(spec.root, env[name] ?? join26(options2.home, fallback));
14725
+ const directory = (name, fallback) => resolve15(spec.root, env[name] ?? join29(options2.home, fallback));
14726
+ if (tool === "opencode") {
14727
+ return {
14728
+ state: "unsupported",
14729
+ source: "OpenCode native memory metadata is not qualified"
14730
+ };
14731
+ }
14517
14732
  if (tool === "antigravity") {
14518
14733
  return {
14519
14734
  state: "unsupported",
@@ -14537,7 +14752,7 @@ function metadata(tool, spec, options2) {
14537
14752
  state,
14538
14753
  source: result.missing ? "Native CLI not installed" : "codex features list; active session overrides are not inspected"
14539
14754
  },
14540
- join26(home2, "memories"),
14755
+ join29(home2, "memories"),
14541
14756
  "store"
14542
14757
  );
14543
14758
  }
@@ -14550,12 +14765,12 @@ function metadata(tool, spec, options2) {
14550
14765
  }
14551
14766
  if (tool === "claude") {
14552
14767
  const home2 = directory("CLAUDE_CONFIG_DIR", ".claude");
14553
- const user2 = settings(join26(home2, "settings.json"));
14768
+ const user2 = settings(join29(home2, "settings.json"));
14554
14769
  const state = env["CLAUDE_CODE_DISABLE_AUTO_MEMORY"] === "1" ? "disabled" : configuredState(user2["autoMemoryEnabled"]);
14555
14770
  const source2 = "User configuration and disable environment flag; project trust and active session overrides are not inspected";
14556
14771
  const override = user2["autoMemoryDirectory"];
14557
14772
  if (typeof override === "string") {
14558
- const path = override.startsWith("~/") ? join26(options2.home, override.slice(2)) : override;
14773
+ const path = override.startsWith("~/") ? join29(options2.home, override.slice(2)) : override;
14559
14774
  if (!isAbsolute7(path)) {
14560
14775
  return {
14561
14776
  state: "unknown",
@@ -14568,7 +14783,7 @@ function metadata(tool, spec, options2) {
14568
14783
  if (env["CLAUDE_CONFIG_DIR"] && projectName && !projectName.includes("/") && !projectName.includes("\\") && projectName !== "." && projectName !== "..") {
14569
14784
  return located(
14570
14785
  { state, source: source2 },
14571
- join26(home2, "projects", projectName, "memory"),
14786
+ join29(home2, "projects", projectName, "memory"),
14572
14787
  "store"
14573
14788
  );
14574
14789
  }
@@ -14577,14 +14792,14 @@ function metadata(tool, spec, options2) {
14577
14792
  state,
14578
14793
  source: `${source2}; native project directory encoding is not guessed`
14579
14794
  },
14580
- join26(home2, "projects"),
14795
+ join29(home2, "projects"),
14581
14796
  "base"
14582
14797
  );
14583
14798
  }
14584
14799
  if (tool === "grok") {
14585
- const home2 = join26(options2.home, ".grok");
14586
- const user2 = settings(join26(home2, "config.toml"), true);
14587
- const project2 = settings(join26(spec.root, ".grok/config.toml"), true);
14800
+ const home2 = join29(options2.home, ".grok");
14801
+ const user2 = settings(join29(home2, "config.toml"), true);
14802
+ const project2 = settings(join29(spec.root, ".grok/config.toml"), true);
14588
14803
  const userMemory = user2["memory"] === void 0 ? {} : object7(user2["memory"]);
14589
14804
  const projectMemory = project2["memory"] === void 0 ? {} : object7(project2["memory"]);
14590
14805
  const overridden = projectMemory["enabled"] !== void 0;
@@ -14594,12 +14809,12 @@ function metadata(tool, spec, options2) {
14594
14809
  state,
14595
14810
  source: "User memory configuration; project trust and workspace encoding are not exposed by a read-only native memory command"
14596
14811
  },
14597
- join26(home2, "memory-v2/workspaces"),
14812
+ join29(home2, "memory-v2/workspaces"),
14598
14813
  "base"
14599
14814
  );
14600
14815
  }
14601
14816
  const home = directory("GEMINI_CLI_HOME", ".gemini");
14602
- const user = settings(join26(home, "settings.json"));
14817
+ const user = settings(join29(home, "settings.json"));
14603
14818
  const context = user["context"] === void 0 ? {} : object7(user["context"]);
14604
14819
  const names = context["fileName"] ?? "GEMINI.md";
14605
14820
  const contextFileNames = typeof names === "string" ? [names] : names;
@@ -14615,7 +14830,7 @@ function metadata(tool, spec, options2) {
14615
14830
  source: "Global memory file existence and user context filenames; active memory tool enablement is not exposed",
14616
14831
  contextFileNames
14617
14832
  },
14618
- join26(home, "GEMINI.md"),
14833
+ join29(home, "GEMINI.md"),
14619
14834
  "store"
14620
14835
  );
14621
14836
  }
@@ -14648,14 +14863,14 @@ function memoryFindings(spec, options2) {
14648
14863
  // src/project/edit.ts
14649
14864
  import {
14650
14865
  cpSync,
14651
- existsSync as existsSync23,
14866
+ existsSync as existsSync24,
14652
14867
  mkdirSync as mkdirSync8,
14653
- readFileSync as readFileSync30,
14654
- rmSync as rmSync6,
14655
- statSync as statSync13,
14868
+ readFileSync as readFileSync31,
14869
+ rmSync as rmSync7,
14870
+ statSync as statSync14,
14656
14871
  writeFileSync as writeFileSync7
14657
14872
  } from "fs";
14658
- import { basename as basename7, dirname as dirname20, join as join27 } from "path";
14873
+ import { basename as basename7, dirname as dirname20, join as join30 } from "path";
14659
14874
  var CROSS_TOOL = ["name", "description"];
14660
14875
  var tomlValue2 = (value) => JSON.stringify(value);
14661
14876
  function findEntry(entries, wanted) {
@@ -14679,7 +14894,7 @@ function addEntry(root, entry2) {
14679
14894
  `${entry2.name} is a ${kind2}; only skills and agents are added to .agents/`
14680
14895
  );
14681
14896
  }
14682
- const { meta, body } = splitFrontmatter(readFileSync30(entry2.path, "utf8"));
14897
+ const { meta, body } = splitFrontmatter(readFileSync31(entry2.path, "utf8"));
14683
14898
  const name = basename7(entry2.slug);
14684
14899
  if (!/^[a-z0-9][a-z0-9-]*$/u.test(name)) {
14685
14900
  throw new ProjectError(
@@ -14687,12 +14902,12 @@ function addEntry(root, entry2) {
14687
14902
  );
14688
14903
  }
14689
14904
  if (kind2 === "skill") {
14690
- const dest2 = join27(root, ".agents/skills", name);
14691
- if (existsSync23(dest2))
14905
+ const dest2 = join30(root, ".agents/skills", name);
14906
+ if (existsSync24(dest2))
14692
14907
  throw new ProjectError(`.agents/skills/${name} already exists`);
14693
14908
  const source2 = entry2.root ?? dirname20(entry2.path);
14694
14909
  mkdirSync8(dirname20(dest2), { recursive: true });
14695
- if (statSync13(source2).isDirectory()) {
14910
+ if (statSync14(source2).isDirectory()) {
14696
14911
  cpSync(source2, dest2, { recursive: true });
14697
14912
  } else {
14698
14913
  mkdirSync8(dest2);
@@ -14703,14 +14918,14 @@ function addEntry(root, entry2) {
14703
14918
  description: meta["description"] ?? entry2.description
14704
14919
  });
14705
14920
  writeFileSync7(
14706
- join27(dest2, "SKILL.md"),
14921
+ join30(dest2, "SKILL.md"),
14707
14922
  `${head}
14708
14923
  ${body.replace(/^\n/u, "")}`
14709
14924
  );
14710
14925
  return { kind: kind2, name, path: `.agents/skills/${name}` };
14711
14926
  }
14712
- const dest = join27(root, ".agents/agents", name);
14713
- if (existsSync23(dest))
14927
+ const dest = join30(root, ".agents/agents", name);
14928
+ if (existsSync24(dest))
14714
14929
  throw new ProjectError(`.agents/agents/${name} already exists`);
14715
14930
  const kept = {};
14716
14931
  const moved = {};
@@ -14720,17 +14935,17 @@ ${body.replace(/^\n/u, "")}`
14720
14935
  }
14721
14936
  mkdirSync8(dest, { recursive: true });
14722
14937
  writeFileSync7(
14723
- join27(dest, "agent.md"),
14938
+ join30(dest, "agent.md"),
14724
14939
  `${renderFrontmatter(kept)}
14725
14940
  ${body.replace(/^\n/u, "")}`
14726
14941
  );
14727
14942
  if (Object.keys(moved).length > 0) {
14728
- const config = join27(root, "pmcp.toml");
14943
+ const config = join30(root, "pmcp.toml");
14729
14944
  const lines2 = [
14730
14945
  `[agents.${name}.claude]`,
14731
14946
  ...Object.entries(moved).map(([k, v]) => `${k} = ${tomlValue2(v)}`)
14732
14947
  ];
14733
- const before = existsSync23(config) ? readFileSync30(config, "utf8") : "";
14948
+ const before = existsSync24(config) ? readFileSync31(config, "utf8") : "";
14734
14949
  const sep7 = before === "" || before.endsWith("\n\n") ? "" : "\n";
14735
14950
  writeFileSync7(config, `${before}${sep7}${lines2.join("\n")}
14736
14951
  `);
@@ -14753,15 +14968,15 @@ function withoutTables(toml, name) {
14753
14968
  function removeAsset(root, name) {
14754
14969
  const removed = [];
14755
14970
  for (const rel of [`.agents/skills/${name}`, `.agents/agents/${name}`]) {
14756
- if (!existsSync23(join27(root, rel))) continue;
14757
- rmSync6(join27(root, rel), { recursive: true, force: true });
14971
+ if (!existsSync24(join30(root, rel))) continue;
14972
+ rmSync7(join30(root, rel), { recursive: true, force: true });
14758
14973
  removed.push(rel);
14759
14974
  }
14760
14975
  if (removed.length === 0)
14761
14976
  throw new ProjectError(`no skill or agent named ${name} in .agents/`);
14762
- const config = join27(root, "pmcp.toml");
14763
- if (existsSync23(config)) {
14764
- const before = readFileSync30(config, "utf8");
14977
+ const config = join30(root, "pmcp.toml");
14978
+ if (existsSync24(config)) {
14979
+ const before = readFileSync31(config, "utf8");
14765
14980
  const after = withoutTables(before, name);
14766
14981
  if (after !== before) writeFileSync7(config, after);
14767
14982
  }
@@ -15000,16 +15215,16 @@ var doctorCommand = {
15000
15215
  };
15001
15216
 
15002
15217
  // src/validate.ts
15003
- import { existsSync as existsSync24, readFileSync as readFileSync31, statSync as statSync14 } from "fs";
15004
- import { basename as basename8, join as join28, resolve as resolve16 } from "path";
15218
+ import { existsSync as existsSync25, readFileSync as readFileSync32, statSync as statSync15 } from "fs";
15219
+ import { basename as basename8, join as join31, resolve as resolve16 } from "path";
15005
15220
  function validateSkillDir(dir) {
15006
15221
  const root = resolve16(dir);
15007
- const skillMd = basename8(root) === "SKILL.md" ? root : join28(root, "SKILL.md");
15008
- if (!existsSync24(skillMd) || !statSync14(skillMd).isFile()) {
15222
+ const skillMd = basename8(root) === "SKILL.md" ? root : join31(root, "SKILL.md");
15223
+ if (!existsSync25(skillMd) || !statSync15(skillMd).isFile()) {
15009
15224
  return [{ path: root, reason: "no SKILL.md", level: "error" }];
15010
15225
  }
15011
- const front = frontmatterObject(readFileSync31(skillMd, "utf8"));
15012
- const directory = basename8(skillMd === root ? join28(root, "..") : root);
15226
+ const front = frontmatterObject(readFileSync32(skillMd, "utf8"));
15227
+ const directory = basename8(skillMd === root ? join31(root, "..") : root);
15013
15228
  return specProblems(front, directory).map((reason) => ({
15014
15229
  path: skillMd,
15015
15230
  reason,
@@ -15054,7 +15269,7 @@ var validateCommand = {
15054
15269
  };
15055
15270
 
15056
15271
  // src/commands/mailbox.ts
15057
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync8 } from "fs";
15272
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync8 } from "fs";
15058
15273
  import { resolve as resolve17 } from "path";
15059
15274
  init_config2();
15060
15275
  init_service();
@@ -15237,7 +15452,7 @@ var mailboxCommand = {
15237
15452
  ownsBinding = true;
15238
15453
  }
15239
15454
  const inputFile = one(context.args, "input");
15240
- const input = inputFile ? JSON.parse(readFileSync32(inputFile, "utf8")) : {};
15455
+ const input = inputFile ? JSON.parse(readFileSync33(inputFile, "utf8")) : {};
15241
15456
  const result = await new MailboxService(store, binding).call(
15242
15457
  operation,
15243
15458
  input
@@ -15321,7 +15536,7 @@ var harnessOptions = [
15321
15536
  ];
15322
15537
 
15323
15538
  // src/commands/harness/invocation.ts
15324
- import { readFileSync as readFileSync33, statSync as statSync15 } from "fs";
15539
+ import { readFileSync as readFileSync34, statSync as statSync16 } from "fs";
15325
15540
  init_validation();
15326
15541
  var common = ["group-file", "generation"];
15327
15542
  var options = {
@@ -15358,10 +15573,10 @@ var options = {
15358
15573
  "recovery:abort-start": [...common, "session"]
15359
15574
  };
15360
15575
  function file(path) {
15361
- const stat = statSync15(path);
15576
+ const stat = statSync16(path);
15362
15577
  if (!stat.isFile() || stat.size > 65536)
15363
15578
  throw new ArgumentError("Input file exceeds 65536 bytes");
15364
- return readFileSync33(path, "utf8");
15579
+ return readFileSync34(path, "utf8");
15365
15580
  }
15366
15581
  function parseInvocation(context) {
15367
15582
  const [family, action, ...extra] = context.args.positional;
@@ -15694,14 +15909,14 @@ import { resolve as resolve21 } from "path";
15694
15909
 
15695
15910
  // src/marketplace/export.ts
15696
15911
  import {
15697
- existsSync as existsSync37,
15912
+ existsSync as existsSync38,
15698
15913
  lstatSync as lstatSync14,
15699
15914
  mkdirSync as mkdirSync13,
15700
- readFileSync as readFileSync38,
15915
+ readFileSync as readFileSync39,
15701
15916
  readdirSync as readdirSync13,
15702
15917
  writeFileSync as writeFileSync14
15703
15918
  } from "fs";
15704
- import { dirname as dirname27, join as join55, resolve as resolve20 } from "path";
15919
+ import { dirname as dirname27, join as join58, resolve as resolve20 } from "path";
15705
15920
  var NATIVE_PLUGIN_RUNTIMES = [
15706
15921
  "claude",
15707
15922
  "codex",
@@ -15726,7 +15941,7 @@ function readResources(directory, prefix, files) {
15726
15941
  for (const entry2 of readdirSync13(directory, { withFileTypes: true })) {
15727
15942
  if (entry2.isSymbolicLink())
15728
15943
  throw new Error("Plugin exports cannot contain symlinks");
15729
- const path = join55(directory, entry2.name);
15944
+ const path = join58(directory, entry2.name);
15730
15945
  const relativePath = `${prefix}/${entry2.name}`;
15731
15946
  if (entry2.isDirectory()) {
15732
15947
  if (relativePath.split("/").length > 6)
@@ -15739,7 +15954,7 @@ function readResources(directory, prefix, files) {
15739
15954
  const stats = lstatSync14(path);
15740
15955
  if (stats.size > 1024 * 1024 || files.size >= 256)
15741
15956
  throw new Error("Plugin resources exceed the export budget");
15742
- files.set(relativePath, readFileSync38(path));
15957
+ files.set(relativePath, readFileSync39(path));
15743
15958
  }
15744
15959
  }
15745
15960
  function pluginExportFiles(root, name, runtime2) {
@@ -15748,7 +15963,7 @@ function pluginExportFiles(root, name, runtime2) {
15748
15963
  const files = /* @__PURE__ */ new Map();
15749
15964
  readResources(containedPath(plugin.directory, "skills"), "skills", files);
15750
15965
  for (const name2 of ["LICENSE", "NOTICE"])
15751
- files.set(name2, readFileSync38(containedPath(root, name2)));
15966
+ files.set(name2, readFileSync39(containedPath(root, name2)));
15752
15967
  const manifests = {
15753
15968
  claude: [".claude-plugin/plugin.json", ".mcp.json"],
15754
15969
  codex: ["plugin.json", "mcp.json"],
@@ -15757,10 +15972,10 @@ function pluginExportFiles(root, name, runtime2) {
15757
15972
  agy: []
15758
15973
  };
15759
15974
  for (const filename of manifests[runtime2]) {
15760
- if (existsSync37(join55(plugin.directory, filename)))
15975
+ if (existsSync38(join58(plugin.directory, filename)))
15761
15976
  files.set(
15762
15977
  filename,
15763
- readFileSync38(containedPath(plugin.directory, filename))
15978
+ readFileSync39(containedPath(plugin.directory, filename))
15764
15979
  );
15765
15980
  }
15766
15981
  if (runtime2 === "agy") {
@@ -15771,11 +15986,11 @@ function pluginExportFiles(root, name, runtime2) {
15771
15986
  `
15772
15987
  )
15773
15988
  );
15774
- const mcp = join55(plugin.directory, ".mcp.json");
15775
- if (existsSync37(mcp))
15989
+ const mcp = join58(plugin.directory, ".mcp.json");
15990
+ if (existsSync38(mcp))
15776
15991
  files.set(
15777
15992
  "mcp_config.json",
15778
- readFileSync38(containedPath(plugin.directory, mcp))
15993
+ readFileSync39(containedPath(plugin.directory, mcp))
15779
15994
  );
15780
15995
  }
15781
15996
  return files;
@@ -15794,7 +16009,7 @@ function exportPublicPlugin(root, name, runtime2, output) {
15794
16009
  throw error;
15795
16010
  }
15796
16011
  for (const [path, bytes] of files) {
15797
- const target2 = join55(destination, path);
16012
+ const target2 = join58(destination, path);
15798
16013
  mkdirSync13(dirname27(target2), { recursive: true });
15799
16014
  writeFileSync14(target2, bytes, { flag: "wx" });
15800
16015
  }
@@ -15946,7 +16161,7 @@ function dispatch(argv, options2 = {}) {
15946
16161
  }
15947
16162
  return run(command3, rest, { ui, env, cwd });
15948
16163
  }
15949
- var VERSION = "0.16.1";
16164
+ var VERSION = "0.17.1";
15950
16165
  async function defaultEntry(options2, context) {
15951
16166
  const terminal = options2.terminal ?? {
15952
16167
  stdin: process.stdin.isTTY === true,